diff --git a/drivers/gpu/drm/imagination/pvr_ccb.c b/drivers/gpu/drm/imagination/pvr_ccb.c index 960bcdb2f751..e408df74853d 100644 --- a/drivers/gpu/drm/imagination/pvr_ccb.c +++ b/drivers/gpu/drm/imagination/pvr_ccb.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -522,6 +523,7 @@ out_unlock: */ void pvr_kccb_fini(struct pvr_device *pvr_dev) { + pvr_fw_object_unmap_and_destroy(pvr_dev->kccb.rtn_obj); pvr_ccb_fini(&pvr_dev->kccb.ccb); WARN_ON(!list_empty(&pvr_dev->kccb.waiters)); WARN_ON(pvr_dev->kccb.reserved_count); @@ -538,14 +540,42 @@ void pvr_kccb_fini(struct pvr_device *pvr_dev) int pvr_kccb_init(struct pvr_device *pvr_dev) { - pvr_dev->kccb.slot_count = 1 << ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT; + const u32 num_slots_log2 = ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT; + const u32 num_slots = 1 << num_slots_log2; + u32 rtn_size; + int err; + + /* + * The inputs here are compile-time constants; there's no reason to try + * to gracefully handle overflow at runtime. + */ + BUILD_BUG_ON(check_mul_overflow(num_slots, sizeof(*pvr_dev->kccb.rtn), &rtn_size)); + + pvr_dev->kccb.slot_count = num_slots; INIT_LIST_HEAD(&pvr_dev->kccb.waiters); pvr_dev->kccb.fence_ctx.id = dma_fence_context_alloc(1); spin_lock_init(&pvr_dev->kccb.fence_ctx.lock); - return pvr_ccb_init(pvr_dev, &pvr_dev->kccb.ccb, - ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT, - sizeof(struct rogue_fwif_kccb_cmd)); + err = pvr_ccb_init(pvr_dev, &pvr_dev->kccb.ccb, num_slots_log2, + sizeof(struct rogue_fwif_kccb_cmd)); + if (err) + return err; + + /* Allocate memory for KCCB return slots. */ + pvr_dev->kccb.rtn = pvr_fw_object_create_and_map(pvr_dev, rtn_size, + PVR_BO_FW_FLAGS_DEVICE_UNCACHED, + NULL, NULL, &pvr_dev->kccb.rtn_obj); + if (IS_ERR(pvr_dev->kccb.rtn)) { + err = PTR_ERR(pvr_dev->kccb.rtn); + goto err_ccb_fini; + } + + return 0; + +err_ccb_fini: + pvr_ccb_fini(&pvr_dev->kccb.ccb); + + return err; } /** diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c index 58ee51cd65df..c6c77b152342 100644 --- a/drivers/gpu/drm/imagination/pvr_fw.c +++ b/drivers/gpu/drm/imagination/pvr_fw.c @@ -945,8 +945,6 @@ pvr_fw_init(struct pvr_device *pvr_dev) [PVR_FW_PROCESSOR_TYPE_RISCV] = &pvr_fw_defs_riscv, }; - u32 kccb_size_log2 = ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT; - u32 kccb_rtn_size = (1 << kccb_size_log2) * sizeof(*pvr_dev->kccb.rtn); struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev; int err; @@ -981,18 +979,9 @@ pvr_fw_init(struct pvr_device *pvr_dev) if (err) goto err_kccb_fini; - /* Allocate memory for KCCB return slots. */ - pvr_dev->kccb.rtn = pvr_fw_object_create_and_map(pvr_dev, kccb_rtn_size, - PVR_BO_FW_FLAGS_DEVICE_UNCACHED, - NULL, NULL, &pvr_dev->kccb.rtn_obj); - if (IS_ERR(pvr_dev->kccb.rtn)) { - err = PTR_ERR(pvr_dev->kccb.rtn); - goto err_fwccb_fini; - } - err = pvr_fw_create_structures(pvr_dev); if (err) - goto err_kccb_rtn_release; + goto err_fwccb_fini; err = pvr_fw_start(pvr_dev); if (err) @@ -1014,9 +1003,6 @@ err_fw_stop: err_destroy_structures: pvr_fw_destroy_structures(pvr_dev); -err_kccb_rtn_release: - pvr_fw_object_unmap_and_destroy(pvr_dev->kccb.rtn_obj); - err_fwccb_fini: pvr_ccb_fini(&pvr_dev->fwccb); @@ -1046,7 +1032,6 @@ pvr_fw_fini(struct pvr_device *pvr_dev) WRITE_ONCE(fw_dev->initialised, false); pvr_fw_destroy_structures(pvr_dev); - pvr_fw_object_unmap_and_destroy(pvr_dev->kccb.rtn_obj); /* * Ensure FWCCB worker has finished executing before destroying FWCCB. The IRQ handler has