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

Merge tag 'devprop-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull device properties framework updates from Rafael Wysocki:
"This introduces 'software nodes' that are analogous to the DT and ACPI
firmware nodes except that they can be created by drivers themselves
and do a couple of assorted cleanups.

Specifics:

- Introduce "software nodes", analogous to the DT and ACPI firmware
nodes except that they can be created by kernel code, in order to
complement fwnodes representing real firmware nodes when they are
incomplete (for example missing device properties) and to supply
the primary fwnode when the firmware lacks hardware description for
a device completely, and replace the "property_set" struct
fwnode_handle type with software nodes (Heikki Krogerus).

- Clean up the just introduced software nodes support and fix a
commet in the graph-handling code (Colin Ian King, Marco Felsch)"

* tag 'devprop-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
device property: fix fwnode_graph_get_next_endpoint() documentation
drivers: base: swnode: remove need for a temporary string for the node name
device property: Remove struct property_set
device property: Move device_add_properties() to swnode.c
drivers: base: Introducing software nodes to the firmware node framework
ACPI / glue: Add acpi_platform_notify() function
drivers core: Prepare support for multiple platform notifications
driver core: platform: Remove duplicated device_remove_properties() call

+766 -514
+10
Documentation/ABI/testing/sysfs-devices-software_node
··· 1 + What: /sys/devices/.../software_node/ 2 + Date: January 2019 3 + Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> 4 + Description: 5 + This directory contains the details about the device that are 6 + assigned in kernel (i.e. software), as opposed to the 7 + firmware_node directory which contains the details that are 8 + assigned for the device in firmware. The main attributes in the 9 + directory will show the properties the device has, and the 10 + relationship it has to some of the other devices.
-1
drivers/acpi/bus.c
··· 1237 1237 acpi_kobj = NULL; 1238 1238 } 1239 1239 1240 - init_acpi_device_notify(); 1241 1240 result = acpi_bus_init(); 1242 1241 if (result) { 1243 1242 disable_acpi();
+13 -8
drivers/acpi/glue.c
··· 296 296 } 297 297 EXPORT_SYMBOL_GPL(acpi_unbind_one); 298 298 299 - static int acpi_platform_notify(struct device *dev) 299 + static int acpi_device_notify(struct device *dev) 300 300 { 301 301 struct acpi_bus_type *type = acpi_get_bus_type(dev); 302 302 struct acpi_device *adev; ··· 343 343 return ret; 344 344 } 345 345 346 - static int acpi_platform_notify_remove(struct device *dev) 346 + static int acpi_device_notify_remove(struct device *dev) 347 347 { 348 348 struct acpi_device *adev = ACPI_COMPANION(dev); 349 349 struct acpi_bus_type *type; ··· 361 361 return 0; 362 362 } 363 363 364 - void __init init_acpi_device_notify(void) 364 + int acpi_platform_notify(struct device *dev, enum kobject_action action) 365 365 { 366 - if (platform_notify || platform_notify_remove) { 367 - printk(KERN_ERR PREFIX "Can't use platform_notify\n"); 368 - return; 366 + switch (action) { 367 + case KOBJ_ADD: 368 + acpi_device_notify(dev); 369 + break; 370 + case KOBJ_REMOVE: 371 + acpi_device_notify_remove(dev); 372 + break; 373 + default: 374 + break; 369 375 } 370 - platform_notify = acpi_platform_notify; 371 - platform_notify_remove = acpi_platform_notify_remove; 376 + return 0; 372 377 }
-1
drivers/acpi/internal.h
··· 23 23 int early_acpi_osi_init(void); 24 24 int acpi_osi_init(void); 25 25 acpi_status acpi_os_initialize1(void); 26 - void init_acpi_device_notify(void); 27 26 int acpi_scan_init(void); 28 27 #ifdef CONFIG_PCI 29 28 void acpi_pci_root_init(void);
+1 -1
drivers/base/Makefile
··· 6 6 cpu.o firmware.o init.o map.o devres.o \ 7 7 attribute_container.o transport_class.o \ 8 8 topology.o container.o property.o cacheinfo.o \ 9 - devcon.o 9 + devcon.o swnode.o 10 10 obj-$(CONFIG_DEVTMPFS) += devtmpfs.o 11 11 obj-y += power/ 12 12 obj-$(CONFIG_ISA_BUS_API) += isa.o
+27 -7
drivers/base/core.c
··· 8 8 * Copyright (c) 2006 Novell, Inc. 9 9 */ 10 10 11 + #include <linux/acpi.h> 11 12 #include <linux/device.h> 12 13 #include <linux/err.h> 13 14 #include <linux/fwnode.h> ··· 728 727 return 1; 729 728 } 730 729 #endif 730 + 731 + static int 732 + device_platform_notify(struct device *dev, enum kobject_action action) 733 + { 734 + int ret; 735 + 736 + ret = acpi_platform_notify(dev, action); 737 + if (ret) 738 + return ret; 739 + 740 + ret = software_node_notify(dev, action); 741 + if (ret) 742 + return ret; 743 + 744 + if (platform_notify && action == KOBJ_ADD) 745 + platform_notify(dev); 746 + else if (platform_notify_remove && action == KOBJ_REMOVE) 747 + platform_notify_remove(dev); 748 + return 0; 749 + } 731 750 732 751 /** 733 752 * dev_driver_string - Return a device's driver name, if at all possible ··· 1904 1883 } 1905 1884 1906 1885 /* notify platform of device entry */ 1907 - if (platform_notify) 1908 - platform_notify(dev); 1886 + error = device_platform_notify(dev, KOBJ_ADD); 1887 + if (error) 1888 + goto platform_error; 1909 1889 1910 1890 error = device_create_file(dev, &dev_attr_uevent); 1911 1891 if (error) ··· 1982 1960 SymlinkError: 1983 1961 device_remove_file(dev, &dev_attr_uevent); 1984 1962 attrError: 1963 + device_platform_notify(dev, KOBJ_REMOVE); 1964 + platform_error: 1985 1965 kobject_uevent(&dev->kobj, KOBJ_REMOVE); 1986 1966 glue_dir = get_glue_dir(dev); 1987 1967 kobject_del(&dev->kobj); ··· 2101 2077 bus_remove_device(dev); 2102 2078 device_pm_remove(dev); 2103 2079 driver_deferred_probe_del(dev); 2080 + device_platform_notify(dev, KOBJ_REMOVE); 2104 2081 device_remove_properties(dev); 2105 2082 device_links_purge(dev); 2106 2083 2107 - /* Notify the platform of the removal, in case they 2108 - * need to do anything... 2109 - */ 2110 - if (platform_notify_remove) 2111 - platform_notify_remove(dev); 2112 2084 if (dev->bus) 2113 2085 blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 2114 2086 BUS_NOTIFY_REMOVED_DEVICE, dev);
-1
drivers/base/platform.c
··· 448 448 int i; 449 449 450 450 if (pdev) { 451 - device_remove_properties(&pdev->dev); 452 451 device_del(&pdev->dev); 453 452 454 453 if (pdev->id_auto) {
+18 -495
drivers/base/property.c
··· 18 18 #include <linux/etherdevice.h> 19 19 #include <linux/phy.h> 20 20 21 - struct property_set { 22 - struct device *dev; 23 - struct fwnode_handle fwnode; 24 - const struct property_entry *properties; 25 - }; 26 - 27 - static const struct fwnode_operations pset_fwnode_ops; 28 - 29 - static inline bool is_pset_node(const struct fwnode_handle *fwnode) 30 - { 31 - return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &pset_fwnode_ops; 32 - } 33 - 34 - #define to_pset_node(__fwnode) \ 35 - ({ \ 36 - typeof(__fwnode) __to_pset_node_fwnode = __fwnode; \ 37 - \ 38 - is_pset_node(__to_pset_node_fwnode) ? \ 39 - container_of(__to_pset_node_fwnode, \ 40 - struct property_set, fwnode) : \ 41 - NULL; \ 42 - }) 43 - 44 - static const struct property_entry * 45 - pset_prop_get(const struct property_set *pset, const char *name) 46 - { 47 - const struct property_entry *prop; 48 - 49 - if (!pset || !pset->properties) 50 - return NULL; 51 - 52 - for (prop = pset->properties; prop->name; prop++) 53 - if (!strcmp(name, prop->name)) 54 - return prop; 55 - 56 - return NULL; 57 - } 58 - 59 - static const void *property_get_pointer(const struct property_entry *prop) 60 - { 61 - switch (prop->type) { 62 - case DEV_PROP_U8: 63 - if (prop->is_array) 64 - return prop->pointer.u8_data; 65 - return &prop->value.u8_data; 66 - case DEV_PROP_U16: 67 - if (prop->is_array) 68 - return prop->pointer.u16_data; 69 - return &prop->value.u16_data; 70 - case DEV_PROP_U32: 71 - if (prop->is_array) 72 - return prop->pointer.u32_data; 73 - return &prop->value.u32_data; 74 - case DEV_PROP_U64: 75 - if (prop->is_array) 76 - return prop->pointer.u64_data; 77 - return &prop->value.u64_data; 78 - case DEV_PROP_STRING: 79 - if (prop->is_array) 80 - return prop->pointer.str; 81 - return &prop->value.str; 82 - default: 83 - return NULL; 84 - } 85 - } 86 - 87 - static void property_set_pointer(struct property_entry *prop, const void *pointer) 88 - { 89 - switch (prop->type) { 90 - case DEV_PROP_U8: 91 - if (prop->is_array) 92 - prop->pointer.u8_data = pointer; 93 - else 94 - prop->value.u8_data = *((u8 *)pointer); 95 - break; 96 - case DEV_PROP_U16: 97 - if (prop->is_array) 98 - prop->pointer.u16_data = pointer; 99 - else 100 - prop->value.u16_data = *((u16 *)pointer); 101 - break; 102 - case DEV_PROP_U32: 103 - if (prop->is_array) 104 - prop->pointer.u32_data = pointer; 105 - else 106 - prop->value.u32_data = *((u32 *)pointer); 107 - break; 108 - case DEV_PROP_U64: 109 - if (prop->is_array) 110 - prop->pointer.u64_data = pointer; 111 - else 112 - prop->value.u64_data = *((u64 *)pointer); 113 - break; 114 - case DEV_PROP_STRING: 115 - if (prop->is_array) 116 - prop->pointer.str = pointer; 117 - else 118 - prop->value.str = pointer; 119 - break; 120 - default: 121 - break; 122 - } 123 - } 124 - 125 - static const void *pset_prop_find(const struct property_set *pset, 126 - const char *propname, size_t length) 127 - { 128 - const struct property_entry *prop; 129 - const void *pointer; 130 - 131 - prop = pset_prop_get(pset, propname); 132 - if (!prop) 133 - return ERR_PTR(-EINVAL); 134 - pointer = property_get_pointer(prop); 135 - if (!pointer) 136 - return ERR_PTR(-ENODATA); 137 - if (length > prop->length) 138 - return ERR_PTR(-EOVERFLOW); 139 - return pointer; 140 - } 141 - 142 - static int pset_prop_read_u8_array(const struct property_set *pset, 143 - const char *propname, 144 - u8 *values, size_t nval) 145 - { 146 - const void *pointer; 147 - size_t length = nval * sizeof(*values); 148 - 149 - pointer = pset_prop_find(pset, propname, length); 150 - if (IS_ERR(pointer)) 151 - return PTR_ERR(pointer); 152 - 153 - memcpy(values, pointer, length); 154 - return 0; 155 - } 156 - 157 - static int pset_prop_read_u16_array(const struct property_set *pset, 158 - const char *propname, 159 - u16 *values, size_t nval) 160 - { 161 - const void *pointer; 162 - size_t length = nval * sizeof(*values); 163 - 164 - pointer = pset_prop_find(pset, propname, length); 165 - if (IS_ERR(pointer)) 166 - return PTR_ERR(pointer); 167 - 168 - memcpy(values, pointer, length); 169 - return 0; 170 - } 171 - 172 - static int pset_prop_read_u32_array(const struct property_set *pset, 173 - const char *propname, 174 - u32 *values, size_t nval) 175 - { 176 - const void *pointer; 177 - size_t length = nval * sizeof(*values); 178 - 179 - pointer = pset_prop_find(pset, propname, length); 180 - if (IS_ERR(pointer)) 181 - return PTR_ERR(pointer); 182 - 183 - memcpy(values, pointer, length); 184 - return 0; 185 - } 186 - 187 - static int pset_prop_read_u64_array(const struct property_set *pset, 188 - const char *propname, 189 - u64 *values, size_t nval) 190 - { 191 - const void *pointer; 192 - size_t length = nval * sizeof(*values); 193 - 194 - pointer = pset_prop_find(pset, propname, length); 195 - if (IS_ERR(pointer)) 196 - return PTR_ERR(pointer); 197 - 198 - memcpy(values, pointer, length); 199 - return 0; 200 - } 201 - 202 - static int pset_prop_count_elems_of_size(const struct property_set *pset, 203 - const char *propname, size_t length) 204 - { 205 - const struct property_entry *prop; 206 - 207 - prop = pset_prop_get(pset, propname); 208 - if (!prop) 209 - return -EINVAL; 210 - 211 - return prop->length / length; 212 - } 213 - 214 - static int pset_prop_read_string_array(const struct property_set *pset, 215 - const char *propname, 216 - const char **strings, size_t nval) 217 - { 218 - const struct property_entry *prop; 219 - const void *pointer; 220 - size_t array_len, length; 221 - 222 - /* Find out the array length. */ 223 - prop = pset_prop_get(pset, propname); 224 - if (!prop) 225 - return -EINVAL; 226 - 227 - if (!prop->is_array) 228 - /* The array length for a non-array string property is 1. */ 229 - array_len = 1; 230 - else 231 - /* Find the length of an array. */ 232 - array_len = pset_prop_count_elems_of_size(pset, propname, 233 - sizeof(const char *)); 234 - 235 - /* Return how many there are if strings is NULL. */ 236 - if (!strings) 237 - return array_len; 238 - 239 - array_len = min(nval, array_len); 240 - length = array_len * sizeof(*strings); 241 - 242 - pointer = pset_prop_find(pset, propname, length); 243 - if (IS_ERR(pointer)) 244 - return PTR_ERR(pointer); 245 - 246 - memcpy(strings, pointer, length); 247 - 248 - return array_len; 249 - } 250 - 251 21 struct fwnode_handle *dev_fwnode(struct device *dev) 252 22 { 253 23 return IS_ENABLED(CONFIG_OF) && dev->of_node ? 254 24 &dev->of_node->fwnode : dev->fwnode; 255 25 } 256 26 EXPORT_SYMBOL_GPL(dev_fwnode); 257 - 258 - static bool pset_fwnode_property_present(const struct fwnode_handle *fwnode, 259 - const char *propname) 260 - { 261 - return !!pset_prop_get(to_pset_node(fwnode), propname); 262 - } 263 - 264 - static int pset_fwnode_read_int_array(const struct fwnode_handle *fwnode, 265 - const char *propname, 266 - unsigned int elem_size, void *val, 267 - size_t nval) 268 - { 269 - const struct property_set *node = to_pset_node(fwnode); 270 - 271 - if (!val) 272 - return pset_prop_count_elems_of_size(node, propname, elem_size); 273 - 274 - switch (elem_size) { 275 - case sizeof(u8): 276 - return pset_prop_read_u8_array(node, propname, val, nval); 277 - case sizeof(u16): 278 - return pset_prop_read_u16_array(node, propname, val, nval); 279 - case sizeof(u32): 280 - return pset_prop_read_u32_array(node, propname, val, nval); 281 - case sizeof(u64): 282 - return pset_prop_read_u64_array(node, propname, val, nval); 283 - } 284 - 285 - return -ENXIO; 286 - } 287 - 288 - static int 289 - pset_fwnode_property_read_string_array(const struct fwnode_handle *fwnode, 290 - const char *propname, 291 - const char **val, size_t nval) 292 - { 293 - return pset_prop_read_string_array(to_pset_node(fwnode), propname, 294 - val, nval); 295 - } 296 - 297 - static const struct fwnode_operations pset_fwnode_ops = { 298 - .property_present = pset_fwnode_property_present, 299 - .property_read_int_array = pset_fwnode_read_int_array, 300 - .property_read_string_array = pset_fwnode_property_read_string_array, 301 - }; 302 27 303 28 /** 304 29 * device_property_present - check if a property of a device is present ··· 484 759 } 485 760 EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args); 486 761 487 - static void property_entry_free_data(const struct property_entry *p) 488 - { 489 - const void *pointer = property_get_pointer(p); 490 - size_t i, nval; 491 - 492 - if (p->is_array) { 493 - if (p->type == DEV_PROP_STRING && p->pointer.str) { 494 - nval = p->length / sizeof(const char *); 495 - for (i = 0; i < nval; i++) 496 - kfree(p->pointer.str[i]); 497 - } 498 - kfree(pointer); 499 - } else if (p->type == DEV_PROP_STRING) { 500 - kfree(p->value.str); 501 - } 502 - kfree(p->name); 503 - } 504 - 505 - static int property_copy_string_array(struct property_entry *dst, 506 - const struct property_entry *src) 507 - { 508 - const char **d; 509 - size_t nval = src->length / sizeof(*d); 510 - int i; 511 - 512 - d = kcalloc(nval, sizeof(*d), GFP_KERNEL); 513 - if (!d) 514 - return -ENOMEM; 515 - 516 - for (i = 0; i < nval; i++) { 517 - d[i] = kstrdup(src->pointer.str[i], GFP_KERNEL); 518 - if (!d[i] && src->pointer.str[i]) { 519 - while (--i >= 0) 520 - kfree(d[i]); 521 - kfree(d); 522 - return -ENOMEM; 523 - } 524 - } 525 - 526 - dst->pointer.str = d; 527 - return 0; 528 - } 529 - 530 - static int property_entry_copy_data(struct property_entry *dst, 531 - const struct property_entry *src) 532 - { 533 - const void *pointer = property_get_pointer(src); 534 - const void *new; 535 - int error; 536 - 537 - if (src->is_array) { 538 - if (!src->length) 539 - return -ENODATA; 540 - 541 - if (src->type == DEV_PROP_STRING) { 542 - error = property_copy_string_array(dst, src); 543 - if (error) 544 - return error; 545 - new = dst->pointer.str; 546 - } else { 547 - new = kmemdup(pointer, src->length, GFP_KERNEL); 548 - if (!new) 549 - return -ENOMEM; 550 - } 551 - } else if (src->type == DEV_PROP_STRING) { 552 - new = kstrdup(src->value.str, GFP_KERNEL); 553 - if (!new && src->value.str) 554 - return -ENOMEM; 555 - } else { 556 - new = pointer; 557 - } 558 - 559 - dst->length = src->length; 560 - dst->is_array = src->is_array; 561 - dst->type = src->type; 562 - 563 - property_set_pointer(dst, new); 564 - 565 - dst->name = kstrdup(src->name, GFP_KERNEL); 566 - if (!dst->name) 567 - goto out_free_data; 568 - 569 - return 0; 570 - 571 - out_free_data: 572 - property_entry_free_data(dst); 573 - return -ENOMEM; 574 - } 575 - 576 - /** 577 - * property_entries_dup - duplicate array of properties 578 - * @properties: array of properties to copy 579 - * 580 - * This function creates a deep copy of the given NULL-terminated array 581 - * of property entries. 582 - */ 583 - struct property_entry * 584 - property_entries_dup(const struct property_entry *properties) 585 - { 586 - struct property_entry *p; 587 - int i, n = 0; 588 - 589 - while (properties[n].name) 590 - n++; 591 - 592 - p = kcalloc(n + 1, sizeof(*p), GFP_KERNEL); 593 - if (!p) 594 - return ERR_PTR(-ENOMEM); 595 - 596 - for (i = 0; i < n; i++) { 597 - int ret = property_entry_copy_data(&p[i], &properties[i]); 598 - if (ret) { 599 - while (--i >= 0) 600 - property_entry_free_data(&p[i]); 601 - kfree(p); 602 - return ERR_PTR(ret); 603 - } 604 - } 605 - 606 - return p; 607 - } 608 - EXPORT_SYMBOL_GPL(property_entries_dup); 609 - 610 - /** 611 - * property_entries_free - free previously allocated array of properties 612 - * @properties: array of properties to destroy 613 - * 614 - * This function frees given NULL-terminated array of property entries, 615 - * along with their data. 616 - */ 617 - void property_entries_free(const struct property_entry *properties) 618 - { 619 - const struct property_entry *p; 620 - 621 - for (p = properties; p->name; p++) 622 - property_entry_free_data(p); 623 - 624 - kfree(properties); 625 - } 626 - EXPORT_SYMBOL_GPL(property_entries_free); 627 - 628 - /** 629 - * pset_free_set - releases memory allocated for copied property set 630 - * @pset: Property set to release 631 - * 632 - * Function takes previously copied property set and releases all the 633 - * memory allocated to it. 634 - */ 635 - static void pset_free_set(struct property_set *pset) 636 - { 637 - if (!pset) 638 - return; 639 - 640 - property_entries_free(pset->properties); 641 - kfree(pset); 642 - } 643 - 644 - /** 645 - * pset_copy_set - copies property set 646 - * @pset: Property set to copy 647 - * 648 - * This function takes a deep copy of the given property set and returns 649 - * pointer to the copy. Call device_free_property_set() to free resources 650 - * allocated in this function. 651 - * 652 - * Return: Pointer to the new property set or error pointer. 653 - */ 654 - static struct property_set *pset_copy_set(const struct property_set *pset) 655 - { 656 - struct property_entry *properties; 657 - struct property_set *p; 658 - 659 - p = kzalloc(sizeof(*p), GFP_KERNEL); 660 - if (!p) 661 - return ERR_PTR(-ENOMEM); 662 - 663 - properties = property_entries_dup(pset->properties); 664 - if (IS_ERR(properties)) { 665 - kfree(p); 666 - return ERR_CAST(properties); 667 - } 668 - 669 - p->properties = properties; 670 - return p; 671 - } 672 - 673 762 /** 674 763 * device_remove_properties - Remove properties from a device object. 675 764 * @dev: Device whose properties to remove. 676 765 * 677 766 * The function removes properties previously associated to the device 678 - * secondary firmware node with device_add_properties(). Memory allocated 679 - * to the properties will also be released. 767 + * firmware node with device_add_properties(). Memory allocated to the 768 + * properties will also be released. 680 769 */ 681 770 void device_remove_properties(struct device *dev) 682 771 { 683 - struct fwnode_handle *fwnode; 684 - struct property_set *pset; 772 + struct fwnode_handle *fwnode = dev_fwnode(dev); 685 773 686 - fwnode = dev_fwnode(dev); 687 774 if (!fwnode) 688 775 return; 689 - /* 690 - * Pick either primary or secondary node depending which one holds 691 - * the pset. If there is no real firmware node (ACPI/DT) primary 692 - * will hold the pset. 693 - */ 694 - pset = to_pset_node(fwnode); 695 - if (pset) { 696 - set_primary_fwnode(dev, NULL); 697 - } else { 698 - pset = to_pset_node(fwnode->secondary); 699 - if (pset && dev == pset->dev) 700 - set_secondary_fwnode(dev, NULL); 776 + 777 + if (is_software_node(fwnode->secondary)) { 778 + fwnode_remove_software_node(fwnode->secondary); 779 + set_secondary_fwnode(dev, NULL); 701 780 } 702 - if (pset && dev == pset->dev) 703 - pset_free_set(pset); 704 781 } 705 782 EXPORT_SYMBOL_GPL(device_remove_properties); 706 783 ··· 512 985 * @properties: Collection of properties to add. 513 986 * 514 987 * Associate a collection of device properties represented by @properties with 515 - * @dev as its secondary firmware node. The function takes a copy of 516 - * @properties. 988 + * @dev. The function takes a copy of @properties. 989 + * 990 + * WARNING: The callers should not use this function if it is known that there 991 + * is no real firmware node associated with @dev! In that case the callers 992 + * should create a software node and assign it to @dev directly. 517 993 */ 518 994 int device_add_properties(struct device *dev, 519 995 const struct property_entry *properties) 520 996 { 521 - struct property_set *p, pset; 997 + struct fwnode_handle *fwnode; 522 998 523 - if (!properties) 524 - return -EINVAL; 999 + fwnode = fwnode_create_software_node(properties, NULL); 1000 + if (IS_ERR(fwnode)) 1001 + return PTR_ERR(fwnode); 525 1002 526 - pset.properties = properties; 527 - 528 - p = pset_copy_set(&pset); 529 - if (IS_ERR(p)) 530 - return PTR_ERR(p); 531 - 532 - p->fwnode.ops = &pset_fwnode_ops; 533 - set_secondary_fwnode(dev, &p->fwnode); 534 - p->dev = dev; 1003 + set_secondary_fwnode(dev, fwnode); 535 1004 return 0; 536 1005 } 537 1006 EXPORT_SYMBOL_GPL(device_add_properties); ··· 864 1341 EXPORT_SYMBOL(fwnode_irq_get); 865 1342 866 1343 /** 867 - * device_graph_get_next_endpoint - Get next endpoint firmware node 1344 + * fwnode_graph_get_next_endpoint - Get next endpoint firmware node 868 1345 * @fwnode: Pointer to the parent firmware node 869 1346 * @prev: Previous endpoint node or %NULL to get the first 870 1347 *
+675
drivers/base/swnode.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Software nodes for the firmware node framework. 4 + * 5 + * Copyright (C) 2018, Intel Corporation 6 + * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> 7 + */ 8 + 9 + #include <linux/device.h> 10 + #include <linux/kernel.h> 11 + #include <linux/property.h> 12 + #include <linux/slab.h> 13 + 14 + struct software_node { 15 + int id; 16 + struct kobject kobj; 17 + struct fwnode_handle fwnode; 18 + 19 + /* hierarchy */ 20 + struct ida child_ids; 21 + struct list_head entry; 22 + struct list_head children; 23 + struct software_node *parent; 24 + 25 + /* properties */ 26 + const struct property_entry *properties; 27 + }; 28 + 29 + static DEFINE_IDA(swnode_root_ids); 30 + static struct kset *swnode_kset; 31 + 32 + #define kobj_to_swnode(_kobj_) container_of(_kobj_, struct software_node, kobj) 33 + 34 + static const struct fwnode_operations software_node_ops; 35 + 36 + bool is_software_node(const struct fwnode_handle *fwnode) 37 + { 38 + return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &software_node_ops; 39 + } 40 + 41 + #define to_software_node(__fwnode) \ 42 + ({ \ 43 + typeof(__fwnode) __to_software_node_fwnode = __fwnode; \ 44 + \ 45 + is_software_node(__to_software_node_fwnode) ? \ 46 + container_of(__to_software_node_fwnode, \ 47 + struct software_node, fwnode) : \ 48 + NULL; \ 49 + }) 50 + 51 + /* -------------------------------------------------------------------------- */ 52 + /* property_entry processing */ 53 + 54 + static const struct property_entry * 55 + property_entry_get(const struct property_entry *prop, const char *name) 56 + { 57 + if (!prop) 58 + return NULL; 59 + 60 + for (; prop->name; prop++) 61 + if (!strcmp(name, prop->name)) 62 + return prop; 63 + 64 + return NULL; 65 + } 66 + 67 + static void 68 + property_set_pointer(struct property_entry *prop, const void *pointer) 69 + { 70 + switch (prop->type) { 71 + case DEV_PROP_U8: 72 + if (prop->is_array) 73 + prop->pointer.u8_data = pointer; 74 + else 75 + prop->value.u8_data = *((u8 *)pointer); 76 + break; 77 + case DEV_PROP_U16: 78 + if (prop->is_array) 79 + prop->pointer.u16_data = pointer; 80 + else 81 + prop->value.u16_data = *((u16 *)pointer); 82 + break; 83 + case DEV_PROP_U32: 84 + if (prop->is_array) 85 + prop->pointer.u32_data = pointer; 86 + else 87 + prop->value.u32_data = *((u32 *)pointer); 88 + break; 89 + case DEV_PROP_U64: 90 + if (prop->is_array) 91 + prop->pointer.u64_data = pointer; 92 + else 93 + prop->value.u64_data = *((u64 *)pointer); 94 + break; 95 + case DEV_PROP_STRING: 96 + if (prop->is_array) 97 + prop->pointer.str = pointer; 98 + else 99 + prop->value.str = pointer; 100 + break; 101 + default: 102 + break; 103 + } 104 + } 105 + 106 + static const void *property_get_pointer(const struct property_entry *prop) 107 + { 108 + switch (prop->type) { 109 + case DEV_PROP_U8: 110 + if (prop->is_array) 111 + return prop->pointer.u8_data; 112 + return &prop->value.u8_data; 113 + case DEV_PROP_U16: 114 + if (prop->is_array) 115 + return prop->pointer.u16_data; 116 + return &prop->value.u16_data; 117 + case DEV_PROP_U32: 118 + if (prop->is_array) 119 + return prop->pointer.u32_data; 120 + return &prop->value.u32_data; 121 + case DEV_PROP_U64: 122 + if (prop->is_array) 123 + return prop->pointer.u64_data; 124 + return &prop->value.u64_data; 125 + case DEV_PROP_STRING: 126 + if (prop->is_array) 127 + return prop->pointer.str; 128 + return &prop->value.str; 129 + default: 130 + return NULL; 131 + } 132 + } 133 + 134 + static const void *property_entry_find(const struct property_entry *props, 135 + const char *propname, size_t length) 136 + { 137 + const struct property_entry *prop; 138 + const void *pointer; 139 + 140 + prop = property_entry_get(props, propname); 141 + if (!prop) 142 + return ERR_PTR(-EINVAL); 143 + pointer = property_get_pointer(prop); 144 + if (!pointer) 145 + return ERR_PTR(-ENODATA); 146 + if (length > prop->length) 147 + return ERR_PTR(-EOVERFLOW); 148 + return pointer; 149 + } 150 + 151 + static int property_entry_read_u8_array(const struct property_entry *props, 152 + const char *propname, 153 + u8 *values, size_t nval) 154 + { 155 + const void *pointer; 156 + size_t length = nval * sizeof(*values); 157 + 158 + pointer = property_entry_find(props, propname, length); 159 + if (IS_ERR(pointer)) 160 + return PTR_ERR(pointer); 161 + 162 + memcpy(values, pointer, length); 163 + return 0; 164 + } 165 + 166 + static int property_entry_read_u16_array(const struct property_entry *props, 167 + const char *propname, 168 + u16 *values, size_t nval) 169 + { 170 + const void *pointer; 171 + size_t length = nval * sizeof(*values); 172 + 173 + pointer = property_entry_find(props, propname, length); 174 + if (IS_ERR(pointer)) 175 + return PTR_ERR(pointer); 176 + 177 + memcpy(values, pointer, length); 178 + return 0; 179 + } 180 + 181 + static int property_entry_read_u32_array(const struct property_entry *props, 182 + const char *propname, 183 + u32 *values, size_t nval) 184 + { 185 + const void *pointer; 186 + size_t length = nval * sizeof(*values); 187 + 188 + pointer = property_entry_find(props, propname, length); 189 + if (IS_ERR(pointer)) 190 + return PTR_ERR(pointer); 191 + 192 + memcpy(values, pointer, length); 193 + return 0; 194 + } 195 + 196 + static int property_entry_read_u64_array(const struct property_entry *props, 197 + const char *propname, 198 + u64 *values, size_t nval) 199 + { 200 + const void *pointer; 201 + size_t length = nval * sizeof(*values); 202 + 203 + pointer = property_entry_find(props, propname, length); 204 + if (IS_ERR(pointer)) 205 + return PTR_ERR(pointer); 206 + 207 + memcpy(values, pointer, length); 208 + return 0; 209 + } 210 + 211 + static int 212 + property_entry_count_elems_of_size(const struct property_entry *props, 213 + const char *propname, size_t length) 214 + { 215 + const struct property_entry *prop; 216 + 217 + prop = property_entry_get(props, propname); 218 + if (!prop) 219 + return -EINVAL; 220 + 221 + return prop->length / length; 222 + } 223 + 224 + static int property_entry_read_int_array(const struct property_entry *props, 225 + const char *name, 226 + unsigned int elem_size, void *val, 227 + size_t nval) 228 + { 229 + if (!val) 230 + return property_entry_count_elems_of_size(props, name, 231 + elem_size); 232 + switch (elem_size) { 233 + case sizeof(u8): 234 + return property_entry_read_u8_array(props, name, val, nval); 235 + case sizeof(u16): 236 + return property_entry_read_u16_array(props, name, val, nval); 237 + case sizeof(u32): 238 + return property_entry_read_u32_array(props, name, val, nval); 239 + case sizeof(u64): 240 + return property_entry_read_u64_array(props, name, val, nval); 241 + } 242 + 243 + return -ENXIO; 244 + } 245 + 246 + static int property_entry_read_string_array(const struct property_entry *props, 247 + const char *propname, 248 + const char **strings, size_t nval) 249 + { 250 + const struct property_entry *prop; 251 + const void *pointer; 252 + size_t array_len, length; 253 + 254 + /* Find out the array length. */ 255 + prop = property_entry_get(props, propname); 256 + if (!prop) 257 + return -EINVAL; 258 + 259 + if (prop->is_array) 260 + /* Find the length of an array. */ 261 + array_len = property_entry_count_elems_of_size(props, propname, 262 + sizeof(const char *)); 263 + else 264 + /* The array length for a non-array string property is 1. */ 265 + array_len = 1; 266 + 267 + /* Return how many there are if strings is NULL. */ 268 + if (!strings) 269 + return array_len; 270 + 271 + array_len = min(nval, array_len); 272 + length = array_len * sizeof(*strings); 273 + 274 + pointer = property_entry_find(props, propname, length); 275 + if (IS_ERR(pointer)) 276 + return PTR_ERR(pointer); 277 + 278 + memcpy(strings, pointer, length); 279 + 280 + return array_len; 281 + } 282 + 283 + static void property_entry_free_data(const struct property_entry *p) 284 + { 285 + const void *pointer = property_get_pointer(p); 286 + size_t i, nval; 287 + 288 + if (p->is_array) { 289 + if (p->type == DEV_PROP_STRING && p->pointer.str) { 290 + nval = p->length / sizeof(const char *); 291 + for (i = 0; i < nval; i++) 292 + kfree(p->pointer.str[i]); 293 + } 294 + kfree(pointer); 295 + } else if (p->type == DEV_PROP_STRING) { 296 + kfree(p->value.str); 297 + } 298 + kfree(p->name); 299 + } 300 + 301 + static int property_copy_string_array(struct property_entry *dst, 302 + const struct property_entry *src) 303 + { 304 + const char **d; 305 + size_t nval = src->length / sizeof(*d); 306 + int i; 307 + 308 + d = kcalloc(nval, sizeof(*d), GFP_KERNEL); 309 + if (!d) 310 + return -ENOMEM; 311 + 312 + for (i = 0; i < nval; i++) { 313 + d[i] = kstrdup(src->pointer.str[i], GFP_KERNEL); 314 + if (!d[i] && src->pointer.str[i]) { 315 + while (--i >= 0) 316 + kfree(d[i]); 317 + kfree(d); 318 + return -ENOMEM; 319 + } 320 + } 321 + 322 + dst->pointer.str = d; 323 + return 0; 324 + } 325 + 326 + static int property_entry_copy_data(struct property_entry *dst, 327 + const struct property_entry *src) 328 + { 329 + const void *pointer = property_get_pointer(src); 330 + const void *new; 331 + int error; 332 + 333 + if (src->is_array) { 334 + if (!src->length) 335 + return -ENODATA; 336 + 337 + if (src->type == DEV_PROP_STRING) { 338 + error = property_copy_string_array(dst, src); 339 + if (error) 340 + return error; 341 + new = dst->pointer.str; 342 + } else { 343 + new = kmemdup(pointer, src->length, GFP_KERNEL); 344 + if (!new) 345 + return -ENOMEM; 346 + } 347 + } else if (src->type == DEV_PROP_STRING) { 348 + new = kstrdup(src->value.str, GFP_KERNEL); 349 + if (!new && src->value.str) 350 + return -ENOMEM; 351 + } else { 352 + new = pointer; 353 + } 354 + 355 + dst->length = src->length; 356 + dst->is_array = src->is_array; 357 + dst->type = src->type; 358 + 359 + property_set_pointer(dst, new); 360 + 361 + dst->name = kstrdup(src->name, GFP_KERNEL); 362 + if (!dst->name) 363 + goto out_free_data; 364 + 365 + return 0; 366 + 367 + out_free_data: 368 + property_entry_free_data(dst); 369 + return -ENOMEM; 370 + } 371 + 372 + /** 373 + * property_entries_dup - duplicate array of properties 374 + * @properties: array of properties to copy 375 + * 376 + * This function creates a deep copy of the given NULL-terminated array 377 + * of property entries. 378 + */ 379 + struct property_entry * 380 + property_entries_dup(const struct property_entry *properties) 381 + { 382 + struct property_entry *p; 383 + int i, n = 0; 384 + int ret; 385 + 386 + while (properties[n].name) 387 + n++; 388 + 389 + p = kcalloc(n + 1, sizeof(*p), GFP_KERNEL); 390 + if (!p) 391 + return ERR_PTR(-ENOMEM); 392 + 393 + for (i = 0; i < n; i++) { 394 + ret = property_entry_copy_data(&p[i], &properties[i]); 395 + if (ret) { 396 + while (--i >= 0) 397 + property_entry_free_data(&p[i]); 398 + kfree(p); 399 + return ERR_PTR(ret); 400 + } 401 + } 402 + 403 + return p; 404 + } 405 + EXPORT_SYMBOL_GPL(property_entries_dup); 406 + 407 + /** 408 + * property_entries_free - free previously allocated array of properties 409 + * @properties: array of properties to destroy 410 + * 411 + * This function frees given NULL-terminated array of property entries, 412 + * along with their data. 413 + */ 414 + void property_entries_free(const struct property_entry *properties) 415 + { 416 + const struct property_entry *p; 417 + 418 + if (!properties) 419 + return; 420 + 421 + for (p = properties; p->name; p++) 422 + property_entry_free_data(p); 423 + 424 + kfree(properties); 425 + } 426 + EXPORT_SYMBOL_GPL(property_entries_free); 427 + 428 + /* -------------------------------------------------------------------------- */ 429 + /* fwnode operations */ 430 + 431 + static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode) 432 + { 433 + struct software_node *swnode = to_software_node(fwnode); 434 + 435 + kobject_get(&swnode->kobj); 436 + 437 + return &swnode->fwnode; 438 + } 439 + 440 + static void software_node_put(struct fwnode_handle *fwnode) 441 + { 442 + struct software_node *swnode = to_software_node(fwnode); 443 + 444 + kobject_put(&swnode->kobj); 445 + } 446 + 447 + static bool software_node_property_present(const struct fwnode_handle *fwnode, 448 + const char *propname) 449 + { 450 + return !!property_entry_get(to_software_node(fwnode)->properties, 451 + propname); 452 + } 453 + 454 + static int software_node_read_int_array(const struct fwnode_handle *fwnode, 455 + const char *propname, 456 + unsigned int elem_size, void *val, 457 + size_t nval) 458 + { 459 + struct software_node *swnode = to_software_node(fwnode); 460 + 461 + return property_entry_read_int_array(swnode->properties, propname, 462 + elem_size, val, nval); 463 + } 464 + 465 + static int software_node_read_string_array(const struct fwnode_handle *fwnode, 466 + const char *propname, 467 + const char **val, size_t nval) 468 + { 469 + struct software_node *swnode = to_software_node(fwnode); 470 + 471 + return property_entry_read_string_array(swnode->properties, propname, 472 + val, nval); 473 + } 474 + 475 + struct fwnode_handle * 476 + software_node_get_parent(const struct fwnode_handle *fwnode) 477 + { 478 + struct software_node *swnode = to_software_node(fwnode); 479 + 480 + return swnode->parent ? &swnode->parent->fwnode : NULL; 481 + } 482 + 483 + struct fwnode_handle * 484 + software_node_get_next_child(const struct fwnode_handle *fwnode, 485 + struct fwnode_handle *child) 486 + { 487 + struct software_node *p = to_software_node(fwnode); 488 + struct software_node *c = to_software_node(child); 489 + 490 + if (list_empty(&p->children) || 491 + (c && list_is_last(&c->entry, &p->children))) 492 + return NULL; 493 + 494 + if (c) 495 + c = list_next_entry(c, entry); 496 + else 497 + c = list_first_entry(&p->children, struct software_node, entry); 498 + return &c->fwnode; 499 + } 500 + 501 + 502 + static const struct fwnode_operations software_node_ops = { 503 + .get = software_node_get, 504 + .put = software_node_put, 505 + .property_present = software_node_property_present, 506 + .property_read_int_array = software_node_read_int_array, 507 + .property_read_string_array = software_node_read_string_array, 508 + .get_parent = software_node_get_parent, 509 + .get_next_child_node = software_node_get_next_child, 510 + }; 511 + 512 + /* -------------------------------------------------------------------------- */ 513 + 514 + static int 515 + software_node_register_properties(struct software_node *swnode, 516 + const struct property_entry *properties) 517 + { 518 + struct property_entry *props; 519 + 520 + props = property_entries_dup(properties); 521 + if (IS_ERR(props)) 522 + return PTR_ERR(props); 523 + 524 + swnode->properties = props; 525 + 526 + return 0; 527 + } 528 + 529 + static void software_node_release(struct kobject *kobj) 530 + { 531 + struct software_node *swnode = kobj_to_swnode(kobj); 532 + 533 + if (swnode->parent) { 534 + ida_simple_remove(&swnode->parent->child_ids, swnode->id); 535 + list_del(&swnode->entry); 536 + } else { 537 + ida_simple_remove(&swnode_root_ids, swnode->id); 538 + } 539 + 540 + ida_destroy(&swnode->child_ids); 541 + property_entries_free(swnode->properties); 542 + kfree(swnode); 543 + } 544 + 545 + static struct kobj_type software_node_type = { 546 + .release = software_node_release, 547 + .sysfs_ops = &kobj_sysfs_ops, 548 + }; 549 + 550 + struct fwnode_handle * 551 + fwnode_create_software_node(const struct property_entry *properties, 552 + const struct fwnode_handle *parent) 553 + { 554 + struct software_node *p = NULL; 555 + struct software_node *swnode; 556 + int ret; 557 + 558 + if (parent) { 559 + if (IS_ERR(parent)) 560 + return ERR_CAST(parent); 561 + if (!is_software_node(parent)) 562 + return ERR_PTR(-EINVAL); 563 + p = to_software_node(parent); 564 + } 565 + 566 + swnode = kzalloc(sizeof(*swnode), GFP_KERNEL); 567 + if (!swnode) 568 + return ERR_PTR(-ENOMEM); 569 + 570 + ret = ida_simple_get(p ? &p->child_ids : &swnode_root_ids, 0, 0, 571 + GFP_KERNEL); 572 + if (ret < 0) { 573 + kfree(swnode); 574 + return ERR_PTR(ret); 575 + } 576 + 577 + swnode->id = ret; 578 + swnode->kobj.kset = swnode_kset; 579 + swnode->fwnode.ops = &software_node_ops; 580 + 581 + ida_init(&swnode->child_ids); 582 + INIT_LIST_HEAD(&swnode->entry); 583 + INIT_LIST_HEAD(&swnode->children); 584 + swnode->parent = p; 585 + 586 + if (p) 587 + list_add_tail(&swnode->entry, &p->children); 588 + 589 + ret = kobject_init_and_add(&swnode->kobj, &software_node_type, 590 + p ? &p->kobj : NULL, "node%d", swnode->id); 591 + if (ret) { 592 + kobject_put(&swnode->kobj); 593 + return ERR_PTR(ret); 594 + } 595 + 596 + ret = software_node_register_properties(swnode, properties); 597 + if (ret) { 598 + kobject_put(&swnode->kobj); 599 + return ERR_PTR(ret); 600 + } 601 + 602 + kobject_uevent(&swnode->kobj, KOBJ_ADD); 603 + return &swnode->fwnode; 604 + } 605 + EXPORT_SYMBOL_GPL(fwnode_create_software_node); 606 + 607 + void fwnode_remove_software_node(struct fwnode_handle *fwnode) 608 + { 609 + struct software_node *swnode = to_software_node(fwnode); 610 + 611 + if (!swnode) 612 + return; 613 + 614 + kobject_put(&swnode->kobj); 615 + } 616 + EXPORT_SYMBOL_GPL(fwnode_remove_software_node); 617 + 618 + int software_node_notify(struct device *dev, unsigned long action) 619 + { 620 + struct fwnode_handle *fwnode = dev_fwnode(dev); 621 + struct software_node *swnode; 622 + int ret; 623 + 624 + if (!fwnode) 625 + return 0; 626 + 627 + if (!is_software_node(fwnode)) 628 + fwnode = fwnode->secondary; 629 + if (!is_software_node(fwnode)) 630 + return 0; 631 + 632 + swnode = to_software_node(fwnode); 633 + 634 + switch (action) { 635 + case KOBJ_ADD: 636 + ret = sysfs_create_link(&dev->kobj, &swnode->kobj, 637 + "software_node"); 638 + if (ret) 639 + break; 640 + 641 + ret = sysfs_create_link(&swnode->kobj, &dev->kobj, 642 + dev_name(dev)); 643 + if (ret) { 644 + sysfs_remove_link(&dev->kobj, "software_node"); 645 + break; 646 + } 647 + kobject_get(&swnode->kobj); 648 + break; 649 + case KOBJ_REMOVE: 650 + sysfs_remove_link(&swnode->kobj, dev_name(dev)); 651 + sysfs_remove_link(&dev->kobj, "software_node"); 652 + kobject_put(&swnode->kobj); 653 + break; 654 + default: 655 + break; 656 + } 657 + 658 + return 0; 659 + } 660 + 661 + static int __init software_node_init(void) 662 + { 663 + swnode_kset = kset_create_and_add("software_nodes", NULL, kernel_kobj); 664 + if (!swnode_kset) 665 + return -ENOMEM; 666 + return 0; 667 + } 668 + postcore_initcall(software_node_init); 669 + 670 + static void __exit software_node_exit(void) 671 + { 672 + ida_destroy(&swnode_root_ids); 673 + kset_unregister(swnode_kset); 674 + } 675 + __exitcall(software_node_exit);
+10
include/linux/acpi.h
··· 1331 1331 } 1332 1332 #endif 1333 1333 1334 + #ifdef CONFIG_ACPI 1335 + extern int acpi_platform_notify(struct device *dev, enum kobject_action action); 1336 + #else 1337 + static inline int 1338 + acpi_platform_notify(struct device *dev, enum kobject_action action) 1339 + { 1340 + return 0; 1341 + } 1342 + #endif 1343 + 1334 1344 #endif /*_LINUX_ACPI_H*/
+12
include/linux/property.h
··· 311 311 int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, 312 312 struct fwnode_endpoint *endpoint); 313 313 314 + /* -------------------------------------------------------------------------- */ 315 + /* Software fwnode support - when HW description is incomplete or missing */ 316 + 317 + bool is_software_node(const struct fwnode_handle *fwnode); 318 + 319 + int software_node_notify(struct device *dev, unsigned long action); 320 + 321 + struct fwnode_handle * 322 + fwnode_create_software_node(const struct property_entry *properties, 323 + const struct fwnode_handle *parent); 324 + void fwnode_remove_software_node(struct fwnode_handle *fwnode); 325 + 314 326 #endif /* _LINUX_PROPERTY_H_ */