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 'devprop-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull device properties framework updates from Rafael Wysocki:
"These mostly rearrange the device properties core code and add a few
helper functions to it as a foundation for future work.

Specifics:

- Rearrange the core device properties code by moving the code
specific to each supported platform configuration framework (ACPI,
DT and build-in) into a separate file (Sakari Ailus).

- Add helper functions for accessing device properties in a
firmware-agnostic way (Sakari Ailus, Kieran Bingham)"

* tag 'devprop-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
device property: Add fwnode_graph_get_port_parent
device property: Add FW type agnostic fwnode_graph_get_remote_node
device property: Introduce fwnode_device_is_available()
device property: Move fwnode graph ops to firmware specific locations
device property: Move FW type specific functionality to FW specific files
ACPI: Constify argument to acpi_device_is_present()

+509 -214
+3 -1
drivers/acpi/device_pm.c
··· 262 262 return -EINVAL; 263 263 264 264 device->power.state = ACPI_STATE_UNKNOWN; 265 - if (!acpi_device_is_present(device)) 265 + if (!acpi_device_is_present(device)) { 266 + device->flags.initialized = false; 266 267 return -ENXIO; 268 + } 267 269 268 270 result = acpi_device_get_power(device, &state); 269 271 if (result)
+1 -1
drivers/acpi/internal.h
··· 111 111 void acpi_device_remove_files(struct acpi_device *dev); 112 112 void acpi_device_add_finalize(struct acpi_device *device); 113 113 void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); 114 - bool acpi_device_is_present(struct acpi_device *adev); 114 + bool acpi_device_is_present(const struct acpi_device *adev); 115 115 bool acpi_device_is_battery(struct acpi_device *adev); 116 116 bool acpi_device_is_first_physical_node(struct acpi_device *adev, 117 117 const struct device *dev);
+117
drivers/acpi/property.c
··· 57 57 58 58 dn->name = link->package.elements[0].string.pointer; 59 59 dn->fwnode.type = FWNODE_ACPI_DATA; 60 + dn->fwnode.ops = &acpi_fwnode_ops; 60 61 dn->parent = parent; 61 62 INIT_LIST_HEAD(&dn->data.subnodes); 62 63 ··· 1120 1119 1121 1120 return 0; 1122 1121 } 1122 + 1123 + static bool acpi_fwnode_device_is_available(struct fwnode_handle *fwnode) 1124 + { 1125 + if (!is_acpi_device_node(fwnode)) 1126 + return false; 1127 + 1128 + return acpi_device_is_present(to_acpi_device_node(fwnode)); 1129 + } 1130 + 1131 + static bool acpi_fwnode_property_present(struct fwnode_handle *fwnode, 1132 + const char *propname) 1133 + { 1134 + return !acpi_node_prop_get(fwnode, propname, NULL); 1135 + } 1136 + 1137 + static int acpi_fwnode_property_read_int_array(struct fwnode_handle *fwnode, 1138 + const char *propname, 1139 + unsigned int elem_size, 1140 + void *val, size_t nval) 1141 + { 1142 + enum dev_prop_type type; 1143 + 1144 + switch (elem_size) { 1145 + case sizeof(u8): 1146 + type = DEV_PROP_U8; 1147 + break; 1148 + case sizeof(u16): 1149 + type = DEV_PROP_U16; 1150 + break; 1151 + case sizeof(u32): 1152 + type = DEV_PROP_U32; 1153 + break; 1154 + case sizeof(u64): 1155 + type = DEV_PROP_U64; 1156 + break; 1157 + default: 1158 + return -ENXIO; 1159 + } 1160 + 1161 + return acpi_node_prop_read(fwnode, propname, type, val, nval); 1162 + } 1163 + 1164 + static int acpi_fwnode_property_read_string_array(struct fwnode_handle *fwnode, 1165 + const char *propname, 1166 + const char **val, size_t nval) 1167 + { 1168 + return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING, 1169 + val, nval); 1170 + } 1171 + 1172 + static struct fwnode_handle * 1173 + acpi_fwnode_get_named_child_node(struct fwnode_handle *fwnode, 1174 + const char *childname) 1175 + { 1176 + struct fwnode_handle *child; 1177 + 1178 + /* 1179 + * Find first matching named child node of this fwnode. 1180 + * For ACPI this will be a data only sub-node. 1181 + */ 1182 + fwnode_for_each_child_node(fwnode, child) 1183 + if (acpi_data_node_match(child, childname)) 1184 + return child; 1185 + 1186 + return NULL; 1187 + } 1188 + 1189 + static struct fwnode_handle * 1190 + acpi_fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode, 1191 + struct fwnode_handle *prev) 1192 + { 1193 + struct fwnode_handle *endpoint; 1194 + 1195 + endpoint = acpi_graph_get_next_endpoint(fwnode, prev); 1196 + if (IS_ERR(endpoint)) 1197 + return NULL; 1198 + 1199 + return endpoint; 1200 + } 1201 + 1202 + static struct fwnode_handle * 1203 + acpi_fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode) 1204 + { 1205 + struct fwnode_handle *endpoint = NULL; 1206 + 1207 + acpi_graph_get_remote_endpoint(fwnode, NULL, NULL, &endpoint); 1208 + 1209 + return endpoint; 1210 + } 1211 + 1212 + static int acpi_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode, 1213 + struct fwnode_endpoint *endpoint) 1214 + { 1215 + struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode); 1216 + 1217 + endpoint->local_fwnode = fwnode; 1218 + 1219 + fwnode_property_read_u32(port_fwnode, "port", &endpoint->port); 1220 + fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id); 1221 + 1222 + return 0; 1223 + } 1224 + 1225 + const struct fwnode_operations acpi_fwnode_ops = { 1226 + .device_is_available = acpi_fwnode_device_is_available, 1227 + .property_present = acpi_fwnode_property_present, 1228 + .property_read_int_array = acpi_fwnode_property_read_int_array, 1229 + .property_read_string_array = acpi_fwnode_property_read_string_array, 1230 + .get_parent = acpi_node_get_parent, 1231 + .get_next_child_node = acpi_get_next_subnode, 1232 + .get_named_child_node = acpi_fwnode_get_named_child_node, 1233 + .graph_get_next_endpoint = acpi_fwnode_graph_get_next_endpoint, 1234 + .graph_get_remote_endpoint = acpi_fwnode_graph_get_remote_endpoint, 1235 + .graph_get_port_parent = acpi_node_get_parent, 1236 + .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, 1237 + };
+4 -6
drivers/acpi/scan.c
··· 1468 1468 device->handle = handle; 1469 1469 device->parent = acpi_bus_get_parent(handle); 1470 1470 device->fwnode.type = FWNODE_ACPI; 1471 + device->fwnode.ops = &acpi_fwnode_ops; 1471 1472 acpi_set_device_status(device, sta); 1472 1473 acpi_device_get_busid(device); 1473 1474 acpi_set_pnp_ids(handle, &device->pnp, type); ··· 1601 1600 return 0; 1602 1601 } 1603 1602 1604 - bool acpi_device_is_present(struct acpi_device *adev) 1603 + bool acpi_device_is_present(const struct acpi_device *adev) 1605 1604 { 1606 - if (adev->status.present || adev->status.functional) 1607 - return true; 1608 - 1609 - adev->flags.initialized = false; 1610 - return false; 1605 + return adev->status.present || adev->status.functional; 1611 1606 } 1612 1607 1613 1608 static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, ··· 1836 1839 acpi_bus_get_status(device); 1837 1840 /* Skip devices that are not present. */ 1838 1841 if (!acpi_device_is_present(device)) { 1842 + device->flags.initialized = false; 1839 1843 acpi_device_clear_enumerated(device); 1840 1844 device->flags.power_manageable = 0; 1841 1845 return;
+156 -206
drivers/base/property.c
··· 187 187 } 188 188 EXPORT_SYMBOL_GPL(dev_fwnode); 189 189 190 + static bool pset_fwnode_property_present(struct fwnode_handle *fwnode, 191 + const char *propname) 192 + { 193 + return !!pset_prop_get(to_pset_node(fwnode), propname); 194 + } 195 + 196 + static int pset_fwnode_read_int_array(struct fwnode_handle *fwnode, 197 + const char *propname, 198 + unsigned int elem_size, void *val, 199 + size_t nval) 200 + { 201 + struct property_set *node = to_pset_node(fwnode); 202 + 203 + if (!val) 204 + return pset_prop_count_elems_of_size(node, propname, elem_size); 205 + 206 + switch (elem_size) { 207 + case sizeof(u8): 208 + return pset_prop_read_u8_array(node, propname, val, nval); 209 + case sizeof(u16): 210 + return pset_prop_read_u16_array(node, propname, val, nval); 211 + case sizeof(u32): 212 + return pset_prop_read_u32_array(node, propname, val, nval); 213 + case sizeof(u64): 214 + return pset_prop_read_u64_array(node, propname, val, nval); 215 + } 216 + 217 + return -ENXIO; 218 + } 219 + 220 + static int pset_fwnode_property_read_string_array(struct fwnode_handle *fwnode, 221 + const char *propname, 222 + const char **val, size_t nval) 223 + { 224 + return pset_prop_read_string_array(to_pset_node(fwnode), propname, 225 + val, nval); 226 + } 227 + 228 + static const struct fwnode_operations pset_fwnode_ops = { 229 + .property_present = pset_fwnode_property_present, 230 + .property_read_int_array = pset_fwnode_read_int_array, 231 + .property_read_string_array = pset_fwnode_property_read_string_array, 232 + }; 233 + 190 234 /** 191 235 * device_property_present - check if a property of a device is present 192 236 * @dev: Device whose property is being checked ··· 244 200 } 245 201 EXPORT_SYMBOL_GPL(device_property_present); 246 202 247 - static bool __fwnode_property_present(struct fwnode_handle *fwnode, 248 - const char *propname) 249 - { 250 - if (is_of_node(fwnode)) 251 - return of_property_read_bool(to_of_node(fwnode), propname); 252 - else if (is_acpi_node(fwnode)) 253 - return !acpi_node_prop_get(fwnode, propname, NULL); 254 - else if (is_pset_node(fwnode)) 255 - return !!pset_prop_get(to_pset_node(fwnode), propname); 256 - return false; 257 - } 258 - 259 203 /** 260 204 * fwnode_property_present - check if a property of a firmware node is present 261 205 * @fwnode: Firmware node whose property to check ··· 253 221 { 254 222 bool ret; 255 223 256 - ret = __fwnode_property_present(fwnode, propname); 224 + ret = fwnode_call_int_op(fwnode, property_present, propname); 257 225 if (ret == false && !IS_ERR_OR_NULL(fwnode) && 258 226 !IS_ERR_OR_NULL(fwnode->secondary)) 259 - ret = __fwnode_property_present(fwnode->secondary, propname); 227 + ret = fwnode_call_int_op(fwnode->secondary, property_present, 228 + propname); 260 229 return ret; 261 230 } 262 231 EXPORT_SYMBOL_GPL(fwnode_property_present); ··· 431 398 } 432 399 EXPORT_SYMBOL_GPL(device_property_match_string); 433 400 434 - #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ 435 - (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ 436 - : of_property_count_elems_of_size((node), (propname), sizeof(type)) 401 + static int fwnode_property_read_int_array(struct fwnode_handle *fwnode, 402 + const char *propname, 403 + unsigned int elem_size, void *val, 404 + size_t nval) 405 + { 406 + int ret; 437 407 438 - #define PSET_PROP_READ_ARRAY(node, propname, type, val, nval) \ 439 - (val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval)) \ 440 - : pset_prop_count_elems_of_size((node), (propname), sizeof(type)) 408 + ret = fwnode_call_int_op(fwnode, property_read_int_array, propname, 409 + elem_size, val, nval); 410 + if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) && 411 + !IS_ERR_OR_NULL(fwnode->secondary)) 412 + ret = fwnode_call_int_op( 413 + fwnode->secondary, property_read_int_array, propname, 414 + elem_size, val, nval); 441 415 442 - #define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ 443 - ({ \ 444 - int _ret_; \ 445 - if (is_of_node(_fwnode_)) \ 446 - _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \ 447 - _type_, _val_, _nval_); \ 448 - else if (is_acpi_node(_fwnode_)) \ 449 - _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \ 450 - _val_, _nval_); \ 451 - else if (is_pset_node(_fwnode_)) \ 452 - _ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_, \ 453 - _type_, _val_, _nval_); \ 454 - else \ 455 - _ret_ = -ENXIO; \ 456 - _ret_; \ 457 - }) 458 - 459 - #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ 460 - ({ \ 461 - int _ret_; \ 462 - _ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, \ 463 - _val_, _nval_); \ 464 - if (_ret_ == -EINVAL && !IS_ERR_OR_NULL(_fwnode_) && \ 465 - !IS_ERR_OR_NULL(_fwnode_->secondary)) \ 466 - _ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_, \ 467 - _proptype_, _val_, _nval_); \ 468 - _ret_; \ 469 - }) 416 + return ret; 417 + } 470 418 471 419 /** 472 420 * fwnode_property_read_u8_array - return a u8 array property of firmware node ··· 470 456 int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, 471 457 const char *propname, u8 *val, size_t nval) 472 458 { 473 - return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8, 474 - val, nval); 459 + return fwnode_property_read_int_array(fwnode, propname, sizeof(u8), 460 + val, nval); 475 461 } 476 462 EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array); 477 463 ··· 496 482 int fwnode_property_read_u16_array(struct fwnode_handle *fwnode, 497 483 const char *propname, u16 *val, size_t nval) 498 484 { 499 - return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16, 500 - val, nval); 485 + return fwnode_property_read_int_array(fwnode, propname, sizeof(u16), 486 + val, nval); 501 487 } 502 488 EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array); 503 489 ··· 522 508 int fwnode_property_read_u32_array(struct fwnode_handle *fwnode, 523 509 const char *propname, u32 *val, size_t nval) 524 510 { 525 - return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32, 526 - val, nval); 511 + return fwnode_property_read_int_array(fwnode, propname, sizeof(u32), 512 + val, nval); 527 513 } 528 514 EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array); 529 515 ··· 548 534 int fwnode_property_read_u64_array(struct fwnode_handle *fwnode, 549 535 const char *propname, u64 *val, size_t nval) 550 536 { 551 - return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64, 552 - val, nval); 537 + return fwnode_property_read_int_array(fwnode, propname, sizeof(u64), 538 + val, nval); 553 539 } 554 540 EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array); 555 - 556 - static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode, 557 - const char *propname, 558 - const char **val, size_t nval) 559 - { 560 - if (is_of_node(fwnode)) 561 - return val ? 562 - of_property_read_string_array(to_of_node(fwnode), 563 - propname, val, nval) : 564 - of_property_count_strings(to_of_node(fwnode), propname); 565 - else if (is_acpi_node(fwnode)) 566 - return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING, 567 - val, nval); 568 - else if (is_pset_node(fwnode)) 569 - return pset_prop_read_string_array(to_pset_node(fwnode), 570 - propname, val, nval); 571 - return -ENXIO; 572 - } 573 541 574 542 /** 575 543 * fwnode_property_read_string_array - return string array property of a node ··· 577 581 { 578 582 int ret; 579 583 580 - ret = __fwnode_property_read_string_array(fwnode, propname, val, nval); 584 + ret = fwnode_call_int_op(fwnode, property_read_string_array, propname, 585 + val, nval); 581 586 if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) && 582 587 !IS_ERR_OR_NULL(fwnode->secondary)) 583 - ret = __fwnode_property_read_string_array(fwnode->secondary, 584 - propname, val, nval); 588 + ret = fwnode_call_int_op(fwnode->secondary, 589 + property_read_string_array, propname, 590 + val, nval); 585 591 return ret; 586 592 } 587 593 EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); ··· 901 903 return PTR_ERR(p); 902 904 903 905 p->fwnode.type = FWNODE_PDATA; 906 + p->fwnode.ops = &pset_fwnode_ops; 904 907 set_secondary_fwnode(dev, &p->fwnode); 905 908 return 0; 906 909 } ··· 937 938 */ 938 939 struct fwnode_handle *fwnode_get_parent(struct fwnode_handle *fwnode) 939 940 { 940 - struct fwnode_handle *parent = NULL; 941 - 942 - if (is_of_node(fwnode)) { 943 - struct device_node *node; 944 - 945 - node = of_get_parent(to_of_node(fwnode)); 946 - if (node) 947 - parent = &node->fwnode; 948 - } else if (is_acpi_node(fwnode)) { 949 - parent = acpi_node_get_parent(fwnode); 950 - } 951 - 952 - return parent; 941 + return fwnode_call_ptr_op(fwnode, get_parent); 953 942 } 954 943 EXPORT_SYMBOL_GPL(fwnode_get_parent); 955 944 ··· 949 962 struct fwnode_handle *fwnode_get_next_child_node(struct fwnode_handle *fwnode, 950 963 struct fwnode_handle *child) 951 964 { 952 - if (is_of_node(fwnode)) { 953 - struct device_node *node; 954 - 955 - node = of_get_next_available_child(to_of_node(fwnode), 956 - to_of_node(child)); 957 - if (node) 958 - return &node->fwnode; 959 - } else if (is_acpi_node(fwnode)) { 960 - return acpi_get_next_subnode(fwnode, child); 961 - } 962 - 963 - return NULL; 965 + return fwnode_call_ptr_op(fwnode, get_next_child_node, child); 964 966 } 965 967 EXPORT_SYMBOL_GPL(fwnode_get_next_child_node); 966 968 ··· 981 1005 struct fwnode_handle *fwnode_get_named_child_node(struct fwnode_handle *fwnode, 982 1006 const char *childname) 983 1007 { 984 - struct fwnode_handle *child; 985 - 986 - /* 987 - * Find first matching named child node of this fwnode. 988 - * For ACPI this will be a data only sub-node. 989 - */ 990 - fwnode_for_each_child_node(fwnode, child) { 991 - if (is_of_node(child)) { 992 - if (!of_node_cmp(to_of_node(child)->name, childname)) 993 - return child; 994 - } else if (is_acpi_data_node(child)) { 995 - if (acpi_data_node_match(child, childname)) 996 - return child; 997 - } 998 - } 999 - 1000 - return NULL; 1008 + return fwnode_call_ptr_op(fwnode, get_named_child_node, childname); 1001 1009 } 1002 1010 EXPORT_SYMBOL_GPL(fwnode_get_named_child_node); 1003 1011 ··· 1003 1043 */ 1004 1044 void fwnode_handle_get(struct fwnode_handle *fwnode) 1005 1045 { 1006 - if (is_of_node(fwnode)) 1007 - of_node_get(to_of_node(fwnode)); 1046 + fwnode_call_void_op(fwnode, get); 1008 1047 } 1009 1048 EXPORT_SYMBOL_GPL(fwnode_handle_get); 1010 1049 ··· 1017 1058 */ 1018 1059 void fwnode_handle_put(struct fwnode_handle *fwnode) 1019 1060 { 1020 - if (is_of_node(fwnode)) 1021 - of_node_put(to_of_node(fwnode)); 1061 + fwnode_call_void_op(fwnode, put); 1022 1062 } 1023 1063 EXPORT_SYMBOL_GPL(fwnode_handle_put); 1064 + 1065 + /** 1066 + * fwnode_device_is_available - check if a device is available for use 1067 + * @fwnode: Pointer to the fwnode of the device. 1068 + */ 1069 + bool fwnode_device_is_available(struct fwnode_handle *fwnode) 1070 + { 1071 + return fwnode_call_int_op(fwnode, device_is_available); 1072 + } 1073 + EXPORT_SYMBOL_GPL(fwnode_device_is_available); 1024 1074 1025 1075 /** 1026 1076 * device_get_child_node_count - return the number of child nodes for device ··· 1166 1198 fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode, 1167 1199 struct fwnode_handle *prev) 1168 1200 { 1169 - struct fwnode_handle *endpoint = NULL; 1170 - 1171 - if (is_of_node(fwnode)) { 1172 - struct device_node *node; 1173 - 1174 - node = of_graph_get_next_endpoint(to_of_node(fwnode), 1175 - to_of_node(prev)); 1176 - 1177 - if (node) 1178 - endpoint = &node->fwnode; 1179 - } else if (is_acpi_node(fwnode)) { 1180 - endpoint = acpi_graph_get_next_endpoint(fwnode, prev); 1181 - if (IS_ERR(endpoint)) 1182 - endpoint = NULL; 1183 - } 1184 - 1185 - return endpoint; 1186 - 1201 + return fwnode_call_ptr_op(fwnode, graph_get_next_endpoint, prev); 1187 1202 } 1188 1203 EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint); 1204 + 1205 + /** 1206 + * fwnode_graph_get_port_parent - Return the device fwnode of a port endpoint 1207 + * @endpoint: Endpoint firmware node of the port 1208 + * 1209 + * Return: the firmware node of the device the @endpoint belongs to. 1210 + */ 1211 + struct fwnode_handle * 1212 + fwnode_graph_get_port_parent(struct fwnode_handle *endpoint) 1213 + { 1214 + struct fwnode_handle *port, *parent; 1215 + 1216 + port = fwnode_get_parent(endpoint); 1217 + parent = fwnode_call_ptr_op(port, graph_get_port_parent); 1218 + 1219 + fwnode_handle_put(port); 1220 + 1221 + return parent; 1222 + } 1223 + EXPORT_SYMBOL_GPL(fwnode_graph_get_port_parent); 1189 1224 1190 1225 /** 1191 1226 * fwnode_graph_get_remote_port_parent - Return fwnode of a remote device ··· 1199 1228 struct fwnode_handle * 1200 1229 fwnode_graph_get_remote_port_parent(struct fwnode_handle *fwnode) 1201 1230 { 1202 - struct fwnode_handle *parent = NULL; 1231 + struct fwnode_handle *endpoint, *parent; 1203 1232 1204 - if (is_of_node(fwnode)) { 1205 - struct device_node *node; 1233 + endpoint = fwnode_graph_get_remote_endpoint(fwnode); 1234 + parent = fwnode_graph_get_port_parent(endpoint); 1206 1235 1207 - node = of_graph_get_remote_port_parent(to_of_node(fwnode)); 1208 - if (node) 1209 - parent = &node->fwnode; 1210 - } else if (is_acpi_node(fwnode)) { 1211 - int ret; 1212 - 1213 - ret = acpi_graph_get_remote_endpoint(fwnode, &parent, NULL, 1214 - NULL); 1215 - if (ret) 1216 - return NULL; 1217 - } 1236 + fwnode_handle_put(endpoint); 1218 1237 1219 1238 return parent; 1220 1239 } ··· 1218 1257 */ 1219 1258 struct fwnode_handle *fwnode_graph_get_remote_port(struct fwnode_handle *fwnode) 1220 1259 { 1221 - struct fwnode_handle *port = NULL; 1222 - 1223 - if (is_of_node(fwnode)) { 1224 - struct device_node *node; 1225 - 1226 - node = of_graph_get_remote_port(to_of_node(fwnode)); 1227 - if (node) 1228 - port = &node->fwnode; 1229 - } else if (is_acpi_node(fwnode)) { 1230 - int ret; 1231 - 1232 - ret = acpi_graph_get_remote_endpoint(fwnode, NULL, &port, NULL); 1233 - if (ret) 1234 - return NULL; 1235 - } 1236 - 1237 - return port; 1260 + return fwnode_get_next_parent(fwnode_graph_get_remote_endpoint(fwnode)); 1238 1261 } 1239 1262 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port); 1240 1263 ··· 1231 1286 struct fwnode_handle * 1232 1287 fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode) 1233 1288 { 1234 - struct fwnode_handle *endpoint = NULL; 1235 - 1236 - if (is_of_node(fwnode)) { 1237 - struct device_node *node; 1238 - 1239 - node = of_parse_phandle(to_of_node(fwnode), "remote-endpoint", 1240 - 0); 1241 - if (node) 1242 - endpoint = &node->fwnode; 1243 - } else if (is_acpi_node(fwnode)) { 1244 - int ret; 1245 - 1246 - ret = acpi_graph_get_remote_endpoint(fwnode, NULL, NULL, 1247 - &endpoint); 1248 - if (ret) 1249 - return NULL; 1250 - } 1251 - 1252 - return endpoint; 1289 + return fwnode_call_ptr_op(fwnode, graph_get_remote_endpoint); 1253 1290 } 1254 1291 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint); 1292 + 1293 + /** 1294 + * fwnode_graph_get_remote_node - get remote parent node for given port/endpoint 1295 + * @fwnode: pointer to parent fwnode_handle containing graph port/endpoint 1296 + * @port_id: identifier of the parent port node 1297 + * @endpoint_id: identifier of the endpoint node 1298 + * 1299 + * Return: Remote fwnode handle associated with remote endpoint node linked 1300 + * to @node. Use fwnode_node_put() on it when done. 1301 + */ 1302 + struct fwnode_handle *fwnode_graph_get_remote_node(struct fwnode_handle *fwnode, 1303 + u32 port_id, u32 endpoint_id) 1304 + { 1305 + struct fwnode_handle *endpoint = NULL; 1306 + 1307 + while ((endpoint = fwnode_graph_get_next_endpoint(fwnode, endpoint))) { 1308 + struct fwnode_endpoint fwnode_ep; 1309 + struct fwnode_handle *remote; 1310 + int ret; 1311 + 1312 + ret = fwnode_graph_parse_endpoint(endpoint, &fwnode_ep); 1313 + if (ret < 0) 1314 + continue; 1315 + 1316 + if (fwnode_ep.port != port_id || fwnode_ep.id != endpoint_id) 1317 + continue; 1318 + 1319 + remote = fwnode_graph_get_remote_port_parent(endpoint); 1320 + if (!remote) 1321 + return NULL; 1322 + 1323 + return fwnode_device_is_available(remote) ? remote : NULL; 1324 + } 1325 + 1326 + return NULL; 1327 + } 1328 + EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_node); 1255 1329 1256 1330 /** 1257 1331 * fwnode_graph_parse_endpoint - parse common endpoint node properties ··· 1284 1320 int fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode, 1285 1321 struct fwnode_endpoint *endpoint) 1286 1322 { 1287 - struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode); 1288 - 1289 1323 memset(endpoint, 0, sizeof(*endpoint)); 1290 1324 1291 - endpoint->local_fwnode = fwnode; 1292 - 1293 - if (is_acpi_node(port_fwnode)) { 1294 - fwnode_property_read_u32(port_fwnode, "port", &endpoint->port); 1295 - fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id); 1296 - } else { 1297 - fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port); 1298 - fwnode_property_read_u32(fwnode, "reg", &endpoint->id); 1299 - } 1300 - 1301 - fwnode_handle_put(port_fwnode); 1302 - 1303 - return 0; 1325 + return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint); 1304 1326 } 1305 1327 EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
+148
drivers/of/property.c
··· 804 804 return remote; 805 805 } 806 806 EXPORT_SYMBOL(of_graph_get_remote_node); 807 + 808 + static void of_fwnode_get(struct fwnode_handle *fwnode) 809 + { 810 + of_node_get(to_of_node(fwnode)); 811 + } 812 + 813 + static void of_fwnode_put(struct fwnode_handle *fwnode) 814 + { 815 + of_node_put(to_of_node(fwnode)); 816 + } 817 + 818 + static bool of_fwnode_device_is_available(struct fwnode_handle *fwnode) 819 + { 820 + return of_device_is_available(to_of_node(fwnode)); 821 + } 822 + 823 + static bool of_fwnode_property_present(struct fwnode_handle *fwnode, 824 + const char *propname) 825 + { 826 + return of_property_read_bool(to_of_node(fwnode), propname); 827 + } 828 + 829 + static int of_fwnode_property_read_int_array(struct fwnode_handle *fwnode, 830 + const char *propname, 831 + unsigned int elem_size, void *val, 832 + size_t nval) 833 + { 834 + struct device_node *node = to_of_node(fwnode); 835 + 836 + if (!val) 837 + return of_property_count_elems_of_size(node, propname, 838 + elem_size); 839 + 840 + switch (elem_size) { 841 + case sizeof(u8): 842 + return of_property_read_u8_array(node, propname, val, nval); 843 + case sizeof(u16): 844 + return of_property_read_u16_array(node, propname, val, nval); 845 + case sizeof(u32): 846 + return of_property_read_u32_array(node, propname, val, nval); 847 + case sizeof(u64): 848 + return of_property_read_u64_array(node, propname, val, nval); 849 + } 850 + 851 + return -ENXIO; 852 + } 853 + 854 + static int of_fwnode_property_read_string_array(struct fwnode_handle *fwnode, 855 + const char *propname, 856 + const char **val, size_t nval) 857 + { 858 + struct device_node *node = to_of_node(fwnode); 859 + 860 + return val ? 861 + of_property_read_string_array(node, propname, val, nval) : 862 + of_property_count_strings(node, propname); 863 + } 864 + 865 + static struct fwnode_handle *of_fwnode_get_parent(struct fwnode_handle *fwnode) 866 + { 867 + return of_fwnode_handle(of_get_parent(to_of_node(fwnode))); 868 + } 869 + 870 + static struct fwnode_handle * 871 + of_fwnode_get_next_child_node(struct fwnode_handle *fwnode, 872 + struct fwnode_handle *child) 873 + { 874 + return of_fwnode_handle(of_get_next_available_child(to_of_node(fwnode), 875 + to_of_node(child))); 876 + } 877 + 878 + static struct fwnode_handle * 879 + of_fwnode_get_named_child_node(struct fwnode_handle *fwnode, 880 + const char *childname) 881 + { 882 + struct device_node *node = to_of_node(fwnode); 883 + struct device_node *child; 884 + 885 + for_each_available_child_of_node(node, child) 886 + if (!of_node_cmp(child->name, childname)) 887 + return of_fwnode_handle(child); 888 + 889 + return NULL; 890 + } 891 + 892 + static struct fwnode_handle * 893 + of_fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode, 894 + struct fwnode_handle *prev) 895 + { 896 + return of_fwnode_handle(of_graph_get_next_endpoint(to_of_node(fwnode), 897 + to_of_node(prev))); 898 + } 899 + 900 + static struct fwnode_handle * 901 + of_fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode) 902 + { 903 + return of_fwnode_handle(of_parse_phandle(to_of_node(fwnode), 904 + "remote-endpoint", 0)); 905 + } 906 + 907 + static struct fwnode_handle * 908 + of_fwnode_graph_get_port_parent(struct fwnode_handle *fwnode) 909 + { 910 + struct device_node *np; 911 + 912 + /* Get the parent of the port */ 913 + np = of_get_next_parent(to_of_node(fwnode)); 914 + if (!np) 915 + return NULL; 916 + 917 + /* Is this the "ports" node? If not, it's the port parent. */ 918 + if (of_node_cmp(np->name, "ports")) 919 + return of_fwnode_handle(np); 920 + 921 + return of_fwnode_handle(of_get_next_parent(np)); 922 + } 923 + 924 + static int of_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode, 925 + struct fwnode_endpoint *endpoint) 926 + { 927 + struct device_node *node = to_of_node(fwnode); 928 + struct device_node *port_node = of_get_parent(node); 929 + 930 + endpoint->local_fwnode = fwnode; 931 + 932 + of_property_read_u32(port_node, "reg", &endpoint->port); 933 + of_property_read_u32(node, "reg", &endpoint->id); 934 + 935 + of_node_put(port_node); 936 + 937 + return 0; 938 + } 939 + 940 + const struct fwnode_operations of_fwnode_ops = { 941 + .get = of_fwnode_get, 942 + .put = of_fwnode_put, 943 + .device_is_available = of_fwnode_device_is_available, 944 + .property_present = of_fwnode_property_present, 945 + .property_read_int_array = of_fwnode_property_read_int_array, 946 + .property_read_string_array = of_fwnode_property_read_string_array, 947 + .get_parent = of_fwnode_get_parent, 948 + .get_next_child_node = of_fwnode_get_next_child_node, 949 + .get_named_child_node = of_fwnode_get_named_child_node, 950 + .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint, 951 + .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint, 952 + .graph_get_port_parent = of_fwnode_graph_get_port_parent, 953 + .graph_parse_endpoint = of_fwnode_graph_parse_endpoint, 954 + };
+4
include/linux/acpi.h
··· 57 57 acpi_fwnode_handle(adev) : NULL) 58 58 #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) 59 59 60 + 61 + extern const struct fwnode_operations acpi_fwnode_ops; 62 + 60 63 static inline struct fwnode_handle *acpi_alloc_fwnode_static(void) 61 64 { 62 65 struct fwnode_handle *fwnode; ··· 69 66 return NULL; 70 67 71 68 fwnode->type = FWNODE_ACPI_STATIC; 69 + fwnode->ops = &acpi_fwnode_ops; 72 70 73 71 return fwnode; 74 72 }
+69
include/linux/fwnode.h
··· 12 12 #ifndef _LINUX_FWNODE_H_ 13 13 #define _LINUX_FWNODE_H_ 14 14 15 + #include <linux/types.h> 16 + 15 17 enum fwnode_type { 16 18 FWNODE_INVALID = 0, 17 19 FWNODE_OF, ··· 24 22 FWNODE_IRQCHIP 25 23 }; 26 24 25 + struct fwnode_operations; 26 + 27 27 struct fwnode_handle { 28 28 enum fwnode_type type; 29 29 struct fwnode_handle *secondary; 30 + const struct fwnode_operations *ops; 30 31 }; 31 32 32 33 /** ··· 43 38 unsigned int id; 44 39 const struct fwnode_handle *local_fwnode; 45 40 }; 41 + 42 + /** 43 + * struct fwnode_operations - Operations for fwnode interface 44 + * @get: Get a reference to an fwnode. 45 + * @put: Put a reference to an fwnode. 46 + * @property_present: Return true if a property is present. 47 + * @property_read_integer_array: Read an array of integer properties. Return 48 + * zero on success, a negative error code 49 + * otherwise. 50 + * @property_read_string_array: Read an array of string properties. Return zero 51 + * on success, a negative error code otherwise. 52 + * @get_parent: Return the parent of an fwnode. 53 + * @get_next_child_node: Return the next child node in an iteration. 54 + * @get_named_child_node: Return a child node with a given name. 55 + * @graph_get_next_endpoint: Return an endpoint node in an iteration. 56 + * @graph_get_remote_endpoint: Return the remote endpoint node of a local 57 + * endpoint node. 58 + * @graph_get_port_parent: Return the parent node of a port node. 59 + * @graph_parse_endpoint: Parse endpoint for port and endpoint id. 60 + */ 61 + struct fwnode_operations { 62 + void (*get)(struct fwnode_handle *fwnode); 63 + void (*put)(struct fwnode_handle *fwnode); 64 + bool (*device_is_available)(struct fwnode_handle *fwnode); 65 + bool (*property_present)(struct fwnode_handle *fwnode, 66 + const char *propname); 67 + int (*property_read_int_array)(struct fwnode_handle *fwnode, 68 + const char *propname, 69 + unsigned int elem_size, void *val, 70 + size_t nval); 71 + int (*property_read_string_array)(struct fwnode_handle *fwnode_handle, 72 + const char *propname, 73 + const char **val, size_t nval); 74 + struct fwnode_handle *(*get_parent)(struct fwnode_handle *fwnode); 75 + struct fwnode_handle * 76 + (*get_next_child_node)(struct fwnode_handle *fwnode, 77 + struct fwnode_handle *child); 78 + struct fwnode_handle * 79 + (*get_named_child_node)(struct fwnode_handle *fwnode, const char *name); 80 + struct fwnode_handle * 81 + (*graph_get_next_endpoint)(struct fwnode_handle *fwnode, 82 + struct fwnode_handle *prev); 83 + struct fwnode_handle * 84 + (*graph_get_remote_endpoint)(struct fwnode_handle *fwnode); 85 + struct fwnode_handle * 86 + (*graph_get_port_parent)(struct fwnode_handle *fwnode); 87 + int (*graph_parse_endpoint)(struct fwnode_handle *fwnode, 88 + struct fwnode_endpoint *endpoint); 89 + }; 90 + 91 + #define fwnode_has_op(fwnode, op) \ 92 + ((fwnode) && (fwnode)->ops && (fwnode)->ops->op) 93 + #define fwnode_call_int_op(fwnode, op, ...) \ 94 + (fwnode ? (fwnode_has_op(fwnode, op) ? \ 95 + (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \ 96 + -EINVAL) 97 + #define fwnode_call_ptr_op(fwnode, op, ...) \ 98 + (fwnode_has_op(fwnode, op) ? \ 99 + (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : NULL) 100 + #define fwnode_call_void_op(fwnode, op, ...) \ 101 + do { \ 102 + if (fwnode_has_op(fwnode, op)) \ 103 + (fwnode)->ops->op(fwnode, ## __VA_ARGS__); \ 104 + } while (false) 46 105 47 106 #endif
+2
include/linux/of.h
··· 100 100 101 101 /* initialize a node */ 102 102 extern struct kobj_type of_node_ktype; 103 + extern const struct fwnode_operations of_fwnode_ops; 103 104 static inline void of_node_init(struct device_node *node) 104 105 { 105 106 kobject_init(&node->kobj, &of_node_ktype); 106 107 node->fwnode.type = FWNODE_OF; 108 + node->fwnode.ops = &of_fwnode_ops; 107 109 } 108 110 109 111 /* true when node is initialized */
+5
include/linux/property.h
··· 51 51 int device_property_match_string(struct device *dev, 52 52 const char *propname, const char *string); 53 53 54 + bool fwnode_device_is_available(struct fwnode_handle *fwnode); 54 55 bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname); 55 56 int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, 56 57 const char *propname, u8 *val, ··· 275 274 276 275 struct fwnode_handle *fwnode_graph_get_next_endpoint( 277 276 struct fwnode_handle *fwnode, struct fwnode_handle *prev); 277 + struct fwnode_handle * 278 + fwnode_graph_get_port_parent(struct fwnode_handle *fwnode); 278 279 struct fwnode_handle *fwnode_graph_get_remote_port_parent( 279 280 struct fwnode_handle *fwnode); 280 281 struct fwnode_handle *fwnode_graph_get_remote_port( 281 282 struct fwnode_handle *fwnode); 282 283 struct fwnode_handle *fwnode_graph_get_remote_endpoint( 283 284 struct fwnode_handle *fwnode); 285 + struct fwnode_handle *fwnode_graph_get_remote_node(struct fwnode_handle *fwnode, 286 + u32 port, u32 endpoint); 284 287 285 288 int fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode, 286 289 struct fwnode_endpoint *endpoint);