etnaviv: Command buffer realloc
authorMarek Vasut <marex@denx.de>
Thu, 5 Sep 2019 17:57:39 +0000 (19:57 +0200)
committerLucas Stach <dev@lynxeye.de>
Fri, 18 Oct 2019 17:03:25 +0000 (17:03 +0000)
Reallocate the command stream buffer in case it is too small.
The older kernel versions are limited to 64 kiB buffer, so
limit the size to avoid oversized buffers.

Signed-off-by: Marek Vasut <marex@denx.de>
src/etnaviv/drm/etnaviv_cmd_stream.c
src/etnaviv/drm/etnaviv_drmif.h

index 6a218ad0bf23ee2d2c4bcbfd5ccd750f7a7f96d3..ef5143003aebd6c5e62b079464656d2a5e94b83b 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 #include <assert.h>
+#include <stdlib.h>
 
 #include "etnaviv_drmif.h"
 #include "etnaviv_priv.h"
@@ -49,6 +50,35 @@ static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz)
        (x)->nr_ ## name ++; \
 })
 
+void etna_cmd_stream_realloc(struct etna_cmd_stream *stream, size_t n)
+{
+       size_t size;
+       void *buffer;
+
+       /*
+        * Increase the command buffer size by 1 kiB. Here we pick 1 kiB
+        * increment to prevent it from growing too much too quickly.
+        */
+       size = ALIGN(stream->size + n, 1024);
+
+       /* Command buffer is too big for older kernel versions */
+       if (size >= 32768)
+               goto error;
+
+       buffer = realloc(stream->buffer, size * 4);
+       if (!buffer)
+               goto error;
+
+       stream->buffer = buffer;
+       stream->size = size;
+
+       return;
+
+error:
+       WARN_MSG("command buffer too long, forcing flush.");
+       etna_cmd_stream_force_flush(stream);
+}
+
 static inline struct etna_cmd_stream_priv *
 etna_cmd_stream_priv(struct etna_cmd_stream *stream)
 {
index 7fb01c8a654524102214fe592428d9e51aba4f53..ff08ab50dbc97174da39cc56b194d586d848b1e2 100644 (file)
@@ -154,10 +154,12 @@ static inline uint32_t etna_cmd_stream_avail(struct etna_cmd_stream *stream)
        return stream->size - stream->offset - END_CLEARANCE;
 }
 
+void etna_cmd_stream_realloc(struct etna_cmd_stream *stream, size_t n);
+
 static inline void etna_cmd_stream_reserve(struct etna_cmd_stream *stream, size_t n)
 {
        if (etna_cmd_stream_avail(stream) < n)
-               etna_cmd_stream_force_flush(stream);
+               etna_cmd_stream_realloc(stream, n);
 }
 
 static inline void etna_cmd_stream_emit(struct etna_cmd_stream *stream, uint32_t data)