Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pmdomain-v6.12-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm

Pull pmdomain fixes from Ulf Hansson:
"pmdomain core:
- Add GENPD_FLAG_DEV_NAME_FW flag to generate unique names

pmdomain providers:
- arm: Use FLAG_DEV_NAME_FW to ensure unique names
- imx93-blk-ctrl: Fix the remove path

arm_scmi/qcom-cpucp:
- Report duplicate OPPs as firmware bugs for arm_scmi
- Skip OPP duplicates for arm_scmi
- Mark the qcom-cpucp mailbox irq with IRQF_NO_SUSPEND flag"

* tag 'pmdomain-v6.12-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm:
mailbox: qcom-cpucp: Mark the irq with IRQF_NO_SUSPEND flag
firmware: arm_scmi: Report duplicate opps as firmware bugs
firmware: arm_scmi: Skip opp duplicates
pmdomain: imx93-blk-ctrl: correct remove path
pmdomain: arm: Use FLAG_DEV_NAME_FW to ensure unique names
pmdomain: core: Add GENPD_FLAG_DEV_NAME_FW flag

+78 -30
+32 -12
drivers/firmware/arm_scmi/perf.c
··· 373 373 return 0; 374 374 } 375 375 376 - static inline void 376 + static inline int 377 377 process_response_opp(struct device *dev, struct perf_dom_info *dom, 378 378 struct scmi_opp *opp, unsigned int loop_idx, 379 379 const struct scmi_msg_resp_perf_describe_levels *r) ··· 386 386 le16_to_cpu(r->opp[loop_idx].transition_latency_us); 387 387 388 388 ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL); 389 - if (ret) 390 - dev_warn(dev, "Failed to add opps_by_lvl at %d for %s - ret:%d\n", 389 + if (ret) { 390 + dev_info(dev, FW_BUG "Failed to add opps_by_lvl at %d for %s - ret:%d\n", 391 391 opp->perf, dom->info.name, ret); 392 + return ret; 393 + } 394 + 395 + return 0; 392 396 } 393 397 394 - static inline void 398 + static inline int 395 399 process_response_opp_v4(struct device *dev, struct perf_dom_info *dom, 396 400 struct scmi_opp *opp, unsigned int loop_idx, 397 401 const struct scmi_msg_resp_perf_describe_levels_v4 *r) ··· 408 404 le16_to_cpu(r->opp[loop_idx].transition_latency_us); 409 405 410 406 ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL); 411 - if (ret) 412 - dev_warn(dev, "Failed to add opps_by_lvl at %d for %s - ret:%d\n", 407 + if (ret) { 408 + dev_info(dev, FW_BUG "Failed to add opps_by_lvl at %d for %s - ret:%d\n", 413 409 opp->perf, dom->info.name, ret); 410 + return ret; 411 + } 414 412 415 413 /* Note that PERF v4 reports always five 32-bit words */ 416 414 opp->indicative_freq = le32_to_cpu(r->opp[loop_idx].indicative_freq); ··· 421 415 422 416 ret = xa_insert(&dom->opps_by_idx, opp->level_index, opp, 423 417 GFP_KERNEL); 424 - if (ret) 418 + if (ret) { 425 419 dev_warn(dev, 426 420 "Failed to add opps_by_idx at %d for %s - ret:%d\n", 427 421 opp->level_index, dom->info.name, ret); 428 422 423 + /* Cleanup by_lvl too */ 424 + xa_erase(&dom->opps_by_lvl, opp->perf); 425 + 426 + return ret; 427 + } 428 + 429 429 hash_add(dom->opps_by_freq, &opp->hash, opp->indicative_freq); 430 430 } 431 + 432 + return 0; 431 433 } 432 434 433 435 static int ··· 443 429 const void *response, 444 430 struct scmi_iterator_state *st, void *priv) 445 431 { 432 + int ret; 446 433 struct scmi_opp *opp; 447 434 struct scmi_perf_ipriv *p = priv; 448 435 449 - opp = &p->perf_dom->opp[st->desc_index + st->loop_idx]; 436 + opp = &p->perf_dom->opp[p->perf_dom->opp_count]; 450 437 if (PROTOCOL_REV_MAJOR(p->version) <= 0x3) 451 - process_response_opp(ph->dev, p->perf_dom, opp, st->loop_idx, 452 - response); 438 + ret = process_response_opp(ph->dev, p->perf_dom, opp, 439 + st->loop_idx, response); 453 440 else 454 - process_response_opp_v4(ph->dev, p->perf_dom, opp, st->loop_idx, 455 - response); 441 + ret = process_response_opp_v4(ph->dev, p->perf_dom, opp, 442 + st->loop_idx, response); 443 + 444 + /* Skip BAD duplicates received from firmware */ 445 + if (ret) 446 + return ret == -EBUSY ? 0 : ret; 447 + 456 448 p->perf_dom->opp_count++; 457 449 458 450 dev_dbg(ph->dev, "Level %d Power %d Latency %dus Ifreq %d Index %d\n",
+1 -1
drivers/mailbox/qcom-cpucp-mbox.c
··· 138 138 return irq; 139 139 140 140 ret = devm_request_irq(dev, irq, qcom_cpucp_mbox_irq_fn, 141 - IRQF_TRIGGER_HIGH, "apss_cpucp_mbox", cpucp); 141 + IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, "apss_cpucp_mbox", cpucp); 142 142 if (ret < 0) 143 143 return dev_err_probe(dev, ret, "Failed to register irq: %d\n", irq); 144 144
+2 -1
drivers/pmdomain/arm/scmi_perf_domain.c
··· 125 125 scmi_pd->ph = ph; 126 126 scmi_pd->genpd.name = scmi_pd->info->name; 127 127 scmi_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON | 128 - GENPD_FLAG_OPP_TABLE_FW; 128 + GENPD_FLAG_OPP_TABLE_FW | 129 + GENPD_FLAG_DEV_NAME_FW; 129 130 scmi_pd->genpd.set_performance_state = scmi_pd_set_perf_state; 130 131 scmi_pd->genpd.attach_dev = scmi_pd_attach_dev; 131 132 scmi_pd->genpd.detach_dev = scmi_pd_detach_dev;
+34 -15
drivers/pmdomain/core.c
··· 7 7 #define pr_fmt(fmt) "PM: " fmt 8 8 9 9 #include <linux/delay.h> 10 + #include <linux/idr.h> 10 11 #include <linux/kernel.h> 11 12 #include <linux/io.h> 12 13 #include <linux/platform_device.h> ··· 23 22 #include <linux/export.h> 24 23 #include <linux/cpu.h> 25 24 #include <linux/debugfs.h> 25 + 26 + /* Provides a unique ID for each genpd device */ 27 + static DEFINE_IDA(genpd_ida); 26 28 27 29 #define GENPD_RETRY_MAX_MS 250 /* Approximate */ 28 30 ··· 175 171 #define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN) 176 172 #define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON) 177 173 #define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW) 174 + #define genpd_is_dev_name_fw(genpd) (genpd->flags & GENPD_FLAG_DEV_NAME_FW) 178 175 179 176 static inline bool irq_safe_dev_in_sleep_domain(struct device *dev, 180 177 const struct generic_pm_domain *genpd) ··· 194 189 195 190 if (ret) 196 191 dev_warn_once(dev, "PM domain %s will not be powered off\n", 197 - genpd->name); 192 + dev_name(&genpd->dev)); 198 193 199 194 return ret; 200 195 } ··· 279 274 if (!genpd_debugfs_dir) 280 275 return; 281 276 282 - debugfs_lookup_and_remove(genpd->name, genpd_debugfs_dir); 277 + debugfs_lookup_and_remove(dev_name(&genpd->dev), genpd_debugfs_dir); 283 278 } 284 279 285 280 static void genpd_update_accounting(struct generic_pm_domain *genpd) ··· 736 731 genpd->states[state_idx].power_on_latency_ns = elapsed_ns; 737 732 genpd->gd->max_off_time_changed = true; 738 733 pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", 739 - genpd->name, "on", elapsed_ns); 734 + dev_name(&genpd->dev), "on", elapsed_ns); 740 735 741 736 out: 742 737 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL); ··· 787 782 genpd->states[state_idx].power_off_latency_ns = elapsed_ns; 788 783 genpd->gd->max_off_time_changed = true; 789 784 pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", 790 - genpd->name, "off", elapsed_ns); 785 + dev_name(&genpd->dev), "off", elapsed_ns); 791 786 792 787 out: 793 788 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF, ··· 1945 1940 1946 1941 if (ret) { 1947 1942 dev_warn(dev, "failed to add notifier for PM domain %s\n", 1948 - genpd->name); 1943 + dev_name(&genpd->dev)); 1949 1944 return ret; 1950 1945 } 1951 1946 ··· 1992 1987 1993 1988 if (ret) { 1994 1989 dev_warn(dev, "failed to remove notifier for PM domain %s\n", 1995 - genpd->name); 1990 + dev_name(&genpd->dev)); 1996 1991 return ret; 1997 1992 } 1998 1993 ··· 2018 2013 */ 2019 2014 if (!genpd_is_irq_safe(genpd) && genpd_is_irq_safe(subdomain)) { 2020 2015 WARN(1, "Parent %s of subdomain %s must be IRQ safe\n", 2021 - genpd->name, subdomain->name); 2016 + dev_name(&genpd->dev), subdomain->name); 2022 2017 return -EINVAL; 2023 2018 } 2024 2019 ··· 2093 2088 2094 2089 if (!list_empty(&subdomain->parent_links) || subdomain->device_count) { 2095 2090 pr_warn("%s: unable to remove subdomain %s\n", 2096 - genpd->name, subdomain->name); 2091 + dev_name(&genpd->dev), subdomain->name); 2097 2092 ret = -EBUSY; 2098 2093 goto out; 2099 2094 } ··· 2230 2225 genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON; 2231 2226 genpd->device_count = 0; 2232 2227 genpd->provider = NULL; 2228 + genpd->device_id = -ENXIO; 2233 2229 genpd->has_provider = false; 2234 2230 genpd->accounting_time = ktime_get_mono_fast_ns(); 2235 2231 genpd->domain.ops.runtime_suspend = genpd_runtime_suspend; ··· 2271 2265 return ret; 2272 2266 2273 2267 device_initialize(&genpd->dev); 2274 - dev_set_name(&genpd->dev, "%s", genpd->name); 2268 + 2269 + if (!genpd_is_dev_name_fw(genpd)) { 2270 + dev_set_name(&genpd->dev, "%s", genpd->name); 2271 + } else { 2272 + ret = ida_alloc(&genpd_ida, GFP_KERNEL); 2273 + if (ret < 0) { 2274 + put_device(&genpd->dev); 2275 + return ret; 2276 + } 2277 + genpd->device_id = ret; 2278 + dev_set_name(&genpd->dev, "%s_%u", genpd->name, genpd->device_id); 2279 + } 2275 2280 2276 2281 mutex_lock(&gpd_list_lock); 2277 2282 list_add(&genpd->gpd_list_node, &gpd_list); ··· 2304 2287 2305 2288 if (genpd->has_provider) { 2306 2289 genpd_unlock(genpd); 2307 - pr_err("Provider present, unable to remove %s\n", genpd->name); 2290 + pr_err("Provider present, unable to remove %s\n", dev_name(&genpd->dev)); 2308 2291 return -EBUSY; 2309 2292 } 2310 2293 2311 2294 if (!list_empty(&genpd->parent_links) || genpd->device_count) { 2312 2295 genpd_unlock(genpd); 2313 - pr_err("%s: unable to remove %s\n", __func__, genpd->name); 2296 + pr_err("%s: unable to remove %s\n", __func__, dev_name(&genpd->dev)); 2314 2297 return -EBUSY; 2315 2298 } 2316 2299 ··· 2324 2307 genpd_unlock(genpd); 2325 2308 genpd_debug_remove(genpd); 2326 2309 cancel_work_sync(&genpd->power_off_work); 2310 + if (genpd->device_id != -ENXIO) 2311 + ida_free(&genpd_ida, genpd->device_id); 2327 2312 genpd_free_data(genpd); 2328 2313 2329 - pr_debug("%s: removed %s\n", __func__, genpd->name); 2314 + pr_debug("%s: removed %s\n", __func__, dev_name(&genpd->dev)); 2330 2315 2331 2316 return 0; 2332 2317 } ··· 3291 3272 else 3292 3273 snprintf(state, sizeof(state), "%s", 3293 3274 status_lookup[genpd->status]); 3294 - seq_printf(s, "%-30s %-30s %u", genpd->name, state, genpd->performance_state); 3275 + seq_printf(s, "%-30s %-30s %u", dev_name(&genpd->dev), state, genpd->performance_state); 3295 3276 3296 3277 /* 3297 3278 * Modifications on the list require holding locks on both 3298 3279 * parent and child, so we are safe. 3299 - * Also genpd->name is immutable. 3280 + * Also the device name is immutable. 3300 3281 */ 3301 3282 list_for_each_entry(link, &genpd->parent_links, parent_node) { 3302 3283 if (list_is_first(&link->parent_node, &genpd->parent_links)) ··· 3521 3502 if (!genpd_debugfs_dir) 3522 3503 return; 3523 3504 3524 - d = debugfs_create_dir(genpd->name, genpd_debugfs_dir); 3505 + d = debugfs_create_dir(dev_name(&genpd->dev), genpd_debugfs_dir); 3525 3506 3526 3507 debugfs_create_file("current_state", 0444, 3527 3508 d, genpd, &status_fops);
+3 -1
drivers/pmdomain/imx/imx93-blk-ctrl.c
··· 313 313 314 314 of_genpd_del_provider(pdev->dev.of_node); 315 315 316 - for (i = 0; bc->onecell_data.num_domains; i++) { 316 + pm_runtime_disable(&pdev->dev); 317 + 318 + for (i = 0; i < bc->onecell_data.num_domains; i++) { 317 319 struct imx93_blk_ctrl_domain *domain = &bc->domains[i]; 318 320 319 321 pm_genpd_remove(&domain->genpd);
+6
include/linux/pm_domain.h
··· 92 92 * GENPD_FLAG_OPP_TABLE_FW: The genpd provider supports performance states, 93 93 * but its corresponding OPP tables are not 94 94 * described in DT, but are given directly by FW. 95 + * 96 + * GENPD_FLAG_DEV_NAME_FW: Instructs genpd to generate an unique device name 97 + * using ida. It is used by genpd providers which 98 + * get their genpd-names directly from FW. 95 99 */ 96 100 #define GENPD_FLAG_PM_CLK (1U << 0) 97 101 #define GENPD_FLAG_IRQ_SAFE (1U << 1) ··· 105 101 #define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5) 106 102 #define GENPD_FLAG_MIN_RESIDENCY (1U << 6) 107 103 #define GENPD_FLAG_OPP_TABLE_FW (1U << 7) 104 + #define GENPD_FLAG_DEV_NAME_FW (1U << 8) 108 105 109 106 enum gpd_status { 110 107 GENPD_STATE_ON = 0, /* PM domain is on */ ··· 168 163 atomic_t sd_count; /* Number of subdomains with power "on" */ 169 164 enum gpd_status status; /* Current state of the domain */ 170 165 unsigned int device_count; /* Number of devices */ 166 + unsigned int device_id; /* unique device id */ 171 167 unsigned int suspended_count; /* System suspend device counter */ 172 168 unsigned int prepared_count; /* Suspend counter of prepared devices */ 173 169 unsigned int performance_state; /* Aggregated max performance state */