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 'opp-updates-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Pull OPP updates for 6.19 from Viresh Kumar:

"- Minor improvements to the Rust interface (Tamir Duberstein).

- Fixes to scope-based pointers (Viresh Kumar)."

* tag 'opp-updates-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
rust: opp: simplify callers of `to_c_str_array`
OPP: Initialize scope-based pointers inline
rust: opp: fix broken rustdoc link

+179 -151
+38 -31
drivers/opp/core.c
··· 309 309 */ 310 310 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev) 311 311 { 312 - struct opp_table *opp_table __free(put_opp_table); 312 + struct opp_table *opp_table __free(put_opp_table) = 313 + _find_opp_table(dev); 313 314 314 - opp_table = _find_opp_table(dev); 315 315 if (IS_ERR(opp_table)) 316 316 return 0; 317 317 ··· 327 327 */ 328 328 unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) 329 329 { 330 - struct opp_table *opp_table __free(put_opp_table); 331 330 struct dev_pm_opp *opp; 332 331 struct regulator *reg; 333 332 unsigned long latency_ns = 0; ··· 336 337 unsigned long max; 337 338 } *uV; 338 339 339 - opp_table = _find_opp_table(dev); 340 + struct opp_table *opp_table __free(put_opp_table) = 341 + _find_opp_table(dev); 342 + 340 343 if (IS_ERR(opp_table)) 341 344 return 0; 342 345 ··· 410 409 */ 411 410 unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev) 412 411 { 413 - struct opp_table *opp_table __free(put_opp_table); 414 412 unsigned long freq = 0; 415 413 416 - opp_table = _find_opp_table(dev); 414 + struct opp_table *opp_table __free(put_opp_table) = 415 + _find_opp_table(dev); 416 + 417 417 if (IS_ERR(opp_table)) 418 418 return 0; 419 419 ··· 449 447 */ 450 448 int dev_pm_opp_get_opp_count(struct device *dev) 451 449 { 452 - struct opp_table *opp_table __free(put_opp_table); 450 + struct opp_table *opp_table __free(put_opp_table) = 451 + _find_opp_table(dev); 453 452 454 - opp_table = _find_opp_table(dev); 455 453 if (IS_ERR(opp_table)) { 456 454 dev_dbg(dev, "%s: OPP table not found (%ld)\n", 457 455 __func__, PTR_ERR(opp_table)); ··· 607 605 unsigned long opp_key, unsigned long key), 608 606 bool (*assert)(struct opp_table *opp_table, unsigned int index)) 609 607 { 610 - struct opp_table *opp_table __free(put_opp_table); 608 + struct opp_table *opp_table __free(put_opp_table) = 609 + _find_opp_table(dev); 611 610 612 - opp_table = _find_opp_table(dev); 613 611 if (IS_ERR(opp_table)) { 614 612 dev_err(dev, "%s: OPP table not found (%ld)\n", __func__, 615 613 PTR_ERR(opp_table)); ··· 1412 1410 */ 1413 1411 int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) 1414 1412 { 1415 - struct opp_table *opp_table __free(put_opp_table); 1416 1413 struct dev_pm_opp *opp __free(put_opp) = NULL; 1417 1414 unsigned long freq = 0, temp_freq; 1418 1415 bool forced = false; 1419 1416 1420 - opp_table = _find_opp_table(dev); 1417 + struct opp_table *opp_table __free(put_opp_table) = 1418 + _find_opp_table(dev); 1419 + 1421 1420 if (IS_ERR(opp_table)) { 1422 1421 dev_err(dev, "%s: device's opp table doesn't exist\n", __func__); 1423 1422 return PTR_ERR(opp_table); ··· 1480 1477 */ 1481 1478 int dev_pm_opp_set_opp(struct device *dev, struct dev_pm_opp *opp) 1482 1479 { 1483 - struct opp_table *opp_table __free(put_opp_table); 1480 + struct opp_table *opp_table __free(put_opp_table) = 1481 + _find_opp_table(dev); 1484 1482 1485 - opp_table = _find_opp_table(dev); 1486 1483 if (IS_ERR(opp_table)) { 1487 1484 dev_err(dev, "%s: device opp doesn't exist\n", __func__); 1488 1485 return PTR_ERR(opp_table); ··· 1797 1794 */ 1798 1795 void dev_pm_opp_remove(struct device *dev, unsigned long freq) 1799 1796 { 1800 - struct opp_table *opp_table __free(put_opp_table); 1801 1797 struct dev_pm_opp *opp = NULL, *iter; 1802 1798 1803 - opp_table = _find_opp_table(dev); 1799 + struct opp_table *opp_table __free(put_opp_table) = 1800 + _find_opp_table(dev); 1801 + 1804 1802 if (IS_ERR(opp_table)) 1805 1803 return; 1806 1804 ··· 1889 1885 */ 1890 1886 void dev_pm_opp_remove_all_dynamic(struct device *dev) 1891 1887 { 1892 - struct opp_table *opp_table __free(put_opp_table); 1888 + struct opp_table *opp_table __free(put_opp_table) = 1889 + _find_opp_table(dev); 1893 1890 1894 - opp_table = _find_opp_table(dev); 1895 1891 if (IS_ERR(opp_table)) 1896 1892 return; 1897 1893 ··· 2875 2871 bool availability_req) 2876 2872 { 2877 2873 struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp; 2878 - struct opp_table *opp_table __free(put_opp_table); 2879 2874 2880 2875 /* Find the opp_table */ 2881 - opp_table = _find_opp_table(dev); 2876 + struct opp_table *opp_table __free(put_opp_table) = 2877 + _find_opp_table(dev); 2878 + 2882 2879 if (IS_ERR(opp_table)) { 2883 2880 dev_warn(dev, "%s: Device OPP not found (%ld)\n", __func__, 2884 2881 PTR_ERR(opp_table)); ··· 2937 2932 2938 2933 { 2939 2934 struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp; 2940 - struct opp_table *opp_table __free(put_opp_table); 2941 2935 int r; 2942 2936 2943 2937 /* Find the opp_table */ 2944 - opp_table = _find_opp_table(dev); 2938 + struct opp_table *opp_table __free(put_opp_table) = 2939 + _find_opp_table(dev); 2940 + 2945 2941 if (IS_ERR(opp_table)) { 2946 2942 r = PTR_ERR(opp_table); 2947 2943 dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); ··· 2992 2986 */ 2993 2987 int dev_pm_opp_sync_regulators(struct device *dev) 2994 2988 { 2995 - struct opp_table *opp_table __free(put_opp_table); 2996 2989 struct regulator *reg; 2997 2990 int ret, i; 2998 2991 2999 2992 /* Device may not have OPP table */ 3000 - opp_table = _find_opp_table(dev); 2993 + struct opp_table *opp_table __free(put_opp_table) = 2994 + _find_opp_table(dev); 2995 + 3001 2996 if (IS_ERR(opp_table)) 3002 2997 return 0; 3003 2998 ··· 3069 3062 */ 3070 3063 int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb) 3071 3064 { 3072 - struct opp_table *opp_table __free(put_opp_table); 3065 + struct opp_table *opp_table __free(put_opp_table) = 3066 + _find_opp_table(dev); 3073 3067 3074 - opp_table = _find_opp_table(dev); 3075 3068 if (IS_ERR(opp_table)) 3076 3069 return PTR_ERR(opp_table); 3077 3070 ··· 3089 3082 int dev_pm_opp_unregister_notifier(struct device *dev, 3090 3083 struct notifier_block *nb) 3091 3084 { 3092 - struct opp_table *opp_table __free(put_opp_table); 3085 + struct opp_table *opp_table __free(put_opp_table) = 3086 + _find_opp_table(dev); 3093 3087 3094 - opp_table = _find_opp_table(dev); 3095 3088 if (IS_ERR(opp_table)) 3096 3089 return PTR_ERR(opp_table); 3097 3090 ··· 3108 3101 */ 3109 3102 void dev_pm_opp_remove_table(struct device *dev) 3110 3103 { 3111 - struct opp_table *opp_table __free(put_opp_table); 3112 - 3113 3104 /* Check for existing table for 'dev' */ 3114 - opp_table = _find_opp_table(dev); 3105 + struct opp_table *opp_table __free(put_opp_table) = 3106 + _find_opp_table(dev); 3107 + 3115 3108 if (IS_ERR(opp_table)) { 3116 3109 int error = PTR_ERR(opp_table); 3117 3110
+9 -7
drivers/opp/cpu.c
··· 56 56 return -ENOMEM; 57 57 58 58 for (i = 0, rate = 0; i < max_opps; i++, rate++) { 59 - struct dev_pm_opp *opp __free(put_opp); 60 - 61 59 /* find next rate */ 62 - opp = dev_pm_opp_find_freq_ceil(dev, &rate); 60 + struct dev_pm_opp *opp __free(put_opp) = 61 + dev_pm_opp_find_freq_ceil(dev, &rate); 62 + 63 63 if (IS_ERR(opp)) { 64 64 ret = PTR_ERR(opp); 65 65 goto out; ··· 154 154 int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, 155 155 const struct cpumask *cpumask) 156 156 { 157 - struct opp_table *opp_table __free(put_opp_table); 158 157 struct opp_device *opp_dev; 159 158 struct device *dev; 160 159 int cpu; 161 160 162 - opp_table = _find_opp_table(cpu_dev); 161 + struct opp_table *opp_table __free(put_opp_table) = 162 + _find_opp_table(cpu_dev); 163 + 163 164 if (IS_ERR(opp_table)) 164 165 return PTR_ERR(opp_table); 165 166 ··· 202 201 */ 203 202 int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) 204 203 { 205 - struct opp_table *opp_table __free(put_opp_table); 206 204 struct opp_device *opp_dev; 207 205 208 - opp_table = _find_opp_table(cpu_dev); 206 + struct opp_table *opp_table __free(put_opp_table) = 207 + _find_opp_table(cpu_dev); 208 + 209 209 if (IS_ERR(opp_table)) 210 210 return PTR_ERR(opp_table); 211 211
+70 -55
drivers/opp/of.c
··· 45 45 struct opp_table *_managed_opp(struct device *dev, int index) 46 46 { 47 47 struct opp_table *opp_table, *managed_table = NULL; 48 - struct device_node *np __free(device_node); 49 48 50 - np = _opp_of_get_opp_desc_node(dev->of_node, index); 49 + struct device_node *np __free(device_node) = 50 + _opp_of_get_opp_desc_node(dev->of_node, index); 51 + 51 52 if (!np) 52 53 return NULL; 53 54 ··· 96 95 /* The caller must call dev_pm_opp_put_opp_table() after the table is used */ 97 96 static struct opp_table *_find_table_of_opp_np(struct device_node *opp_np) 98 97 { 99 - struct device_node *opp_table_np __free(device_node); 100 98 struct opp_table *opp_table; 101 99 102 - opp_table_np = of_get_parent(opp_np); 100 + struct device_node *opp_table_np __free(device_node) = 101 + of_get_parent(opp_np); 102 + 103 103 if (!opp_table_np) 104 104 return ERR_PTR(-ENODEV); 105 105 ··· 148 146 struct device_node *opp_np) 149 147 { 150 148 struct opp_table **required_opp_tables; 151 - struct device_node *np __free(device_node); 152 149 bool lazy = false; 153 150 int count, i, size; 154 151 155 152 /* Traversing the first OPP node is all we need */ 156 - np = of_get_next_available_child(opp_np, NULL); 153 + struct device_node *np __free(device_node) = 154 + of_get_next_available_child(opp_np, NULL); 155 + 157 156 if (!np) { 158 157 dev_warn(dev, "Empty OPP table\n"); 159 158 return; ··· 174 171 opp_table->required_opp_count = count; 175 172 176 173 for (i = 0; i < count; i++) { 177 - struct device_node *required_np __free(device_node); 174 + struct device_node *required_np __free(device_node) = 175 + of_parse_required_opp(np, i); 178 176 179 - required_np = of_parse_required_opp(np, i); 180 177 if (!required_np) { 181 178 _opp_table_free_required_tables(opp_table); 182 179 return; ··· 202 199 void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, 203 200 int index) 204 201 { 205 - struct device_node *np __free(device_node), *opp_np; 202 + struct device_node *opp_np; 206 203 u32 val; 207 204 208 205 /* 209 206 * Only required for backward compatibility with v1 bindings, but isn't 210 207 * harmful for other cases. And so we do it unconditionally. 211 208 */ 212 - np = of_node_get(dev->of_node); 209 + struct device_node *np __free(device_node) = of_node_get(dev->of_node); 210 + 213 211 if (!np) 214 212 return; 215 213 ··· 277 273 static int _link_required_opps(struct dev_pm_opp *opp, 278 274 struct opp_table *required_table, int index) 279 275 { 280 - struct device_node *np __free(device_node); 276 + struct device_node *np __free(device_node) = 277 + of_parse_required_opp(opp->np, index); 281 278 282 - np = of_parse_required_opp(opp->np, index); 283 279 if (unlikely(!np)) 284 280 return -ENODEV; 285 281 ··· 353 349 guard(mutex)(&opp_table_lock); 354 350 355 351 list_for_each_entry_safe(opp_table, temp, &lazy_opp_tables, lazy) { 356 - struct device_node *opp_np __free(device_node); 357 352 bool lazy = false; 358 353 359 354 /* opp_np can't be invalid here */ 360 - opp_np = of_get_next_available_child(opp_table->np, NULL); 355 + struct device_node *opp_np __free(device_node) = 356 + of_get_next_available_child(opp_table->np, NULL); 361 357 362 358 for (i = 0; i < opp_table->required_opp_count; i++) { 363 - struct device_node *required_np __free(device_node) = NULL; 364 - struct device_node *required_table_np __free(device_node) = NULL; 365 - 366 359 required_opp_tables = opp_table->required_opp_tables; 367 360 368 361 /* Required opp-table is already parsed */ ··· 367 366 continue; 368 367 369 368 /* required_np can't be invalid here */ 370 - required_np = of_parse_required_opp(opp_np, i); 371 - required_table_np = of_get_parent(required_np); 369 + struct device_node *required_np __free(device_node) = 370 + of_parse_required_opp(opp_np, i); 371 + struct device_node *required_table_np __free(device_node) = 372 + of_get_parent(required_np); 372 373 373 374 /* 374 375 * Newly added table isn't the required opp-table for ··· 405 402 static int _bandwidth_supported(struct device *dev, struct opp_table *opp_table) 406 403 { 407 404 struct device_node *opp_np __free(device_node) = NULL; 408 - struct device_node *np __free(device_node) = NULL; 409 405 struct property *prop; 410 406 411 407 if (!opp_table) { 412 - struct device_node *np __free(device_node); 408 + struct device_node *np __free(device_node) = 409 + of_node_get(dev->of_node); 413 410 414 - np = of_node_get(dev->of_node); 415 411 if (!np) 416 412 return -ENODEV; 417 413 ··· 424 422 return 0; 425 423 426 424 /* Checking only first OPP is sufficient */ 427 - np = of_get_next_available_child(opp_np, NULL); 425 + struct device_node *np __free(device_node) = 426 + of_get_next_available_child(opp_np, NULL); 427 + 428 428 if (!np) { 429 429 dev_err(dev, "OPP table empty\n"); 430 430 return -EINVAL; ··· 1273 1269 int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, 1274 1270 struct cpumask *cpumask) 1275 1271 { 1276 - struct device_node *np __free(device_node); 1277 1272 int cpu; 1278 1273 1279 1274 /* Get OPP descriptor node */ 1280 - np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); 1275 + struct device_node *np __free(device_node) = 1276 + dev_pm_opp_of_get_opp_desc_node(cpu_dev); 1277 + 1281 1278 if (!np) { 1282 1279 dev_dbg(cpu_dev, "%s: Couldn't find opp node.\n", __func__); 1283 1280 return -ENOENT; ··· 1291 1286 return 0; 1292 1287 1293 1288 for_each_possible_cpu(cpu) { 1294 - struct device_node *cpu_np __free(device_node) = NULL; 1295 - struct device_node *tmp_np __free(device_node) = NULL; 1296 - 1297 1289 if (cpu == cpu_dev->id) 1298 1290 continue; 1299 1291 1300 - cpu_np = of_cpu_device_node_get(cpu); 1292 + struct device_node *cpu_np __free(device_node) = 1293 + of_cpu_device_node_get(cpu); 1294 + 1301 1295 if (!cpu_np) { 1302 1296 dev_err(cpu_dev, "%s: failed to get cpu%d node\n", 1303 1297 __func__, cpu); ··· 1304 1300 } 1305 1301 1306 1302 /* Get OPP descriptor node */ 1307 - tmp_np = _opp_of_get_opp_desc_node(cpu_np, 0); 1303 + struct device_node *tmp_np __free(device_node) = 1304 + _opp_of_get_opp_desc_node(cpu_np, 0); 1305 + 1308 1306 if (!tmp_np) { 1309 1307 pr_err("%pOF: Couldn't find opp node\n", cpu_np); 1310 1308 return -ENOENT; ··· 1334 1328 */ 1335 1329 int of_get_required_opp_performance_state(struct device_node *np, int index) 1336 1330 { 1337 - struct device_node *required_np __free(device_node); 1338 - struct opp_table *opp_table __free(put_opp_table) = NULL; 1339 - struct dev_pm_opp *opp __free(put_opp) = NULL; 1340 1331 int pstate = -EINVAL; 1341 1332 1342 - required_np = of_parse_required_opp(np, index); 1333 + struct device_node *required_np __free(device_node) = 1334 + of_parse_required_opp(np, index); 1335 + 1343 1336 if (!required_np) 1344 1337 return -ENODEV; 1345 1338 1346 - opp_table = _find_table_of_opp_np(required_np); 1339 + struct opp_table *opp_table __free(put_opp_table) = 1340 + _find_table_of_opp_np(required_np); 1341 + 1347 1342 if (IS_ERR(opp_table)) { 1348 1343 pr_err("%s: Failed to find required OPP table %pOF: %ld\n", 1349 1344 __func__, np, PTR_ERR(opp_table)); ··· 1357 1350 return -EINVAL; 1358 1351 } 1359 1352 1360 - opp = _find_opp_of_np(opp_table, required_np); 1353 + struct dev_pm_opp *opp __free(put_opp) = 1354 + _find_opp_of_np(opp_table, required_np); 1355 + 1361 1356 if (opp) { 1362 1357 if (opp->level == OPP_LEVEL_UNSET) { 1363 1358 pr_err("%s: OPP levels aren't available for %pOF\n", ··· 1385 1376 */ 1386 1377 bool dev_pm_opp_of_has_required_opp(struct device *dev) 1387 1378 { 1388 - struct device_node *np __free(device_node) = NULL, *opp_np __free(device_node); 1389 1379 int count; 1390 1380 1391 - opp_np = _opp_of_get_opp_desc_node(dev->of_node, 0); 1381 + struct device_node *opp_np __free(device_node) = 1382 + _opp_of_get_opp_desc_node(dev->of_node, 0); 1383 + 1392 1384 if (!opp_np) 1393 1385 return false; 1394 1386 1395 - np = of_get_next_available_child(opp_np, NULL); 1387 + struct device_node *np __free(device_node) = 1388 + of_get_next_available_child(opp_np, NULL); 1389 + 1396 1390 if (!np) { 1397 1391 dev_warn(dev, "Empty OPP table\n"); 1398 1392 return false; ··· 1437 1425 static int __maybe_unused 1438 1426 _get_dt_power(struct device *dev, unsigned long *uW, unsigned long *kHz) 1439 1427 { 1440 - struct dev_pm_opp *opp __free(put_opp); 1441 1428 unsigned long opp_freq, opp_power; 1442 1429 1443 1430 /* Find the right frequency and related OPP */ 1444 1431 opp_freq = *kHz * 1000; 1445 - opp = dev_pm_opp_find_freq_ceil(dev, &opp_freq); 1432 + 1433 + struct dev_pm_opp *opp __free(put_opp) = 1434 + dev_pm_opp_find_freq_ceil(dev, &opp_freq); 1435 + 1446 1436 if (IS_ERR(opp)) 1447 1437 return -EINVAL; 1448 1438 ··· 1479 1465 int dev_pm_opp_calc_power(struct device *dev, unsigned long *uW, 1480 1466 unsigned long *kHz) 1481 1467 { 1482 - struct dev_pm_opp *opp __free(put_opp) = NULL; 1483 - struct device_node *np __free(device_node); 1484 1468 unsigned long mV, Hz; 1485 1469 u32 cap; 1486 1470 u64 tmp; 1487 1471 int ret; 1488 1472 1489 - np = of_node_get(dev->of_node); 1473 + struct device_node *np __free(device_node) = of_node_get(dev->of_node); 1474 + 1490 1475 if (!np) 1491 1476 return -EINVAL; 1492 1477 ··· 1494 1481 return -EINVAL; 1495 1482 1496 1483 Hz = *kHz * 1000; 1497 - opp = dev_pm_opp_find_freq_ceil(dev, &Hz); 1484 + 1485 + struct dev_pm_opp *opp __free(put_opp) = 1486 + dev_pm_opp_find_freq_ceil(dev, &Hz); 1487 + 1498 1488 if (IS_ERR(opp)) 1499 1489 return -EINVAL; 1500 1490 ··· 1518 1502 1519 1503 static bool _of_has_opp_microwatt_property(struct device *dev) 1520 1504 { 1521 - struct dev_pm_opp *opp __free(put_opp); 1522 1505 unsigned long freq = 0; 1523 1506 1524 1507 /* Check if at least one OPP has needed property */ 1525 - opp = dev_pm_opp_find_freq_ceil(dev, &freq); 1508 + struct dev_pm_opp *opp __free(put_opp) = 1509 + dev_pm_opp_find_freq_ceil(dev, &freq); 1510 + 1526 1511 if (IS_ERR(opp)) 1527 1512 return false; 1528 1513 ··· 1543 1526 */ 1544 1527 int dev_pm_opp_of_register_em(struct device *dev, struct cpumask *cpus) 1545 1528 { 1546 - struct device_node *np __free(device_node) = NULL; 1547 1529 struct em_data_callback em_cb; 1548 1530 int ret, nr_opp; 1549 1531 u32 cap; 1550 1532 1551 - if (IS_ERR_OR_NULL(dev)) { 1533 + if (IS_ERR_OR_NULL(dev)) 1534 + return -EINVAL; 1535 + 1536 + struct device_node *np __free(device_node) = of_node_get(dev->of_node); 1537 + 1538 + if (!np) { 1552 1539 ret = -EINVAL; 1553 1540 goto failed; 1554 1541 } ··· 1567 1546 if (_of_has_opp_microwatt_property(dev)) { 1568 1547 EM_SET_ACTIVE_POWER_CB(em_cb, _get_dt_power); 1569 1548 goto register_em; 1570 - } 1571 - 1572 - np = of_node_get(dev->of_node); 1573 - if (!np) { 1574 - ret = -EINVAL; 1575 - goto failed; 1576 1549 } 1577 1550 1578 1551 /*
+62 -58
rust/kernel/opp.rs
··· 87 87 88 88 use macros::vtable; 89 89 90 - /// Creates a null-terminated slice of pointers to [`Cstring`]s. 90 + /// Creates a null-terminated slice of pointers to [`CString`]s. 91 91 fn to_c_str_array(names: &[CString]) -> Result<KVec<*const u8>> { 92 92 // Allocated a null-terminated vector of pointers. 93 93 let mut list = KVec::with_capacity(names.len() + 1, GFP_KERNEL)?; ··· 443 443 /// 444 444 /// The returned [`ConfigToken`] will remove the configuration when dropped. 445 445 pub fn set(self, dev: &Device) -> Result<ConfigToken> { 446 - let (_clk_list, clk_names) = match &self.clk_names { 447 - Some(x) => { 448 - let list = to_c_str_array(x)?; 449 - let ptr = list.as_ptr(); 450 - (Some(list), ptr) 451 - } 452 - None => (None, ptr::null()), 446 + let clk_names = self.clk_names.as_deref().map(to_c_str_array).transpose()?; 447 + let regulator_names = self 448 + .regulator_names 449 + .as_deref() 450 + .map(to_c_str_array) 451 + .transpose()?; 452 + 453 + let set_config = || { 454 + let clk_names = clk_names.as_ref().map_or(ptr::null(), |c| c.as_ptr()); 455 + let regulator_names = regulator_names.as_ref().map_or(ptr::null(), |c| c.as_ptr()); 456 + 457 + let prop_name = self 458 + .prop_name 459 + .as_ref() 460 + .map_or(ptr::null(), |p| p.as_char_ptr()); 461 + 462 + let (supported_hw, supported_hw_count) = self 463 + .supported_hw 464 + .as_ref() 465 + .map_or((ptr::null(), 0), |hw| (hw.as_ptr(), hw.len() as u32)); 466 + 467 + let (required_dev, required_dev_index) = self 468 + .required_dev 469 + .as_ref() 470 + .map_or((ptr::null_mut(), 0), |(dev, idx)| (dev.as_raw(), *idx)); 471 + 472 + let mut config = bindings::dev_pm_opp_config { 473 + clk_names, 474 + config_clks: if T::HAS_CONFIG_CLKS { 475 + Some(Self::config_clks) 476 + } else { 477 + None 478 + }, 479 + prop_name, 480 + regulator_names, 481 + config_regulators: if T::HAS_CONFIG_REGULATORS { 482 + Some(Self::config_regulators) 483 + } else { 484 + None 485 + }, 486 + supported_hw, 487 + supported_hw_count, 488 + 489 + required_dev, 490 + required_dev_index, 491 + }; 492 + 493 + // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 494 + // requirements. The OPP core guarantees not to access fields of [`Config`] after this 495 + // call and so we don't need to save a copy of them for future use. 496 + let ret = unsafe { bindings::dev_pm_opp_set_config(dev.as_raw(), &mut config) }; 497 + 498 + to_result(ret).map(|()| ConfigToken(ret)) 453 499 }; 454 500 455 - let (_regulator_list, regulator_names) = match &self.regulator_names { 456 - Some(x) => { 457 - let list = to_c_str_array(x)?; 458 - let ptr = list.as_ptr(); 459 - (Some(list), ptr) 460 - } 461 - None => (None, ptr::null()), 462 - }; 501 + // Ensure the closure does not accidentally drop owned data; if violated, the compiler 502 + // produces E0525 with e.g.: 503 + // 504 + // ``` 505 + // closure is `FnOnce` because it moves the variable `clk_names` out of its environment 506 + // ``` 507 + let _: &dyn Fn() -> _ = &set_config; 463 508 464 - let prop_name = self 465 - .prop_name 466 - .as_ref() 467 - .map_or(ptr::null(), |p| p.as_char_ptr()); 468 - 469 - let (supported_hw, supported_hw_count) = self 470 - .supported_hw 471 - .as_ref() 472 - .map_or((ptr::null(), 0), |hw| (hw.as_ptr(), hw.len() as u32)); 473 - 474 - let (required_dev, required_dev_index) = self 475 - .required_dev 476 - .as_ref() 477 - .map_or((ptr::null_mut(), 0), |(dev, idx)| (dev.as_raw(), *idx)); 478 - 479 - let mut config = bindings::dev_pm_opp_config { 480 - clk_names, 481 - config_clks: if T::HAS_CONFIG_CLKS { 482 - Some(Self::config_clks) 483 - } else { 484 - None 485 - }, 486 - prop_name, 487 - regulator_names, 488 - config_regulators: if T::HAS_CONFIG_REGULATORS { 489 - Some(Self::config_regulators) 490 - } else { 491 - None 492 - }, 493 - supported_hw, 494 - supported_hw_count, 495 - 496 - required_dev, 497 - required_dev_index, 498 - }; 499 - 500 - // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 501 - // requirements. The OPP core guarantees not to access fields of [`Config`] after this call 502 - // and so we don't need to save a copy of them for future use. 503 - let ret = unsafe { bindings::dev_pm_opp_set_config(dev.as_raw(), &mut config) }; 504 - 505 - to_result(ret).map(|()| ConfigToken(ret)) 509 + set_config() 506 510 } 507 511 508 512 /// Config's clk callback.