From: Alessio Belle <[email protected]> pvr_kccb_send_cmd_reserved_powered() returned void while the other two variants of pvr_kccb_send_cmd*() returned int.
The error is now propagated all the way to the DRM scheduler's run_job() callback, which is the only user of pvr_kccb_send_cmd_reserved_powered() outside of the other variants of pvr_kccb_send_cmd*(). Signed-off-by: Alessio Belle <[email protected]> --- Signed-off-by: Alexandru Dadu <[email protected]> --- drivers/gpu/drm/imagination/pvr_ccb.c | 33 +++++++++++++++++++++++++-------- drivers/gpu/drm/imagination/pvr_ccb.h | 6 +++--- drivers/gpu/drm/imagination/pvr_cccb.c | 12 ++++++++---- drivers/gpu/drm/imagination/pvr_cccb.h | 20 ++++++++++---------- drivers/gpu/drm/imagination/pvr_queue.c | 28 ++++++++++++++++------------ 5 files changed, 62 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_ccb.c b/drivers/gpu/drm/imagination/pvr_ccb.c index 4accf18e2341..8182babd8ad8 100644 --- a/drivers/gpu/drm/imagination/pvr_ccb.c +++ b/drivers/gpu/drm/imagination/pvr_ccb.c @@ -257,8 +257,13 @@ pvr_kccb_used_slot_count_locked(struct pvr_device *pvr_dev) * @pvr_dev: Device pointer. * @cmd: Command to sent. * @kccb_slot: Address to store the KCCB slot for this command. May be %NULL. + * + * Returns: + * * Zero on success, + * * -EIO if the device is lost, or + * * -EINVAL if a KCCB slot was not reserved or is not available. */ -void +int pvr_kccb_send_cmd_reserved_powered(struct pvr_device *pvr_dev, struct rogue_fwif_kccb_cmd *cmd, u32 *kccb_slot) @@ -268,19 +273,25 @@ pvr_kccb_send_cmd_reserved_powered(struct pvr_device *pvr_dev, struct rogue_fwif_ccb_ctl *ctrl = pvr_ccb->ctrl; u32 old_write_offset; u32 new_write_offset; + int err; - WARN_ON(pvr_dev->lost); + if (pvr_dev->lost) + return -EIO; mutex_lock(&pvr_ccb->lock); - if (WARN_ON(!pvr_dev->kccb.reserved_count)) + if (WARN_ON(!pvr_dev->kccb.reserved_count)) { + err = -EINVAL; goto out_unlock; + } old_write_offset = READ_ONCE(ctrl->write_offset); /* We reserved the slot, we should have one available. */ - if (WARN_ON(!pvr_ccb_slot_available_locked(pvr_ccb, &new_write_offset))) + if (WARN_ON(!pvr_ccb_slot_available_locked(pvr_ccb, &new_write_offset))) { + err = -EINVAL; goto out_unlock; + } memcpy(&kccb[old_write_offset], cmd, sizeof(struct rogue_fwif_kccb_cmd)); @@ -298,8 +309,14 @@ pvr_kccb_send_cmd_reserved_powered(struct pvr_device *pvr_dev, pvr_fw_mts_schedule(pvr_dev, PVR_FWIF_DM_GP & ~ROGUE_CR_MTS_SCHEDULE_DM_CLRMSK); + mutex_unlock(&pvr_ccb->lock); + + return 0; + out_unlock: mutex_unlock(&pvr_ccb->lock); + + return err; } /** @@ -365,8 +382,9 @@ static int pvr_kccb_reserve_slot_sync(struct pvr_device *pvr_dev) * @kccb_slot: Address to store the KCCB slot for this command. May be %NULL. * * Returns: - * * Zero on success, or - * * -EBUSY if timeout while waiting for a free KCCB slot. + * * Zero on success, + * * Any error returned by pvr_kccb_reserve_slot_sync(), or + * * Any error returned by pvr_kccb_send_cmd_reserved_powered(). */ int pvr_kccb_send_cmd_powered(struct pvr_device *pvr_dev, struct rogue_fwif_kccb_cmd *cmd, @@ -378,8 +396,7 @@ pvr_kccb_send_cmd_powered(struct pvr_device *pvr_dev, struct rogue_fwif_kccb_cmd if (err) return err; - pvr_kccb_send_cmd_reserved_powered(pvr_dev, cmd, kccb_slot); - return 0; + return pvr_kccb_send_cmd_reserved_powered(pvr_dev, cmd, kccb_slot); } /** diff --git a/drivers/gpu/drm/imagination/pvr_ccb.h b/drivers/gpu/drm/imagination/pvr_ccb.h index 4c8aef31eeb0..8b698206c68b 100644 --- a/drivers/gpu/drm/imagination/pvr_ccb.h +++ b/drivers/gpu/drm/imagination/pvr_ccb.h @@ -60,9 +60,9 @@ int pvr_kccb_send_cmd(struct pvr_device *pvr_dev, int pvr_kccb_send_cmd_powered(struct pvr_device *pvr_dev, struct rogue_fwif_kccb_cmd *cmd, u32 *kccb_slot); -void pvr_kccb_send_cmd_reserved_powered(struct pvr_device *pvr_dev, - struct rogue_fwif_kccb_cmd *cmd, - u32 *kccb_slot); +int pvr_kccb_send_cmd_reserved_powered(struct pvr_device *pvr_dev, + struct rogue_fwif_kccb_cmd *cmd, + u32 *kccb_slot); int pvr_kccb_wait_for_completion(struct pvr_device *pvr_dev, u32 slot_nr, u32 timeout, u32 *rtn_out); bool pvr_kccb_is_idle(struct pvr_device *pvr_dev); diff --git a/drivers/gpu/drm/imagination/pvr_cccb.c b/drivers/gpu/drm/imagination/pvr_cccb.c index 4fabab41bea7..da6e6d94e29f 100644 --- a/drivers/gpu/drm/imagination/pvr_cccb.c +++ b/drivers/gpu/drm/imagination/pvr_cccb.c @@ -220,8 +220,12 @@ static void fill_cmd_kick_data(struct pvr_cccb *cccb, u32 ctx_fw_addr, * You must call pvr_kccb_reserve_slot() and wait for the returned fence to * signal (if this function didn't return NULL) before calling * pvr_cccb_send_kccb_kick(). + * + * Returns: + * * Zero on success, or + * * Any error returned by pvr_kccb_send_cmd_reserved_powered(). */ -void +int pvr_cccb_send_kccb_kick(struct pvr_device *pvr_dev, struct pvr_cccb *pvr_cccb, u32 cctx_fw_addr, struct pvr_hwrt_data *hwrt) @@ -235,10 +239,10 @@ pvr_cccb_send_kccb_kick(struct pvr_device *pvr_dev, /* Make sure the writes to the CCCB are flushed before sending the KICK. */ wmb(); - pvr_kccb_send_cmd_reserved_powered(pvr_dev, &cmd_kick, NULL); + return pvr_kccb_send_cmd_reserved_powered(pvr_dev, &cmd_kick, NULL); } -void +int pvr_cccb_send_kccb_combined_kick(struct pvr_device *pvr_dev, struct pvr_cccb *geom_cccb, struct pvr_cccb *frag_cccb, @@ -263,5 +267,5 @@ pvr_cccb_send_kccb_combined_kick(struct pvr_device *pvr_dev, /* Make sure the writes to the CCCB are flushed before sending the KICK. */ wmb(); - pvr_kccb_send_cmd_reserved_powered(pvr_dev, &cmd_kick, NULL); + return pvr_kccb_send_cmd_reserved_powered(pvr_dev, &cmd_kick, NULL); } diff --git a/drivers/gpu/drm/imagination/pvr_cccb.h b/drivers/gpu/drm/imagination/pvr_cccb.h index 943fe8f2c963..a2155f732bf1 100644 --- a/drivers/gpu/drm/imagination/pvr_cccb.h +++ b/drivers/gpu/drm/imagination/pvr_cccb.h @@ -59,16 +59,16 @@ void pvr_cccb_fini(struct pvr_cccb *cccb); void pvr_cccb_write_command_with_header(struct pvr_cccb *pvr_cccb, u32 cmd_type, u32 cmd_size, void *cmd_data, u32 ext_job_ref, u32 int_job_ref); -void pvr_cccb_send_kccb_kick(struct pvr_device *pvr_dev, - struct pvr_cccb *pvr_cccb, u32 cctx_fw_addr, - struct pvr_hwrt_data *hwrt); -void pvr_cccb_send_kccb_combined_kick(struct pvr_device *pvr_dev, - struct pvr_cccb *geom_cccb, - struct pvr_cccb *frag_cccb, - u32 geom_ctx_fw_addr, - u32 frag_ctx_fw_addr, - struct pvr_hwrt_data *hwrt, - bool frag_is_pr); +int pvr_cccb_send_kccb_kick(struct pvr_device *pvr_dev, + struct pvr_cccb *pvr_cccb, u32 cctx_fw_addr, + struct pvr_hwrt_data *hwrt); +int pvr_cccb_send_kccb_combined_kick(struct pvr_device *pvr_dev, + struct pvr_cccb *geom_cccb, + struct pvr_cccb *frag_cccb, + u32 geom_ctx_fw_addr, + u32 frag_ctx_fw_addr, + struct pvr_hwrt_data *hwrt, + bool frag_is_pr); bool pvr_cccb_cmdseq_fits(struct pvr_cccb *pvr_cccb, size_t size); /** diff --git a/drivers/gpu/drm/imagination/pvr_queue.c b/drivers/gpu/drm/imagination/pvr_queue.c index 54e88b4208d7..0f46bbfb9886 100644 --- a/drivers/gpu/drm/imagination/pvr_queue.c +++ b/drivers/gpu/drm/imagination/pvr_queue.c @@ -792,24 +792,28 @@ static struct dma_fence *pvr_queue_run_job(struct drm_sched_job *sched_job) /* Submit the fragment job along the geometry job and send a combined kick. */ pvr_queue_submit_job_to_cccb(frag_job); - pvr_cccb_send_kccb_combined_kick(pvr_dev, - &geom_queue->cccb, &frag_queue->cccb, - pvr_context_get_fw_addr(geom_job->ctx) + - geom_queue->ctx_offset, - pvr_context_get_fw_addr(frag_job->ctx) + - frag_queue->ctx_offset, - job->hwrt, - frag_job->fw_ccb_cmd_type == - ROGUE_FWIF_CCB_CMD_TYPE_FRAG_PR); + err = pvr_cccb_send_kccb_combined_kick(pvr_dev, + &geom_queue->cccb, &frag_queue->cccb, + pvr_context_get_fw_addr(geom_job->ctx) + + geom_queue->ctx_offset, + pvr_context_get_fw_addr(frag_job->ctx) + + frag_queue->ctx_offset, + job->hwrt, + frag_job->fw_ccb_cmd_type == + ROGUE_FWIF_CCB_CMD_TYPE_FRAG_PR); } else { struct pvr_queue *queue = container_of(job->base.sched, struct pvr_queue, scheduler); - pvr_cccb_send_kccb_kick(pvr_dev, &queue->cccb, - pvr_context_get_fw_addr(job->ctx) + queue->ctx_offset, - job->hwrt); + err = pvr_cccb_send_kccb_kick(pvr_dev, &queue->cccb, + pvr_context_get_fw_addr(job->ctx) + + queue->ctx_offset, + job->hwrt); } + if (WARN_ON(err)) + return ERR_PTR(err); + return dma_fence_get(job->done_fence); } --- base-commit: e55fead22ff9ee047ab9f1903860c4b43043514e change-id: 20260810-b4-upstream-propagate-all-errors-from-kccb-cmd-submission-code-0dae4f05fcb5 Best regards, -- Alexandru Dadu <[email protected]>
