[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