diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c index c09d2f8c1947..bd93ded07131 100644 --- a/drivers/gpu/msm/adreno_a5xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a5xx_snapshot.c @@ -358,10 +358,12 @@ static const unsigned int a5xx_registers[] = { 0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B, 0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095, 0x0097, 0x00BB, 0x03A0, 0x0464, 0x0469, 0x046F, 0x04D2, 0x04D3, - 0x04E0, 0x0533, 0x0540, 0x0555, 0xF400, 0xF400, 0xF800, 0xF807, + 0x04E0, 0x04F4, 0X04F6, 0x0533, 0x0540, 0x0555, 0xF400, 0xF400, + 0xF800, 0xF807, /* CP */ 0x0800, 0x081A, 0x081F, 0x0841, 0x0860, 0x0860, 0x0880, 0x08A0, - 0x0B00, 0x0B12, 0x0B15, 0x0B28, 0x0B78, 0x0B7F, 0x0BB0, 0x0BBD, + 0x0B00, 0x0B12, 0x0B15, 0X0B1C, 0X0B1E, 0x0B28, 0x0B78, 0x0B7F, + 0x0BB0, 0x0BBD, /* VSC */ 0x0BC0, 0x0BC6, 0x0BD0, 0x0C53, 0x0C60, 0x0C61, /* GRAS */ @@ -412,6 +414,19 @@ static const unsigned int a5xx_registers[] = { 0xA800, 0xA8FF, 0xAC60, 0xAC60, }; +/* + * Set of registers to dump for A5XX before actually triggering crash dumper. + * Registers in pairs - first value is the start offset, second + * is the stop offset (inclusive) + */ +static const unsigned int a5xx_pre_crashdumper_registers[] = { + /* RBBM: RBBM_STATUS */ + 0x04F5, 0x04F5, + /* CP: CP_STATUS_1 */ + 0x0B1D, 0x0B1D, +}; + + struct a5xx_hlsq_sp_tp_regs { unsigned int statetype; unsigned int ahbaddr; @@ -634,6 +649,18 @@ static void a5xx_snapshot_shader(struct kgsl_device *device, } } +/* Dump registers which get affected by crash dumper trigger */ +static size_t a5xx_snapshot_pre_crashdump_regs(struct kgsl_device *device, + u8 *buf, size_t remain, void *priv) +{ + struct kgsl_snapshot_registers pre_cdregs = { + .regs = a5xx_pre_crashdumper_registers, + .count = ARRAY_SIZE(a5xx_pre_crashdumper_registers)/2, + }; + + return kgsl_snapshot_dump_registers(device, buf, remain, &pre_cdregs); +} + static size_t a5xx_legacy_snapshot_registers(struct kgsl_device *device, u8 *buf, size_t remain) { @@ -833,16 +860,22 @@ void a5xx_snapshot(struct adreno_device *adreno_dev, /* Disable Clock gating temporarily for the debug bus to work */ a5xx_hwcg_set(adreno_dev, false); - /* Try to run the crash dumper */ - _a5xx_do_crashdump(device); - + /* Dump the registers which get affected by crash dumper trigger */ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, - snapshot, a5xx_snapshot_registers, NULL); + snapshot, a5xx_snapshot_pre_crashdump_regs, NULL); + /* Dump vbif registers as well which get affected by crash dumper */ adreno_snapshot_vbif_registers(device, snapshot, a5xx_vbif_snapshot_registers, ARRAY_SIZE(a5xx_vbif_snapshot_registers)); + /* Try to run the crash dumper */ + if (device->snapshot_crashdumper) + _a5xx_do_crashdump(device); + + kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, + snapshot, a5xx_snapshot_registers, NULL); + /* Dump SP TP HLSQ registers */ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, a5xx_snapshot_dump_hlsq_sp_tp_regs, NULL); diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 04935e8d0019..7d68c23ad5b7 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -264,6 +264,10 @@ struct kgsl_device { u32 snapshot_faultcount; /* Total number of faults since boot */ bool force_panic; /* Force panic after snapshot dump */ + + /* Use CP Crash dumper to get GPU snapshot*/ + bool snapshot_crashdumper; + struct kobject snapshot_kobj; struct kobject ppd_kobj; diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c index 13dc3017072d..1caa673db6ff 100644 --- a/drivers/gpu/msm/kgsl_snapshot.c +++ b/drivers/gpu/msm/kgsl_snapshot.c @@ -833,6 +833,32 @@ static ssize_t force_panic_store(struct kgsl_device *device, const char *buf, return (ssize_t) ret < 0 ? ret : count; } + +/* Show the snapshot_crashdumper request status */ +static ssize_t snapshot_crashdumper_show(struct kgsl_device *device, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_crashdumper); +} + + +/* Store the value to snapshot_crashdumper*/ +static ssize_t snapshot_crashdumper_store(struct kgsl_device *device, + const char *buf, size_t count) +{ + unsigned int val = 0; + int ret; + + if (device && count > 0) + device->snapshot_crashdumper = 1; + + ret = kgsl_sysfs_store(buf, &val); + + if (!ret && device) + device->snapshot_crashdumper = (bool)val; + + return (ssize_t) ret < 0 ? ret : count; +} + /* Show the timestamp of the last collected snapshot */ static ssize_t timestamp_show(struct kgsl_device *device, char *buf) { @@ -859,6 +885,8 @@ struct kgsl_snapshot_attribute attr_##_name = { \ static SNAPSHOT_ATTR(timestamp, 0444, timestamp_show, NULL); static SNAPSHOT_ATTR(faultcount, 0644, faultcount_show, faultcount_store); static SNAPSHOT_ATTR(force_panic, 0644, force_panic_show, force_panic_store); +static SNAPSHOT_ATTR(snapshot_crashdumper, 0644, snapshot_crashdumper_show, + snapshot_crashdumper_store); static ssize_t snapshot_sysfs_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -939,6 +967,7 @@ int kgsl_device_snapshot_init(struct kgsl_device *device) device->snapshot = NULL; device->snapshot_faultcount = 0; device->force_panic = 0; + device->snapshot_crashdumper = 1; ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot, &device->dev->kobj, "snapshot"); @@ -959,6 +988,11 @@ int kgsl_device_snapshot_init(struct kgsl_device *device) ret = sysfs_create_file(&device->snapshot_kobj, &attr_force_panic.attr); + if (ret) + goto done; + + ret = sysfs_create_file(&device->snapshot_kobj, + &attr_snapshot_crashdumper.attr); done: return ret; } @@ -984,6 +1018,7 @@ void kgsl_device_snapshot_close(struct kgsl_device *device) device->snapshot_memory.size = 0; device->snapshot_faultcount = 0; device->force_panic = 0; + device->snapshot_crashdumper = 1; } EXPORT_SYMBOL(kgsl_device_snapshot_close);