Loading drivers/powercap/arm_scmi_powercap.c +92 −67 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/powercap.h> #include <linux/scmi_protocol.h> #include <linux/slab.h> #define to_scmi_powercap_zone(z) \ container_of(z, struct scmi_powercap_zone, zone) Loading @@ -19,6 +20,8 @@ static const struct scmi_powercap_proto_ops *powercap_ops; struct scmi_powercap_zone { bool registered; bool invalid; unsigned int height; struct device *dev; struct scmi_protocol_handle *ph; Loading @@ -32,6 +35,7 @@ struct scmi_powercap_root { unsigned int num_zones; struct scmi_powercap_zone *spzones; struct list_head *registered_zones; struct list_head scmi_zones; }; static struct powercap_control_type *scmi_top_pcntrl; Loading Loading @@ -271,12 +275,6 @@ static void scmi_powercap_unregister_all_zones(struct scmi_powercap_root *pr) } } static inline bool scmi_powercap_is_zone_registered(struct scmi_powercap_zone *spz) { return !list_empty(&spz->node); } static inline unsigned int scmi_powercap_get_zone_height(struct scmi_powercap_zone *spz) { Loading @@ -295,11 +293,46 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) return &spz->spzones[spz->info->parent_id]; } static int scmi_powercap_register_zone(struct scmi_powercap_root *pr, struct scmi_powercap_zone *spz, struct scmi_powercap_zone *parent) { int ret = 0; struct powercap_zone *z; if (spz->invalid) { list_del(&spz->node); return -EINVAL; } z = powercap_register_zone(&spz->zone, scmi_top_pcntrl, spz->info->name, parent ? &parent->zone : NULL, &zone_ops, 1, &constraint_ops); if (!IS_ERR(z)) { spz->height = scmi_powercap_get_zone_height(spz); spz->registered = true; list_move(&spz->node, &pr->registered_zones[spz->height]); dev_dbg(spz->dev, "Registered node %s - parent %s - height:%d\n", spz->info->name, parent ? parent->info->name : "ROOT", spz->height); } else { list_del(&spz->node); ret = PTR_ERR(z); dev_err(spz->dev, "Error registering node:%s - parent:%s - h:%d - ret:%d\n", spz->info->name, parent ? parent->info->name : "ROOT", spz->height, ret); } return ret; } /** * scmi_powercap_register_zone - Register an SCMI powercap zone recursively * scmi_zones_register- Register SCMI powercap zones starting from parent zones * * @dev: A reference to the SCMI device * @pr: A reference to the root powercap zones descriptors * @spz: A reference to the SCMI powercap zone to register * * When registering SCMI powercap zones with the powercap framework we should * take care to always register zones starting from the root ones and to Loading @@ -309,10 +342,10 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) * zones provided by the SCMI platform firmware is built to comply with such * requirement. * * This function, given an SCMI powercap zone to register, takes care to walk * the SCMI powercap zones tree up to the root looking recursively for * unregistered parent zones before registering the provided zone; at the same * time each registered zone height in such a tree is accounted for and each * This function, given the set of SCMI powercap zones to register, takes care * to walk the SCMI powercap zones trees up to the root registering any * unregistered parent zone before registering the child zones; at the same * time each registered-zone height in such a tree is accounted for and each * zone, once registered, is stored in the @registered_zones array that is * indexed by zone height: this way will be trivial, at unregister time, to walk * the @registered_zones array backward and unregister all the zones starting Loading @@ -330,57 +363,55 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) * * Return: 0 on Success */ static int scmi_powercap_register_zone(struct scmi_powercap_root *pr, struct scmi_powercap_zone *spz) static int scmi_zones_register(struct device *dev, struct scmi_powercap_root *pr) { int ret = 0; struct scmi_powercap_zone *parent; unsigned int sp = 0, reg_zones = 0; struct scmi_powercap_zone *spz, **zones_stack; if (!spz->info) return ret; zones_stack = kcalloc(pr->num_zones, sizeof(spz), GFP_KERNEL); if (!zones_stack) return -ENOMEM; spz = list_first_entry_or_null(&pr->scmi_zones, struct scmi_powercap_zone, node); while (spz) { struct scmi_powercap_zone *parent; parent = scmi_powercap_get_parent_zone(spz); if (parent && !scmi_powercap_is_zone_registered(parent)) { /* * Bail out if a parent domain was marked as unsupported: * only domains participating as leaves can be skipped. if (parent && !parent->registered) { zones_stack[sp++] = spz; spz = parent; } else { ret = scmi_powercap_register_zone(pr, spz, parent); if (!ret) { reg_zones++; } else if (sp) { /* Failed to register a non-leaf zone. * Bail-out. */ if (!parent->info) return -ENODEV; ret = scmi_powercap_register_zone(pr, parent); if (ret) return ret; dev_err(dev, "Failed to register non-leaf zone - ret:%d\n", ret); scmi_powercap_unregister_all_zones(pr); reg_zones = 0; goto out; } if (!scmi_powercap_is_zone_registered(spz)) { struct powercap_zone *z; z = powercap_register_zone(&spz->zone, scmi_top_pcntrl, spz->info->name, parent ? &parent->zone : NULL, &zone_ops, 1, &constraint_ops); if (!IS_ERR(z)) { spz->height = scmi_powercap_get_zone_height(spz); list_add(&spz->node, &pr->registered_zones[spz->height]); dev_dbg(spz->dev, "Registered node %s - parent %s - height:%d\n", spz->info->name, parent ? parent->info->name : "ROOT", spz->height); ret = 0; } else { ret = PTR_ERR(z); dev_err(spz->dev, "Error registering node:%s - parent:%s - h:%d - ret:%d\n", spz->info->name, parent ? parent->info->name : "ROOT", spz->height, ret); /* Pick next zone to process */ if (sp) spz = zones_stack[--sp]; else spz = list_first_entry_or_null(&pr->scmi_zones, struct scmi_powercap_zone, node); } } out: kfree(zones_stack); dev_info(dev, "Registered %d SCMI Powercap domains !\n", reg_zones); return ret; } Loading Loading @@ -424,6 +455,8 @@ static int scmi_powercap_probe(struct scmi_device *sdev) if (!pr->registered_zones) return -ENOMEM; INIT_LIST_HEAD(&pr->scmi_zones); for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) { /* * Powercap domains are validate by the protocol layer, i.e. Loading @@ -438,6 +471,7 @@ static int scmi_powercap_probe(struct scmi_device *sdev) INIT_LIST_HEAD(&spz->node); INIT_LIST_HEAD(&pr->registered_zones[i]); list_add_tail(&spz->node, &pr->scmi_zones); /* * Forcibly skip powercap domains using an abstract scale. * Note that only leaves domains can be skipped, so this could Loading @@ -448,7 +482,7 @@ static int scmi_powercap_probe(struct scmi_device *sdev) dev_warn(dev, "Abstract power scale not supported. Skip %s.\n", spz->info->name); spz->info = NULL; spz->invalid = true; continue; } } Loading @@ -457,21 +491,12 @@ static int scmi_powercap_probe(struct scmi_device *sdev) * Scan array of retrieved SCMI powercap domains and register them * recursively starting from the root domains. */ for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) { ret = scmi_powercap_register_zone(pr, spz); if (ret) { dev_err(dev, "Failed to register powercap zone %s - ret:%d\n", spz->info->name, ret); scmi_powercap_unregister_all_zones(pr); ret = scmi_zones_register(dev, pr); if (ret) return ret; } } dev_set_drvdata(dev, pr); dev_info(dev, "Registered %d SCMI Powercap domains !\n", pr->num_zones); return ret; } Loading drivers/powercap/intel_rapl_common.c +1 −1 Original line number Diff line number Diff line Loading @@ -1485,7 +1485,7 @@ static int rapl_detect_domains(struct rapl_package *rp) } pr_debug("found %d domains on %s\n", rp->nr_domains, rp->name); rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain), rp->domains = kcalloc(rp->nr_domains, sizeof(struct rapl_domain), GFP_KERNEL); if (!rp->domains) return -ENOMEM; Loading Loading
drivers/powercap/arm_scmi_powercap.c +92 −67 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/powercap.h> #include <linux/scmi_protocol.h> #include <linux/slab.h> #define to_scmi_powercap_zone(z) \ container_of(z, struct scmi_powercap_zone, zone) Loading @@ -19,6 +20,8 @@ static const struct scmi_powercap_proto_ops *powercap_ops; struct scmi_powercap_zone { bool registered; bool invalid; unsigned int height; struct device *dev; struct scmi_protocol_handle *ph; Loading @@ -32,6 +35,7 @@ struct scmi_powercap_root { unsigned int num_zones; struct scmi_powercap_zone *spzones; struct list_head *registered_zones; struct list_head scmi_zones; }; static struct powercap_control_type *scmi_top_pcntrl; Loading Loading @@ -271,12 +275,6 @@ static void scmi_powercap_unregister_all_zones(struct scmi_powercap_root *pr) } } static inline bool scmi_powercap_is_zone_registered(struct scmi_powercap_zone *spz) { return !list_empty(&spz->node); } static inline unsigned int scmi_powercap_get_zone_height(struct scmi_powercap_zone *spz) { Loading @@ -295,11 +293,46 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) return &spz->spzones[spz->info->parent_id]; } static int scmi_powercap_register_zone(struct scmi_powercap_root *pr, struct scmi_powercap_zone *spz, struct scmi_powercap_zone *parent) { int ret = 0; struct powercap_zone *z; if (spz->invalid) { list_del(&spz->node); return -EINVAL; } z = powercap_register_zone(&spz->zone, scmi_top_pcntrl, spz->info->name, parent ? &parent->zone : NULL, &zone_ops, 1, &constraint_ops); if (!IS_ERR(z)) { spz->height = scmi_powercap_get_zone_height(spz); spz->registered = true; list_move(&spz->node, &pr->registered_zones[spz->height]); dev_dbg(spz->dev, "Registered node %s - parent %s - height:%d\n", spz->info->name, parent ? parent->info->name : "ROOT", spz->height); } else { list_del(&spz->node); ret = PTR_ERR(z); dev_err(spz->dev, "Error registering node:%s - parent:%s - h:%d - ret:%d\n", spz->info->name, parent ? parent->info->name : "ROOT", spz->height, ret); } return ret; } /** * scmi_powercap_register_zone - Register an SCMI powercap zone recursively * scmi_zones_register- Register SCMI powercap zones starting from parent zones * * @dev: A reference to the SCMI device * @pr: A reference to the root powercap zones descriptors * @spz: A reference to the SCMI powercap zone to register * * When registering SCMI powercap zones with the powercap framework we should * take care to always register zones starting from the root ones and to Loading @@ -309,10 +342,10 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) * zones provided by the SCMI platform firmware is built to comply with such * requirement. * * This function, given an SCMI powercap zone to register, takes care to walk * the SCMI powercap zones tree up to the root looking recursively for * unregistered parent zones before registering the provided zone; at the same * time each registered zone height in such a tree is accounted for and each * This function, given the set of SCMI powercap zones to register, takes care * to walk the SCMI powercap zones trees up to the root registering any * unregistered parent zone before registering the child zones; at the same * time each registered-zone height in such a tree is accounted for and each * zone, once registered, is stored in the @registered_zones array that is * indexed by zone height: this way will be trivial, at unregister time, to walk * the @registered_zones array backward and unregister all the zones starting Loading @@ -330,57 +363,55 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) * * Return: 0 on Success */ static int scmi_powercap_register_zone(struct scmi_powercap_root *pr, struct scmi_powercap_zone *spz) static int scmi_zones_register(struct device *dev, struct scmi_powercap_root *pr) { int ret = 0; struct scmi_powercap_zone *parent; unsigned int sp = 0, reg_zones = 0; struct scmi_powercap_zone *spz, **zones_stack; if (!spz->info) return ret; zones_stack = kcalloc(pr->num_zones, sizeof(spz), GFP_KERNEL); if (!zones_stack) return -ENOMEM; spz = list_first_entry_or_null(&pr->scmi_zones, struct scmi_powercap_zone, node); while (spz) { struct scmi_powercap_zone *parent; parent = scmi_powercap_get_parent_zone(spz); if (parent && !scmi_powercap_is_zone_registered(parent)) { /* * Bail out if a parent domain was marked as unsupported: * only domains participating as leaves can be skipped. if (parent && !parent->registered) { zones_stack[sp++] = spz; spz = parent; } else { ret = scmi_powercap_register_zone(pr, spz, parent); if (!ret) { reg_zones++; } else if (sp) { /* Failed to register a non-leaf zone. * Bail-out. */ if (!parent->info) return -ENODEV; ret = scmi_powercap_register_zone(pr, parent); if (ret) return ret; dev_err(dev, "Failed to register non-leaf zone - ret:%d\n", ret); scmi_powercap_unregister_all_zones(pr); reg_zones = 0; goto out; } if (!scmi_powercap_is_zone_registered(spz)) { struct powercap_zone *z; z = powercap_register_zone(&spz->zone, scmi_top_pcntrl, spz->info->name, parent ? &parent->zone : NULL, &zone_ops, 1, &constraint_ops); if (!IS_ERR(z)) { spz->height = scmi_powercap_get_zone_height(spz); list_add(&spz->node, &pr->registered_zones[spz->height]); dev_dbg(spz->dev, "Registered node %s - parent %s - height:%d\n", spz->info->name, parent ? parent->info->name : "ROOT", spz->height); ret = 0; } else { ret = PTR_ERR(z); dev_err(spz->dev, "Error registering node:%s - parent:%s - h:%d - ret:%d\n", spz->info->name, parent ? parent->info->name : "ROOT", spz->height, ret); /* Pick next zone to process */ if (sp) spz = zones_stack[--sp]; else spz = list_first_entry_or_null(&pr->scmi_zones, struct scmi_powercap_zone, node); } } out: kfree(zones_stack); dev_info(dev, "Registered %d SCMI Powercap domains !\n", reg_zones); return ret; } Loading Loading @@ -424,6 +455,8 @@ static int scmi_powercap_probe(struct scmi_device *sdev) if (!pr->registered_zones) return -ENOMEM; INIT_LIST_HEAD(&pr->scmi_zones); for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) { /* * Powercap domains are validate by the protocol layer, i.e. Loading @@ -438,6 +471,7 @@ static int scmi_powercap_probe(struct scmi_device *sdev) INIT_LIST_HEAD(&spz->node); INIT_LIST_HEAD(&pr->registered_zones[i]); list_add_tail(&spz->node, &pr->scmi_zones); /* * Forcibly skip powercap domains using an abstract scale. * Note that only leaves domains can be skipped, so this could Loading @@ -448,7 +482,7 @@ static int scmi_powercap_probe(struct scmi_device *sdev) dev_warn(dev, "Abstract power scale not supported. Skip %s.\n", spz->info->name); spz->info = NULL; spz->invalid = true; continue; } } Loading @@ -457,21 +491,12 @@ static int scmi_powercap_probe(struct scmi_device *sdev) * Scan array of retrieved SCMI powercap domains and register them * recursively starting from the root domains. */ for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) { ret = scmi_powercap_register_zone(pr, spz); if (ret) { dev_err(dev, "Failed to register powercap zone %s - ret:%d\n", spz->info->name, ret); scmi_powercap_unregister_all_zones(pr); ret = scmi_zones_register(dev, pr); if (ret) return ret; } } dev_set_drvdata(dev, pr); dev_info(dev, "Registered %d SCMI Powercap domains !\n", pr->num_zones); return ret; } Loading
drivers/powercap/intel_rapl_common.c +1 −1 Original line number Diff line number Diff line Loading @@ -1485,7 +1485,7 @@ static int rapl_detect_domains(struct rapl_package *rp) } pr_debug("found %d domains on %s\n", rp->nr_domains, rp->name); rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain), rp->domains = kcalloc(rp->nr_domains, sizeof(struct rapl_domain), GFP_KERNEL); if (!rp->domains) return -ENOMEM; Loading