While dev_pm_domain_detach_list() itself contains the necessary NULL check,
the access to struct dev_pm_domain_list->num_pds does not and thus faults
on devices with <=1 power domains (where the struct dev_pm_domain_list
machinery is skipped for simplicity).

This can be reproduced on AM625, which produces the following log[1]:

[   10.820056] powervr fd00000.gpu: Direct firmware load for 
powervr/rogue_33.15.11.3_v1.fw failed with error -2
[   10.831903] powervr fd00000.gpu: [drm] *ERROR* failed to load firmware 
powervr/rogue_33.15.11.3_v1.fw (err=-2)
...
[   10.844023] Unable to handle kernel NULL pointer dereference at virtual 
address 0000000000000018
...
[   11.090162] Call trace:
[   11.092600]  pvr_power_domains_fini+0x18/0xa0 [powervr] (P)
[   11.098218]  pvr_probe+0x100/0x14c [powervr]
[   11.102505]  platform_probe+0x5c/0xa4

Fixes: e19cc5ab347e3 ("drm/imagination: Use dev_pm_domain_attach_list()")
Reported-by: Mark Brown <[email protected]>
Closes: 
https://lore.kernel.org/r/[email protected]/ 
[1]
Signed-off-by: Matt Coster <[email protected]>
---
 drivers/gpu/drm/imagination/pvr_power.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_power.c 
b/drivers/gpu/drm/imagination/pvr_power.c
index 006a72ed5064..be8018085b2d 100644
--- a/drivers/gpu/drm/imagination/pvr_power.c
+++ b/drivers/gpu/drm/imagination/pvr_power.c
@@ -668,14 +668,16 @@ void pvr_power_domains_fini(struct pvr_device *pvr_dev)
 {
        struct pvr_device_power *pvr_power = &pvr_dev->power;
 
-       int i = (int)pvr_power->domains->num_pds - 1;
+       if (!pvr_power->domains)
+               goto out;
 
-       while (--i >= 0)
+       for (int i = (int)pvr_power->domains->num_pds - 2; i >= 0; --i)
                device_link_del(pvr_power->domain_links[i]);
 
        dev_pm_domain_detach_list(pvr_power->domains);
 
        kfree(pvr_power->domain_links);
 
+out:
        *pvr_power = (struct pvr_device_power){ 0 };
 }

-- 
2.53.0

Reply via email to