[PATCH 2/2] drm/radeon: add lockup faulty command recording

j.glisse at gmail.com j.glisse at gmail.com
Wed May 16 14:22:32 PDT 2012


From: Jerome Glisse <jglisse at redhat.com>

This try to identify the faulty user command stream that caused
lockup. If it finds one it create big blob that contains all
information needed to replay the faulty command stream.

Signed-off-by: Jerome Glisse <jglisse at redhat.com>
---
 drivers/gpu/drm/radeon/r100.c          |    6 +-
 drivers/gpu/drm/radeon/r300.c          |    2 +-
 drivers/gpu/drm/radeon/r420.c          |    2 +-
 drivers/gpu/drm/radeon/r600.c          |    2 +-
 drivers/gpu/drm/radeon/r600_cs.c       |    4 +-
 drivers/gpu/drm/radeon/radeon.h        |   72 +++++++++-----
 drivers/gpu/drm/radeon/radeon_cs.c     |   68 ++++++++++++--
 drivers/gpu/drm/radeon/radeon_device.c |   25 +++++-
 drivers/gpu/drm/radeon/radeon_family.h |  145 ++++++++++++++--------------
 drivers/gpu/drm/radeon/radeon_fence.c  |    2 +-
 drivers/gpu/drm/radeon/radeon_gart.c   |   10 ++-
 drivers/gpu/drm/radeon/radeon_object.h |   12 ++-
 drivers/gpu/drm/radeon/radeon_pm.c     |    2 +-
 drivers/gpu/drm/radeon/radeon_ring.c   |   21 ++++-
 drivers/gpu/drm/radeon/radeon_sa.c     |  112 ++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon_ttm.c    |    2 +-
 drivers/gpu/drm/radeon/rs400.c         |    2 +-
 drivers/gpu/drm/radeon/rv515.c         |    4 +-
 include/drm/rati.h                     |  163 ++++++++++++++++++++++++++++++++
 19 files changed, 524 insertions(+), 132 deletions(-)
 create mode 100644 include/drm/rati.h

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 0874a6d..8ed365f 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2694,7 +2694,7 @@ static struct drm_info_list r100_debugfs_mc_info_list[] = {
 int r100_debugfs_rbbm_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1);
+	return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1, NULL);
 #else
 	return 0;
 #endif
@@ -2703,7 +2703,7 @@ int r100_debugfs_rbbm_init(struct radeon_device *rdev)
 int r100_debugfs_cp_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2);
+	return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2, NULL);
 #else
 	return 0;
 #endif
@@ -2712,7 +2712,7 @@ int r100_debugfs_cp_init(struct radeon_device *rdev)
 int r100_debugfs_mc_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1);
+	return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1, NULL);
 #else
 	return 0;
 #endif
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 97722a3..edb9eeb 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -586,7 +586,7 @@ static struct drm_info_list rv370_pcie_gart_info_list[] = {
 static int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, rv370_pcie_gart_info_list, 1);
+	return radeon_debugfs_add_files(rdev, rv370_pcie_gart_info_list, 1, NULL);
 #else
 	return 0;
 #endif
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index 99137be..4eddcfc 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -491,7 +491,7 @@ static struct drm_info_list r420_pipes_info_list[] = {
 int r420_debugfs_pipes_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1);
+	return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1, NULL);
 #else
 	return 0;
 #endif
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 4c0d8c9..afc458a 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -3589,7 +3589,7 @@ static struct drm_info_list r600_mc_info_list[] = {
 int r600_debugfs_mc_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, r600_mc_info_list, ARRAY_SIZE(r600_mc_info_list));
+	return radeon_debugfs_add_files(rdev, r600_mc_info_list, ARRAY_SIZE(r600_mc_info_list), NULL);
 #else
 	return 0;
 #endif
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 0133f5f..0518c45 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -97,7 +97,7 @@ struct gpu_formats {
 	unsigned blockheight;
 	unsigned blocksize;
 	unsigned valid_color;
-	enum radeon_family min_family;
+	unsigned min_family;
 };
 
 static const struct gpu_formats color_formats_table[] = {
@@ -185,7 +185,7 @@ bool r600_fmt_is_valid_color(u32 format)
 	return false;
 }
 
-bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family)
+bool r600_fmt_is_valid_texture(u32 format, unsigned family)
 {
 	if (format >= ARRAY_SIZE(color_formats_table))
 		return false;
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 9783178..4bebecf 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -75,6 +75,8 @@
 #include "radeon_mode.h"
 #include "radeon_reg.h"
 
+#include "rati.h"
+
 /*
  * Modules parameters.
  */
@@ -395,6 +397,11 @@ struct radeon_sa_manager {
 
 struct radeon_sa_bo;
 
+struct radeon_dump {
+	struct rati_data_buffer_v001	buffer;
+	struct radeon_bo		*bo;
+};
+
 /* sub-allocation buffer */
 struct radeon_sa_bo {
 	struct list_head		olist;
@@ -403,6 +410,8 @@ struct radeon_sa_bo {
 	unsigned			soffset;
 	unsigned			eoffset;
 	struct radeon_fence		*fence;
+	unsigned			nbuffers;
+	struct radeon_dump		*buffers;
 };
 
 /*
@@ -846,6 +855,8 @@ struct radeon_cs_parser {
 	u32			cs_flags;
 	u32			ring;
 	s32			priority;
+	unsigned		nbuffers;
+	struct radeon_dump	*buffers;
 };
 
 extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
@@ -1128,7 +1139,8 @@ struct radeon_debugfs {
 
 int radeon_debugfs_add_files(struct radeon_device *rdev,
 			     struct drm_info_list *files,
-			     unsigned nfiles);
+			     unsigned nfiles,
+			     drm_debugfs_read_t read);
 int radeon_debugfs_fence_init(struct radeon_device *rdev);
 
 
@@ -1469,7 +1481,7 @@ struct radeon_device {
 	struct pci_dev			*pdev;
 	/* ASIC */
 	union radeon_asic_config	config;
-	enum radeon_family		family;
+	unsigned			family;
 	unsigned long			flags;
 	int				usec_timeout;
 	enum radeon_pll_errata		pll_errata;
@@ -1519,34 +1531,39 @@ struct radeon_device {
 	bool				suspend;
 	bool				need_dma32;
 	bool				accel_working;
-	struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
-	const struct firmware *me_fw;	/* all family ME firmware */
-	const struct firmware *pfp_fw;	/* r6/700 PFP firmware */
-	const struct firmware *rlc_fw;	/* r6/700 RLC firmware */
-	const struct firmware *mc_fw;	/* NI MC firmware */
-	const struct firmware *ce_fw;	/* SI CE firmware */
-	struct r600_blit r600_blit;
-	struct r600_vram_scratch vram_scratch;
-	int msi_enabled; /* msi enabled */
-	struct r600_ih ih; /* r6/700 interrupt ring */
-	struct si_rlc rlc;
-	struct work_struct hotplug_work;
-	struct work_struct audio_work;
-	int num_crtc; /* number of crtcs */
-	struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
-	struct mutex vram_mutex;
-	struct r600_audio audio; /* audio stuff */
-	struct notifier_block acpi_nb;
+	struct radeon_surface_reg	surface_regs[RADEON_GEM_MAX_SURFACES];
+	const struct firmware		*me_fw;	/* all family ME firmware */
+	const struct firmware		*pfp_fw;	/* r6/700 PFP firmware */
+	const struct firmware		*rlc_fw;	/* r6/700 RLC firmware */
+	const struct firmware		*mc_fw;	/* NI MC firmware */
+	const struct firmware		*ce_fw;	/* SI CE firmware */
+	struct r600_blit		r600_blit;
+	struct r600_vram_scratch	vram_scratch;
+	int				msi_enabled; /* msi enabled */
+	struct r600_ih			ih; /* r6/700 interrupt ring */
+	struct si_rlc			rlc;
+	struct work_struct		hotplug_work;
+	struct work_struct		audio_work;
+	int				num_crtc; /* number of crtcs */
+	struct mutex			dc_hw_i2c_mutex; /* display controller hw i2c mutex */
+	struct mutex			vram_mutex;
+	struct r600_audio		audio; /* audio stuff */
+	struct notifier_block		acpi_nb;
 	/* only one userspace can use Hyperz features or CMASK at a time */
-	struct drm_file *hyperz_filp;
-	struct drm_file *cmask_filp;
+	struct drm_file			*hyperz_filp;
+	struct drm_file			*cmask_filp;
 	/* i2c buses */
-	struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS];
+	struct radeon_i2c_chan		*i2c_bus[RADEON_MAX_I2C_BUS];
 	/* debugfs */
-	struct radeon_debugfs	debugfs[RADEON_DEBUGFS_MAX_COMPONENTS];
-	unsigned 		debugfs_count;
+	struct radeon_debugfs		debugfs[RADEON_DEBUGFS_MAX_COMPONENTS];
+	unsigned 			debugfs_count;
 	/* virtual memory */
 	struct radeon_vm_manager	vm_manager;
+	/* lockup blob dumping */
+	unsigned			blob_dump;
+	struct rati_header_v001		blob_header;
+	uint64_t			blob_size;
+	void				*blob;
 };
 
 int radeon_device_init(struct radeon_device *rdev,
@@ -1793,7 +1810,8 @@ void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm);
 int radeon_vm_bo_update_pte(struct radeon_device *rdev,
 			    struct radeon_vm *vm,
 			    struct radeon_bo *bo,
-			    struct ttm_mem_reg *mem);
+			    struct ttm_mem_reg *mem,
+			    uint64_t *vm_offset);
 void radeon_vm_bo_invalidate(struct radeon_device *rdev,
 			     struct radeon_bo *bo);
 int radeon_vm_bo_add(struct radeon_device *rdev,
@@ -1819,7 +1837,7 @@ void r600_vram_scratch_fini(struct radeon_device *rdev);
  */
 unsigned r600_mip_minify(unsigned size, unsigned level);
 bool r600_fmt_is_valid_color(u32 format);
-bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family);
+bool r600_fmt_is_valid_texture(u32 format, unsigned family);
 int r600_fmt_get_blocksize(u32 format);
 int r600_fmt_get_nblocksx(u32 format, u32 w);
 int r600_fmt_get_nblocksy(u32 format, u32 h);
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index c7d64a7..0064e7c 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -36,7 +36,7 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
 {
 	struct drm_device *ddev = p->rdev->ddev;
 	struct radeon_cs_chunk *chunk;
-	unsigned i, j;
+	unsigned i, j, ib;
 	bool duplicate;
 
 	if (p->chunk_relocs_idx == -1) {
@@ -53,7 +53,16 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
 	if (p->relocs == NULL) {
 		return -ENOMEM;
 	}
-	for (i = 0; i < p->nrelocs; i++) {
+	p->buffers = NULL;
+	p->nbuffers = 0;
+	if (p->rdev->blob_dump) {
+		p->buffers = kcalloc(p->nrelocs, sizeof(*p->buffers), GFP_KERNEL);
+		if (p->buffers == NULL) {
+			return -ENOMEM;
+		}
+		p->nbuffers = p->nrelocs;
+	}
+	for (i = 0, ib = 0; i < p->nrelocs; i++) {
 		struct drm_radeon_cs_reloc *r;
 
 		duplicate = false;
@@ -84,9 +93,22 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
 			p->relocs[i].flags = r->flags;
 			radeon_bo_list_add_object(&p->relocs[i].lobj,
 						  &p->validated);
-
-		} else
+			/* initialize dump struct */
+			if (p->rdev->blob_dump) {
+				p->buffers[ib].bo =  p->relocs[i].robj;
+				p->buffers[ib].buffer.id = RATI_DATA_BUFFER;
+				p->buffers[ib].buffer.ver = 1;
+				p->buffers[ib].buffer.size = radeon_bo_size(p->buffers[i].bo);
+				p->buffers[ib].buffer.paded_ndw = ALIGN(p->buffers[i].buffer.size >> 2, 2);
+				p->buffers[ib].buffer.alignment = radeon_bo_alignment(p->buffers[i].bo);
+				ib++;
+			}
+		} else {
 			p->relocs[i].handle = 0;
+			if (p->rdev->blob_dump) {
+				p->nbuffers--;
+			}
+		}
 	}
 	return radeon_bo_list_validate(&p->validated);
 }
@@ -303,11 +325,13 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
 {
 	unsigned i;
 
-	if (!error)
+	if (!error) {
 		ttm_eu_fence_buffer_objects(&parser->validated,
 					    parser->ib.fence);
-	else
+	} else {
 		ttm_eu_backoff_reservation(&parser->validated);
+		kfree(parser->buffers);
+	}
 
 	if (parser->relocs != NULL) {
 		for (i = 0; i < parser->nrelocs; i++) {
@@ -335,6 +359,7 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
 			      struct radeon_cs_parser *parser)
 {
 	struct radeon_cs_chunk *ib_chunk;
+	unsigned i;
 	int r;
 
 	if (parser->chunk_ib_idx == -1)
@@ -370,6 +395,17 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
 		DRM_ERROR("Failed to synchronize rings !\n");
 	}
 	parser->ib.vm_id = 0;
+
+	/* update dump informations */
+	if (parser->rdev->blob_dump) {
+		for (i = 0; i < parser->nbuffers; i++) {
+			parser->buffers[i].buffer.offset = radeon_bo_gpu_offset(parser->buffers[i].bo);
+		}
+		parser->ib.sa_bo->buffers = parser->buffers;
+		parser->ib.sa_bo->nbuffers = parser->nbuffers;
+		parser->buffers = NULL;
+	}
+
 	r = radeon_ib_schedule(rdev, &parser->ib);
 	if (r) {
 		DRM_ERROR("Failed to schedule IB !\n");
@@ -382,14 +418,24 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser,
 {
 	struct radeon_bo_list *lobj;
 	struct radeon_bo *bo;
+	uint64_t vm_offset;
+	unsigned i;
 	int r;
 
 	list_for_each_entry(lobj, &parser->validated, tv.head) {
 		bo = lobj->bo;
-		r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem);
+		r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem, &vm_offset);
 		if (r) {
 			return r;
 		}
+		if (parser->rdev->blob_dump) {
+			for (i = 0; i < parser->nbuffers; i++) {
+				if (parser->buffers[i].bo == bo) {
+					parser->buffers[i].buffer.offset = vm_offset;
+					break;
+				}
+			}
+		}
 	}
 	return 0;
 }
@@ -488,6 +534,14 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
 	 */
 	parser->ib.gpu_addr = parser->ib.sa_bo->soffset;
 	parser->ib.is_const_ib = false;
+
+	/* update dump informations */
+	if (parser->rdev->blob_dump) {
+		parser->ib.sa_bo->buffers = parser->buffers;
+		parser->ib.sa_bo->nbuffers = parser->nbuffers;
+		parser->buffers = NULL;
+	}
+
 	r = radeon_ib_schedule(rdev, &parser->ib);
 out:
 	if (!r) {
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 944ac11..e785742 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -38,6 +38,7 @@
 #include "atom.h"
 
 static const char radeon_family_name[][16] = {
+	"UNKNOWN",
 	"R100",
 	"RV100",
 	"RS100",
@@ -722,6 +723,14 @@ int radeon_device_init(struct radeon_device *rdev,
 	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
 	rdev->accel_working = false;
 
+	/* initializa blob dumping */
+	rdev->blob_dump = true;
+	rdev->blob_header.id = RATI_HEADER;
+	rdev->blob_header.ver = 1;
+	rdev->blob_header.pciid = rdev->pdev->vendor << 16;
+	rdev->blob_header.pciid |= rdev->pdev->device;
+	rdev->blob_header.family = rdev->family;
+
 	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
 		radeon_family_name[rdev->family], pdev->vendor, pdev->device,
 		pdev->subsystem_vendor, pdev->subsystem_device);
@@ -860,6 +869,10 @@ void radeon_device_fini(struct radeon_device *rdev)
 	iounmap(rdev->rmmio);
 	rdev->rmmio = NULL;
 	radeon_debugfs_remove_files(rdev);
+
+	rdev->blob_size = 0;
+	vfree(rdev->blob);
+	rdev->blob = NULL;
 }
 
 
@@ -987,6 +1000,11 @@ int radeon_gpu_reset(struct radeon_device *rdev)
 	int r;
 	int resched;
 
+	/* FIXME we should detect which ring caused a lockup and pass
+	 * appropriate ring parameter here
+	 */
+	radeon_sa_bo_faulty(rdev, &rdev->ring_tmp_bo, RADEON_RING_TYPE_GFX_INDEX);
+
 	radeon_save_bios_scratch_regs(rdev);
 	/* block TTM */
 	resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
@@ -1015,7 +1033,8 @@ int radeon_gpu_reset(struct radeon_device *rdev)
  */
 int radeon_debugfs_add_files(struct radeon_device *rdev,
 			     struct drm_info_list *files,
-			     unsigned nfiles)
+			     unsigned nfiles,
+			     drm_debugfs_read_t read)
 {
 	unsigned i;
 
@@ -1039,10 +1058,10 @@ int radeon_debugfs_add_files(struct radeon_device *rdev,
 #if defined(CONFIG_DEBUG_FS)
 	drm_debugfs_create_files(files, nfiles,
 				 rdev->ddev->control->debugfs_root,
-				 rdev->ddev->control, NULL);
+				 rdev->ddev->control, read);
 	drm_debugfs_create_files(files, nfiles,
 				 rdev->ddev->primary->debugfs_root,
-				 rdev->ddev->primary, NULL);
+				 rdev->ddev->primary, read);
 #endif
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h
index d1fafea..8eaeb51 100644
--- a/drivers/gpu/drm/radeon/radeon_family.h
+++ b/drivers/gpu/drm/radeon/radeon_family.h
@@ -25,90 +25,87 @@
  *          Alex Deucher
  *          Jerome Glisse
  */
-
 /* this file defines the CHIP_  and family flags used in the pciids,
  * its is common between kms and non-kms because duplicating it and
  * changing one place is fail.
  */
 #ifndef RADEON_FAMILY_H
 #define RADEON_FAMILY_H
+
 /*
- * Radeon chip families
+ * chip family
  */
-enum radeon_family {
-	CHIP_R100 = 0,
-	CHIP_RV100,
-	CHIP_RS100,
-	CHIP_RV200,
-	CHIP_RS200,
-	CHIP_R200,
-	CHIP_RV250,
-	CHIP_RS300,
-	CHIP_RV280,
-	CHIP_R300,
-	CHIP_R350,
-	CHIP_RV350,
-	CHIP_RV380,
-	CHIP_R420,
-	CHIP_R423,
-	CHIP_RV410,
-	CHIP_RS400,
-	CHIP_RS480,
-	CHIP_RS600,
-	CHIP_RS690,
-	CHIP_RS740,
-	CHIP_RV515,
-	CHIP_R520,
-	CHIP_RV530,
-	CHIP_RV560,
-	CHIP_RV570,
-	CHIP_R580,
-	CHIP_R600,
-	CHIP_RV610,
-	CHIP_RV630,
-	CHIP_RV670,
-	CHIP_RV620,
-	CHIP_RV635,
-	CHIP_RS780,
-	CHIP_RS880,
-	CHIP_RV770,
-	CHIP_RV730,
-	CHIP_RV710,
-	CHIP_RV740,
-	CHIP_CEDAR,
-	CHIP_REDWOOD,
-	CHIP_JUNIPER,
-	CHIP_CYPRESS,
-	CHIP_HEMLOCK,
-	CHIP_PALM,
-	CHIP_SUMO,
-	CHIP_SUMO2,
-	CHIP_BARTS,
-	CHIP_TURKS,
-	CHIP_CAICOS,
-	CHIP_CAYMAN,
-	CHIP_ARUBA,
-	CHIP_TAHITI,
-	CHIP_PITCAIRN,
-	CHIP_VERDE,
-	CHIP_LAST,
-};
+#define CHIP_UNKNOWN        0x00
+#define CHIP_R100           0x01
+#define CHIP_RV100          0x02
+#define CHIP_RS100          0x03
+#define CHIP_RV200          0x04
+#define CHIP_RS200          0x05
+#define CHIP_R200           0x06
+#define CHIP_RV250          0x07
+#define CHIP_RS300          0x08
+#define CHIP_RV280          0x09
+#define CHIP_R300           0x0a
+#define CHIP_R350           0x0b
+#define CHIP_RV350          0x0c
+#define CHIP_RV380          0x0d
+#define CHIP_R420           0x0e
+#define CHIP_R423           0x0f
+#define CHIP_RV410          0x10
+#define CHIP_RS400          0x11
+#define CHIP_RS480          0x12
+#define CHIP_RS600          0x13
+#define CHIP_RS690          0x14
+#define CHIP_RS740          0x15
+#define CHIP_RV515          0x16
+#define CHIP_R520           0x17
+#define CHIP_RV530          0x18
+#define CHIP_RV560          0x19
+#define CHIP_RV570          0x1a
+#define CHIP_R580           0x1b
+#define CHIP_R600           0x1c
+#define CHIP_RV610          0x1d
+#define CHIP_RV630          0x1e
+#define CHIP_RV670          0x1f
+#define CHIP_RV620          0x20
+#define CHIP_RV635          0x21
+#define CHIP_RS780          0x22
+#define CHIP_RS880          0x23
+#define CHIP_RV770          0x24
+#define CHIP_RV730          0x25
+#define CHIP_RV710          0x26
+#define CHIP_RV740          0x27
+#define CHIP_CEDAR          0x28
+#define CHIP_REDWOOD        0x29
+#define CHIP_JUNIPER        0x2a
+#define CHIP_CYPRESS        0x2b
+#define CHIP_HEMLOCK        0x2c
+#define CHIP_PALM           0x2d
+#define CHIP_SUMO           0x2e
+#define CHIP_SUMO2          0x2f
+#define CHIP_BARTS          0x30
+#define CHIP_TURKS          0x31
+#define CHIP_CAICOS         0x32
+#define CHIP_CAYMAN         0x33
+#define CHIP_ARUBA          0x34
+#define CHIP_TAHITI         0x35
+#define CHIP_PITCAIRN       0x36
+#define CHIP_VERDE          0x37
+#define CHIP_LAST           0x38
 
 /*
- * Chip flags
+ * chip flags
  */
-enum radeon_chip_flags {
-	RADEON_FAMILY_MASK = 0x0000ffffUL,
-	RADEON_FLAGS_MASK = 0xffff0000UL,
-	RADEON_IS_MOBILITY = 0x00010000UL,
-	RADEON_IS_IGP = 0x00020000UL,
-	RADEON_SINGLE_CRTC = 0x00040000UL,
-	RADEON_IS_AGP = 0x00080000UL,
-	RADEON_HAS_HIERZ = 0x00100000UL,
-	RADEON_IS_PCIE = 0x00200000UL,
-	RADEON_NEW_MEMMAP = 0x00400000UL,
-	RADEON_IS_PCI = 0x00800000UL,
-	RADEON_IS_IGPGART = 0x01000000UL,
-};
+#define RADEON_FAMILY_MASK  0x0000ffffUL
+#define RADEON_FLAGS_MASK   0xffff0000UL
+#define RADEON_IS_MOBILITY  0x00010000UL
+#define RADEON_IS_IGP       0x00020000UL
+#define RADEON_SINGLE_CRTC  0x00040000UL
+#define RADEON_IS_AGP       0x00080000UL
+#define RADEON_HAS_HIERZ    0x00100000UL
+#define RADEON_IS_PCIE      0x00200000UL
+#define RADEON_NEW_MEMMAP   0x00400000UL
+#define RADEON_IS_PCI       0x00800000UL
+#define RADEON_IS_IGPGART   0x01000000UL
 
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 11f5f40..b4979c9 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -618,7 +618,7 @@ static struct drm_info_list radeon_debugfs_fence_list[] = {
 int radeon_debugfs_fence_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 1);
+	return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 1, NULL);
 #else
 	return 0;
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index 8e9ef34..f9d7249 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -433,7 +433,7 @@ retry_id:
 	vm->id = id;
 	list_add_tail(&vm->list, &rdev->vm_manager.lru_vm);
 	return radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo,
-				       &rdev->ring_tmp_bo.bo->tbo.mem);
+				       &rdev->ring_tmp_bo.bo->tbo.mem, NULL);
 }
 
 /* object have to be reserved */
@@ -540,7 +540,8 @@ static u64 radeon_vm_get_addr(struct radeon_device *rdev,
 int radeon_vm_bo_update_pte(struct radeon_device *rdev,
 			    struct radeon_vm *vm,
 			    struct radeon_bo *bo,
-			    struct ttm_mem_reg *mem)
+			    struct ttm_mem_reg *mem,
+			    uint64_t *vm_offset)
 {
 	struct radeon_bo_va *bo_va;
 	unsigned ngpu_pages, i;
@@ -560,6 +561,9 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
 	if (bo_va->valid)
 		return 0;
 
+	if (vm_offset) {
+		*vm_offset = bo_va->soffset;
+	}
 	ngpu_pages = radeon_bo_ngpu_pages(bo);
 	bo_va->flags &= ~RADEON_VM_PAGE_VALID;
 	bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM;
@@ -597,7 +601,7 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
 
 	mutex_lock(&vm->mutex);
 	radeon_mutex_lock(&rdev->cs_mutex);
-	radeon_vm_bo_update_pte(rdev, vm, bo, NULL);
+	radeon_vm_bo_update_pte(rdev, vm, bo, NULL, NULL);
 	radeon_mutex_unlock(&rdev->cs_mutex);
 	list_del(&bo_va->vm_list);
 	mutex_unlock(&vm->mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index befec7d..f9f4561 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -93,6 +93,11 @@ static inline unsigned radeon_bo_gpu_page_alignment(struct radeon_bo *bo)
 	return (bo->tbo.mem.page_alignment << PAGE_SHIFT) / RADEON_GPU_PAGE_SIZE;
 }
 
+static inline unsigned radeon_bo_alignment(struct radeon_bo *bo)
+{
+	return (bo->tbo.mem.page_alignment << PAGE_SHIFT);
+}
+
 /**
  * radeon_bo_mmap_offset - return mmap offset of bo
  * @bo:	radeon object for which we query the offset
@@ -152,7 +157,7 @@ static inline uint64_t radeon_sa_bo_gpu_addr(struct radeon_sa_bo *sa_bo)
 	return sa_bo->manager->gpu_addr + sa_bo->soffset;
 }
 
-static inline void * radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo)
+static inline void *radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo)
 {
 	return sa_bo->manager->cpu_ptr + sa_bo->soffset;
 }
@@ -173,7 +178,12 @@ extern int radeon_sa_bo_new(struct radeon_device *rdev,
 extern void radeon_sa_bo_free(struct radeon_device *rdev,
 			      struct radeon_sa_bo **sa_bo,
 			      struct radeon_fence *fence);
+extern void radeon_sa_bo_faulty(struct radeon_device *rdev,
+				struct radeon_sa_manager *sa_manager,
+				unsigned ring);
 #if defined(CONFIG_DEBUG_FS)
+extern ssize_t radeon_blob_read(struct file *filp, char __user *ubuf,
+				size_t max, loff_t *ppos);
 extern void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
 					 struct seq_file *m);
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 0882554..ee4fd15 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -876,7 +876,7 @@ static struct drm_info_list radeon_pm_info_list[] = {
 static int radeon_debugfs_pm_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, radeon_pm_info_list, ARRAY_SIZE(radeon_pm_info_list));
+	return radeon_debugfs_add_files(rdev, radeon_pm_info_list, ARRAY_SIZE(radeon_pm_info_list), NULL);
 #else
 	return 0;
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index a5dee76..f364f64 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -494,11 +494,21 @@ static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
 	radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m);
 
 	return 0;
+}
+
+static int radeon_debugfs_lockup(struct seq_file *m, void *data)
+{
+	/* empty, should never be call */
+	return 0;
 
 }
 
 static struct drm_info_list radeon_debugfs_sa_list[] = {
-        {"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL},
+	{"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL},
+};
+
+static struct drm_info_list radeon_debugfs_lockup_list[] = {
+	{"radeon_lockup", &radeon_debugfs_lockup, 0, NULL},
 };
 
 #endif
@@ -515,7 +525,7 @@ int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *rin
 		if (&rdev->ring[ridx] != ring)
 			continue;
 
-		r = radeon_debugfs_add_files(rdev, info, 1);
+		r = radeon_debugfs_add_files(rdev, info, 1, NULL);
 		if (r)
 			return r;
 	}
@@ -525,8 +535,13 @@ int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *rin
 
 int radeon_debugfs_sa_init(struct radeon_device *rdev)
 {
+	int r;
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1);
+	r = radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1, NULL);
+	if (r) {
+		return r;
+	}
+	return radeon_debugfs_add_files(rdev, radeon_debugfs_lockup_list, 1, radeon_blob_read);
 #else
 	return 0;
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c
index c3ac7f4..81c31e8 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -148,6 +148,7 @@ static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo)
 	list_del_init(&sa_bo->olist);
 	list_del_init(&sa_bo->flist);
 	radeon_fence_unref(&sa_bo->fence);
+	kfree(sa_bo->buffers);
 	kfree(sa_bo);
 }
 
@@ -294,6 +295,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
 	}
 	(*sa_bo)->manager = sa_manager;
 	(*sa_bo)->fence = NULL;
+	(*sa_bo)->buffers = NULL;
+	(*sa_bo)->nbuffers = 0;
 	INIT_LIST_HEAD(&(*sa_bo)->olist);
 	INIT_LIST_HEAD(&(*sa_bo)->flist);
 
@@ -360,7 +363,116 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo,
 	*sa_bo = NULL;
 }
 
+void radeon_sa_bo_faulty(struct radeon_device *rdev,
+			 struct radeon_sa_manager *sa_manager,
+			 unsigned ring)
+{
+	struct radeon_sa_bo *sa_bo = NULL, *tmp;
+	struct rati_cmd_buffer_v001 cmd;
+	unsigned long offset = 0;
+	unsigned i;
+
+	rdev->blob_size = 0;
+	vfree(rdev->blob);
+	rdev->blob = NULL;
+
+	spin_lock(&sa_manager->lock);
+	list_for_each_entry(tmp, &sa_manager->olist, olist) {
+		if (tmp->fence == NULL ||
+		    tmp->buffers == NULL ||
+		    tmp->fence->ring != ring ||
+		    tmp->fence->seq == RADEON_FENCE_NOTEMITED_SEQ ||
+		    radeon_fence_signaled(tmp->fence)) {
+			continue;
+		}
+		/* select the oldest unsignaled fence */
+		if (sa_bo == NULL || tmp->fence->seq < sa_bo->fence->seq) {
+			sa_bo = tmp;
+		}
+	}
+	spin_unlock(&sa_manager->lock);
+
+	if (sa_bo == NULL) {
+		return;
+	}
+
+	/* init cmd buffer */
+	cmd.id = RATI_CMD_BUFFER;
+	cmd.ver = 1;
+	switch (ring) {
+	case RADEON_RING_TYPE_GFX_INDEX:
+		cmd.ring = RATI_RING_GFX;
+		break;
+	case CAYMAN_RING_TYPE_CP1_INDEX:
+	case CAYMAN_RING_TYPE_CP2_INDEX:
+		cmd.ring = RATI_RING_COMPUTE;
+		break;
+	default:
+		return;
+	}
+	cmd.ndw = (sa_bo->eoffset - sa_bo->soffset) >> 2;
+	cmd.paded_ndw = ALIGN(cmd.ndw, 2);
+
+	/* update header */
+	rdev->blob_header.ncmd_buffers = 1;
+	rdev->blob_header.ndata_buffers = sa_bo->nbuffers;
+
+	/* compute blob size */
+	rdev->blob_size = sizeof(rdev->blob_header) + sizeof(cmd);
+	rdev->blob_size += sa_bo->nbuffers * sizeof(struct rati_data_buffer_v001);
+	rdev->blob_size += cmd.paded_ndw * 4;
+
+	for (i = 0; i < sa_bo->nbuffers; i++) {
+		rdev->blob_size += sa_bo->buffers[i].buffer.paded_ndw * 4;
+	}
+
+	rdev->blob = vmalloc(rdev->blob_size);
+	if (rdev->blob == NULL) {
+		dev_err(rdev->dev, "failed allocating %lldkb for lockup dump\n", rdev->blob_size >> 10);
+		return;
+	}
+
+	/* build blob */
+	memcpy(rdev->blob, &rdev->blob_header, sizeof(rdev->blob_header));
+	offset += sizeof(rdev->blob_header);
+	memcpy(rdev->blob + offset, &cmd, sizeof(cmd));
+	offset += sizeof(cmd);
+	memcpy(rdev->blob + offset, radeon_sa_bo_cpu_addr(sa_bo), cmd.ndw * 4);
+	offset += cmd.paded_ndw * 4;
+	for (i = 0; i < sa_bo->nbuffers; i++) {
+		void *ptr;
+		int r;
+
+		memcpy(rdev->blob + offset, &sa_bo->buffers[i].buffer,
+		       sizeof(struct rati_data_buffer_v001));
+		offset += sizeof(struct rati_data_buffer_v001);
+		r = radeon_bo_reserve(sa_bo->buffers[i].bo, true);
+		if (!r) {
+			if (!radeon_bo_kmap(sa_bo->buffers[i].bo, &ptr)) {
+				memcpy(rdev->blob + offset, ptr,
+				       sa_bo->buffers[i].buffer.size);
+				radeon_bo_kunmap(sa_bo->buffers[i].bo);
+			}
+			radeon_bo_unreserve(sa_bo->buffers[i].bo);
+		}
+		offset += sa_bo->buffers[i].buffer.paded_ndw * 4;
+	}
+
+	dev_err(rdev->dev, "added %lldkb lockup dump\n", rdev->blob_size >> 10);
+}
+
 #if defined(CONFIG_DEBUG_FS)
+ssize_t radeon_blob_read(struct file *filp, char __user *ubuf,
+			 size_t max, loff_t *ppos)
+{
+	struct seq_file *m = filp->private_data;
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	return simple_read_from_buffer(ubuf, max, ppos, rdev->blob, rdev->blob_size);
+}
+
 void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
 				  struct seq_file *m)
 {
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 0f6aee8..b01c3c6 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -903,7 +903,7 @@ static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
 		radeon_mem_types_list[i++].data = NULL;
 	}
 #endif
-	return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i);
+	return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i, NULL);
 
 #endif
 	return 0;
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
index a464eb5..b135601 100644
--- a/drivers/gpu/drm/radeon/rs400.c
+++ b/drivers/gpu/drm/radeon/rs400.c
@@ -364,7 +364,7 @@ static struct drm_info_list rs400_gart_info_list[] = {
 static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, rs400_gart_info_list, 1);
+	return radeon_debugfs_add_files(rdev, rs400_gart_info_list, 1, NULL);
 #else
 	return 0;
 #endif
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 7f08ced..9a74cf2 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -264,7 +264,7 @@ static struct drm_info_list rv515_ga_info_list[] = {
 int rv515_debugfs_pipes_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, rv515_pipes_info_list, 1);
+	return radeon_debugfs_add_files(rdev, rv515_pipes_info_list, 1, NULL);
 #else
 	return 0;
 #endif
@@ -273,7 +273,7 @@ int rv515_debugfs_pipes_info_init(struct radeon_device *rdev)
 int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, rv515_ga_info_list, 1);
+	return radeon_debugfs_add_files(rdev, rv515_ga_info_list, 1, NULL);
 #else
 	return 0;
 #endif
diff --git a/include/drm/rati.h b/include/drm/rati.h
new file mode 100644
index 0000000..b9776ee
--- /dev/null
+++ b/include/drm/rati.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *      Jerome Glisse
+ */
+/* Radeon raw binary file format for dumping command stream and
+ * associated buffer.
+ */
+#ifndef RATI_H
+#define RATI_H
+
+/* This is API we don't want compiler to mess with the struct, all
+ * fields should be properly 64 bits aligned if 64bits or 32bits
+ * aligned if 32bits
+ */
+#pragma pack(1)
+
+/* List of uniq identifiant of each structure, the identifiant of the header
+ * also serve as file signature.
+ */
+#define RATI_HEADER         0xCAFEDEAD
+#define RATI_CMD_BUFFER     1
+#define RATI_DATA_BUFFER    2
+
+/*
+ * define ring
+ */
+#define RATI_RING_UNKNOWN   0
+#define RATI_RING_GFX       1
+#define RATI_RING_COMPUTE   2
+
+
+#if 0
+#define RATI_R6XX_CONF      3
+#endif
+
+/* struct rati_header_v001
+ *
+ * Header of the file
+ *
+ * @id:             uniq identifiant of the structure must be RATI_HEADER
+ * @ver:            version
+ * @pciid:          pciid of the GPU
+ * @family:         GPU family
+ * @ndata_buffers:  number of data buffer
+ * @ncmd_buffers:   number of cmd buffer
+ */
+struct rati_header_v001 {
+    uint32_t            id;
+    uint32_t            ver;
+    uint32_t            pciid;
+    uint32_t            family;
+    uint32_t            ndata_buffers;
+    uint32_t            ncmd_buffers;
+};
+
+/* struct rati_cmd_buffer_v001
+ *
+ * cmd buffer, follow by paded_ndw (paded ndw must leave next struct
+ * on 64bits aligned offset)
+ *
+ * @id:             uniq identifiant of the structure must be RATI_CMD_BUFFER
+ * @ver:            version
+ * @paded_ndw:      paded number of dwords
+ * @ndw:            ndwords in this command buffer
+ * @ring:           which ring this cmd buffer should be executed on
+ */
+struct rati_cmd_buffer_v001 {
+    uint32_t            id;
+    uint32_t            ver;
+    uint32_t            paded_ndw;
+    uint32_t            ndw;
+    uint32_t            ring;
+    uint32_t            pad;
+};
+
+/* struct rati_data_buffer_v001
+ *
+ * data buffer, follow by paded_ndw (paded ndw must leave next struct
+ * on 64bits aligned offset)
+ *
+ * @id:             uniq identifiant of the structure must be RATI_DATA_BUFFER
+ * @ver:            header version
+ * @alignment:      alignment of buffer
+ * @paded_ndw:      paded number of dwords
+ * @size:           size of buffer in byte
+ * @offset:         offset of this buffer while this was captured (could be 0
+ *                  for all buffer is capturing from userspace)
+ */
+struct rati_data_buffer_v001 {
+    uint32_t            id;
+    uint32_t            ver;
+    uint32_t            alignment;
+    uint32_t            pad;
+    uint64_t            paded_ndw;
+    uint64_t            size;
+    uint64_t            offset;
+};
+
+#if 0
+/* struct rati_r6xx_conf_v001
+ *
+ * r6xx configuration
+ *
+ * @id:      uniq identifiant of the structure must be RATI_R6XX_CONF
+ * @ver:     header version
+ */
+struct rati_r6xx_conf_v001 {
+    uint32_t            id;
+    uint32_t            struct_size;
+    uint32_t            ver;
+};
+#endif
+
+/*
+ * union of all version of each rati struct
+ */
+union rati_header {
+    struct rati_header_v001         v001;
+};
+
+union rati_cmd_buffer {
+    struct rati_cmd_buffer_v001     v001;
+};
+
+union rati_data_buffer {
+    struct rati_data_buffer_v001    v001;
+};
+
+#pragma pack()
+
+/*
+ * for version validation
+ */
+struct rati_struct_validation {
+    unsigned                        id;
+    unsigned                        ver;
+    unsigned                        size;
+};
+
+extern const struct rati_struct_validation *rati_struct_validation(uint32_t id, uint32_t ver);
+
+#endif
-- 
1.7.7.6



More information about the dri-devel mailing list