[Mesa-dev] [PATCH] winsys/radeon: add command stream replay dump for faulty lockup v2

2013-03-27 Thread j . glisse
From: Jerome Glisse 

Build time option, set RADEON_CS_DUMP_ON_LOCKUP to 1 in radeon_drm_cs.h to
enable it.

When enabled after each cs submission the code will try to detect lockup by
waiting on one of the buffer of the cs to become idle, after a timeout it
will consider that the cs triggered a lockup and will write a radeon_lockup.c
file in current directory that have all information for replaying the cs.

To build this file :
gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup -I/usr/include/libdrm

v2: Add radeon_ctx.h file to mesa git tree

Signed-off-by: Jerome Glisse 
---
 src/gallium/winsys/radeon/drm/Makefile.sources |   1 +
 src/gallium/winsys/radeon/drm/radeon_drm_bo.c  |  80 +++
 src/gallium/winsys/radeon/drm/radeon_drm_bo.h  |   2 +
 src/gallium/winsys/radeon/drm/radeon_drm_cs.c  |   4 +
 src/gallium/winsys/radeon/drm/radeon_drm_cs.h  |   6 +
 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 141 
 src/gallium/winsys/radeon/tools/radeon_ctx.h   | 237 +
 7 files changed, 434 insertions(+), 37 deletions(-)
 create mode 100644 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c
 create mode 100644 src/gallium/winsys/radeon/tools/radeon_ctx.h

diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources 
b/src/gallium/winsys/radeon/drm/Makefile.sources
index 1d18d61..4ca5ebb 100644
--- a/src/gallium/winsys/radeon/drm/Makefile.sources
+++ b/src/gallium/winsys/radeon/drm/Makefile.sources
@@ -1,4 +1,5 @@
 C_SOURCES := \
radeon_drm_bo.c \
radeon_drm_cs.c \
+   radeon_drm_cs_dump.c \
radeon_drm_winsys.c
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c 
b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
index f4ac526..5a9493a 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -391,14 +391,54 @@ static void radeon_bo_destroy(struct pb_buffer *_buf)
 FREE(bo);
 }
 
+void *radeon_bo_do_map(struct radeon_bo *bo)
+{
+struct drm_radeon_gem_mmap args = {0};
+void *ptr;
+
+/* Return the pointer if it's already mapped. */
+if (bo->ptr)
+return bo->ptr;
+
+/* Map the buffer. */
+pipe_mutex_lock(bo->map_mutex);
+/* Return the pointer if it's already mapped (in case of a race). */
+if (bo->ptr) {
+pipe_mutex_unlock(bo->map_mutex);
+return bo->ptr;
+}
+args.handle = bo->handle;
+args.offset = 0;
+args.size = (uint64_t)bo->base.size;
+if (drmCommandWriteRead(bo->rws->fd,
+DRM_RADEON_GEM_MMAP,
+&args,
+sizeof(args))) {
+pipe_mutex_unlock(bo->map_mutex);
+fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
+bo, bo->handle);
+return NULL;
+}
+
+ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
+   bo->rws->fd, args.addr_ptr);
+if (ptr == MAP_FAILED) {
+pipe_mutex_unlock(bo->map_mutex);
+fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
+return NULL;
+}
+bo->ptr = ptr;
+pipe_mutex_unlock(bo->map_mutex);
+
+return bo->ptr;
+}
+
 static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf,
struct radeon_winsys_cs *rcs,
enum pipe_transfer_usage usage)
 {
 struct radeon_bo *bo = (struct radeon_bo*)buf;
 struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs;
-struct drm_radeon_gem_mmap args = {0};
-void *ptr;
 
 /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */
 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
@@ -461,41 +501,7 @@ static void *radeon_bo_map(struct radeon_winsys_cs_handle 
*buf,
 }
 }
 
-/* Return the pointer if it's already mapped. */
-if (bo->ptr)
-return bo->ptr;
-
-/* Map the buffer. */
-pipe_mutex_lock(bo->map_mutex);
-/* Return the pointer if it's already mapped (in case of a race). */
-if (bo->ptr) {
-pipe_mutex_unlock(bo->map_mutex);
-return bo->ptr;
-}
-args.handle = bo->handle;
-args.offset = 0;
-args.size = (uint64_t)bo->base.size;
-if (drmCommandWriteRead(bo->rws->fd,
-DRM_RADEON_GEM_MMAP,
-&args,
-sizeof(args))) {
-pipe_mutex_unlock(bo->map_mutex);
-fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
-bo, bo->handle);
-return NULL;
-}
-
-ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
-   bo->rws->fd, args.addr_ptr);
-if (ptr == MAP_FAILED) {
-pipe_mutex_unlock(bo->map_mutex);
-fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
-return NULL;
-}
-bo->ptr = ptr;
-pipe_mutex_unlock(bo->map_mutex);
-
-return bo->ptr;
+return radeon_bo_do_map(bo);
 }
 
 static vo

Re: [Mesa-dev] [PATCH] winsys/radeon: add command stream replay dump for faulty lockup

2013-03-27 Thread Marek Olšák
On Wed, Mar 27, 2013 at 4:38 PM, Jerome Glisse  wrote:
> On Wed, Mar 27, 2013 at 11:27 AM,   wrote:
>> From: Jerome Glisse 
>>
>> Build time option, set RADEON_CS_DUMP_ON_LOCKUP to 1 in radeon_drm_cs.h to
>> enable it.
>>
>> When enabled after each cs submission the code will try to detect lockup by
>> waiting on one of the buffer of the cs to become idle, after a timeout it
>> will consider that the cs triggered a lockup and will write a radeon_lockup.c
>> file in current directory that have all information for replaying the cs.
>>
>> To build this file :
>> gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup -I/usr/include/libdrm
>>
>> Signed-off-by: Jerome Glisse 
>
> Maybe i should add the radeon_ctx.h file to winsys dir as you need it
> to build the radeon_lockup.c i did not wanted to printf the whole
> helper. For example you can check radeon_lockup.c and radeon_ctx.h
> here :
> http://people.freedesktop.org/~glisse/rlockup/

It would be better to put the file in a separate directory (maybe a
subdirectory in the winsys) and add a note that it's supposed to be
used by out-of-tree code.

Otherwise it looks good.

Marek

>
> Note this is a radeon si verde capture for a 2d tiling that lockup
> (can be hard lockup sometimes so be careful).
>
> Cheers,
> Jerome
>
>> ---
>>  src/gallium/winsys/radeon/drm/Makefile.sources |   1 +
>>  src/gallium/winsys/radeon/drm/radeon_drm_bo.c  |  80 ++--
>>  src/gallium/winsys/radeon/drm/radeon_drm_bo.h  |   2 +
>>  src/gallium/winsys/radeon/drm/radeon_drm_cs.c  |   4 +
>>  src/gallium/winsys/radeon/drm/radeon_drm_cs.h  |   6 +
>>  src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 135 
>> +
>>  6 files changed, 191 insertions(+), 37 deletions(-)
>>  create mode 100644 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c
>>
>> diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources 
>> b/src/gallium/winsys/radeon/drm/Makefile.sources
>> index 1d18d61..4ca5ebb 100644
>> --- a/src/gallium/winsys/radeon/drm/Makefile.sources
>> +++ b/src/gallium/winsys/radeon/drm/Makefile.sources
>> @@ -1,4 +1,5 @@
>>  C_SOURCES := \
>> radeon_drm_bo.c \
>> radeon_drm_cs.c \
>> +   radeon_drm_cs_dump.c \
>> radeon_drm_winsys.c
>> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c 
>> b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> index f4ac526..5a9493a 100644
>> --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> @@ -391,14 +391,54 @@ static void radeon_bo_destroy(struct pb_buffer *_buf)
>>  FREE(bo);
>>  }
>>
>> +void *radeon_bo_do_map(struct radeon_bo *bo)
>> +{
>> +struct drm_radeon_gem_mmap args = {0};
>> +void *ptr;
>> +
>> +/* Return the pointer if it's already mapped. */
>> +if (bo->ptr)
>> +return bo->ptr;
>> +
>> +/* Map the buffer. */
>> +pipe_mutex_lock(bo->map_mutex);
>> +/* Return the pointer if it's already mapped (in case of a race). */
>> +if (bo->ptr) {
>> +pipe_mutex_unlock(bo->map_mutex);
>> +return bo->ptr;
>> +}
>> +args.handle = bo->handle;
>> +args.offset = 0;
>> +args.size = (uint64_t)bo->base.size;
>> +if (drmCommandWriteRead(bo->rws->fd,
>> +DRM_RADEON_GEM_MMAP,
>> +&args,
>> +sizeof(args))) {
>> +pipe_mutex_unlock(bo->map_mutex);
>> +fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
>> +bo, bo->handle);
>> +return NULL;
>> +}
>> +
>> +ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
>> +   bo->rws->fd, args.addr_ptr);
>> +if (ptr == MAP_FAILED) {
>> +pipe_mutex_unlock(bo->map_mutex);
>> +fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
>> +return NULL;
>> +}
>> +bo->ptr = ptr;
>> +pipe_mutex_unlock(bo->map_mutex);
>> +
>> +return bo->ptr;
>> +}
>> +
>>  static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf,
>> struct radeon_winsys_cs *rcs,
>> enum pipe_transfer_usage usage)
>>  {
>>  struct radeon_bo *bo = (struct radeon_bo*)buf;
>>  struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs;
>> -struct drm_radeon_gem_mmap args = {0};
>> -void *ptr;
>>
>>  /* If it's not unsynchronized bo_map, flush CS if needed and then wait. 
>> */
>>  if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
>> @@ -461,41 +501,7 @@ static void *radeon_bo_map(struct 
>> radeon_winsys_cs_handle *buf,
>>  }
>>  }
>>
>> -/* Return the pointer if it's already mapped. */
>> -if (bo->ptr)
>> -return bo->ptr;
>> -
>> -/* Map the buffer. */
>> -pipe_mutex_lock(bo->map_mutex);
>> -/* Return the pointer if it's already mapped (in case of a race). */
>> -if (bo->ptr) {
>> -pipe_mutex_unlock(bo->map_mutex);
>> -return bo->pt

Re: [Mesa-dev] [PATCH] winsys/radeon: add command stream replay dump for faulty lockup

2013-03-27 Thread Jerome Glisse
On Wed, Mar 27, 2013 at 11:27 AM,   wrote:
> From: Jerome Glisse 
>
> Build time option, set RADEON_CS_DUMP_ON_LOCKUP to 1 in radeon_drm_cs.h to
> enable it.
>
> When enabled after each cs submission the code will try to detect lockup by
> waiting on one of the buffer of the cs to become idle, after a timeout it
> will consider that the cs triggered a lockup and will write a radeon_lockup.c
> file in current directory that have all information for replaying the cs.
>
> To build this file :
> gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup -I/usr/include/libdrm
>
> Signed-off-by: Jerome Glisse 

Maybe i should add the radeon_ctx.h file to winsys dir as you need it
to build the radeon_lockup.c i did not wanted to printf the whole
helper. For example you can check radeon_lockup.c and radeon_ctx.h
here :
http://people.freedesktop.org/~glisse/rlockup/

Note this is a radeon si verde capture for a 2d tiling that lockup
(can be hard lockup sometimes so be careful).

Cheers,
Jerome

> ---
>  src/gallium/winsys/radeon/drm/Makefile.sources |   1 +
>  src/gallium/winsys/radeon/drm/radeon_drm_bo.c  |  80 ++--
>  src/gallium/winsys/radeon/drm/radeon_drm_bo.h  |   2 +
>  src/gallium/winsys/radeon/drm/radeon_drm_cs.c  |   4 +
>  src/gallium/winsys/radeon/drm/radeon_drm_cs.h  |   6 +
>  src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 135 
> +
>  6 files changed, 191 insertions(+), 37 deletions(-)
>  create mode 100644 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c
>
> diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources 
> b/src/gallium/winsys/radeon/drm/Makefile.sources
> index 1d18d61..4ca5ebb 100644
> --- a/src/gallium/winsys/radeon/drm/Makefile.sources
> +++ b/src/gallium/winsys/radeon/drm/Makefile.sources
> @@ -1,4 +1,5 @@
>  C_SOURCES := \
> radeon_drm_bo.c \
> radeon_drm_cs.c \
> +   radeon_drm_cs_dump.c \
> radeon_drm_winsys.c
> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c 
> b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> index f4ac526..5a9493a 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> @@ -391,14 +391,54 @@ static void radeon_bo_destroy(struct pb_buffer *_buf)
>  FREE(bo);
>  }
>
> +void *radeon_bo_do_map(struct radeon_bo *bo)
> +{
> +struct drm_radeon_gem_mmap args = {0};
> +void *ptr;
> +
> +/* Return the pointer if it's already mapped. */
> +if (bo->ptr)
> +return bo->ptr;
> +
> +/* Map the buffer. */
> +pipe_mutex_lock(bo->map_mutex);
> +/* Return the pointer if it's already mapped (in case of a race). */
> +if (bo->ptr) {
> +pipe_mutex_unlock(bo->map_mutex);
> +return bo->ptr;
> +}
> +args.handle = bo->handle;
> +args.offset = 0;
> +args.size = (uint64_t)bo->base.size;
> +if (drmCommandWriteRead(bo->rws->fd,
> +DRM_RADEON_GEM_MMAP,
> +&args,
> +sizeof(args))) {
> +pipe_mutex_unlock(bo->map_mutex);
> +fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
> +bo, bo->handle);
> +return NULL;
> +}
> +
> +ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
> +   bo->rws->fd, args.addr_ptr);
> +if (ptr == MAP_FAILED) {
> +pipe_mutex_unlock(bo->map_mutex);
> +fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
> +return NULL;
> +}
> +bo->ptr = ptr;
> +pipe_mutex_unlock(bo->map_mutex);
> +
> +return bo->ptr;
> +}
> +
>  static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf,
> struct radeon_winsys_cs *rcs,
> enum pipe_transfer_usage usage)
>  {
>  struct radeon_bo *bo = (struct radeon_bo*)buf;
>  struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs;
> -struct drm_radeon_gem_mmap args = {0};
> -void *ptr;
>
>  /* If it's not unsynchronized bo_map, flush CS if needed and then wait. 
> */
>  if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
> @@ -461,41 +501,7 @@ static void *radeon_bo_map(struct 
> radeon_winsys_cs_handle *buf,
>  }
>  }
>
> -/* Return the pointer if it's already mapped. */
> -if (bo->ptr)
> -return bo->ptr;
> -
> -/* Map the buffer. */
> -pipe_mutex_lock(bo->map_mutex);
> -/* Return the pointer if it's already mapped (in case of a race). */
> -if (bo->ptr) {
> -pipe_mutex_unlock(bo->map_mutex);
> -return bo->ptr;
> -}
> -args.handle = bo->handle;
> -args.offset = 0;
> -args.size = (uint64_t)bo->base.size;
> -if (drmCommandWriteRead(bo->rws->fd,
> -DRM_RADEON_GEM_MMAP,
> -&args,
> -sizeof(args))) {
> -pipe_mutex_unlock(bo->map_mutex);
> -fprintf(stderr, "radeon: gem_mmap faile

[Mesa-dev] [PATCH] winsys/radeon: add command stream replay dump for faulty lockup

2013-03-27 Thread j . glisse
From: Jerome Glisse 

Build time option, set RADEON_CS_DUMP_ON_LOCKUP to 1 in radeon_drm_cs.h to
enable it.

When enabled after each cs submission the code will try to detect lockup by
waiting on one of the buffer of the cs to become idle, after a timeout it
will consider that the cs triggered a lockup and will write a radeon_lockup.c
file in current directory that have all information for replaying the cs.

To build this file :
gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup -I/usr/include/libdrm

Signed-off-by: Jerome Glisse 
---
 src/gallium/winsys/radeon/drm/Makefile.sources |   1 +
 src/gallium/winsys/radeon/drm/radeon_drm_bo.c  |  80 ++--
 src/gallium/winsys/radeon/drm/radeon_drm_bo.h  |   2 +
 src/gallium/winsys/radeon/drm/radeon_drm_cs.c  |   4 +
 src/gallium/winsys/radeon/drm/radeon_drm_cs.h  |   6 +
 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 135 +
 6 files changed, 191 insertions(+), 37 deletions(-)
 create mode 100644 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c

diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources 
b/src/gallium/winsys/radeon/drm/Makefile.sources
index 1d18d61..4ca5ebb 100644
--- a/src/gallium/winsys/radeon/drm/Makefile.sources
+++ b/src/gallium/winsys/radeon/drm/Makefile.sources
@@ -1,4 +1,5 @@
 C_SOURCES := \
radeon_drm_bo.c \
radeon_drm_cs.c \
+   radeon_drm_cs_dump.c \
radeon_drm_winsys.c
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c 
b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
index f4ac526..5a9493a 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -391,14 +391,54 @@ static void radeon_bo_destroy(struct pb_buffer *_buf)
 FREE(bo);
 }
 
+void *radeon_bo_do_map(struct radeon_bo *bo)
+{
+struct drm_radeon_gem_mmap args = {0};
+void *ptr;
+
+/* Return the pointer if it's already mapped. */
+if (bo->ptr)
+return bo->ptr;
+
+/* Map the buffer. */
+pipe_mutex_lock(bo->map_mutex);
+/* Return the pointer if it's already mapped (in case of a race). */
+if (bo->ptr) {
+pipe_mutex_unlock(bo->map_mutex);
+return bo->ptr;
+}
+args.handle = bo->handle;
+args.offset = 0;
+args.size = (uint64_t)bo->base.size;
+if (drmCommandWriteRead(bo->rws->fd,
+DRM_RADEON_GEM_MMAP,
+&args,
+sizeof(args))) {
+pipe_mutex_unlock(bo->map_mutex);
+fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
+bo, bo->handle);
+return NULL;
+}
+
+ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
+   bo->rws->fd, args.addr_ptr);
+if (ptr == MAP_FAILED) {
+pipe_mutex_unlock(bo->map_mutex);
+fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
+return NULL;
+}
+bo->ptr = ptr;
+pipe_mutex_unlock(bo->map_mutex);
+
+return bo->ptr;
+}
+
 static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf,
struct radeon_winsys_cs *rcs,
enum pipe_transfer_usage usage)
 {
 struct radeon_bo *bo = (struct radeon_bo*)buf;
 struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs;
-struct drm_radeon_gem_mmap args = {0};
-void *ptr;
 
 /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */
 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
@@ -461,41 +501,7 @@ static void *radeon_bo_map(struct radeon_winsys_cs_handle 
*buf,
 }
 }
 
-/* Return the pointer if it's already mapped. */
-if (bo->ptr)
-return bo->ptr;
-
-/* Map the buffer. */
-pipe_mutex_lock(bo->map_mutex);
-/* Return the pointer if it's already mapped (in case of a race). */
-if (bo->ptr) {
-pipe_mutex_unlock(bo->map_mutex);
-return bo->ptr;
-}
-args.handle = bo->handle;
-args.offset = 0;
-args.size = (uint64_t)bo->base.size;
-if (drmCommandWriteRead(bo->rws->fd,
-DRM_RADEON_GEM_MMAP,
-&args,
-sizeof(args))) {
-pipe_mutex_unlock(bo->map_mutex);
-fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
-bo, bo->handle);
-return NULL;
-}
-
-ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
-   bo->rws->fd, args.addr_ptr);
-if (ptr == MAP_FAILED) {
-pipe_mutex_unlock(bo->map_mutex);
-fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
-return NULL;
-}
-bo->ptr = ptr;
-pipe_mutex_unlock(bo->map_mutex);
-
-return bo->ptr;
+return radeon_bo_do_map(bo);
 }
 
 static void radeon_bo_unmap(struct radeon_winsys_cs_handle *_buf)
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h 
b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
index 82ea