diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index fcc21dbf8ced..8aeabbcb5966 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -3062,26 +3062,32 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, * was successful */ if (!(status & fence_mask)) - return 0; + break; + /* Wait a small amount of time before trying again */ udelay(GMU_CORE_WAKEUP_DELAY_US); /* Try to write the fenced register again */ adreno_writereg(adreno_dev, offset, val); + } - if (i == GMU_CORE_SHORT_WAKEUP_RETRY_LIMIT) - dev_err(adreno_dev->dev.dev, - "Waited %d usecs to write fenced register 0x%x. Continuing to wait...\n", - (GMU_CORE_SHORT_WAKEUP_RETRY_LIMIT * - GMU_CORE_WAKEUP_DELAY_US), - reg_offset); + if (i < GMU_CORE_SHORT_WAKEUP_RETRY_LIMIT) + return 0; + + if (i == GMU_CORE_LONG_WAKEUP_RETRY_LIMIT) { + dev_err(adreno_dev->dev.dev, + "Timed out waiting %d usecs to write fenced register 0x%x\n", + i * GMU_CORE_WAKEUP_DELAY_US, + reg_offset); + return -ETIMEDOUT; } dev_err(adreno_dev->dev.dev, - "Timed out waiting %d usecs to write fenced register 0x%x\n", - GMU_CORE_LONG_WAKEUP_RETRY_LIMIT * GMU_CORE_WAKEUP_DELAY_US, + "Waited %d usecs to write fenced register 0x%x\n", + i * GMU_CORE_WAKEUP_DELAY_US, reg_offset); - return -ETIMEDOUT; + + return 0; } bool adreno_is_cx_dbgc_register(struct kgsl_device *device, diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched.c b/drivers/gpu/msm/adreno_a6xx_hwsched.c index 6e1d85a156b9..b47d40acef61 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched.c +++ b/drivers/gpu/msm/adreno_a6xx_hwsched.c @@ -120,6 +120,12 @@ void a6xx_hwsched_snapshot(struct adreno_device *adreno_dev, snapshot, adreno_snapshot_global, entry->gpu_md); + if (entry->desc.mem_kind == MEMKIND_PROFILE) + kgsl_snapshot_add_section(device, + KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2, + snapshot, adreno_snapshot_global, + entry->gpu_md); + if (entry->desc.mem_kind == MEMKIND_CSW_SMMU_INFO) kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2, diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h index e0b286d78fa9..5dc4be971baa 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h +++ b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h @@ -6,6 +6,11 @@ #ifndef _ADRENO_A6XX_HWSCHED_HFI_H_ #define _ADRENO_A6XX_HWSCHED_HFI_H_ +/* Maximum number of IBs in a submission */ +#define HWSCHED_MAX_NUMIBS \ + ((HFI_MAX_MSG_SIZE - offsetof(struct hfi_issue_cmd_cmd, ibs)) \ + / sizeof(struct hfi_issue_ib)) + enum mem_kind { /** @MEMKIND_GENERIC: Used for requesting generic memory */ MEMKIND_GENERIC = 0, diff --git a/drivers/gpu/msm/adreno_hwsched.c b/drivers/gpu/msm/adreno_hwsched.c index 3fa6ac3cf260..402fe2a02bec 100644 --- a/drivers/gpu/msm/adreno_hwsched.c +++ b/drivers/gpu/msm/adreno_hwsched.c @@ -836,6 +836,23 @@ int adreno_hwsched_queue_cmds(struct kgsl_device_private *dev_priv, if (!count) return -EINVAL; + for (i = 0; i < count; i++) { + struct kgsl_drawobj_cmd *cmdobj; + struct kgsl_memobj_node *ib; + u32 numibs = 0; + + if (drawobj[i]->type != CMDOBJ_TYPE) + continue; + + cmdobj = CMDOBJ(drawobj[i]); + + list_for_each_entry(ib, &cmdobj->cmdlist, node) + numibs++; + + if (numibs > HWSCHED_MAX_NUMIBS) + return -EINVAL; + } + ret = _check_context_state(&drawctxt->base); if (ret) return ret; diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index 1f0874a539dc..6d534a38ba3d 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -854,6 +854,10 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot, snapshot, adreno_snapshot_global, adreno_dev->pwron_fixup); + kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2, + snapshot, adreno_snapshot_global, + adreno_dev->profile_buffer); + if (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_IOMMU) adreno_snapshot_iommu(device, snapshot); diff --git a/drivers/gpu/msm/adreno_sysfs.c b/drivers/gpu/msm/adreno_sysfs.c index c9bd4c7f1cbf..be8ef6db3d74 100644 --- a/drivers/gpu/msm/adreno_sysfs.c +++ b/drivers/gpu/msm/adreno_sysfs.c @@ -144,16 +144,38 @@ static void change_preemption(struct adreno_device *adreno_dev, void *priv) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct kgsl_context *context; struct adreno_context *drawctxt; - int id; + struct adreno_ringbuffer *rb; + int id, i, ret; + + /* Make sure all ringbuffers are finished */ + FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { + ret = adreno_ringbuffer_waittimestamp(rb, rb->timestamp, + 2 * 1000); + if (ret) { + dev_err(device->dev, + "Cannot disable preemption because couldn't idle ringbuffer[%d] ret: %d\n", + rb->id, ret); + return; + } + } change_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv); - adreno_dev->cur_rb = &(adreno_dev->ringbuffers[0]); + adreno_dev->cur_rb = &adreno_dev->ringbuffers[0]; + adreno_dev->next_rb = NULL; + adreno_dev->prev_rb = NULL; /* Update the ringbuffer for each draw context */ write_lock(&device->context_lock); idr_for_each_entry(&device->context_idr, context, id) { drawctxt = ADRENO_CONTEXT(context); drawctxt->rb = adreno_ctx_get_rb(adreno_dev, drawctxt); + + /* + * Make sure context destroy checks against the correct + * ringbuffer's timestamp. + */ + adreno_rb_readtimestamp(adreno_dev, drawctxt->rb, + KGSL_TIMESTAMP_RETIRED, &drawctxt->internal_timestamp); } write_unlock(&device->context_lock); }