diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index ab12399ba236..85387889b5ce 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -244,6 +244,48 @@ static inline bool iommu_is_setstate_addr(struct kgsl_device *device, size); } +static void dump_all_ibs(struct kgsl_device *device, + struct adreno_ringbuffer *rb, + struct kgsl_snapshot *snapshot) +{ + int index = 0; + unsigned int *rbptr; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + rbptr = rb->buffer_desc.hostptr; + + for (index = 0; index < KGSL_RB_DWORDS;) { + + if (adreno_cmd_is_ib(adreno_dev, rbptr[index])) { + uint64_t ibaddr; + uint64_t ibsize; + + if (ADRENO_LEGACY_PM4(adreno_dev)) { + ibaddr = rbptr[index + 1]; + ibsize = rbptr[index + 2]; + index += 3; + } else { + ibaddr = rbptr[index + 2]; + ibaddr = ibaddr << 32 | rbptr[index + 1]; + ibsize = rbptr[index + 3]; + index += 4; + } + + /* Don't parse known global IBs */ + if (iommu_is_setstate_addr(device, ibaddr, ibsize)) + continue; + + if (kgsl_gpuaddr_in_memdesc(&adreno_dev->pwron_fixup, + ibaddr, ibsize)) + continue; + + parse_ib(device, snapshot, snapshot->process, ibaddr, + ibsize); + } else + index = index + 1; + } +} + /** * snapshot_rb_ibs() - Dump rb data and capture the IB's in the RB as well * @rb: The RB to dump @@ -295,6 +337,18 @@ static void snapshot_rb_ibs(struct adreno_ringbuffer *rb, break; } while (index != rb->wptr); + /* + * If the ib1 was not found, for example, if ib1base was restored + * incorrectly after preemption, then simply dump the entire + * ringbuffer along with all the IBs in the ringbuffer. + */ + + if (index == rb->wptr) { + memcpy(data, rb->buffer_desc.hostptr, KGSL_RB_SIZE); + dump_all_ibs(device, rb, snapshot); + return; + } + /* * index points at the last submitted IB. We can only trust that the * memory between the context switch and the hanging IB is valid, so