diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h index cfda215e7428..d51c57cf9332 100644 --- a/drivers/gpu/drm/imagination/pvr_device.h +++ b/drivers/gpu/drm/imagination/pvr_device.h @@ -152,15 +152,13 @@ struct pvr_device { * @power: Optional power domain devices. * * On platforms with more than one power domain for the GPU, they are - * stored here in @domain_devs, along with links between them in - * @domain_links. The size of @domain_devs is given by @domain_count, - * while the size of @domain_links is (2 * @domain_count) - 1. + * stored here in @domains, along with links between them in + * @domain_links. The size of @domain_links is one less than + * struct dev_pm_domain_list->num_pds in @domains. */ struct pvr_device_power { - struct device **domain_devs; + struct dev_pm_domain_list *domains; struct device_link **domain_links; - - u32 domain_count; } power; /** diff --git a/drivers/gpu/drm/imagination/pvr_power.c b/drivers/gpu/drm/imagination/pvr_power.c index b9f801c63260..a0834c550a85 100644 --- a/drivers/gpu/drm/imagination/pvr_power.c +++ b/drivers/gpu/drm/imagination/pvr_power.c @@ -593,14 +593,16 @@ pvr_watchdog_fini(struct pvr_device *pvr_dev) int pvr_power_domains_init(struct pvr_device *pvr_dev) { - struct device *dev = from_pvr_device(pvr_dev)->dev; + static const char *const ROGUE_PD_NAMES[] = { "a", "b", "c", "d", "e" }; + + struct drm_device *drm_dev = from_pvr_device(pvr_dev); + struct device *dev = drm_dev->dev; struct device_link **domain_links __free(kfree) = NULL; - struct device **domain_devs __free(kfree) = NULL; + struct dev_pm_domain_list *domains = NULL; int domain_count; int link_count; - char dev_name[2] = "a"; int err; int i; @@ -612,46 +614,33 @@ int pvr_power_domains_init(struct pvr_device *pvr_dev) if (domain_count <= 1) return 0; - link_count = domain_count + (domain_count - 1); + if (domain_count > ARRAY_SIZE(ROGUE_PD_NAMES)) { + drm_err(drm_dev, "%s() only supports %zu domains on Rogue", + __func__, ARRAY_SIZE(ROGUE_PD_NAMES)); + return -EOPNOTSUPP; + } - domain_devs = kcalloc(domain_count, sizeof(*domain_devs), GFP_KERNEL); - if (!domain_devs) - return -ENOMEM; + link_count = domain_count - 1; domain_links = kcalloc(link_count, sizeof(*domain_links), GFP_KERNEL); if (!domain_links) return -ENOMEM; - for (i = 0; i < domain_count; i++) { - struct device *domain_dev; + const struct dev_pm_domain_attach_data pd_attach_data = { + .pd_names = ROGUE_PD_NAMES, + .num_pd_names = domain_count, + .pd_flags = 0, + }; - dev_name[0] = 'a' + i; - domain_dev = dev_pm_domain_attach_by_name(dev, dev_name); - if (IS_ERR_OR_NULL(domain_dev)) { - err = domain_dev ? PTR_ERR(domain_dev) : -ENODEV; - goto err_detach; - } + err = dev_pm_domain_attach_list(dev, &pd_attach_data, &domains); + if (err < 0) + return err; - domain_devs[i] = domain_dev; - } - - for (i = 0; i < domain_count; i++) { + for (i = 0; i < link_count; i++) { struct device_link *link; - link = device_link_add(dev, domain_devs[i], DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); - if (!link) { - err = -ENODEV; - goto err_unlink; - } - - domain_links[i] = link; - } - - for (i = domain_count; i < link_count; i++) { - struct device_link *link; - - link = device_link_add(domain_devs[i - domain_count + 1], - domain_devs[i - domain_count], + link = device_link_add(domains->pd_devs[i + 1], + domains->pd_devs[i], DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); if (!link) { err = -ENODEV; @@ -662,9 +651,8 @@ int pvr_power_domains_init(struct pvr_device *pvr_dev) } pvr_dev->power = (struct pvr_device_power){ - .domain_devs = no_free_ptr(domain_devs), + .domains = domains, .domain_links = no_free_ptr(domain_links), - .domain_count = domain_count, }; return 0; @@ -673,31 +661,21 @@ int pvr_power_domains_init(struct pvr_device *pvr_dev) while (--i >= 0) device_link_del(domain_links[i]); - i = domain_count; - -err_detach: - while (--i >= 0) - dev_pm_domain_detach(domain_devs[i], true); - return err; } void pvr_power_domains_fini(struct pvr_device *pvr_dev) { - const int domain_count = pvr_dev->power.domain_count; + struct pvr_device_power *pvr_power = &pvr_dev->power; - int i = domain_count + (domain_count - 1); + int i = (int)pvr_power->domains->num_pds - 1; while (--i >= 0) - device_link_del(pvr_dev->power.domain_links[i]); + device_link_del(pvr_power->domain_links[i]); - i = domain_count; + dev_pm_domain_detach_list(pvr_power->domains); - while (--i >= 0) - dev_pm_domain_detach(pvr_dev->power.domain_devs[i], true); + kfree(pvr_power->domain_links); - kfree(pvr_dev->power.domain_links); - kfree(pvr_dev->power.domain_devs); - - pvr_dev->power = (struct pvr_device_power){ 0 }; + *pvr_power = (struct pvr_device_power){ 0 }; }