Skip to content

Commit 490c30f

Browse files
brendan-kinggregkh
authored andcommitted
drm/imagination: fix firmware memory leaks
commit a5b230e upstream. Free the memory used to hold the results of firmware image processing when the module is unloaded. Fix the related issue of the same memory being leaked if processing of the firmware image fails during module load. Ensure all firmware GEM objects are destroyed if firmware image processing fails. Fixes memory leaks on powervr module unload detected by Kmemleak: unreferenced object 0xffff000042e20000 (size 94208): comm "modprobe", pid 470, jiffies 4295277154 hex dump (first 32 bytes): 02 ae 7f ed bf 45 84 00 3c 5b 1f ed 9f 45 45 05 .....E..<[...EE. d5 4f 5d 14 6c 00 3d 23 30 d0 3a 4a 66 0e 48 c8 .O].l.=#0.:Jf.H. backtrace (crc dd329dec): kmemleak_alloc+0x30/0x40 ___kmalloc_large_node+0x140/0x188 __kmalloc_large_node_noprof+0x2c/0x13c __kmalloc_noprof+0x48/0x4c0 pvr_fw_init+0xaa4/0x1f50 [powervr] unreferenced object 0xffff000042d20000 (size 20480): comm "modprobe", pid 470, jiffies 4295277154 hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 09 00 00 00 0b 00 00 00 ................ 00 00 00 00 00 00 00 00 07 00 00 00 08 00 00 00 ................ backtrace (crc 395b02e3): kmemleak_alloc+0x30/0x40 ___kmalloc_large_node+0x140/0x188 __kmalloc_large_node_noprof+0x2c/0x13c __kmalloc_noprof+0x48/0x4c0 pvr_fw_init+0xb0c/0x1f50 [powervr] Cc: [email protected] Fixes: cc1aeed ("drm/imagination: Implement firmware infrastructure and META FW support") Signed-off-by: Brendan King <[email protected]> Reviewed-by: Matt Coster <[email protected]> Link: https://lore.kernel.org/r/20250318-ddkopsrc-1339-firmware-related-memory-leak-on-module-unload-v1-1-155337c57bb4@imgtec.com Signed-off-by: Matt Coster <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 6e2c805 commit 490c30f

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

drivers/gpu/drm/imagination/pvr_fw.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ pvr_fw_process(struct pvr_device *pvr_dev)
732732
fw_mem->core_data, fw_mem->core_code_alloc_size);
733733

734734
if (err)
735-
goto err_free_fw_core_data_obj;
735+
goto err_free_kdata;
736736

737737
memcpy(fw_code_ptr, fw_mem->code, fw_mem->code_alloc_size);
738738
memcpy(fw_data_ptr, fw_mem->data, fw_mem->data_alloc_size);
@@ -742,18 +742,22 @@ pvr_fw_process(struct pvr_device *pvr_dev)
742742
memcpy(fw_core_data_ptr, fw_mem->core_data, fw_mem->core_data_alloc_size);
743743

744744
/* We're finished with the firmware section memory on the CPU, unmap. */
745-
if (fw_core_data_ptr)
745+
if (fw_core_data_ptr) {
746746
pvr_fw_object_vunmap(fw_mem->core_data_obj);
747-
if (fw_core_code_ptr)
747+
fw_core_data_ptr = NULL;
748+
}
749+
if (fw_core_code_ptr) {
748750
pvr_fw_object_vunmap(fw_mem->core_code_obj);
751+
fw_core_code_ptr = NULL;
752+
}
749753
pvr_fw_object_vunmap(fw_mem->data_obj);
750754
fw_data_ptr = NULL;
751755
pvr_fw_object_vunmap(fw_mem->code_obj);
752756
fw_code_ptr = NULL;
753757

754758
err = pvr_fw_create_fwif_connection_ctl(pvr_dev);
755759
if (err)
756-
goto err_free_fw_core_data_obj;
760+
goto err_free_kdata;
757761

758762
return 0;
759763

@@ -763,13 +767,16 @@ pvr_fw_process(struct pvr_device *pvr_dev)
763767
kfree(fw_mem->data);
764768
kfree(fw_mem->code);
765769

766-
err_free_fw_core_data_obj:
767770
if (fw_core_data_ptr)
768-
pvr_fw_object_unmap_and_destroy(fw_mem->core_data_obj);
771+
pvr_fw_object_vunmap(fw_mem->core_data_obj);
772+
if (fw_mem->core_data_obj)
773+
pvr_fw_object_destroy(fw_mem->core_data_obj);
769774

770775
err_free_fw_core_code_obj:
771776
if (fw_core_code_ptr)
772-
pvr_fw_object_unmap_and_destroy(fw_mem->core_code_obj);
777+
pvr_fw_object_vunmap(fw_mem->core_code_obj);
778+
if (fw_mem->core_code_obj)
779+
pvr_fw_object_destroy(fw_mem->core_code_obj);
773780

774781
err_free_fw_data_obj:
775782
if (fw_data_ptr)
@@ -836,6 +843,12 @@ pvr_fw_cleanup(struct pvr_device *pvr_dev)
836843
struct pvr_fw_mem *fw_mem = &pvr_dev->fw_dev.mem;
837844

838845
pvr_fw_fini_fwif_connection_ctl(pvr_dev);
846+
847+
kfree(fw_mem->core_data);
848+
kfree(fw_mem->core_code);
849+
kfree(fw_mem->data);
850+
kfree(fw_mem->code);
851+
839852
if (fw_mem->core_code_obj)
840853
pvr_fw_object_destroy(fw_mem->core_code_obj);
841854
if (fw_mem->core_data_obj)

0 commit comments

Comments
 (0)