diff options
Diffstat (limited to 'drivers/base')
| -rw-r--r-- | drivers/base/core.c | 51 | ||||
| -rw-r--r-- | drivers/base/dd.c | 14 | ||||
| -rw-r--r-- | drivers/base/platform.c | 2 | ||||
| -rw-r--r-- | drivers/base/power/domain.c | 70 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 20 | ||||
| -rw-r--r-- | drivers/base/power/trace.c | 6 | ||||
| -rw-r--r-- | drivers/base/property.c | 198 |
7 files changed, 278 insertions, 83 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index cadf165651d8..21d13038534e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| 14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
| 15 | #include <linux/fwnode.h> | ||
| 15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| @@ -2144,3 +2145,53 @@ define_dev_printk_level(dev_notice, KERN_NOTICE); | |||
| 2144 | define_dev_printk_level(_dev_info, KERN_INFO); | 2145 | define_dev_printk_level(_dev_info, KERN_INFO); |
| 2145 | 2146 | ||
| 2146 | #endif | 2147 | #endif |
| 2148 | |||
| 2149 | static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) | ||
| 2150 | { | ||
| 2151 | return fwnode && !IS_ERR(fwnode->secondary); | ||
| 2152 | } | ||
| 2153 | |||
| 2154 | /** | ||
| 2155 | * set_primary_fwnode - Change the primary firmware node of a given device. | ||
| 2156 | * @dev: Device to handle. | ||
| 2157 | * @fwnode: New primary firmware node of the device. | ||
| 2158 | * | ||
| 2159 | * Set the device's firmware node pointer to @fwnode, but if a secondary | ||
| 2160 | * firmware node of the device is present, preserve it. | ||
| 2161 | */ | ||
| 2162 | void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode) | ||
| 2163 | { | ||
| 2164 | if (fwnode) { | ||
| 2165 | struct fwnode_handle *fn = dev->fwnode; | ||
| 2166 | |||
| 2167 | if (fwnode_is_primary(fn)) | ||
| 2168 | fn = fn->secondary; | ||
| 2169 | |||
| 2170 | fwnode->secondary = fn; | ||
| 2171 | dev->fwnode = fwnode; | ||
| 2172 | } else { | ||
| 2173 | dev->fwnode = fwnode_is_primary(dev->fwnode) ? | ||
| 2174 | dev->fwnode->secondary : NULL; | ||
| 2175 | } | ||
| 2176 | } | ||
| 2177 | EXPORT_SYMBOL_GPL(set_primary_fwnode); | ||
| 2178 | |||
| 2179 | /** | ||
| 2180 | * set_secondary_fwnode - Change the secondary firmware node of a given device. | ||
| 2181 | * @dev: Device to handle. | ||
| 2182 | * @fwnode: New secondary firmware node of the device. | ||
| 2183 | * | ||
| 2184 | * If a primary firmware node of the device is present, set its secondary | ||
| 2185 | * pointer to @fwnode. Otherwise, set the device's firmware node pointer to | ||
| 2186 | * @fwnode. | ||
| 2187 | */ | ||
| 2188 | void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode) | ||
| 2189 | { | ||
| 2190 | if (fwnode) | ||
| 2191 | fwnode->secondary = ERR_PTR(-ENODEV); | ||
| 2192 | |||
| 2193 | if (fwnode_is_primary(dev->fwnode)) | ||
| 2194 | dev->fwnode->secondary = fwnode; | ||
| 2195 | else | ||
| 2196 | dev->fwnode = fwnode; | ||
| 2197 | } | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 49a4a12fafef..e843fdbe4925 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
| @@ -298,6 +298,12 @@ static int really_probe(struct device *dev, struct device_driver *drv) | |||
| 298 | goto probe_failed; | 298 | goto probe_failed; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | if (dev->pm_domain && dev->pm_domain->activate) { | ||
| 302 | ret = dev->pm_domain->activate(dev); | ||
| 303 | if (ret) | ||
| 304 | goto probe_failed; | ||
| 305 | } | ||
| 306 | |||
| 301 | if (dev->bus->probe) { | 307 | if (dev->bus->probe) { |
| 302 | ret = dev->bus->probe(dev); | 308 | ret = dev->bus->probe(dev); |
| 303 | if (ret) | 309 | if (ret) |
| @@ -308,6 +314,9 @@ static int really_probe(struct device *dev, struct device_driver *drv) | |||
| 308 | goto probe_failed; | 314 | goto probe_failed; |
| 309 | } | 315 | } |
| 310 | 316 | ||
| 317 | if (dev->pm_domain && dev->pm_domain->sync) | ||
| 318 | dev->pm_domain->sync(dev); | ||
| 319 | |||
| 311 | driver_bound(dev); | 320 | driver_bound(dev); |
| 312 | ret = 1; | 321 | ret = 1; |
| 313 | pr_debug("bus: '%s': %s: bound device %s to driver %s\n", | 322 | pr_debug("bus: '%s': %s: bound device %s to driver %s\n", |
| @@ -319,6 +328,8 @@ probe_failed: | |||
| 319 | driver_sysfs_remove(dev); | 328 | driver_sysfs_remove(dev); |
| 320 | dev->driver = NULL; | 329 | dev->driver = NULL; |
| 321 | dev_set_drvdata(dev, NULL); | 330 | dev_set_drvdata(dev, NULL); |
| 331 | if (dev->pm_domain && dev->pm_domain->dismiss) | ||
| 332 | dev->pm_domain->dismiss(dev); | ||
| 322 | 333 | ||
| 323 | switch (ret) { | 334 | switch (ret) { |
| 324 | case -EPROBE_DEFER: | 335 | case -EPROBE_DEFER: |
| @@ -529,6 +540,9 @@ static void __device_release_driver(struct device *dev) | |||
| 529 | devres_release_all(dev); | 540 | devres_release_all(dev); |
| 530 | dev->driver = NULL; | 541 | dev->driver = NULL; |
| 531 | dev_set_drvdata(dev, NULL); | 542 | dev_set_drvdata(dev, NULL); |
| 543 | if (dev->pm_domain && dev->pm_domain->dismiss) | ||
| 544 | dev->pm_domain->dismiss(dev); | ||
| 545 | |||
| 532 | klist_remove(&dev->p->knode_driver); | 546 | klist_remove(&dev->p->knode_driver); |
| 533 | if (dev->bus) | 547 | if (dev->bus) |
| 534 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 548 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index e68ab79df28b..ebf034b97278 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -463,7 +463,7 @@ struct platform_device *platform_device_register_full( | |||
| 463 | goto err_alloc; | 463 | goto err_alloc; |
| 464 | 464 | ||
| 465 | pdev->dev.parent = pdevinfo->parent; | 465 | pdev->dev.parent = pdevinfo->parent; |
| 466 | ACPI_COMPANION_SET(&pdev->dev, pdevinfo->acpi_node.companion); | 466 | pdev->dev.fwnode = pdevinfo->fwnode; |
| 467 | 467 | ||
| 468 | if (pdevinfo->dma_mask) { | 468 | if (pdevinfo->dma_mask) { |
| 469 | /* | 469 | /* |
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 45937f88e77c..2327613d4539 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
| @@ -68,7 +68,36 @@ static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name) | |||
| 68 | return genpd; | 68 | return genpd; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | struct generic_pm_domain *dev_to_genpd(struct device *dev) | 71 | /* |
| 72 | * Get the generic PM domain for a particular struct device. | ||
| 73 | * This validates the struct device pointer, the PM domain pointer, | ||
| 74 | * and checks that the PM domain pointer is a real generic PM domain. | ||
| 75 | * Any failure results in NULL being returned. | ||
| 76 | */ | ||
| 77 | struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev) | ||
| 78 | { | ||
| 79 | struct generic_pm_domain *genpd = NULL, *gpd; | ||
| 80 | |||
| 81 | if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain)) | ||
| 82 | return NULL; | ||
| 83 | |||
| 84 | mutex_lock(&gpd_list_lock); | ||
| 85 | list_for_each_entry(gpd, &gpd_list, gpd_list_node) { | ||
| 86 | if (&gpd->domain == dev->pm_domain) { | ||
| 87 | genpd = gpd; | ||
| 88 | break; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | mutex_unlock(&gpd_list_lock); | ||
| 92 | |||
| 93 | return genpd; | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | ||
| 97 | * This should only be used where we are certain that the pm_domain | ||
| 98 | * attached to the device is a genpd domain. | ||
| 99 | */ | ||
| 100 | static struct generic_pm_domain *dev_to_genpd(struct device *dev) | ||
| 72 | { | 101 | { |
| 73 | if (IS_ERR_OR_NULL(dev->pm_domain)) | 102 | if (IS_ERR_OR_NULL(dev->pm_domain)) |
| 74 | return ERR_PTR(-EINVAL); | 103 | return ERR_PTR(-EINVAL); |
| @@ -173,8 +202,8 @@ static int genpd_power_on(struct generic_pm_domain *genpd) | |||
| 173 | genpd->power_on_latency_ns = elapsed_ns; | 202 | genpd->power_on_latency_ns = elapsed_ns; |
| 174 | genpd->max_off_time_changed = true; | 203 | genpd->max_off_time_changed = true; |
| 175 | genpd_recalc_cpu_exit_latency(genpd); | 204 | genpd_recalc_cpu_exit_latency(genpd); |
| 176 | pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", | 205 | pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", |
| 177 | genpd->name, "on", elapsed_ns); | 206 | genpd->name, "on", elapsed_ns); |
| 178 | 207 | ||
| 179 | return ret; | 208 | return ret; |
| 180 | } | 209 | } |
| @@ -199,8 +228,8 @@ static int genpd_power_off(struct generic_pm_domain *genpd) | |||
| 199 | 228 | ||
| 200 | genpd->power_off_latency_ns = elapsed_ns; | 229 | genpd->power_off_latency_ns = elapsed_ns; |
| 201 | genpd->max_off_time_changed = true; | 230 | genpd->max_off_time_changed = true; |
| 202 | pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", | 231 | pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", |
| 203 | genpd->name, "off", elapsed_ns); | 232 | genpd->name, "off", elapsed_ns); |
| 204 | 233 | ||
| 205 | return ret; | 234 | return ret; |
| 206 | } | 235 | } |
| @@ -1513,9 +1542,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd, | |||
| 1513 | 1542 | ||
| 1514 | dev_dbg(dev, "%s()\n", __func__); | 1543 | dev_dbg(dev, "%s()\n", __func__); |
| 1515 | 1544 | ||
| 1516 | if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev) | 1545 | if (!genpd || genpd != pm_genpd_lookup_dev(dev)) |
| 1517 | || IS_ERR_OR_NULL(dev->pm_domain) | ||
| 1518 | || pd_to_genpd(dev->pm_domain) != genpd) | ||
| 1519 | return -EINVAL; | 1546 | return -EINVAL; |
| 1520 | 1547 | ||
| 1521 | /* The above validation also means we have existing domain_data. */ | 1548 | /* The above validation also means we have existing domain_data. */ |
| @@ -2093,21 +2120,10 @@ EXPORT_SYMBOL_GPL(of_genpd_get_from_provider); | |||
| 2093 | */ | 2120 | */ |
| 2094 | static void genpd_dev_pm_detach(struct device *dev, bool power_off) | 2121 | static void genpd_dev_pm_detach(struct device *dev, bool power_off) |
| 2095 | { | 2122 | { |
| 2096 | struct generic_pm_domain *pd = NULL, *gpd; | 2123 | struct generic_pm_domain *pd; |
| 2097 | int ret = 0; | 2124 | int ret = 0; |
| 2098 | 2125 | ||
| 2099 | if (!dev->pm_domain) | 2126 | pd = pm_genpd_lookup_dev(dev); |
| 2100 | return; | ||
| 2101 | |||
| 2102 | mutex_lock(&gpd_list_lock); | ||
| 2103 | list_for_each_entry(gpd, &gpd_list, gpd_list_node) { | ||
| 2104 | if (&gpd->domain == dev->pm_domain) { | ||
| 2105 | pd = gpd; | ||
| 2106 | break; | ||
| 2107 | } | ||
| 2108 | } | ||
| 2109 | mutex_unlock(&gpd_list_lock); | ||
| 2110 | |||
| 2111 | if (!pd) | 2127 | if (!pd) |
| 2112 | return; | 2128 | return; |
| 2113 | 2129 | ||
| @@ -2130,6 +2146,17 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) | |||
| 2130 | genpd_queue_power_off_work(pd); | 2146 | genpd_queue_power_off_work(pd); |
| 2131 | } | 2147 | } |
| 2132 | 2148 | ||
| 2149 | static void genpd_dev_pm_sync(struct device *dev) | ||
| 2150 | { | ||
| 2151 | struct generic_pm_domain *pd; | ||
| 2152 | |||
| 2153 | pd = dev_to_genpd(dev); | ||
| 2154 | if (IS_ERR(pd)) | ||
| 2155 | return; | ||
| 2156 | |||
| 2157 | genpd_queue_power_off_work(pd); | ||
| 2158 | } | ||
| 2159 | |||
| 2133 | /** | 2160 | /** |
| 2134 | * genpd_dev_pm_attach - Attach a device to its PM domain using DT. | 2161 | * genpd_dev_pm_attach - Attach a device to its PM domain using DT. |
| 2135 | * @dev: Device to attach. | 2162 | * @dev: Device to attach. |
| @@ -2196,6 +2223,7 @@ int genpd_dev_pm_attach(struct device *dev) | |||
| 2196 | } | 2223 | } |
| 2197 | 2224 | ||
| 2198 | dev->pm_domain->detach = genpd_dev_pm_detach; | 2225 | dev->pm_domain->detach = genpd_dev_pm_detach; |
| 2226 | dev->pm_domain->sync = genpd_dev_pm_sync; | ||
| 2199 | pm_genpd_poweron(pd); | 2227 | pm_genpd_poweron(pd); |
| 2200 | 2228 | ||
| 2201 | return 0; | 2229 | return 0; |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 9717d5f20139..3d874eca7104 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
| 24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
| 25 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
| 26 | #include <linux/resume-trace.h> | 26 | #include <linux/pm-trace.h> |
| 27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
| 28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
| 29 | #include <linux/async.h> | 29 | #include <linux/async.h> |
| @@ -1017,6 +1017,9 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a | |||
| 1017 | char *info = NULL; | 1017 | char *info = NULL; |
| 1018 | int error = 0; | 1018 | int error = 0; |
| 1019 | 1019 | ||
| 1020 | TRACE_DEVICE(dev); | ||
| 1021 | TRACE_SUSPEND(0); | ||
| 1022 | |||
| 1020 | if (async_error) | 1023 | if (async_error) |
| 1021 | goto Complete; | 1024 | goto Complete; |
| 1022 | 1025 | ||
| @@ -1057,6 +1060,7 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a | |||
| 1057 | 1060 | ||
| 1058 | Complete: | 1061 | Complete: |
| 1059 | complete_all(&dev->power.completion); | 1062 | complete_all(&dev->power.completion); |
| 1063 | TRACE_SUSPEND(error); | ||
| 1060 | return error; | 1064 | return error; |
| 1061 | } | 1065 | } |
| 1062 | 1066 | ||
| @@ -1078,7 +1082,7 @@ static int device_suspend_noirq(struct device *dev) | |||
| 1078 | { | 1082 | { |
| 1079 | reinit_completion(&dev->power.completion); | 1083 | reinit_completion(&dev->power.completion); |
| 1080 | 1084 | ||
| 1081 | if (pm_async_enabled && dev->power.async_suspend) { | 1085 | if (is_async(dev)) { |
| 1082 | get_device(dev); | 1086 | get_device(dev); |
| 1083 | async_schedule(async_suspend_noirq, dev); | 1087 | async_schedule(async_suspend_noirq, dev); |
| 1084 | return 0; | 1088 | return 0; |
| @@ -1157,6 +1161,9 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as | |||
| 1157 | char *info = NULL; | 1161 | char *info = NULL; |
| 1158 | int error = 0; | 1162 | int error = 0; |
| 1159 | 1163 | ||
| 1164 | TRACE_DEVICE(dev); | ||
| 1165 | TRACE_SUSPEND(0); | ||
| 1166 | |||
| 1160 | __pm_runtime_disable(dev, false); | 1167 | __pm_runtime_disable(dev, false); |
| 1161 | 1168 | ||
| 1162 | if (async_error) | 1169 | if (async_error) |
| @@ -1198,6 +1205,7 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as | |||
| 1198 | async_error = error; | 1205 | async_error = error; |
| 1199 | 1206 | ||
| 1200 | Complete: | 1207 | Complete: |
| 1208 | TRACE_SUSPEND(error); | ||
| 1201 | complete_all(&dev->power.completion); | 1209 | complete_all(&dev->power.completion); |
| 1202 | return error; | 1210 | return error; |
| 1203 | } | 1211 | } |
| @@ -1219,7 +1227,7 @@ static int device_suspend_late(struct device *dev) | |||
| 1219 | { | 1227 | { |
| 1220 | reinit_completion(&dev->power.completion); | 1228 | reinit_completion(&dev->power.completion); |
| 1221 | 1229 | ||
| 1222 | if (pm_async_enabled && dev->power.async_suspend) { | 1230 | if (is_async(dev)) { |
| 1223 | get_device(dev); | 1231 | get_device(dev); |
| 1224 | async_schedule(async_suspend_late, dev); | 1232 | async_schedule(async_suspend_late, dev); |
| 1225 | return 0; | 1233 | return 0; |
| @@ -1338,6 +1346,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
| 1338 | int error = 0; | 1346 | int error = 0; |
| 1339 | DECLARE_DPM_WATCHDOG_ON_STACK(wd); | 1347 | DECLARE_DPM_WATCHDOG_ON_STACK(wd); |
| 1340 | 1348 | ||
| 1349 | TRACE_DEVICE(dev); | ||
| 1350 | TRACE_SUSPEND(0); | ||
| 1351 | |||
| 1341 | dpm_wait_for_children(dev, async); | 1352 | dpm_wait_for_children(dev, async); |
| 1342 | 1353 | ||
| 1343 | if (async_error) | 1354 | if (async_error) |
| @@ -1444,6 +1455,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
| 1444 | if (error) | 1455 | if (error) |
| 1445 | async_error = error; | 1456 | async_error = error; |
| 1446 | 1457 | ||
| 1458 | TRACE_SUSPEND(error); | ||
| 1447 | return error; | 1459 | return error; |
| 1448 | } | 1460 | } |
| 1449 | 1461 | ||
| @@ -1465,7 +1477,7 @@ static int device_suspend(struct device *dev) | |||
| 1465 | { | 1477 | { |
| 1466 | reinit_completion(&dev->power.completion); | 1478 | reinit_completion(&dev->power.completion); |
| 1467 | 1479 | ||
| 1468 | if (pm_async_enabled && dev->power.async_suspend) { | 1480 | if (is_async(dev)) { |
| 1469 | get_device(dev); | 1481 | get_device(dev); |
| 1470 | async_schedule(async_suspend, dev); | 1482 | async_schedule(async_suspend, dev); |
| 1471 | return 0; | 1483 | return 0; |
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index d94a1f5121cf..a311cfa4c5bd 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | * devices may be working. | 7 | * devices may be working. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/resume-trace.h> | 10 | #include <linux/pm-trace.h> |
| 11 | #include <linux/export.h> | 11 | #include <linux/export.h> |
| 12 | #include <linux/rtc.h> | 12 | #include <linux/rtc.h> |
| 13 | 13 | ||
| @@ -154,7 +154,7 @@ EXPORT_SYMBOL(set_trace_device); | |||
| 154 | * it's not any guarantee, but it's a high _likelihood_ that | 154 | * it's not any guarantee, but it's a high _likelihood_ that |
| 155 | * the match is valid). | 155 | * the match is valid). |
| 156 | */ | 156 | */ |
| 157 | void generate_resume_trace(const void *tracedata, unsigned int user) | 157 | void generate_pm_trace(const void *tracedata, unsigned int user) |
| 158 | { | 158 | { |
| 159 | unsigned short lineno = *(unsigned short *)tracedata; | 159 | unsigned short lineno = *(unsigned short *)tracedata; |
| 160 | const char *file = *(const char **)(tracedata + 2); | 160 | const char *file = *(const char **)(tracedata + 2); |
| @@ -164,7 +164,7 @@ void generate_resume_trace(const void *tracedata, unsigned int user) | |||
| 164 | file_hash_value = hash_string(lineno, file, FILEHASH); | 164 | file_hash_value = hash_string(lineno, file, FILEHASH); |
| 165 | set_magic_time(user_hash_value, file_hash_value, dev_hash_value); | 165 | set_magic_time(user_hash_value, file_hash_value, dev_hash_value); |
| 166 | } | 166 | } |
| 167 | EXPORT_SYMBOL(generate_resume_trace); | 167 | EXPORT_SYMBOL(generate_pm_trace); |
| 168 | 168 | ||
| 169 | extern char __tracedata_start, __tracedata_end; | 169 | extern char __tracedata_start, __tracedata_end; |
| 170 | static int show_file_hash(unsigned int value) | 170 | static int show_file_hash(unsigned int value) |
diff --git a/drivers/base/property.c b/drivers/base/property.c index 423df593f262..1d0b116cae95 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c | |||
| @@ -10,10 +10,102 @@ | |||
| 10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/property.h> | ||
| 14 | #include <linux/export.h> | ||
| 15 | #include <linux/acpi.h> | 13 | #include <linux/acpi.h> |
| 14 | #include <linux/export.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
| 17 | #include <linux/property.h> | ||
| 18 | |||
| 19 | /** | ||
| 20 | * device_add_property_set - Add a collection of properties to a device object. | ||
| 21 | * @dev: Device to add properties to. | ||
| 22 | * @pset: Collection of properties to add. | ||
| 23 | * | ||
| 24 | * Associate a collection of device properties represented by @pset with @dev | ||
| 25 | * as its secondary firmware node. | ||
| 26 | */ | ||
| 27 | void device_add_property_set(struct device *dev, struct property_set *pset) | ||
| 28 | { | ||
| 29 | if (pset) | ||
| 30 | pset->fwnode.type = FWNODE_PDATA; | ||
| 31 | |||
| 32 | set_secondary_fwnode(dev, &pset->fwnode); | ||
| 33 | } | ||
| 34 | EXPORT_SYMBOL_GPL(device_add_property_set); | ||
| 35 | |||
| 36 | static inline bool is_pset(struct fwnode_handle *fwnode) | ||
| 37 | { | ||
| 38 | return fwnode && fwnode->type == FWNODE_PDATA; | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline struct property_set *to_pset(struct fwnode_handle *fwnode) | ||
| 42 | { | ||
| 43 | return is_pset(fwnode) ? | ||
| 44 | container_of(fwnode, struct property_set, fwnode) : NULL; | ||
| 45 | } | ||
| 46 | |||
| 47 | static struct property_entry *pset_prop_get(struct property_set *pset, | ||
| 48 | const char *name) | ||
| 49 | { | ||
| 50 | struct property_entry *prop; | ||
| 51 | |||
| 52 | if (!pset || !pset->properties) | ||
| 53 | return NULL; | ||
| 54 | |||
| 55 | for (prop = pset->properties; prop->name; prop++) | ||
| 56 | if (!strcmp(name, prop->name)) | ||
| 57 | return prop; | ||
| 58 | |||
| 59 | return NULL; | ||
| 60 | } | ||
| 61 | |||
| 62 | static int pset_prop_read_array(struct property_set *pset, const char *name, | ||
| 63 | enum dev_prop_type type, void *val, size_t nval) | ||
| 64 | { | ||
| 65 | struct property_entry *prop; | ||
| 66 | unsigned int item_size; | ||
| 67 | |||
| 68 | prop = pset_prop_get(pset, name); | ||
| 69 | if (!prop) | ||
| 70 | return -ENODATA; | ||
| 71 | |||
| 72 | if (prop->type != type) | ||
| 73 | return -EPROTO; | ||
| 74 | |||
| 75 | if (!val) | ||
| 76 | return prop->nval; | ||
| 77 | |||
| 78 | if (prop->nval < nval) | ||
| 79 | return -EOVERFLOW; | ||
| 80 | |||
| 81 | switch (type) { | ||
| 82 | case DEV_PROP_U8: | ||
| 83 | item_size = sizeof(u8); | ||
| 84 | break; | ||
| 85 | case DEV_PROP_U16: | ||
| 86 | item_size = sizeof(u16); | ||
| 87 | break; | ||
| 88 | case DEV_PROP_U32: | ||
| 89 | item_size = sizeof(u32); | ||
| 90 | break; | ||
| 91 | case DEV_PROP_U64: | ||
| 92 | item_size = sizeof(u64); | ||
| 93 | break; | ||
| 94 | case DEV_PROP_STRING: | ||
| 95 | item_size = sizeof(const char *); | ||
| 96 | break; | ||
| 97 | default: | ||
| 98 | return -EINVAL; | ||
| 99 | } | ||
| 100 | memcpy(val, prop->value.raw_data, nval * item_size); | ||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static inline struct fwnode_handle *dev_fwnode(struct device *dev) | ||
| 105 | { | ||
| 106 | return IS_ENABLED(CONFIG_OF) && dev->of_node ? | ||
| 107 | &dev->of_node->fwnode : dev->fwnode; | ||
| 108 | } | ||
| 17 | 109 | ||
| 18 | /** | 110 | /** |
| 19 | * device_property_present - check if a property of a device is present | 111 | * device_property_present - check if a property of a device is present |
| @@ -24,10 +116,7 @@ | |||
| 24 | */ | 116 | */ |
| 25 | bool device_property_present(struct device *dev, const char *propname) | 117 | bool device_property_present(struct device *dev, const char *propname) |
| 26 | { | 118 | { |
| 27 | if (IS_ENABLED(CONFIG_OF) && dev->of_node) | 119 | return fwnode_property_present(dev_fwnode(dev), propname); |
| 28 | return of_property_read_bool(dev->of_node, propname); | ||
| 29 | |||
| 30 | return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL); | ||
| 31 | } | 120 | } |
| 32 | EXPORT_SYMBOL_GPL(device_property_present); | 121 | EXPORT_SYMBOL_GPL(device_property_present); |
| 33 | 122 | ||
| @@ -43,32 +132,22 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname) | |||
| 43 | else if (is_acpi_node(fwnode)) | 132 | else if (is_acpi_node(fwnode)) |
| 44 | return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL); | 133 | return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL); |
| 45 | 134 | ||
| 46 | return false; | 135 | return !!pset_prop_get(to_pset(fwnode), propname); |
| 47 | } | 136 | } |
| 48 | EXPORT_SYMBOL_GPL(fwnode_property_present); | 137 | EXPORT_SYMBOL_GPL(fwnode_property_present); |
| 49 | 138 | ||
| 50 | #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ | ||
| 51 | (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ | ||
| 52 | : of_property_count_elems_of_size((node), (propname), sizeof(type)) | ||
| 53 | |||
| 54 | #define DEV_PROP_READ_ARRAY(_dev_, _propname_, _type_, _proptype_, _val_, _nval_) \ | ||
| 55 | IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \ | ||
| 56 | (OF_DEV_PROP_READ_ARRAY(_dev_->of_node, _propname_, _type_, \ | ||
| 57 | _val_, _nval_)) : \ | ||
| 58 | acpi_dev_prop_read(ACPI_COMPANION(_dev_), _propname_, \ | ||
| 59 | _proptype_, _val_, _nval_) | ||
| 60 | |||
| 61 | /** | 139 | /** |
| 62 | * device_property_read_u8_array - return a u8 array property of a device | 140 | * device_property_read_u8_array - return a u8 array property of a device |
| 63 | * @dev: Device to get the property of | 141 | * @dev: Device to get the property of |
| 64 | * @propname: Name of the property | 142 | * @propname: Name of the property |
| 65 | * @val: The values are stored here | 143 | * @val: The values are stored here or %NULL to return the number of values |
| 66 | * @nval: Size of the @val array | 144 | * @nval: Size of the @val array |
| 67 | * | 145 | * |
| 68 | * Function reads an array of u8 properties with @propname from the device | 146 | * Function reads an array of u8 properties with @propname from the device |
| 69 | * firmware description and stores them to @val if found. | 147 | * firmware description and stores them to @val if found. |
| 70 | * | 148 | * |
| 71 | * Return: %0 if the property was found (success), | 149 | * Return: number of values if @val was %NULL, |
| 150 | * %0 if the property was found (success), | ||
| 72 | * %-EINVAL if given arguments are not valid, | 151 | * %-EINVAL if given arguments are not valid, |
| 73 | * %-ENODATA if the property does not have a value, | 152 | * %-ENODATA if the property does not have a value, |
| 74 | * %-EPROTO if the property is not an array of numbers, | 153 | * %-EPROTO if the property is not an array of numbers, |
| @@ -77,7 +156,7 @@ EXPORT_SYMBOL_GPL(fwnode_property_present); | |||
| 77 | int device_property_read_u8_array(struct device *dev, const char *propname, | 156 | int device_property_read_u8_array(struct device *dev, const char *propname, |
| 78 | u8 *val, size_t nval) | 157 | u8 *val, size_t nval) |
| 79 | { | 158 | { |
| 80 | return DEV_PROP_READ_ARRAY(dev, propname, u8, DEV_PROP_U8, val, nval); | 159 | return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval); |
| 81 | } | 160 | } |
| 82 | EXPORT_SYMBOL_GPL(device_property_read_u8_array); | 161 | EXPORT_SYMBOL_GPL(device_property_read_u8_array); |
| 83 | 162 | ||
| @@ -85,13 +164,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u8_array); | |||
| 85 | * device_property_read_u16_array - return a u16 array property of a device | 164 | * device_property_read_u16_array - return a u16 array property of a device |
| 86 | * @dev: Device to get the property of | 165 | * @dev: Device to get the property of |
| 87 | * @propname: Name of the property | 166 | * @propname: Name of the property |
| 88 | * @val: The values are stored here | 167 | * @val: The values are stored here or %NULL to return the number of values |
| 89 | * @nval: Size of the @val array | 168 | * @nval: Size of the @val array |
| 90 | * | 169 | * |
| 91 | * Function reads an array of u16 properties with @propname from the device | 170 | * Function reads an array of u16 properties with @propname from the device |
| 92 | * firmware description and stores them to @val if found. | 171 | * firmware description and stores them to @val if found. |
| 93 | * | 172 | * |
| 94 | * Return: %0 if the property was found (success), | 173 | * Return: number of values if @val was %NULL, |
| 174 | * %0 if the property was found (success), | ||
| 95 | * %-EINVAL if given arguments are not valid, | 175 | * %-EINVAL if given arguments are not valid, |
| 96 | * %-ENODATA if the property does not have a value, | 176 | * %-ENODATA if the property does not have a value, |
| 97 | * %-EPROTO if the property is not an array of numbers, | 177 | * %-EPROTO if the property is not an array of numbers, |
| @@ -100,7 +180,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u8_array); | |||
| 100 | int device_property_read_u16_array(struct device *dev, const char *propname, | 180 | int device_property_read_u16_array(struct device *dev, const char *propname, |
| 101 | u16 *val, size_t nval) | 181 | u16 *val, size_t nval) |
| 102 | { | 182 | { |
| 103 | return DEV_PROP_READ_ARRAY(dev, propname, u16, DEV_PROP_U16, val, nval); | 183 | return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval); |
| 104 | } | 184 | } |
| 105 | EXPORT_SYMBOL_GPL(device_property_read_u16_array); | 185 | EXPORT_SYMBOL_GPL(device_property_read_u16_array); |
| 106 | 186 | ||
| @@ -108,13 +188,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u16_array); | |||
| 108 | * device_property_read_u32_array - return a u32 array property of a device | 188 | * device_property_read_u32_array - return a u32 array property of a device |
| 109 | * @dev: Device to get the property of | 189 | * @dev: Device to get the property of |
| 110 | * @propname: Name of the property | 190 | * @propname: Name of the property |
| 111 | * @val: The values are stored here | 191 | * @val: The values are stored here or %NULL to return the number of values |
| 112 | * @nval: Size of the @val array | 192 | * @nval: Size of the @val array |
| 113 | * | 193 | * |
| 114 | * Function reads an array of u32 properties with @propname from the device | 194 | * Function reads an array of u32 properties with @propname from the device |
| 115 | * firmware description and stores them to @val if found. | 195 | * firmware description and stores them to @val if found. |
| 116 | * | 196 | * |
| 117 | * Return: %0 if the property was found (success), | 197 | * Return: number of values if @val was %NULL, |
| 198 | * %0 if the property was found (success), | ||
| 118 | * %-EINVAL if given arguments are not valid, | 199 | * %-EINVAL if given arguments are not valid, |
| 119 | * %-ENODATA if the property does not have a value, | 200 | * %-ENODATA if the property does not have a value, |
| 120 | * %-EPROTO if the property is not an array of numbers, | 201 | * %-EPROTO if the property is not an array of numbers, |
| @@ -123,7 +204,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u16_array); | |||
| 123 | int device_property_read_u32_array(struct device *dev, const char *propname, | 204 | int device_property_read_u32_array(struct device *dev, const char *propname, |
| 124 | u32 *val, size_t nval) | 205 | u32 *val, size_t nval) |
| 125 | { | 206 | { |
| 126 | return DEV_PROP_READ_ARRAY(dev, propname, u32, DEV_PROP_U32, val, nval); | 207 | return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval); |
| 127 | } | 208 | } |
| 128 | EXPORT_SYMBOL_GPL(device_property_read_u32_array); | 209 | EXPORT_SYMBOL_GPL(device_property_read_u32_array); |
| 129 | 210 | ||
| @@ -131,13 +212,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u32_array); | |||
| 131 | * device_property_read_u64_array - return a u64 array property of a device | 212 | * device_property_read_u64_array - return a u64 array property of a device |
| 132 | * @dev: Device to get the property of | 213 | * @dev: Device to get the property of |
| 133 | * @propname: Name of the property | 214 | * @propname: Name of the property |
| 134 | * @val: The values are stored here | 215 | * @val: The values are stored here or %NULL to return the number of values |
| 135 | * @nval: Size of the @val array | 216 | * @nval: Size of the @val array |
| 136 | * | 217 | * |
| 137 | * Function reads an array of u64 properties with @propname from the device | 218 | * Function reads an array of u64 properties with @propname from the device |
| 138 | * firmware description and stores them to @val if found. | 219 | * firmware description and stores them to @val if found. |
| 139 | * | 220 | * |
| 140 | * Return: %0 if the property was found (success), | 221 | * Return: number of values if @val was %NULL, |
| 222 | * %0 if the property was found (success), | ||
| 141 | * %-EINVAL if given arguments are not valid, | 223 | * %-EINVAL if given arguments are not valid, |
| 142 | * %-ENODATA if the property does not have a value, | 224 | * %-ENODATA if the property does not have a value, |
| 143 | * %-EPROTO if the property is not an array of numbers, | 225 | * %-EPROTO if the property is not an array of numbers, |
| @@ -146,7 +228,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u32_array); | |||
| 146 | int device_property_read_u64_array(struct device *dev, const char *propname, | 228 | int device_property_read_u64_array(struct device *dev, const char *propname, |
| 147 | u64 *val, size_t nval) | 229 | u64 *val, size_t nval) |
| 148 | { | 230 | { |
| 149 | return DEV_PROP_READ_ARRAY(dev, propname, u64, DEV_PROP_U64, val, nval); | 231 | return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval); |
| 150 | } | 232 | } |
| 151 | EXPORT_SYMBOL_GPL(device_property_read_u64_array); | 233 | EXPORT_SYMBOL_GPL(device_property_read_u64_array); |
| 152 | 234 | ||
| @@ -154,13 +236,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u64_array); | |||
| 154 | * device_property_read_string_array - return a string array property of device | 236 | * device_property_read_string_array - return a string array property of device |
| 155 | * @dev: Device to get the property of | 237 | * @dev: Device to get the property of |
| 156 | * @propname: Name of the property | 238 | * @propname: Name of the property |
| 157 | * @val: The values are stored here | 239 | * @val: The values are stored here or %NULL to return the number of values |
| 158 | * @nval: Size of the @val array | 240 | * @nval: Size of the @val array |
| 159 | * | 241 | * |
| 160 | * Function reads an array of string properties with @propname from the device | 242 | * Function reads an array of string properties with @propname from the device |
| 161 | * firmware description and stores them to @val if found. | 243 | * firmware description and stores them to @val if found. |
| 162 | * | 244 | * |
| 163 | * Return: %0 if the property was found (success), | 245 | * Return: number of values if @val was %NULL, |
| 246 | * %0 if the property was found (success), | ||
| 164 | * %-EINVAL if given arguments are not valid, | 247 | * %-EINVAL if given arguments are not valid, |
| 165 | * %-ENODATA if the property does not have a value, | 248 | * %-ENODATA if the property does not have a value, |
| 166 | * %-EPROTO or %-EILSEQ if the property is not an array of strings, | 249 | * %-EPROTO or %-EILSEQ if the property is not an array of strings, |
| @@ -169,10 +252,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u64_array); | |||
| 169 | int device_property_read_string_array(struct device *dev, const char *propname, | 252 | int device_property_read_string_array(struct device *dev, const char *propname, |
| 170 | const char **val, size_t nval) | 253 | const char **val, size_t nval) |
| 171 | { | 254 | { |
| 172 | return IS_ENABLED(CONFIG_OF) && dev->of_node ? | 255 | return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval); |
| 173 | of_property_read_string_array(dev->of_node, propname, val, nval) : | ||
| 174 | acpi_dev_prop_read(ACPI_COMPANION(dev), propname, | ||
| 175 | DEV_PROP_STRING, val, nval); | ||
| 176 | } | 256 | } |
| 177 | EXPORT_SYMBOL_GPL(device_property_read_string_array); | 257 | EXPORT_SYMBOL_GPL(device_property_read_string_array); |
| 178 | 258 | ||
| @@ -193,13 +273,14 @@ EXPORT_SYMBOL_GPL(device_property_read_string_array); | |||
| 193 | int device_property_read_string(struct device *dev, const char *propname, | 273 | int device_property_read_string(struct device *dev, const char *propname, |
| 194 | const char **val) | 274 | const char **val) |
| 195 | { | 275 | { |
| 196 | return IS_ENABLED(CONFIG_OF) && dev->of_node ? | 276 | return fwnode_property_read_string(dev_fwnode(dev), propname, val); |
| 197 | of_property_read_string(dev->of_node, propname, val) : | ||
| 198 | acpi_dev_prop_read(ACPI_COMPANION(dev), propname, | ||
| 199 | DEV_PROP_STRING, val, 1); | ||
| 200 | } | 277 | } |
| 201 | EXPORT_SYMBOL_GPL(device_property_read_string); | 278 | EXPORT_SYMBOL_GPL(device_property_read_string); |
| 202 | 279 | ||
| 280 | #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ | ||
| 281 | (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ | ||
| 282 | : of_property_count_elems_of_size((node), (propname), sizeof(type)) | ||
| 283 | |||
| 203 | #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ | 284 | #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ |
| 204 | ({ \ | 285 | ({ \ |
| 205 | int _ret_; \ | 286 | int _ret_; \ |
| @@ -210,7 +291,8 @@ EXPORT_SYMBOL_GPL(device_property_read_string); | |||
| 210 | _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \ | 291 | _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \ |
| 211 | _proptype_, _val_, _nval_); \ | 292 | _proptype_, _val_, _nval_); \ |
| 212 | else \ | 293 | else \ |
| 213 | _ret_ = -ENXIO; \ | 294 | _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \ |
| 295 | _proptype_, _val_, _nval_); \ | ||
| 214 | _ret_; \ | 296 | _ret_; \ |
| 215 | }) | 297 | }) |
| 216 | 298 | ||
| @@ -218,13 +300,14 @@ EXPORT_SYMBOL_GPL(device_property_read_string); | |||
| 218 | * fwnode_property_read_u8_array - return a u8 array property of firmware node | 300 | * fwnode_property_read_u8_array - return a u8 array property of firmware node |
| 219 | * @fwnode: Firmware node to get the property of | 301 | * @fwnode: Firmware node to get the property of |
| 220 | * @propname: Name of the property | 302 | * @propname: Name of the property |
| 221 | * @val: The values are stored here | 303 | * @val: The values are stored here or %NULL to return the number of values |
| 222 | * @nval: Size of the @val array | 304 | * @nval: Size of the @val array |
| 223 | * | 305 | * |
| 224 | * Read an array of u8 properties with @propname from @fwnode and stores them to | 306 | * Read an array of u8 properties with @propname from @fwnode and stores them to |
| 225 | * @val if found. | 307 | * @val if found. |
| 226 | * | 308 | * |
| 227 | * Return: %0 if the property was found (success), | 309 | * Return: number of values if @val was %NULL, |
| 310 | * %0 if the property was found (success), | ||
| 228 | * %-EINVAL if given arguments are not valid, | 311 | * %-EINVAL if given arguments are not valid, |
| 229 | * %-ENODATA if the property does not have a value, | 312 | * %-ENODATA if the property does not have a value, |
| 230 | * %-EPROTO if the property is not an array of numbers, | 313 | * %-EPROTO if the property is not an array of numbers, |
| @@ -243,13 +326,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array); | |||
| 243 | * fwnode_property_read_u16_array - return a u16 array property of firmware node | 326 | * fwnode_property_read_u16_array - return a u16 array property of firmware node |
| 244 | * @fwnode: Firmware node to get the property of | 327 | * @fwnode: Firmware node to get the property of |
| 245 | * @propname: Name of the property | 328 | * @propname: Name of the property |
| 246 | * @val: The values are stored here | 329 | * @val: The values are stored here or %NULL to return the number of values |
| 247 | * @nval: Size of the @val array | 330 | * @nval: Size of the @val array |
| 248 | * | 331 | * |
| 249 | * Read an array of u16 properties with @propname from @fwnode and store them to | 332 | * Read an array of u16 properties with @propname from @fwnode and store them to |
| 250 | * @val if found. | 333 | * @val if found. |
| 251 | * | 334 | * |
| 252 | * Return: %0 if the property was found (success), | 335 | * Return: number of values if @val was %NULL, |
| 336 | * %0 if the property was found (success), | ||
| 253 | * %-EINVAL if given arguments are not valid, | 337 | * %-EINVAL if given arguments are not valid, |
| 254 | * %-ENODATA if the property does not have a value, | 338 | * %-ENODATA if the property does not have a value, |
| 255 | * %-EPROTO if the property is not an array of numbers, | 339 | * %-EPROTO if the property is not an array of numbers, |
| @@ -268,13 +352,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array); | |||
| 268 | * fwnode_property_read_u32_array - return a u32 array property of firmware node | 352 | * fwnode_property_read_u32_array - return a u32 array property of firmware node |
| 269 | * @fwnode: Firmware node to get the property of | 353 | * @fwnode: Firmware node to get the property of |
| 270 | * @propname: Name of the property | 354 | * @propname: Name of the property |
| 271 | * @val: The values are stored here | 355 | * @val: The values are stored here or %NULL to return the number of values |
| 272 | * @nval: Size of the @val array | 356 | * @nval: Size of the @val array |
| 273 | * | 357 | * |
| 274 | * Read an array of u32 properties with @propname from @fwnode store them to | 358 | * Read an array of u32 properties with @propname from @fwnode store them to |
| 275 | * @val if found. | 359 | * @val if found. |
| 276 | * | 360 | * |
| 277 | * Return: %0 if the property was found (success), | 361 | * Return: number of values if @val was %NULL, |
| 362 | * %0 if the property was found (success), | ||
| 278 | * %-EINVAL if given arguments are not valid, | 363 | * %-EINVAL if given arguments are not valid, |
| 279 | * %-ENODATA if the property does not have a value, | 364 | * %-ENODATA if the property does not have a value, |
| 280 | * %-EPROTO if the property is not an array of numbers, | 365 | * %-EPROTO if the property is not an array of numbers, |
| @@ -293,13 +378,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array); | |||
| 293 | * fwnode_property_read_u64_array - return a u64 array property firmware node | 378 | * fwnode_property_read_u64_array - return a u64 array property firmware node |
| 294 | * @fwnode: Firmware node to get the property of | 379 | * @fwnode: Firmware node to get the property of |
| 295 | * @propname: Name of the property | 380 | * @propname: Name of the property |
| 296 | * @val: The values are stored here | 381 | * @val: The values are stored here or %NULL to return the number of values |
| 297 | * @nval: Size of the @val array | 382 | * @nval: Size of the @val array |
| 298 | * | 383 | * |
| 299 | * Read an array of u64 properties with @propname from @fwnode and store them to | 384 | * Read an array of u64 properties with @propname from @fwnode and store them to |
| 300 | * @val if found. | 385 | * @val if found. |
| 301 | * | 386 | * |
| 302 | * Return: %0 if the property was found (success), | 387 | * Return: number of values if @val was %NULL, |
| 388 | * %0 if the property was found (success), | ||
| 303 | * %-EINVAL if given arguments are not valid, | 389 | * %-EINVAL if given arguments are not valid, |
| 304 | * %-ENODATA if the property does not have a value, | 390 | * %-ENODATA if the property does not have a value, |
| 305 | * %-EPROTO if the property is not an array of numbers, | 391 | * %-EPROTO if the property is not an array of numbers, |
| @@ -318,13 +404,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array); | |||
| 318 | * fwnode_property_read_string_array - return string array property of a node | 404 | * fwnode_property_read_string_array - return string array property of a node |
| 319 | * @fwnode: Firmware node to get the property of | 405 | * @fwnode: Firmware node to get the property of |
| 320 | * @propname: Name of the property | 406 | * @propname: Name of the property |
| 321 | * @val: The values are stored here | 407 | * @val: The values are stored here or %NULL to return the number of values |
| 322 | * @nval: Size of the @val array | 408 | * @nval: Size of the @val array |
| 323 | * | 409 | * |
| 324 | * Read an string list property @propname from the given firmware node and store | 410 | * Read an string list property @propname from the given firmware node and store |
| 325 | * them to @val if found. | 411 | * them to @val if found. |
| 326 | * | 412 | * |
| 327 | * Return: %0 if the property was found (success), | 413 | * Return: number of values if @val was %NULL, |
| 414 | * %0 if the property was found (success), | ||
| 328 | * %-EINVAL if given arguments are not valid, | 415 | * %-EINVAL if given arguments are not valid, |
| 329 | * %-ENODATA if the property does not have a value, | 416 | * %-ENODATA if the property does not have a value, |
| 330 | * %-EPROTO if the property is not an array of strings, | 417 | * %-EPROTO if the property is not an array of strings, |
| @@ -336,13 +423,16 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode, | |||
| 336 | size_t nval) | 423 | size_t nval) |
| 337 | { | 424 | { |
| 338 | if (is_of_node(fwnode)) | 425 | if (is_of_node(fwnode)) |
| 339 | return of_property_read_string_array(of_node(fwnode), propname, | 426 | return val ? |
| 340 | val, nval); | 427 | of_property_read_string_array(of_node(fwnode), propname, |
| 428 | val, nval) : | ||
| 429 | of_property_count_strings(of_node(fwnode), propname); | ||
| 341 | else if (is_acpi_node(fwnode)) | 430 | else if (is_acpi_node(fwnode)) |
| 342 | return acpi_dev_prop_read(acpi_node(fwnode), propname, | 431 | return acpi_dev_prop_read(acpi_node(fwnode), propname, |
| 343 | DEV_PROP_STRING, val, nval); | 432 | DEV_PROP_STRING, val, nval); |
| 344 | 433 | ||
| 345 | return -ENXIO; | 434 | return pset_prop_read_array(to_pset(fwnode), propname, |
| 435 | DEV_PROP_STRING, val, nval); | ||
| 346 | } | 436 | } |
| 347 | EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); | 437 | EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); |
| 348 | 438 | ||
