Loading drivers/gpu/msm/adreno_a5xx_snapshot.c +76 −43 Original line number Original line Diff line number Diff line /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -412,6 +412,15 @@ static const unsigned int a5xx_registers[] = { 0xEC00, 0xEC05, 0xEC08, 0xECE9, 0xECF0, 0xECF0, 0xEC00, 0xEC05, 0xEC08, 0xECE9, 0xECF0, 0xECF0, /* VPC CTX 1 */ /* VPC CTX 1 */ 0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2, 0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2, }; /* * GPMU registers to dump for A5XX on snapshot. * Registers in pairs - first value is the start offset, second * is the stop offset (inclusive) */ static const unsigned int a5xx_gpmu_registers[] = { /* GPMU */ /* GPMU */ 0xA800, 0xA8FF, 0xAC60, 0xAC60, 0xA800, 0xA8FF, 0xAC60, 0xAC60, }; }; Loading Loading @@ -664,24 +673,23 @@ static size_t a5xx_snapshot_pre_crashdump_regs(struct kgsl_device *device, return kgsl_snapshot_dump_registers(device, buf, remain, &pre_cdregs); return kgsl_snapshot_dump_registers(device, buf, remain, &pre_cdregs); } } struct registers { const unsigned int *regs; size_t size; }; static size_t a5xx_legacy_snapshot_registers(struct kgsl_device *device, static size_t a5xx_legacy_snapshot_registers(struct kgsl_device *device, u8 *buf, size_t remain) u8 *buf, size_t remain, const unsigned int *regs, size_t size) { { struct kgsl_snapshot_registers regs = { struct kgsl_snapshot_registers snapshot_regs = { .regs = a5xx_registers, .regs = regs, .count = ARRAY_SIZE(a5xx_registers) / 2, .count = size / 2, }; }; return kgsl_snapshot_dump_registers(device, buf, remain, ®s); return kgsl_snapshot_dump_registers(device, buf, remain, &snapshot_regs); } } static struct cdregs { const unsigned int *regs; unsigned int size; } _a5xx_cd_registers[] = { { a5xx_registers, ARRAY_SIZE(a5xx_registers) }, }; #define REG_PAIR_COUNT(_a, _i) \ #define REG_PAIR_COUNT(_a, _i) \ (((_a)[(2 * (_i)) + 1] - (_a)[2 * (_i)]) + 1) (((_a)[(2 * (_i)) + 1] - (_a)[2 * (_i)]) + 1) Loading @@ -691,11 +699,13 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf, struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf; struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf; unsigned int *data = (unsigned int *)(buf + sizeof(*header)); unsigned int *data = (unsigned int *)(buf + sizeof(*header)); unsigned int *src = (unsigned int *) registers.hostptr; unsigned int *src = (unsigned int *) registers.hostptr; unsigned int i, j, k; struct registers *regs = (struct registers *)priv; unsigned int j, k; unsigned int count = 0; unsigned int count = 0; if (crash_dump_valid == false) if (crash_dump_valid == false) return a5xx_legacy_snapshot_registers(device, buf, remain); return a5xx_legacy_snapshot_registers(device, buf, remain, regs->regs, regs->size); if (remain < sizeof(*header)) { if (remain < sizeof(*header)) { SNAPSHOT_ERR_NOMEM(device, "REGISTERS"); SNAPSHOT_ERR_NOMEM(device, "REGISTERS"); Loading @@ -704,9 +714,6 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf, remain -= sizeof(*header); remain -= sizeof(*header); for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { struct cdregs *regs = &_a5xx_cd_registers[i]; for (j = 0; j < regs->size / 2; j++) { for (j = 0; j < regs->size / 2; j++) { unsigned int start = regs->regs[2 * j]; unsigned int start = regs->regs[2 * j]; unsigned int end = regs->regs[(2 * j) + 1]; unsigned int end = regs->regs[(2 * j) + 1]; Loading @@ -723,7 +730,6 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf, *data++ = *src++; *data++ = *src++; } } } } } out: out: header->count = count; header->count = count; Loading Loading @@ -861,6 +867,7 @@ void a5xx_snapshot(struct adreno_device *adreno_dev, struct adreno_snapshot_data *snap_data = gpudev->snapshot_data; struct adreno_snapshot_data *snap_data = gpudev->snapshot_data; unsigned int reg, i; unsigned int reg, i; struct adreno_ringbuffer *rb; struct adreno_ringbuffer *rb; struct registers regs; /* Disable Clock gating temporarily for the debug bus to work */ /* Disable Clock gating temporarily for the debug bus to work */ a5xx_hwcg_set(adreno_dev, false); a5xx_hwcg_set(adreno_dev, false); Loading @@ -877,8 +884,20 @@ void a5xx_snapshot(struct adreno_device *adreno_dev, /* Try to run the crash dumper */ /* Try to run the crash dumper */ _a5xx_do_crashdump(device); _a5xx_do_crashdump(device); regs.regs = a5xx_registers; regs.size = ARRAY_SIZE(a5xx_registers); kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, a5xx_snapshot_registers, ®s); if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { regs.regs = a5xx_gpmu_registers; regs.size = ARRAY_SIZE(a5xx_gpmu_registers); kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, a5xx_snapshot_registers, NULL); snapshot, a5xx_snapshot_registers, ®s); } /* Dump SP TP HLSQ registers */ /* Dump SP TP HLSQ registers */ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, Loading Loading @@ -1035,17 +1054,23 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev) * To save the registers, we need 16 bytes per register pair for the * To save the registers, we need 16 bytes per register pair for the * script and a dword for each register int the data * script and a dword for each register int the data */ */ for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { struct cdregs *regs = &_a5xx_cd_registers[i]; /* Each pair needs 16 bytes (2 qwords) */ /* Each pair needs 16 bytes (2 qwords) */ script_size += (regs->size / 2) * 16; script_size += (ARRAY_SIZE(a5xx_registers) / 2) * 16; /* Each register needs a dword in the data */ /* Each register needs a dword in the data */ for (j = 0; j < regs->size / 2; j++) for (j = 0; j < ARRAY_SIZE(a5xx_registers) / 2; j++) data_size += REG_PAIR_COUNT(regs->regs, j) * data_size += REG_PAIR_COUNT(a5xx_registers, j) * sizeof(unsigned int); sizeof(unsigned int); if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { /* Each pair needs 16 bytes (2 qwords) */ script_size += (ARRAY_SIZE(a5xx_gpmu_registers) / 2) * 16; /* Each register needs a dword in the data */ for (j = 0; j < ARRAY_SIZE(a5xx_gpmu_registers) / 2; j++) data_size += REG_PAIR_COUNT(a5xx_gpmu_registers, j) * sizeof(unsigned int); } } /* /* Loading Loading @@ -1083,13 +1108,21 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev) ptr = (uint64_t *) capturescript.hostptr; ptr = (uint64_t *) capturescript.hostptr; /* For the registers, program a read command for each pair */ /* For the registers, program a read command for each pair */ for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { struct cdregs *regs = &_a5xx_cd_registers[i]; for (j = 0; j < regs->size / 2; j++) { for (j = 0; j < ARRAY_SIZE(a5xx_registers) / 2; j++) { unsigned int r = REG_PAIR_COUNT(regs->regs, j); unsigned int r = REG_PAIR_COUNT(a5xx_registers, j); *ptr++ = registers.gpuaddr + offset; *ptr++ = (((uint64_t) a5xx_registers[2 * j]) << 44) | r; offset += r * sizeof(unsigned int); } if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { for (j = 0; j < ARRAY_SIZE(a5xx_gpmu_registers) / 2; j++) { unsigned int r = REG_PAIR_COUNT(a5xx_gpmu_registers, j); *ptr++ = registers.gpuaddr + offset; *ptr++ = registers.gpuaddr + offset; *ptr++ = (((uint64_t) regs->regs[2 * j]) << 44) | r; *ptr++ = (((uint64_t) a5xx_gpmu_registers[2 * j]) << 44) | r; offset += r * sizeof(unsigned int); offset += r * sizeof(unsigned int); } } } } Loading Loading
drivers/gpu/msm/adreno_a5xx_snapshot.c +76 −43 Original line number Original line Diff line number Diff line /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -412,6 +412,15 @@ static const unsigned int a5xx_registers[] = { 0xEC00, 0xEC05, 0xEC08, 0xECE9, 0xECF0, 0xECF0, 0xEC00, 0xEC05, 0xEC08, 0xECE9, 0xECF0, 0xECF0, /* VPC CTX 1 */ /* VPC CTX 1 */ 0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2, 0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2, }; /* * GPMU registers to dump for A5XX on snapshot. * Registers in pairs - first value is the start offset, second * is the stop offset (inclusive) */ static const unsigned int a5xx_gpmu_registers[] = { /* GPMU */ /* GPMU */ 0xA800, 0xA8FF, 0xAC60, 0xAC60, 0xA800, 0xA8FF, 0xAC60, 0xAC60, }; }; Loading Loading @@ -664,24 +673,23 @@ static size_t a5xx_snapshot_pre_crashdump_regs(struct kgsl_device *device, return kgsl_snapshot_dump_registers(device, buf, remain, &pre_cdregs); return kgsl_snapshot_dump_registers(device, buf, remain, &pre_cdregs); } } struct registers { const unsigned int *regs; size_t size; }; static size_t a5xx_legacy_snapshot_registers(struct kgsl_device *device, static size_t a5xx_legacy_snapshot_registers(struct kgsl_device *device, u8 *buf, size_t remain) u8 *buf, size_t remain, const unsigned int *regs, size_t size) { { struct kgsl_snapshot_registers regs = { struct kgsl_snapshot_registers snapshot_regs = { .regs = a5xx_registers, .regs = regs, .count = ARRAY_SIZE(a5xx_registers) / 2, .count = size / 2, }; }; return kgsl_snapshot_dump_registers(device, buf, remain, ®s); return kgsl_snapshot_dump_registers(device, buf, remain, &snapshot_regs); } } static struct cdregs { const unsigned int *regs; unsigned int size; } _a5xx_cd_registers[] = { { a5xx_registers, ARRAY_SIZE(a5xx_registers) }, }; #define REG_PAIR_COUNT(_a, _i) \ #define REG_PAIR_COUNT(_a, _i) \ (((_a)[(2 * (_i)) + 1] - (_a)[2 * (_i)]) + 1) (((_a)[(2 * (_i)) + 1] - (_a)[2 * (_i)]) + 1) Loading @@ -691,11 +699,13 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf, struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf; struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf; unsigned int *data = (unsigned int *)(buf + sizeof(*header)); unsigned int *data = (unsigned int *)(buf + sizeof(*header)); unsigned int *src = (unsigned int *) registers.hostptr; unsigned int *src = (unsigned int *) registers.hostptr; unsigned int i, j, k; struct registers *regs = (struct registers *)priv; unsigned int j, k; unsigned int count = 0; unsigned int count = 0; if (crash_dump_valid == false) if (crash_dump_valid == false) return a5xx_legacy_snapshot_registers(device, buf, remain); return a5xx_legacy_snapshot_registers(device, buf, remain, regs->regs, regs->size); if (remain < sizeof(*header)) { if (remain < sizeof(*header)) { SNAPSHOT_ERR_NOMEM(device, "REGISTERS"); SNAPSHOT_ERR_NOMEM(device, "REGISTERS"); Loading @@ -704,9 +714,6 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf, remain -= sizeof(*header); remain -= sizeof(*header); for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { struct cdregs *regs = &_a5xx_cd_registers[i]; for (j = 0; j < regs->size / 2; j++) { for (j = 0; j < regs->size / 2; j++) { unsigned int start = regs->regs[2 * j]; unsigned int start = regs->regs[2 * j]; unsigned int end = regs->regs[(2 * j) + 1]; unsigned int end = regs->regs[(2 * j) + 1]; Loading @@ -723,7 +730,6 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf, *data++ = *src++; *data++ = *src++; } } } } } out: out: header->count = count; header->count = count; Loading Loading @@ -861,6 +867,7 @@ void a5xx_snapshot(struct adreno_device *adreno_dev, struct adreno_snapshot_data *snap_data = gpudev->snapshot_data; struct adreno_snapshot_data *snap_data = gpudev->snapshot_data; unsigned int reg, i; unsigned int reg, i; struct adreno_ringbuffer *rb; struct adreno_ringbuffer *rb; struct registers regs; /* Disable Clock gating temporarily for the debug bus to work */ /* Disable Clock gating temporarily for the debug bus to work */ a5xx_hwcg_set(adreno_dev, false); a5xx_hwcg_set(adreno_dev, false); Loading @@ -877,8 +884,20 @@ void a5xx_snapshot(struct adreno_device *adreno_dev, /* Try to run the crash dumper */ /* Try to run the crash dumper */ _a5xx_do_crashdump(device); _a5xx_do_crashdump(device); regs.regs = a5xx_registers; regs.size = ARRAY_SIZE(a5xx_registers); kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, a5xx_snapshot_registers, ®s); if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { regs.regs = a5xx_gpmu_registers; regs.size = ARRAY_SIZE(a5xx_gpmu_registers); kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, a5xx_snapshot_registers, NULL); snapshot, a5xx_snapshot_registers, ®s); } /* Dump SP TP HLSQ registers */ /* Dump SP TP HLSQ registers */ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, Loading Loading @@ -1035,17 +1054,23 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev) * To save the registers, we need 16 bytes per register pair for the * To save the registers, we need 16 bytes per register pair for the * script and a dword for each register int the data * script and a dword for each register int the data */ */ for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { struct cdregs *regs = &_a5xx_cd_registers[i]; /* Each pair needs 16 bytes (2 qwords) */ /* Each pair needs 16 bytes (2 qwords) */ script_size += (regs->size / 2) * 16; script_size += (ARRAY_SIZE(a5xx_registers) / 2) * 16; /* Each register needs a dword in the data */ /* Each register needs a dword in the data */ for (j = 0; j < regs->size / 2; j++) for (j = 0; j < ARRAY_SIZE(a5xx_registers) / 2; j++) data_size += REG_PAIR_COUNT(regs->regs, j) * data_size += REG_PAIR_COUNT(a5xx_registers, j) * sizeof(unsigned int); sizeof(unsigned int); if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { /* Each pair needs 16 bytes (2 qwords) */ script_size += (ARRAY_SIZE(a5xx_gpmu_registers) / 2) * 16; /* Each register needs a dword in the data */ for (j = 0; j < ARRAY_SIZE(a5xx_gpmu_registers) / 2; j++) data_size += REG_PAIR_COUNT(a5xx_gpmu_registers, j) * sizeof(unsigned int); } } /* /* Loading Loading @@ -1083,13 +1108,21 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev) ptr = (uint64_t *) capturescript.hostptr; ptr = (uint64_t *) capturescript.hostptr; /* For the registers, program a read command for each pair */ /* For the registers, program a read command for each pair */ for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { struct cdregs *regs = &_a5xx_cd_registers[i]; for (j = 0; j < regs->size / 2; j++) { for (j = 0; j < ARRAY_SIZE(a5xx_registers) / 2; j++) { unsigned int r = REG_PAIR_COUNT(regs->regs, j); unsigned int r = REG_PAIR_COUNT(a5xx_registers, j); *ptr++ = registers.gpuaddr + offset; *ptr++ = (((uint64_t) a5xx_registers[2 * j]) << 44) | r; offset += r * sizeof(unsigned int); } if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { for (j = 0; j < ARRAY_SIZE(a5xx_gpmu_registers) / 2; j++) { unsigned int r = REG_PAIR_COUNT(a5xx_gpmu_registers, j); *ptr++ = registers.gpuaddr + offset; *ptr++ = registers.gpuaddr + offset; *ptr++ = (((uint64_t) regs->regs[2 * j]) << 44) | r; *ptr++ = (((uint64_t) a5xx_gpmu_registers[2 * j]) << 44) | r; offset += r * sizeof(unsigned int); offset += r * sizeof(unsigned int); } } } } Loading