mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 15:12:13 +02:00
drm/imagination: Use dev_pm_domain_attach_list()
This helper handles the attaching and linking of the entire list of power domains. Besides making pvr_power_domains_init() simpler, this also lays the groundwork to simplify supporting the varied power domain names used in Volcanic GPU cores. Note that we still need to create the links between power domains to ensure they're brought up in a valid sequence. Reviewed-by: Alessio Belle <alessio.belle@imgtec.com> Link: https://patch.msgid.link/20260123-pm-domain-attach-list-v1-1-d51dd7e43253@imgtec.com Signed-off-by: Matt Coster <matt.coster@imgtec.com>
This commit is contained in:
parent
55473b6017
commit
e19cc5ab34
|
|
@ -152,15 +152,13 @@ struct pvr_device {
|
||||||
* @power: Optional power domain devices.
|
* @power: Optional power domain devices.
|
||||||
*
|
*
|
||||||
* On platforms with more than one power domain for the GPU, they are
|
* On platforms with more than one power domain for the GPU, they are
|
||||||
* stored here in @domain_devs, along with links between them in
|
* stored here in @domains, along with links between them in
|
||||||
* @domain_links. The size of @domain_devs is given by @domain_count,
|
* @domain_links. The size of @domain_links is one less than
|
||||||
* while the size of @domain_links is (2 * @domain_count) - 1.
|
* struct dev_pm_domain_list->num_pds in @domains.
|
||||||
*/
|
*/
|
||||||
struct pvr_device_power {
|
struct pvr_device_power {
|
||||||
struct device **domain_devs;
|
struct dev_pm_domain_list *domains;
|
||||||
struct device_link **domain_links;
|
struct device_link **domain_links;
|
||||||
|
|
||||||
u32 domain_count;
|
|
||||||
} power;
|
} power;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -593,14 +593,16 @@ pvr_watchdog_fini(struct pvr_device *pvr_dev)
|
||||||
|
|
||||||
int pvr_power_domains_init(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_link **domain_links __free(kfree) = NULL;
|
||||||
struct device **domain_devs __free(kfree) = NULL;
|
struct dev_pm_domain_list *domains = NULL;
|
||||||
int domain_count;
|
int domain_count;
|
||||||
int link_count;
|
int link_count;
|
||||||
|
|
||||||
char dev_name[2] = "a";
|
|
||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
@ -612,46 +614,33 @@ int pvr_power_domains_init(struct pvr_device *pvr_dev)
|
||||||
if (domain_count <= 1)
|
if (domain_count <= 1)
|
||||||
return 0;
|
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);
|
link_count = domain_count - 1;
|
||||||
if (!domain_devs)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
domain_links = kcalloc(link_count, sizeof(*domain_links), GFP_KERNEL);
|
domain_links = kcalloc(link_count, sizeof(*domain_links), GFP_KERNEL);
|
||||||
if (!domain_links)
|
if (!domain_links)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < domain_count; i++) {
|
const struct dev_pm_domain_attach_data pd_attach_data = {
|
||||||
struct device *domain_dev;
|
.pd_names = ROGUE_PD_NAMES,
|
||||||
|
.num_pd_names = domain_count,
|
||||||
|
.pd_flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
dev_name[0] = 'a' + i;
|
err = dev_pm_domain_attach_list(dev, &pd_attach_data, &domains);
|
||||||
domain_dev = dev_pm_domain_attach_by_name(dev, dev_name);
|
if (err < 0)
|
||||||
if (IS_ERR_OR_NULL(domain_dev)) {
|
return err;
|
||||||
err = domain_dev ? PTR_ERR(domain_dev) : -ENODEV;
|
|
||||||
goto err_detach;
|
|
||||||
}
|
|
||||||
|
|
||||||
domain_devs[i] = domain_dev;
|
for (i = 0; i < link_count; i++) {
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < domain_count; i++) {
|
|
||||||
struct device_link *link;
|
struct device_link *link;
|
||||||
|
|
||||||
link = device_link_add(dev, domain_devs[i], DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
|
link = device_link_add(domains->pd_devs[i + 1],
|
||||||
if (!link) {
|
domains->pd_devs[i],
|
||||||
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],
|
|
||||||
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
|
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
|
||||||
if (!link) {
|
if (!link) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
|
|
@ -662,9 +651,8 @@ int pvr_power_domains_init(struct pvr_device *pvr_dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
pvr_dev->power = (struct pvr_device_power){
|
pvr_dev->power = (struct pvr_device_power){
|
||||||
.domain_devs = no_free_ptr(domain_devs),
|
.domains = domains,
|
||||||
.domain_links = no_free_ptr(domain_links),
|
.domain_links = no_free_ptr(domain_links),
|
||||||
.domain_count = domain_count,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -673,31 +661,21 @@ int pvr_power_domains_init(struct pvr_device *pvr_dev)
|
||||||
while (--i >= 0)
|
while (--i >= 0)
|
||||||
device_link_del(domain_links[i]);
|
device_link_del(domain_links[i]);
|
||||||
|
|
||||||
i = domain_count;
|
|
||||||
|
|
||||||
err_detach:
|
|
||||||
while (--i >= 0)
|
|
||||||
dev_pm_domain_detach(domain_devs[i], true);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pvr_power_domains_fini(struct pvr_device *pvr_dev)
|
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)
|
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)
|
kfree(pvr_power->domain_links);
|
||||||
dev_pm_domain_detach(pvr_dev->power.domain_devs[i], true);
|
|
||||||
|
|
||||||
kfree(pvr_dev->power.domain_links);
|
*pvr_power = (struct pvr_device_power){ 0 };
|
||||||
kfree(pvr_dev->power.domain_devs);
|
|
||||||
|
|
||||||
pvr_dev->power = (struct pvr_device_power){ 0 };
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user