This source file includes following definitions.
- acpi_nondev_subnode_extract
- acpi_nondev_subnode_data_ok
- acpi_nondev_subnode_ok
- acpi_add_nondev_subnodes
- acpi_enumerate_nondev_subnodes
- acpi_property_value_ok
- acpi_properties_format_valid
- acpi_init_of_compatible
- acpi_is_property_guid
- acpi_data_add_props
- acpi_extract_properties
- acpi_init_properties
- acpi_destroy_nondev_subnodes
- acpi_free_properties
- acpi_data_get_property
- acpi_dev_get_property
- acpi_device_data_of_node
- acpi_node_prop_get
- acpi_data_get_property_array
- acpi_fwnode_get_named_child_node
- __acpi_node_get_property_reference
- acpi_data_prop_read_single
- acpi_dev_prop_read_single
- acpi_copy_property_array_u8
- acpi_copy_property_array_u16
- acpi_copy_property_array_u32
- acpi_copy_property_array_u64
- acpi_copy_property_array_string
- acpi_data_prop_read
- acpi_dev_prop_read
- acpi_node_prop_read
- acpi_get_next_subnode
- acpi_node_get_parent
- is_acpi_graph_node
- acpi_graph_get_next_endpoint
- acpi_graph_get_child_prop_value
- acpi_graph_get_remote_endpoint
- acpi_fwnode_device_is_available
- acpi_fwnode_property_present
- acpi_fwnode_property_read_int_array
- acpi_fwnode_property_read_string_array
- acpi_fwnode_get_reference_args
- acpi_fwnode_get_parent
- acpi_fwnode_graph_parse_endpoint
- acpi_fwnode_device_get_match_data
- is_acpi_device_node
- is_acpi_data_node
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 #include <linux/acpi.h>
  14 #include <linux/device.h>
  15 #include <linux/export.h>
  16 
  17 #include "internal.h"
  18 
  19 static int acpi_data_get_property_array(const struct acpi_device_data *data,
  20                                         const char *name,
  21                                         acpi_object_type type,
  22                                         const union acpi_object **obj);
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 static const guid_t prp_guids[] = {
  33         
  34         GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
  35                   0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01),
  36         
  37         GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3,
  38                   0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4),
  39         
  40         GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
  41                   0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
  42         
  43         GUID_INIT(0xc44d002f, 0x69f9, 0x4e7d,
  44                   0xa9, 0x04, 0xa7, 0xba, 0xab, 0xdf, 0x43, 0xf7),
  45         
  46         GUID_INIT(0x6c501103, 0xc189, 0x4296,
  47                   0xba, 0x72, 0x9b, 0xf5, 0xa2, 0x6e, 0xbe, 0x5d),
  48 };
  49 
  50 
  51 static const guid_t ads_guid =
  52         GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
  53                   0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
  54 
  55 static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
  56                                            const union acpi_object *desc,
  57                                            struct acpi_device_data *data,
  58                                            struct fwnode_handle *parent);
  59 static bool acpi_extract_properties(const union acpi_object *desc,
  60                                     struct acpi_device_data *data);
  61 
  62 static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
  63                                         acpi_handle handle,
  64                                         const union acpi_object *link,
  65                                         struct list_head *list,
  66                                         struct fwnode_handle *parent)
  67 {
  68         struct acpi_data_node *dn;
  69         bool result;
  70 
  71         dn = kzalloc(sizeof(*dn), GFP_KERNEL);
  72         if (!dn)
  73                 return false;
  74 
  75         dn->name = link->package.elements[0].string.pointer;
  76         dn->fwnode.ops = &acpi_data_fwnode_ops;
  77         dn->parent = parent;
  78         INIT_LIST_HEAD(&dn->data.properties);
  79         INIT_LIST_HEAD(&dn->data.subnodes);
  80 
  81         result = acpi_extract_properties(desc, &dn->data);
  82 
  83         if (handle) {
  84                 acpi_handle scope;
  85                 acpi_status status;
  86 
  87                 
  88 
  89 
  90 
  91 
  92 
  93                 status = acpi_get_parent(handle, &scope);
  94                 if (ACPI_SUCCESS(status)
  95                     && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data,
  96                                                       &dn->fwnode))
  97                         result = true;
  98         } else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data,
  99                                                   &dn->fwnode)) {
 100                 result = true;
 101         }
 102 
 103         if (result) {
 104                 dn->handle = handle;
 105                 dn->data.pointer = desc;
 106                 list_add_tail(&dn->sibling, list);
 107                 return true;
 108         }
 109 
 110         kfree(dn);
 111         acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
 112         return false;
 113 }
 114 
 115 static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
 116                                         const union acpi_object *link,
 117                                         struct list_head *list,
 118                                         struct fwnode_handle *parent)
 119 {
 120         struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
 121         acpi_status status;
 122 
 123         status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
 124                                             ACPI_TYPE_PACKAGE);
 125         if (ACPI_FAILURE(status))
 126                 return false;
 127 
 128         if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list,
 129                                         parent))
 130                 return true;
 131 
 132         ACPI_FREE(buf.pointer);
 133         return false;
 134 }
 135 
 136 static bool acpi_nondev_subnode_ok(acpi_handle scope,
 137                                    const union acpi_object *link,
 138                                    struct list_head *list,
 139                                    struct fwnode_handle *parent)
 140 {
 141         acpi_handle handle;
 142         acpi_status status;
 143 
 144         if (!scope)
 145                 return false;
 146 
 147         status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
 148                                  &handle);
 149         if (ACPI_FAILURE(status))
 150                 return false;
 151 
 152         return acpi_nondev_subnode_data_ok(handle, link, list, parent);
 153 }
 154 
 155 static int acpi_add_nondev_subnodes(acpi_handle scope,
 156                                     const union acpi_object *links,
 157                                     struct list_head *list,
 158                                     struct fwnode_handle *parent)
 159 {
 160         bool ret = false;
 161         int i;
 162 
 163         for (i = 0; i < links->package.count; i++) {
 164                 const union acpi_object *link, *desc;
 165                 acpi_handle handle;
 166                 bool result;
 167 
 168                 link = &links->package.elements[i];
 169                 
 170                 if (link->package.count != 2)
 171                         continue;
 172 
 173                 
 174                 if (link->package.elements[0].type != ACPI_TYPE_STRING)
 175                         continue;
 176 
 177                 
 178                 switch (link->package.elements[1].type) {
 179                 case ACPI_TYPE_STRING:
 180                         result = acpi_nondev_subnode_ok(scope, link, list,
 181                                                          parent);
 182                         break;
 183                 case ACPI_TYPE_LOCAL_REFERENCE:
 184                         handle = link->package.elements[1].reference.handle;
 185                         result = acpi_nondev_subnode_data_ok(handle, link, list,
 186                                                              parent);
 187                         break;
 188                 case ACPI_TYPE_PACKAGE:
 189                         desc = &link->package.elements[1];
 190                         result = acpi_nondev_subnode_extract(desc, NULL, link,
 191                                                              list, parent);
 192                         break;
 193                 default:
 194                         result = false;
 195                         break;
 196                 }
 197                 ret = ret || result;
 198         }
 199 
 200         return ret;
 201 }
 202 
 203 static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
 204                                            const union acpi_object *desc,
 205                                            struct acpi_device_data *data,
 206                                            struct fwnode_handle *parent)
 207 {
 208         int i;
 209 
 210         
 211         for (i = 0; i < desc->package.count; i += 2) {
 212                 const union acpi_object *guid, *links;
 213 
 214                 guid = &desc->package.elements[i];
 215                 links = &desc->package.elements[i + 1];
 216 
 217                 
 218 
 219 
 220 
 221                 if (guid->type != ACPI_TYPE_BUFFER ||
 222                     guid->buffer.length != 16 ||
 223                     links->type != ACPI_TYPE_PACKAGE)
 224                         break;
 225 
 226                 if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
 227                         continue;
 228 
 229                 return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
 230                                                 parent);
 231         }
 232 
 233         return false;
 234 }
 235 
 236 static bool acpi_property_value_ok(const union acpi_object *value)
 237 {
 238         int j;
 239 
 240         
 241 
 242 
 243 
 244         switch (value->type) {
 245         case ACPI_TYPE_INTEGER:
 246         case ACPI_TYPE_STRING:
 247         case ACPI_TYPE_LOCAL_REFERENCE:
 248                 return true;
 249 
 250         case ACPI_TYPE_PACKAGE:
 251                 for (j = 0; j < value->package.count; j++)
 252                         switch (value->package.elements[j].type) {
 253                         case ACPI_TYPE_INTEGER:
 254                         case ACPI_TYPE_STRING:
 255                         case ACPI_TYPE_LOCAL_REFERENCE:
 256                                 continue;
 257 
 258                         default:
 259                                 return false;
 260                         }
 261 
 262                 return true;
 263         }
 264         return false;
 265 }
 266 
 267 static bool acpi_properties_format_valid(const union acpi_object *properties)
 268 {
 269         int i;
 270 
 271         for (i = 0; i < properties->package.count; i++) {
 272                 const union acpi_object *property;
 273 
 274                 property = &properties->package.elements[i];
 275                 
 276 
 277 
 278 
 279                 if (property->package.count != 2
 280                     || property->package.elements[0].type != ACPI_TYPE_STRING
 281                     || !acpi_property_value_ok(&property->package.elements[1]))
 282                         return false;
 283         }
 284         return true;
 285 }
 286 
 287 static void acpi_init_of_compatible(struct acpi_device *adev)
 288 {
 289         const union acpi_object *of_compatible;
 290         int ret;
 291 
 292         ret = acpi_data_get_property_array(&adev->data, "compatible",
 293                                            ACPI_TYPE_STRING, &of_compatible);
 294         if (ret) {
 295                 ret = acpi_dev_get_property(adev, "compatible",
 296                                             ACPI_TYPE_STRING, &of_compatible);
 297                 if (ret) {
 298                         if (adev->parent
 299                             && adev->parent->flags.of_compatible_ok)
 300                                 goto out;
 301 
 302                         return;
 303                 }
 304         }
 305         adev->data.of_compatible = of_compatible;
 306 
 307  out:
 308         adev->flags.of_compatible_ok = 1;
 309 }
 310 
 311 static bool acpi_is_property_guid(const guid_t *guid)
 312 {
 313         int i;
 314 
 315         for (i = 0; i < ARRAY_SIZE(prp_guids); i++) {
 316                 if (guid_equal(guid, &prp_guids[i]))
 317                         return true;
 318         }
 319 
 320         return false;
 321 }
 322 
 323 struct acpi_device_properties *
 324 acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
 325                     const union acpi_object *properties)
 326 {
 327         struct acpi_device_properties *props;
 328 
 329         props = kzalloc(sizeof(*props), GFP_KERNEL);
 330         if (props) {
 331                 INIT_LIST_HEAD(&props->list);
 332                 props->guid = guid;
 333                 props->properties = properties;
 334                 list_add_tail(&props->list, &data->properties);
 335         }
 336 
 337         return props;
 338 }
 339 
 340 static bool acpi_extract_properties(const union acpi_object *desc,
 341                                     struct acpi_device_data *data)
 342 {
 343         int i;
 344 
 345         if (desc->package.count % 2)
 346                 return false;
 347 
 348         
 349         for (i = 0; i < desc->package.count; i += 2) {
 350                 const union acpi_object *guid, *properties;
 351 
 352                 guid = &desc->package.elements[i];
 353                 properties = &desc->package.elements[i + 1];
 354 
 355                 
 356 
 357 
 358 
 359                 if (guid->type != ACPI_TYPE_BUFFER ||
 360                     guid->buffer.length != 16 ||
 361                     properties->type != ACPI_TYPE_PACKAGE)
 362                         break;
 363 
 364                 if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
 365                         continue;
 366 
 367                 
 368 
 369 
 370 
 371                 if (!acpi_properties_format_valid(properties))
 372                         continue;
 373 
 374                 acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
 375                                     properties);
 376         }
 377 
 378         return !list_empty(&data->properties);
 379 }
 380 
 381 void acpi_init_properties(struct acpi_device *adev)
 382 {
 383         struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
 384         struct acpi_hardware_id *hwid;
 385         acpi_status status;
 386         bool acpi_of = false;
 387 
 388         INIT_LIST_HEAD(&adev->data.properties);
 389         INIT_LIST_HEAD(&adev->data.subnodes);
 390 
 391         if (!adev->handle)
 392                 return;
 393 
 394         
 395 
 396 
 397 
 398         list_for_each_entry(hwid, &adev->pnp.ids, list) {
 399                 if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
 400                         acpi_of = true;
 401                         break;
 402                 }
 403         }
 404 
 405         status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
 406                                             ACPI_TYPE_PACKAGE);
 407         if (ACPI_FAILURE(status))
 408                 goto out;
 409 
 410         if (acpi_extract_properties(buf.pointer, &adev->data)) {
 411                 adev->data.pointer = buf.pointer;
 412                 if (acpi_of)
 413                         acpi_init_of_compatible(adev);
 414         }
 415         if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer,
 416                                         &adev->data, acpi_fwnode_handle(adev)))
 417                 adev->data.pointer = buf.pointer;
 418 
 419         if (!adev->data.pointer) {
 420                 acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
 421                 ACPI_FREE(buf.pointer);
 422         }
 423 
 424  out:
 425         if (acpi_of && !adev->flags.of_compatible_ok)
 426                 acpi_handle_info(adev->handle,
 427                          ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
 428 
 429         if (!adev->data.pointer)
 430                 acpi_extract_apple_properties(adev);
 431 }
 432 
 433 static void acpi_destroy_nondev_subnodes(struct list_head *list)
 434 {
 435         struct acpi_data_node *dn, *next;
 436 
 437         if (list_empty(list))
 438                 return;
 439 
 440         list_for_each_entry_safe_reverse(dn, next, list, sibling) {
 441                 acpi_destroy_nondev_subnodes(&dn->data.subnodes);
 442                 wait_for_completion(&dn->kobj_done);
 443                 list_del(&dn->sibling);
 444                 ACPI_FREE((void *)dn->data.pointer);
 445                 kfree(dn);
 446         }
 447 }
 448 
 449 void acpi_free_properties(struct acpi_device *adev)
 450 {
 451         struct acpi_device_properties *props, *tmp;
 452 
 453         acpi_destroy_nondev_subnodes(&adev->data.subnodes);
 454         ACPI_FREE((void *)adev->data.pointer);
 455         adev->data.of_compatible = NULL;
 456         adev->data.pointer = NULL;
 457         list_for_each_entry_safe(props, tmp, &adev->data.properties, list) {
 458                 list_del(&props->list);
 459                 kfree(props);
 460         }
 461 }
 462 
 463 
 464 
 465 
 466 
 467 
 468 
 469 
 470 
 471 
 472 
 473 
 474 
 475 
 476 
 477 
 478 
 479 
 480 
 481 static int acpi_data_get_property(const struct acpi_device_data *data,
 482                                   const char *name, acpi_object_type type,
 483                                   const union acpi_object **obj)
 484 {
 485         const struct acpi_device_properties *props;
 486 
 487         if (!data || !name)
 488                 return -EINVAL;
 489 
 490         if (!data->pointer || list_empty(&data->properties))
 491                 return -EINVAL;
 492 
 493         list_for_each_entry(props, &data->properties, list) {
 494                 const union acpi_object *properties;
 495                 unsigned int i;
 496 
 497                 properties = props->properties;
 498                 for (i = 0; i < properties->package.count; i++) {
 499                         const union acpi_object *propname, *propvalue;
 500                         const union acpi_object *property;
 501 
 502                         property = &properties->package.elements[i];
 503 
 504                         propname = &property->package.elements[0];
 505                         propvalue = &property->package.elements[1];
 506 
 507                         if (!strcmp(name, propname->string.pointer)) {
 508                                 if (type != ACPI_TYPE_ANY &&
 509                                     propvalue->type != type)
 510                                         return -EPROTO;
 511                                 if (obj)
 512                                         *obj = propvalue;
 513 
 514                                 return 0;
 515                         }
 516                 }
 517         }
 518         return -EINVAL;
 519 }
 520 
 521 
 522 
 523 
 524 
 525 
 526 
 527 
 528 int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
 529                           acpi_object_type type, const union acpi_object **obj)
 530 {
 531         return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
 532 }
 533 EXPORT_SYMBOL_GPL(acpi_dev_get_property);
 534 
 535 static const struct acpi_device_data *
 536 acpi_device_data_of_node(const struct fwnode_handle *fwnode)
 537 {
 538         if (is_acpi_device_node(fwnode)) {
 539                 const struct acpi_device *adev = to_acpi_device_node(fwnode);
 540                 return &adev->data;
 541         } else if (is_acpi_data_node(fwnode)) {
 542                 const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
 543                 return &dn->data;
 544         }
 545         return NULL;
 546 }
 547 
 548 
 549 
 550 
 551 
 552 
 553 
 554 int acpi_node_prop_get(const struct fwnode_handle *fwnode,
 555                        const char *propname, void **valptr)
 556 {
 557         return acpi_data_get_property(acpi_device_data_of_node(fwnode),
 558                                       propname, ACPI_TYPE_ANY,
 559                                       (const union acpi_object **)valptr);
 560 }
 561 
 562 
 563 
 564 
 565 
 566 
 567 
 568 
 569 
 570 
 571 
 572 
 573 
 574 
 575 
 576 
 577 
 578 
 579 
 580 
 581 static int acpi_data_get_property_array(const struct acpi_device_data *data,
 582                                         const char *name,
 583                                         acpi_object_type type,
 584                                         const union acpi_object **obj)
 585 {
 586         const union acpi_object *prop;
 587         int ret, i;
 588 
 589         ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
 590         if (ret)
 591                 return ret;
 592 
 593         if (type != ACPI_TYPE_ANY) {
 594                 
 595                 for (i = 0; i < prop->package.count; i++)
 596                         if (prop->package.elements[i].type != type)
 597                                 return -EPROTO;
 598         }
 599         if (obj)
 600                 *obj = prop;
 601 
 602         return 0;
 603 }
 604 
 605 static struct fwnode_handle *
 606 acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
 607                                  const char *childname)
 608 {
 609         char name[ACPI_PATH_SEGMENT_LENGTH];
 610         struct fwnode_handle *child;
 611         struct acpi_buffer path;
 612         acpi_status status;
 613 
 614         path.length = sizeof(name);
 615         path.pointer = name;
 616 
 617         fwnode_for_each_child_node(fwnode, child) {
 618                 if (is_acpi_data_node(child)) {
 619                         if (acpi_data_node_match(child, childname))
 620                                 return child;
 621                         continue;
 622                 }
 623 
 624                 status = acpi_get_name(ACPI_HANDLE_FWNODE(child),
 625                                        ACPI_SINGLE_NAME, &path);
 626                 if (ACPI_FAILURE(status))
 627                         break;
 628 
 629                 if (!strncmp(name, childname, ACPI_NAMESEG_SIZE))
 630                         return child;
 631         }
 632 
 633         return NULL;
 634 }
 635 
 636 
 637 
 638 
 639 
 640 
 641 
 642 
 643 
 644 
 645 
 646 
 647 
 648 
 649 
 650 
 651 
 652 
 653 
 654 
 655 
 656 
 657 
 658 
 659 
 660 
 661 
 662 
 663 
 664 
 665 
 666 
 667 
 668 
 669 
 670 
 671 int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
 672         const char *propname, size_t index, size_t num_args,
 673         struct fwnode_reference_args *args)
 674 {
 675         const union acpi_object *element, *end;
 676         const union acpi_object *obj;
 677         const struct acpi_device_data *data;
 678         struct acpi_device *device;
 679         int ret, idx = 0;
 680 
 681         data = acpi_device_data_of_node(fwnode);
 682         if (!data)
 683                 return -ENOENT;
 684 
 685         ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
 686         if (ret)
 687                 return ret == -EINVAL ? -ENOENT : -EINVAL;
 688 
 689         
 690 
 691 
 692 
 693         if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
 694                 if (index)
 695                         return -EINVAL;
 696 
 697                 ret = acpi_bus_get_device(obj->reference.handle, &device);
 698                 if (ret)
 699                         return ret == -ENODEV ? -EINVAL : ret;
 700 
 701                 args->fwnode = acpi_fwnode_handle(device);
 702                 args->nargs = 0;
 703                 return 0;
 704         }
 705 
 706         
 707 
 708 
 709 
 710 
 711 
 712 
 713 
 714 
 715         if (obj->type != ACPI_TYPE_PACKAGE)
 716                 return -EINVAL;
 717         if (index >= obj->package.count)
 718                 return -ENOENT;
 719 
 720         element = obj->package.elements;
 721         end = element + obj->package.count;
 722 
 723         while (element < end) {
 724                 u32 nargs, i;
 725 
 726                 if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
 727                         struct fwnode_handle *ref_fwnode;
 728 
 729                         ret = acpi_bus_get_device(element->reference.handle,
 730                                                   &device);
 731                         if (ret)
 732                                 return -EINVAL;
 733 
 734                         nargs = 0;
 735                         element++;
 736 
 737                         
 738 
 739 
 740 
 741                         for (ref_fwnode = acpi_fwnode_handle(device);
 742                              element < end && element->type == ACPI_TYPE_STRING;
 743                              element++) {
 744                                 ref_fwnode = acpi_fwnode_get_named_child_node(
 745                                         ref_fwnode, element->string.pointer);
 746                                 if (!ref_fwnode)
 747                                         return -EINVAL;
 748                         }
 749 
 750                         
 751                         for (i = 0; element + i < end && i < num_args; i++) {
 752                                 int type = element[i].type;
 753 
 754                                 if (type == ACPI_TYPE_INTEGER)
 755                                         nargs++;
 756                                 else if (type == ACPI_TYPE_LOCAL_REFERENCE)
 757                                         break;
 758                                 else
 759                                         return -EINVAL;
 760                         }
 761 
 762                         if (nargs > NR_FWNODE_REFERENCE_ARGS)
 763                                 return -EINVAL;
 764 
 765                         if (idx == index) {
 766                                 args->fwnode = ref_fwnode;
 767                                 args->nargs = nargs;
 768                                 for (i = 0; i < nargs; i++)
 769                                         args->args[i] = element[i].integer.value;
 770 
 771                                 return 0;
 772                         }
 773 
 774                         element += nargs;
 775                 } else if (element->type == ACPI_TYPE_INTEGER) {
 776                         if (idx == index)
 777                                 return -ENOENT;
 778                         element++;
 779                 } else {
 780                         return -EINVAL;
 781                 }
 782 
 783                 idx++;
 784         }
 785 
 786         return -ENOENT;
 787 }
 788 EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
 789 
 790 static int acpi_data_prop_read_single(const struct acpi_device_data *data,
 791                                       const char *propname,
 792                                       enum dev_prop_type proptype, void *val)
 793 {
 794         const union acpi_object *obj;
 795         int ret;
 796 
 797         if (!val)
 798                 return -EINVAL;
 799 
 800         if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
 801                 ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
 802                 if (ret)
 803                         return ret;
 804 
 805                 switch (proptype) {
 806                 case DEV_PROP_U8:
 807                         if (obj->integer.value > U8_MAX)
 808                                 return -EOVERFLOW;
 809                         *(u8 *)val = obj->integer.value;
 810                         break;
 811                 case DEV_PROP_U16:
 812                         if (obj->integer.value > U16_MAX)
 813                                 return -EOVERFLOW;
 814                         *(u16 *)val = obj->integer.value;
 815                         break;
 816                 case DEV_PROP_U32:
 817                         if (obj->integer.value > U32_MAX)
 818                                 return -EOVERFLOW;
 819                         *(u32 *)val = obj->integer.value;
 820                         break;
 821                 default:
 822                         *(u64 *)val = obj->integer.value;
 823                         break;
 824                 }
 825         } else if (proptype == DEV_PROP_STRING) {
 826                 ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
 827                 if (ret)
 828                         return ret;
 829 
 830                 *(char **)val = obj->string.pointer;
 831 
 832                 return 1;
 833         } else {
 834                 ret = -EINVAL;
 835         }
 836         return ret;
 837 }
 838 
 839 int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
 840                               enum dev_prop_type proptype, void *val)
 841 {
 842         int ret;
 843 
 844         if (!adev)
 845                 return -EINVAL;
 846 
 847         ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val);
 848         if (ret < 0 || proptype != ACPI_TYPE_STRING)
 849                 return ret;
 850         return 0;
 851 }
 852 
 853 static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
 854                                        size_t nval)
 855 {
 856         int i;
 857 
 858         for (i = 0; i < nval; i++) {
 859                 if (items[i].type != ACPI_TYPE_INTEGER)
 860                         return -EPROTO;
 861                 if (items[i].integer.value > U8_MAX)
 862                         return -EOVERFLOW;
 863 
 864                 val[i] = items[i].integer.value;
 865         }
 866         return 0;
 867 }
 868 
 869 static int acpi_copy_property_array_u16(const union acpi_object *items,
 870                                         u16 *val, size_t nval)
 871 {
 872         int i;
 873 
 874         for (i = 0; i < nval; i++) {
 875                 if (items[i].type != ACPI_TYPE_INTEGER)
 876                         return -EPROTO;
 877                 if (items[i].integer.value > U16_MAX)
 878                         return -EOVERFLOW;
 879 
 880                 val[i] = items[i].integer.value;
 881         }
 882         return 0;
 883 }
 884 
 885 static int acpi_copy_property_array_u32(const union acpi_object *items,
 886                                         u32 *val, size_t nval)
 887 {
 888         int i;
 889 
 890         for (i = 0; i < nval; i++) {
 891                 if (items[i].type != ACPI_TYPE_INTEGER)
 892                         return -EPROTO;
 893                 if (items[i].integer.value > U32_MAX)
 894                         return -EOVERFLOW;
 895 
 896                 val[i] = items[i].integer.value;
 897         }
 898         return 0;
 899 }
 900 
 901 static int acpi_copy_property_array_u64(const union acpi_object *items,
 902                                         u64 *val, size_t nval)
 903 {
 904         int i;
 905 
 906         for (i = 0; i < nval; i++) {
 907                 if (items[i].type != ACPI_TYPE_INTEGER)
 908                         return -EPROTO;
 909 
 910                 val[i] = items[i].integer.value;
 911         }
 912         return 0;
 913 }
 914 
 915 static int acpi_copy_property_array_string(const union acpi_object *items,
 916                                            char **val, size_t nval)
 917 {
 918         int i;
 919 
 920         for (i = 0; i < nval; i++) {
 921                 if (items[i].type != ACPI_TYPE_STRING)
 922                         return -EPROTO;
 923 
 924                 val[i] = items[i].string.pointer;
 925         }
 926         return nval;
 927 }
 928 
 929 static int acpi_data_prop_read(const struct acpi_device_data *data,
 930                                const char *propname,
 931                                enum dev_prop_type proptype,
 932                                void *val, size_t nval)
 933 {
 934         const union acpi_object *obj;
 935         const union acpi_object *items;
 936         int ret;
 937 
 938         if (val && nval == 1) {
 939                 ret = acpi_data_prop_read_single(data, propname, proptype, val);
 940                 if (ret >= 0)
 941                         return ret;
 942         }
 943 
 944         ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
 945         if (ret)
 946                 return ret;
 947 
 948         if (!val)
 949                 return obj->package.count;
 950 
 951         if (proptype != DEV_PROP_STRING && nval > obj->package.count)
 952                 return -EOVERFLOW;
 953         else if (nval <= 0)
 954                 return -EINVAL;
 955 
 956         items = obj->package.elements;
 957 
 958         switch (proptype) {
 959         case DEV_PROP_U8:
 960                 ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
 961                 break;
 962         case DEV_PROP_U16:
 963                 ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
 964                 break;
 965         case DEV_PROP_U32:
 966                 ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
 967                 break;
 968         case DEV_PROP_U64:
 969                 ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
 970                 break;
 971         case DEV_PROP_STRING:
 972                 ret = acpi_copy_property_array_string(
 973                         items, (char **)val,
 974                         min_t(u32, nval, obj->package.count));
 975                 break;
 976         default:
 977                 ret = -EINVAL;
 978                 break;
 979         }
 980         return ret;
 981 }
 982 
 983 int acpi_dev_prop_read(const struct acpi_device *adev, const char *propname,
 984                        enum dev_prop_type proptype, void *val, size_t nval)
 985 {
 986         return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
 987 }
 988 
 989 
 990 
 991 
 992 
 993 
 994 
 995 
 996 
 997 
 998 
 999 
1000 
1001 int acpi_node_prop_read(const struct fwnode_handle *fwnode,
1002                         const char *propname, enum dev_prop_type proptype,
1003                         void *val, size_t nval)
1004 {
1005         return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
1006                                    propname, proptype, val, nval);
1007 }
1008 
1009 
1010 
1011 
1012 
1013 
1014 struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
1015                                             struct fwnode_handle *child)
1016 {
1017         const struct acpi_device *adev = to_acpi_device_node(fwnode);
1018         const struct list_head *head;
1019         struct list_head *next;
1020 
1021         if (!child || is_acpi_device_node(child)) {
1022                 struct acpi_device *child_adev;
1023 
1024                 if (adev)
1025                         head = &adev->children;
1026                 else
1027                         goto nondev;
1028 
1029                 if (list_empty(head))
1030                         goto nondev;
1031 
1032                 if (child) {
1033                         adev = to_acpi_device_node(child);
1034                         next = adev->node.next;
1035                         if (next == head) {
1036                                 child = NULL;
1037                                 goto nondev;
1038                         }
1039                         child_adev = list_entry(next, struct acpi_device, node);
1040                 } else {
1041                         child_adev = list_first_entry(head, struct acpi_device,
1042                                                       node);
1043                 }
1044                 return acpi_fwnode_handle(child_adev);
1045         }
1046 
1047  nondev:
1048         if (!child || is_acpi_data_node(child)) {
1049                 const struct acpi_data_node *data = to_acpi_data_node(fwnode);
1050                 struct acpi_data_node *dn;
1051 
1052                 
1053 
1054 
1055 
1056 
1057 
1058 
1059                 adev = to_acpi_device_node(fwnode);
1060                 if (adev)
1061                         head = &adev->data.subnodes;
1062                 else if (data)
1063                         head = &data->data.subnodes;
1064                 else
1065                         return NULL;
1066 
1067                 if (list_empty(head))
1068                         return NULL;
1069 
1070                 if (child) {
1071                         dn = to_acpi_data_node(child);
1072                         next = dn->sibling.next;
1073                         if (next == head)
1074                                 return NULL;
1075 
1076                         dn = list_entry(next, struct acpi_data_node, sibling);
1077                 } else {
1078                         dn = list_first_entry(head, struct acpi_data_node, sibling);
1079                 }
1080                 return &dn->fwnode;
1081         }
1082         return NULL;
1083 }
1084 
1085 
1086 
1087 
1088 
1089 
1090 
1091 
1092 struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode)
1093 {
1094         if (is_acpi_data_node(fwnode)) {
1095                 
1096                 return to_acpi_data_node(fwnode)->parent;
1097         } else if (is_acpi_device_node(fwnode)) {
1098                 acpi_handle handle, parent_handle;
1099 
1100                 handle = to_acpi_device_node(fwnode)->handle;
1101                 if (ACPI_SUCCESS(acpi_get_parent(handle, &parent_handle))) {
1102                         struct acpi_device *adev;
1103 
1104                         if (!acpi_bus_get_device(parent_handle, &adev))
1105                                 return acpi_fwnode_handle(adev);
1106                 }
1107         }
1108 
1109         return NULL;
1110 }
1111 
1112 
1113 
1114 
1115 
1116 static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
1117                                const char *str)
1118 {
1119         unsigned int len = strlen(str);
1120         const char *name;
1121 
1122         if (!len || !is_acpi_data_node(fwnode))
1123                 return false;
1124 
1125         name = to_acpi_data_node(fwnode)->name;
1126 
1127         return (fwnode_property_present(fwnode, "reg") &&
1128                 !strncmp(name, str, len) && name[len] == '@') ||
1129                 fwnode_property_present(fwnode, str);
1130 }
1131 
1132 
1133 
1134 
1135 
1136 
1137 
1138 
1139 
1140 
1141 static struct fwnode_handle *acpi_graph_get_next_endpoint(
1142         const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
1143 {
1144         struct fwnode_handle *port = NULL;
1145         struct fwnode_handle *endpoint;
1146 
1147         if (!prev) {
1148                 do {
1149                         port = fwnode_get_next_child_node(fwnode, port);
1150                         
1151 
1152 
1153 
1154 
1155 
1156 
1157                         if (is_acpi_graph_node(port, "port"))
1158                                 break;
1159                 } while (port);
1160         } else {
1161                 port = fwnode_get_parent(prev);
1162         }
1163 
1164         if (!port)
1165                 return NULL;
1166 
1167         endpoint = fwnode_get_next_child_node(port, prev);
1168         while (!endpoint) {
1169                 port = fwnode_get_next_child_node(fwnode, port);
1170                 if (!port)
1171                         break;
1172                 if (is_acpi_graph_node(port, "port"))
1173                         endpoint = fwnode_get_next_child_node(port, NULL);
1174         }
1175 
1176         
1177 
1178 
1179 
1180 
1181 
1182 
1183         if (!is_acpi_graph_node(endpoint, "endpoint"))
1184                 return NULL;
1185 
1186         return endpoint;
1187 }
1188 
1189 
1190 
1191 
1192 
1193 
1194 
1195 
1196 
1197 
1198 static struct fwnode_handle *acpi_graph_get_child_prop_value(
1199         const struct fwnode_handle *fwnode, const char *prop_name,
1200         unsigned int val)
1201 {
1202         struct fwnode_handle *child;
1203 
1204         fwnode_for_each_child_node(fwnode, child) {
1205                 u32 nr;
1206 
1207                 if (fwnode_property_read_u32(child, prop_name, &nr))
1208                         continue;
1209 
1210                 if (val == nr)
1211                         return child;
1212         }
1213 
1214         return NULL;
1215 }
1216 
1217 
1218 
1219 
1220 
1221 
1222 
1223 
1224 
1225 static struct fwnode_handle *
1226 acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
1227 {
1228         struct fwnode_handle *fwnode;
1229         unsigned int port_nr, endpoint_nr;
1230         struct fwnode_reference_args args;
1231         int ret;
1232 
1233         memset(&args, 0, sizeof(args));
1234         ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
1235                                                &args);
1236         if (ret)
1237                 return NULL;
1238 
1239         
1240         if (!is_acpi_device_node(args.fwnode))
1241                 return args.nargs ? NULL : args.fwnode;
1242 
1243         
1244 
1245 
1246 
1247         if (args.nargs != 2)
1248                 return NULL;
1249 
1250         fwnode = args.fwnode;
1251         port_nr = args.args[0];
1252         endpoint_nr = args.args[1];
1253 
1254         fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
1255 
1256         return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
1257 }
1258 
1259 static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
1260 {
1261         if (!is_acpi_device_node(fwnode))
1262                 return false;
1263 
1264         return acpi_device_is_present(to_acpi_device_node(fwnode));
1265 }
1266 
1267 static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
1268                                          const char *propname)
1269 {
1270         return !acpi_node_prop_get(fwnode, propname, NULL);
1271 }
1272 
1273 static int
1274 acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
1275                                     const char *propname,
1276                                     unsigned int elem_size, void *val,
1277                                     size_t nval)
1278 {
1279         enum dev_prop_type type;
1280 
1281         switch (elem_size) {
1282         case sizeof(u8):
1283                 type = DEV_PROP_U8;
1284                 break;
1285         case sizeof(u16):
1286                 type = DEV_PROP_U16;
1287                 break;
1288         case sizeof(u32):
1289                 type = DEV_PROP_U32;
1290                 break;
1291         case sizeof(u64):
1292                 type = DEV_PROP_U64;
1293                 break;
1294         default:
1295                 return -ENXIO;
1296         }
1297 
1298         return acpi_node_prop_read(fwnode, propname, type, val, nval);
1299 }
1300 
1301 static int
1302 acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
1303                                        const char *propname, const char **val,
1304                                        size_t nval)
1305 {
1306         return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
1307                                    val, nval);
1308 }
1309 
1310 static int
1311 acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
1312                                const char *prop, const char *nargs_prop,
1313                                unsigned int args_count, unsigned int index,
1314                                struct fwnode_reference_args *args)
1315 {
1316         return __acpi_node_get_property_reference(fwnode, prop, index,
1317                                                   args_count, args);
1318 }
1319 
1320 static struct fwnode_handle *
1321 acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
1322 {
1323         return acpi_node_get_parent(fwnode);
1324 }
1325 
1326 static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
1327                                             struct fwnode_endpoint *endpoint)
1328 {
1329         struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
1330 
1331         endpoint->local_fwnode = fwnode;
1332 
1333         if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
1334                 fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
1335         if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
1336                 fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
1337 
1338         return 0;
1339 }
1340 
1341 static const void *
1342 acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
1343                                   const struct device *dev)
1344 {
1345         return acpi_device_get_match_data(dev);
1346 }
1347 
1348 #define DECLARE_ACPI_FWNODE_OPS(ops) \
1349         const struct fwnode_operations ops = {                          \
1350                 .device_is_available = acpi_fwnode_device_is_available, \
1351                 .device_get_match_data = acpi_fwnode_device_get_match_data, \
1352                 .property_present = acpi_fwnode_property_present,       \
1353                 .property_read_int_array =                              \
1354                         acpi_fwnode_property_read_int_array,            \
1355                 .property_read_string_array =                           \
1356                         acpi_fwnode_property_read_string_array,         \
1357                 .get_parent = acpi_node_get_parent,                     \
1358                 .get_next_child_node = acpi_get_next_subnode,           \
1359                 .get_named_child_node = acpi_fwnode_get_named_child_node, \
1360                 .get_reference_args = acpi_fwnode_get_reference_args,   \
1361                 .graph_get_next_endpoint =                              \
1362                         acpi_graph_get_next_endpoint,                   \
1363                 .graph_get_remote_endpoint =                            \
1364                         acpi_graph_get_remote_endpoint,                 \
1365                 .graph_get_port_parent = acpi_fwnode_get_parent,        \
1366                 .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
1367         };                                                              \
1368         EXPORT_SYMBOL_GPL(ops)
1369 
1370 DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
1371 DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
1372 const struct fwnode_operations acpi_static_fwnode_ops;
1373 
1374 bool is_acpi_device_node(const struct fwnode_handle *fwnode)
1375 {
1376         return !IS_ERR_OR_NULL(fwnode) &&
1377                 fwnode->ops == &acpi_device_fwnode_ops;
1378 }
1379 EXPORT_SYMBOL(is_acpi_device_node);
1380 
1381 bool is_acpi_data_node(const struct fwnode_handle *fwnode)
1382 {
1383         return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
1384 }
1385 EXPORT_SYMBOL(is_acpi_data_node);