0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/acpi.h>
0014 #include <linux/device.h>
0015 #include <linux/export.h>
0016
0017 #include "internal.h"
0018
0019 static int acpi_data_get_property_array(const struct acpi_device_data *data,
0020 const char *name,
0021 acpi_object_type type,
0022 const union acpi_object **obj);
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 static const guid_t prp_guids[] = {
0033
0034 GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
0035 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01),
0036
0037 GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3,
0038 0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4),
0039
0040 GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
0041 0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
0042
0043 GUID_INIT(0xc44d002f, 0x69f9, 0x4e7d,
0044 0xa9, 0x04, 0xa7, 0xba, 0xab, 0xdf, 0x43, 0xf7),
0045
0046 GUID_INIT(0x6c501103, 0xc189, 0x4296,
0047 0xba, 0x72, 0x9b, 0xf5, 0xa2, 0x6e, 0xbe, 0x5d),
0048
0049 GUID_INIT(0x5025030f, 0x842f, 0x4ab4,
0050 0xa5, 0x61, 0x99, 0xa5, 0x18, 0x97, 0x62, 0xd0),
0051 };
0052
0053
0054 static const guid_t ads_guid =
0055 GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
0056 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
0057
0058 static const guid_t buffer_prop_guid =
0059 GUID_INIT(0xedb12dd0, 0x363d, 0x4085,
0060 0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4);
0061
0062 static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
0063 union acpi_object *desc,
0064 struct acpi_device_data *data,
0065 struct fwnode_handle *parent);
0066 static bool acpi_extract_properties(acpi_handle handle,
0067 union acpi_object *desc,
0068 struct acpi_device_data *data);
0069
0070 static bool acpi_nondev_subnode_extract(union acpi_object *desc,
0071 acpi_handle handle,
0072 const union acpi_object *link,
0073 struct list_head *list,
0074 struct fwnode_handle *parent)
0075 {
0076 struct acpi_data_node *dn;
0077 bool result;
0078
0079 dn = kzalloc(sizeof(*dn), GFP_KERNEL);
0080 if (!dn)
0081 return false;
0082
0083 dn->name = link->package.elements[0].string.pointer;
0084 fwnode_init(&dn->fwnode, &acpi_data_fwnode_ops);
0085 dn->parent = parent;
0086 INIT_LIST_HEAD(&dn->data.properties);
0087 INIT_LIST_HEAD(&dn->data.subnodes);
0088
0089 result = acpi_extract_properties(handle, desc, &dn->data);
0090
0091 if (handle) {
0092 acpi_handle scope;
0093 acpi_status status;
0094
0095
0096
0097
0098
0099
0100
0101 status = acpi_get_parent(handle, &scope);
0102 if (ACPI_SUCCESS(status)
0103 && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data,
0104 &dn->fwnode))
0105 result = true;
0106 } else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data,
0107 &dn->fwnode)) {
0108 result = true;
0109 }
0110
0111 if (result) {
0112 dn->handle = handle;
0113 dn->data.pointer = desc;
0114 list_add_tail(&dn->sibling, list);
0115 return true;
0116 }
0117
0118 kfree(dn);
0119 acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
0120 return false;
0121 }
0122
0123 static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
0124 const union acpi_object *link,
0125 struct list_head *list,
0126 struct fwnode_handle *parent)
0127 {
0128 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
0129 acpi_status status;
0130
0131 status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
0132 ACPI_TYPE_PACKAGE);
0133 if (ACPI_FAILURE(status))
0134 return false;
0135
0136 if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list,
0137 parent))
0138 return true;
0139
0140 ACPI_FREE(buf.pointer);
0141 return false;
0142 }
0143
0144 static bool acpi_nondev_subnode_ok(acpi_handle scope,
0145 const union acpi_object *link,
0146 struct list_head *list,
0147 struct fwnode_handle *parent)
0148 {
0149 acpi_handle handle;
0150 acpi_status status;
0151
0152 if (!scope)
0153 return false;
0154
0155 status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
0156 &handle);
0157 if (ACPI_FAILURE(status))
0158 return false;
0159
0160 return acpi_nondev_subnode_data_ok(handle, link, list, parent);
0161 }
0162
0163 static bool acpi_add_nondev_subnodes(acpi_handle scope,
0164 union acpi_object *links,
0165 struct list_head *list,
0166 struct fwnode_handle *parent)
0167 {
0168 bool ret = false;
0169 int i;
0170
0171 for (i = 0; i < links->package.count; i++) {
0172 union acpi_object *link, *desc;
0173 acpi_handle handle;
0174 bool result;
0175
0176 link = &links->package.elements[i];
0177
0178 if (link->package.count != 2)
0179 continue;
0180
0181
0182 if (link->package.elements[0].type != ACPI_TYPE_STRING)
0183 continue;
0184
0185
0186 switch (link->package.elements[1].type) {
0187 case ACPI_TYPE_STRING:
0188 result = acpi_nondev_subnode_ok(scope, link, list,
0189 parent);
0190 break;
0191 case ACPI_TYPE_LOCAL_REFERENCE:
0192 handle = link->package.elements[1].reference.handle;
0193 result = acpi_nondev_subnode_data_ok(handle, link, list,
0194 parent);
0195 break;
0196 case ACPI_TYPE_PACKAGE:
0197 desc = &link->package.elements[1];
0198 result = acpi_nondev_subnode_extract(desc, NULL, link,
0199 list, parent);
0200 break;
0201 default:
0202 result = false;
0203 break;
0204 }
0205 ret = ret || result;
0206 }
0207
0208 return ret;
0209 }
0210
0211 static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
0212 union acpi_object *desc,
0213 struct acpi_device_data *data,
0214 struct fwnode_handle *parent)
0215 {
0216 int i;
0217
0218
0219 for (i = 0; i < desc->package.count; i += 2) {
0220 const union acpi_object *guid;
0221 union acpi_object *links;
0222
0223 guid = &desc->package.elements[i];
0224 links = &desc->package.elements[i + 1];
0225
0226
0227
0228
0229
0230 if (guid->type != ACPI_TYPE_BUFFER ||
0231 guid->buffer.length != 16 ||
0232 links->type != ACPI_TYPE_PACKAGE)
0233 break;
0234
0235 if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
0236 continue;
0237
0238 return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
0239 parent);
0240 }
0241
0242 return false;
0243 }
0244
0245 static bool acpi_property_value_ok(const union acpi_object *value)
0246 {
0247 int j;
0248
0249
0250
0251
0252
0253 switch (value->type) {
0254 case ACPI_TYPE_INTEGER:
0255 case ACPI_TYPE_STRING:
0256 case ACPI_TYPE_LOCAL_REFERENCE:
0257 return true;
0258
0259 case ACPI_TYPE_PACKAGE:
0260 for (j = 0; j < value->package.count; j++)
0261 switch (value->package.elements[j].type) {
0262 case ACPI_TYPE_INTEGER:
0263 case ACPI_TYPE_STRING:
0264 case ACPI_TYPE_LOCAL_REFERENCE:
0265 continue;
0266
0267 default:
0268 return false;
0269 }
0270
0271 return true;
0272 }
0273 return false;
0274 }
0275
0276 static bool acpi_properties_format_valid(const union acpi_object *properties)
0277 {
0278 int i;
0279
0280 for (i = 0; i < properties->package.count; i++) {
0281 const union acpi_object *property;
0282
0283 property = &properties->package.elements[i];
0284
0285
0286
0287
0288 if (property->package.count != 2
0289 || property->package.elements[0].type != ACPI_TYPE_STRING
0290 || !acpi_property_value_ok(&property->package.elements[1]))
0291 return false;
0292 }
0293 return true;
0294 }
0295
0296 static void acpi_init_of_compatible(struct acpi_device *adev)
0297 {
0298 const union acpi_object *of_compatible;
0299 int ret;
0300
0301 ret = acpi_data_get_property_array(&adev->data, "compatible",
0302 ACPI_TYPE_STRING, &of_compatible);
0303 if (ret) {
0304 ret = acpi_dev_get_property(adev, "compatible",
0305 ACPI_TYPE_STRING, &of_compatible);
0306 if (ret) {
0307 if (adev->parent
0308 && adev->parent->flags.of_compatible_ok)
0309 goto out;
0310
0311 return;
0312 }
0313 }
0314 adev->data.of_compatible = of_compatible;
0315
0316 out:
0317 adev->flags.of_compatible_ok = 1;
0318 }
0319
0320 static bool acpi_is_property_guid(const guid_t *guid)
0321 {
0322 int i;
0323
0324 for (i = 0; i < ARRAY_SIZE(prp_guids); i++) {
0325 if (guid_equal(guid, &prp_guids[i]))
0326 return true;
0327 }
0328
0329 return false;
0330 }
0331
0332 struct acpi_device_properties *
0333 acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
0334 union acpi_object *properties)
0335 {
0336 struct acpi_device_properties *props;
0337
0338 props = kzalloc(sizeof(*props), GFP_KERNEL);
0339 if (props) {
0340 INIT_LIST_HEAD(&props->list);
0341 props->guid = guid;
0342 props->properties = properties;
0343 list_add_tail(&props->list, &data->properties);
0344 }
0345
0346 return props;
0347 }
0348
0349 static void acpi_nondev_subnode_tag(acpi_handle handle, void *context)
0350 {
0351 }
0352
0353 static void acpi_untie_nondev_subnodes(struct acpi_device_data *data)
0354 {
0355 struct acpi_data_node *dn;
0356
0357 list_for_each_entry(dn, &data->subnodes, sibling) {
0358 acpi_detach_data(dn->handle, acpi_nondev_subnode_tag);
0359
0360 acpi_untie_nondev_subnodes(&dn->data);
0361 }
0362 }
0363
0364 static bool acpi_tie_nondev_subnodes(struct acpi_device_data *data)
0365 {
0366 struct acpi_data_node *dn;
0367
0368 list_for_each_entry(dn, &data->subnodes, sibling) {
0369 acpi_status status;
0370 bool ret;
0371
0372 status = acpi_attach_data(dn->handle, acpi_nondev_subnode_tag, dn);
0373 if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) {
0374 acpi_handle_err(dn->handle, "Can't tag data node\n");
0375 return false;
0376 }
0377
0378 ret = acpi_tie_nondev_subnodes(&dn->data);
0379 if (!ret)
0380 return ret;
0381 }
0382
0383 return true;
0384 }
0385
0386 static void acpi_data_add_buffer_props(acpi_handle handle,
0387 struct acpi_device_data *data,
0388 union acpi_object *properties)
0389 {
0390 struct acpi_device_properties *props;
0391 union acpi_object *package;
0392 size_t alloc_size;
0393 unsigned int i;
0394 u32 *count;
0395
0396 if (check_mul_overflow((size_t)properties->package.count,
0397 sizeof(*package) + sizeof(void *),
0398 &alloc_size) ||
0399 check_add_overflow(sizeof(*props) + sizeof(*package), alloc_size,
0400 &alloc_size)) {
0401 acpi_handle_warn(handle,
0402 "can't allocate memory for %u buffer props",
0403 properties->package.count);
0404 return;
0405 }
0406
0407 props = kvzalloc(alloc_size, GFP_KERNEL);
0408 if (!props)
0409 return;
0410
0411 props->guid = &buffer_prop_guid;
0412 props->bufs = (void *)(props + 1);
0413 props->properties = (void *)(props->bufs + properties->package.count);
0414
0415
0416 package = props->properties;
0417 package->type = ACPI_TYPE_PACKAGE;
0418 package->package.elements = package + 1;
0419 count = &package->package.count;
0420 *count = 0;
0421
0422
0423 package++;
0424
0425 for (i = 0; i < properties->package.count; i++) {
0426 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
0427 union acpi_object *property = &properties->package.elements[i];
0428 union acpi_object *prop, *obj, *buf_obj;
0429 acpi_status status;
0430
0431 if (property->type != ACPI_TYPE_PACKAGE ||
0432 property->package.count != 2) {
0433 acpi_handle_warn(handle,
0434 "buffer property %u has %u entries\n",
0435 i, property->package.count);
0436 continue;
0437 }
0438
0439 prop = &property->package.elements[0];
0440 obj = &property->package.elements[1];
0441
0442 if (prop->type != ACPI_TYPE_STRING ||
0443 obj->type != ACPI_TYPE_STRING) {
0444 acpi_handle_warn(handle,
0445 "wrong object types %u and %u\n",
0446 prop->type, obj->type);
0447 continue;
0448 }
0449
0450 status = acpi_evaluate_object_typed(handle, obj->string.pointer,
0451 NULL, &buf,
0452 ACPI_TYPE_BUFFER);
0453 if (ACPI_FAILURE(status)) {
0454 acpi_handle_warn(handle,
0455 "can't evaluate \"%*pE\" as buffer\n",
0456 obj->string.length,
0457 obj->string.pointer);
0458 continue;
0459 }
0460
0461 package->type = ACPI_TYPE_PACKAGE;
0462 package->package.elements = prop;
0463 package->package.count = 2;
0464
0465 buf_obj = buf.pointer;
0466
0467
0468 obj->type = ACPI_TYPE_BUFFER;
0469 obj->buffer.length = buf_obj->buffer.length;
0470 obj->buffer.pointer = buf_obj->buffer.pointer;
0471
0472 props->bufs[i] = buf.pointer;
0473 package++;
0474 (*count)++;
0475 }
0476
0477 if (*count)
0478 list_add(&props->list, &data->properties);
0479 else
0480 kvfree(props);
0481 }
0482
0483 static bool acpi_extract_properties(acpi_handle scope, union acpi_object *desc,
0484 struct acpi_device_data *data)
0485 {
0486 int i;
0487
0488 if (desc->package.count % 2)
0489 return false;
0490
0491
0492 for (i = 0; i < desc->package.count; i += 2) {
0493 const union acpi_object *guid;
0494 union acpi_object *properties;
0495
0496 guid = &desc->package.elements[i];
0497 properties = &desc->package.elements[i + 1];
0498
0499
0500
0501
0502
0503 if (guid->type != ACPI_TYPE_BUFFER ||
0504 guid->buffer.length != 16 ||
0505 properties->type != ACPI_TYPE_PACKAGE)
0506 break;
0507
0508 if (guid_equal((guid_t *)guid->buffer.pointer,
0509 &buffer_prop_guid)) {
0510 acpi_data_add_buffer_props(scope, data, properties);
0511 continue;
0512 }
0513
0514 if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
0515 continue;
0516
0517
0518
0519
0520
0521 if (!acpi_properties_format_valid(properties))
0522 continue;
0523
0524 acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
0525 properties);
0526 }
0527
0528 return !list_empty(&data->properties);
0529 }
0530
0531 void acpi_init_properties(struct acpi_device *adev)
0532 {
0533 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
0534 struct acpi_hardware_id *hwid;
0535 acpi_status status;
0536 bool acpi_of = false;
0537
0538 INIT_LIST_HEAD(&adev->data.properties);
0539 INIT_LIST_HEAD(&adev->data.subnodes);
0540
0541 if (!adev->handle)
0542 return;
0543
0544
0545
0546
0547
0548 list_for_each_entry(hwid, &adev->pnp.ids, list) {
0549 if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
0550 acpi_of = true;
0551 break;
0552 }
0553 }
0554
0555 status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
0556 ACPI_TYPE_PACKAGE);
0557 if (ACPI_FAILURE(status))
0558 goto out;
0559
0560 if (acpi_extract_properties(adev->handle, buf.pointer, &adev->data)) {
0561 adev->data.pointer = buf.pointer;
0562 if (acpi_of)
0563 acpi_init_of_compatible(adev);
0564 }
0565 if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer,
0566 &adev->data, acpi_fwnode_handle(adev)))
0567 adev->data.pointer = buf.pointer;
0568
0569 if (!adev->data.pointer) {
0570 acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
0571 ACPI_FREE(buf.pointer);
0572 } else {
0573 if (!acpi_tie_nondev_subnodes(&adev->data))
0574 acpi_untie_nondev_subnodes(&adev->data);
0575 }
0576
0577 out:
0578 if (acpi_of && !adev->flags.of_compatible_ok)
0579 acpi_handle_info(adev->handle,
0580 ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
0581
0582 if (!adev->data.pointer)
0583 acpi_extract_apple_properties(adev);
0584 }
0585
0586 static void acpi_free_device_properties(struct list_head *list)
0587 {
0588 struct acpi_device_properties *props, *tmp;
0589
0590 list_for_each_entry_safe(props, tmp, list, list) {
0591 u32 i;
0592
0593 list_del(&props->list);
0594
0595 if (props->bufs)
0596 for (i = 0; i < props->properties->package.count; i++)
0597 ACPI_FREE(props->bufs[i]);
0598 kvfree(props);
0599 }
0600 }
0601
0602 static void acpi_destroy_nondev_subnodes(struct list_head *list)
0603 {
0604 struct acpi_data_node *dn, *next;
0605
0606 if (list_empty(list))
0607 return;
0608
0609 list_for_each_entry_safe_reverse(dn, next, list, sibling) {
0610 acpi_destroy_nondev_subnodes(&dn->data.subnodes);
0611 wait_for_completion(&dn->kobj_done);
0612 list_del(&dn->sibling);
0613 ACPI_FREE((void *)dn->data.pointer);
0614 acpi_free_device_properties(&dn->data.properties);
0615 kfree(dn);
0616 }
0617 }
0618
0619 void acpi_free_properties(struct acpi_device *adev)
0620 {
0621 acpi_untie_nondev_subnodes(&adev->data);
0622 acpi_destroy_nondev_subnodes(&adev->data.subnodes);
0623 ACPI_FREE((void *)adev->data.pointer);
0624 adev->data.of_compatible = NULL;
0625 adev->data.pointer = NULL;
0626 acpi_free_device_properties(&adev->data.properties);
0627 }
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647 static int acpi_data_get_property(const struct acpi_device_data *data,
0648 const char *name, acpi_object_type type,
0649 const union acpi_object **obj)
0650 {
0651 const struct acpi_device_properties *props;
0652
0653 if (!data || !name)
0654 return -EINVAL;
0655
0656 if (!data->pointer || list_empty(&data->properties))
0657 return -EINVAL;
0658
0659 list_for_each_entry(props, &data->properties, list) {
0660 const union acpi_object *properties;
0661 unsigned int i;
0662
0663 properties = props->properties;
0664 for (i = 0; i < properties->package.count; i++) {
0665 const union acpi_object *propname, *propvalue;
0666 const union acpi_object *property;
0667
0668 property = &properties->package.elements[i];
0669
0670 propname = &property->package.elements[0];
0671 propvalue = &property->package.elements[1];
0672
0673 if (!strcmp(name, propname->string.pointer)) {
0674 if (type != ACPI_TYPE_ANY &&
0675 propvalue->type != type)
0676 return -EPROTO;
0677 if (obj)
0678 *obj = propvalue;
0679
0680 return 0;
0681 }
0682 }
0683 }
0684 return -EINVAL;
0685 }
0686
0687
0688
0689
0690
0691
0692
0693
0694 int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
0695 acpi_object_type type, const union acpi_object **obj)
0696 {
0697 return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
0698 }
0699 EXPORT_SYMBOL_GPL(acpi_dev_get_property);
0700
0701 static const struct acpi_device_data *
0702 acpi_device_data_of_node(const struct fwnode_handle *fwnode)
0703 {
0704 if (is_acpi_device_node(fwnode)) {
0705 const struct acpi_device *adev = to_acpi_device_node(fwnode);
0706 return &adev->data;
0707 }
0708 if (is_acpi_data_node(fwnode)) {
0709 const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
0710 return &dn->data;
0711 }
0712 return NULL;
0713 }
0714
0715
0716
0717
0718
0719
0720
0721 int acpi_node_prop_get(const struct fwnode_handle *fwnode,
0722 const char *propname, void **valptr)
0723 {
0724 return acpi_data_get_property(acpi_device_data_of_node(fwnode),
0725 propname, ACPI_TYPE_ANY,
0726 (const union acpi_object **)valptr);
0727 }
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748 static int acpi_data_get_property_array(const struct acpi_device_data *data,
0749 const char *name,
0750 acpi_object_type type,
0751 const union acpi_object **obj)
0752 {
0753 const union acpi_object *prop;
0754 int ret, i;
0755
0756 ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
0757 if (ret)
0758 return ret;
0759
0760 if (type != ACPI_TYPE_ANY) {
0761
0762 for (i = 0; i < prop->package.count; i++)
0763 if (prop->package.elements[i].type != type)
0764 return -EPROTO;
0765 }
0766 if (obj)
0767 *obj = prop;
0768
0769 return 0;
0770 }
0771
0772 static struct fwnode_handle *
0773 acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
0774 const char *childname)
0775 {
0776 struct fwnode_handle *child;
0777
0778 fwnode_for_each_child_node(fwnode, child) {
0779 if (is_acpi_data_node(child)) {
0780 if (acpi_data_node_match(child, childname))
0781 return child;
0782 continue;
0783 }
0784
0785 if (!strncmp(acpi_device_bid(to_acpi_device_node(child)),
0786 childname, ACPI_NAMESEG_SIZE))
0787 return child;
0788 }
0789
0790 return NULL;
0791 }
0792
0793 static int acpi_get_ref_args(struct fwnode_reference_args *args,
0794 struct fwnode_handle *ref_fwnode,
0795 const union acpi_object **element,
0796 const union acpi_object *end, size_t num_args)
0797 {
0798 u32 nargs = 0, i;
0799
0800
0801
0802
0803
0804 for (; *element < end && (*element)->type == ACPI_TYPE_STRING;
0805 (*element)++) {
0806 const char *child_name = (*element)->string.pointer;
0807
0808 ref_fwnode = acpi_fwnode_get_named_child_node(ref_fwnode, child_name);
0809 if (!ref_fwnode)
0810 return -EINVAL;
0811 }
0812
0813
0814
0815
0816
0817
0818 for (i = 0; (*element) + i < end && i < num_args; i++) {
0819 acpi_object_type type = (*element)[i].type;
0820
0821 if (type == ACPI_TYPE_LOCAL_REFERENCE)
0822 break;
0823
0824 if (type == ACPI_TYPE_INTEGER)
0825 nargs++;
0826 else
0827 return -EINVAL;
0828 }
0829
0830 if (nargs > NR_FWNODE_REFERENCE_ARGS)
0831 return -EINVAL;
0832
0833 if (args) {
0834 args->fwnode = ref_fwnode;
0835 args->nargs = nargs;
0836 for (i = 0; i < nargs; i++)
0837 args->args[i] = (*element)[i].integer.value;
0838 }
0839
0840 (*element) += nargs;
0841
0842 return 0;
0843 }
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878
0879
0880 int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
0881 const char *propname, size_t index, size_t num_args,
0882 struct fwnode_reference_args *args)
0883 {
0884 const union acpi_object *element, *end;
0885 const union acpi_object *obj;
0886 const struct acpi_device_data *data;
0887 struct acpi_device *device;
0888 int ret, idx = 0;
0889
0890 data = acpi_device_data_of_node(fwnode);
0891 if (!data)
0892 return -ENOENT;
0893
0894 ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
0895 if (ret)
0896 return ret == -EINVAL ? -ENOENT : -EINVAL;
0897
0898 switch (obj->type) {
0899 case ACPI_TYPE_LOCAL_REFERENCE:
0900
0901 if (index)
0902 return -ENOENT;
0903
0904 device = acpi_fetch_acpi_dev(obj->reference.handle);
0905 if (!device)
0906 return -EINVAL;
0907
0908 args->fwnode = acpi_fwnode_handle(device);
0909 args->nargs = 0;
0910 return 0;
0911 case ACPI_TYPE_PACKAGE:
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921 break;
0922 default:
0923 return -EINVAL;
0924 }
0925
0926 if (index >= obj->package.count)
0927 return -ENOENT;
0928
0929 element = obj->package.elements;
0930 end = element + obj->package.count;
0931
0932 while (element < end) {
0933 switch (element->type) {
0934 case ACPI_TYPE_LOCAL_REFERENCE:
0935 device = acpi_fetch_acpi_dev(element->reference.handle);
0936 if (!device)
0937 return -EINVAL;
0938
0939 element++;
0940
0941 ret = acpi_get_ref_args(idx == index ? args : NULL,
0942 acpi_fwnode_handle(device),
0943 &element, end, num_args);
0944 if (ret < 0)
0945 return ret;
0946
0947 if (idx == index)
0948 return 0;
0949
0950 break;
0951 case ACPI_TYPE_INTEGER:
0952 if (idx == index)
0953 return -ENOENT;
0954 element++;
0955 break;
0956 default:
0957 return -EINVAL;
0958 }
0959
0960 idx++;
0961 }
0962
0963 return -ENOENT;
0964 }
0965 EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
0966
0967 static int acpi_data_prop_read_single(const struct acpi_device_data *data,
0968 const char *propname,
0969 enum dev_prop_type proptype, void *val)
0970 {
0971 const union acpi_object *obj;
0972 int ret;
0973
0974 if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
0975 ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
0976 if (ret)
0977 return ret;
0978
0979 switch (proptype) {
0980 case DEV_PROP_U8:
0981 if (obj->integer.value > U8_MAX)
0982 return -EOVERFLOW;
0983
0984 if (val)
0985 *(u8 *)val = obj->integer.value;
0986
0987 break;
0988 case DEV_PROP_U16:
0989 if (obj->integer.value > U16_MAX)
0990 return -EOVERFLOW;
0991
0992 if (val)
0993 *(u16 *)val = obj->integer.value;
0994
0995 break;
0996 case DEV_PROP_U32:
0997 if (obj->integer.value > U32_MAX)
0998 return -EOVERFLOW;
0999
1000 if (val)
1001 *(u32 *)val = obj->integer.value;
1002
1003 break;
1004 default:
1005 if (val)
1006 *(u64 *)val = obj->integer.value;
1007
1008 break;
1009 }
1010
1011 if (!val)
1012 return 1;
1013 } else if (proptype == DEV_PROP_STRING) {
1014 ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
1015 if (ret)
1016 return ret;
1017
1018 if (val)
1019 *(char **)val = obj->string.pointer;
1020
1021 return 1;
1022 } else {
1023 ret = -EINVAL;
1024 }
1025 return ret;
1026 }
1027
1028 #define acpi_copy_property_array_uint(items, val, nval) \
1029 ({ \
1030 typeof(items) __items = items; \
1031 typeof(val) __val = val; \
1032 typeof(nval) __nval = nval; \
1033 size_t i; \
1034 int ret = 0; \
1035 \
1036 for (i = 0; i < __nval; i++) { \
1037 if (__items->type == ACPI_TYPE_BUFFER) { \
1038 __val[i] = __items->buffer.pointer[i]; \
1039 continue; \
1040 } \
1041 if (__items[i].type != ACPI_TYPE_INTEGER) { \
1042 ret = -EPROTO; \
1043 break; \
1044 } \
1045 if (__items[i].integer.value > _Generic(__val, \
1046 u8 *: U8_MAX, \
1047 u16 *: U16_MAX, \
1048 u32 *: U32_MAX, \
1049 u64 *: U64_MAX)) { \
1050 ret = -EOVERFLOW; \
1051 break; \
1052 } \
1053 \
1054 __val[i] = __items[i].integer.value; \
1055 } \
1056 ret; \
1057 })
1058
1059 static int acpi_copy_property_array_string(const union acpi_object *items,
1060 char **val, size_t nval)
1061 {
1062 int i;
1063
1064 for (i = 0; i < nval; i++) {
1065 if (items[i].type != ACPI_TYPE_STRING)
1066 return -EPROTO;
1067
1068 val[i] = items[i].string.pointer;
1069 }
1070 return nval;
1071 }
1072
1073 static int acpi_data_prop_read(const struct acpi_device_data *data,
1074 const char *propname,
1075 enum dev_prop_type proptype,
1076 void *val, size_t nval)
1077 {
1078 const union acpi_object *obj;
1079 const union acpi_object *items;
1080 int ret;
1081
1082 if (nval == 1 || !val) {
1083 ret = acpi_data_prop_read_single(data, propname, proptype, val);
1084
1085
1086
1087
1088 if (ret >= 0 || ret == -EOVERFLOW)
1089 return ret;
1090
1091
1092
1093
1094
1095
1096 }
1097
1098 ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
1099 if (ret && proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64)
1100 ret = acpi_data_get_property(data, propname, ACPI_TYPE_BUFFER,
1101 &obj);
1102 if (ret)
1103 return ret;
1104
1105 if (!val) {
1106 if (obj->type == ACPI_TYPE_BUFFER)
1107 return obj->buffer.length;
1108
1109 return obj->package.count;
1110 }
1111
1112 switch (proptype) {
1113 case DEV_PROP_STRING:
1114 break;
1115 case DEV_PROP_U8 ... DEV_PROP_U64:
1116 if (obj->type == ACPI_TYPE_BUFFER) {
1117 if (nval > obj->buffer.length)
1118 return -EOVERFLOW;
1119 break;
1120 }
1121 fallthrough;
1122 default:
1123 if (nval > obj->package.count)
1124 return -EOVERFLOW;
1125 break;
1126 }
1127 if (nval == 0)
1128 return -EINVAL;
1129
1130 if (obj->type != ACPI_TYPE_BUFFER)
1131 items = obj->package.elements;
1132 else
1133 items = obj;
1134
1135 switch (proptype) {
1136 case DEV_PROP_U8:
1137 ret = acpi_copy_property_array_uint(items, (u8 *)val, nval);
1138 break;
1139 case DEV_PROP_U16:
1140 ret = acpi_copy_property_array_uint(items, (u16 *)val, nval);
1141 break;
1142 case DEV_PROP_U32:
1143 ret = acpi_copy_property_array_uint(items, (u32 *)val, nval);
1144 break;
1145 case DEV_PROP_U64:
1146 ret = acpi_copy_property_array_uint(items, (u64 *)val, nval);
1147 break;
1148 case DEV_PROP_STRING:
1149 ret = acpi_copy_property_array_string(
1150 items, (char **)val,
1151 min_t(u32, nval, obj->package.count));
1152 break;
1153 default:
1154 ret = -EINVAL;
1155 break;
1156 }
1157 return ret;
1158 }
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 static int acpi_node_prop_read(const struct fwnode_handle *fwnode,
1173 const char *propname, enum dev_prop_type proptype,
1174 void *val, size_t nval)
1175 {
1176 return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
1177 propname, proptype, val, nval);
1178 }
1179
1180 static int stop_on_next(struct acpi_device *adev, void *data)
1181 {
1182 struct acpi_device **ret_p = data;
1183
1184 if (!*ret_p) {
1185 *ret_p = adev;
1186 return 1;
1187 }
1188
1189
1190 if (*ret_p == adev)
1191 *ret_p = NULL;
1192
1193 return 0;
1194 }
1195
1196
1197
1198
1199
1200
1201 struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
1202 struct fwnode_handle *child)
1203 {
1204 struct acpi_device *adev = to_acpi_device_node(fwnode);
1205
1206 if ((!child || is_acpi_device_node(child)) && adev) {
1207 struct acpi_device *child_adev = to_acpi_device_node(child);
1208
1209 acpi_dev_for_each_child(adev, stop_on_next, &child_adev);
1210 if (child_adev)
1211 return acpi_fwnode_handle(child_adev);
1212
1213 child = NULL;
1214 }
1215
1216 if (!child || is_acpi_data_node(child)) {
1217 const struct acpi_data_node *data = to_acpi_data_node(fwnode);
1218 const struct list_head *head;
1219 struct list_head *next;
1220 struct acpi_data_node *dn;
1221
1222
1223
1224
1225
1226
1227
1228
1229 adev = to_acpi_device_node(fwnode);
1230 if (adev)
1231 head = &adev->data.subnodes;
1232 else if (data)
1233 head = &data->data.subnodes;
1234 else
1235 return NULL;
1236
1237 if (list_empty(head))
1238 return NULL;
1239
1240 if (child) {
1241 dn = to_acpi_data_node(child);
1242 next = dn->sibling.next;
1243 if (next == head)
1244 return NULL;
1245
1246 dn = list_entry(next, struct acpi_data_node, sibling);
1247 } else {
1248 dn = list_first_entry(head, struct acpi_data_node, sibling);
1249 }
1250 return &dn->fwnode;
1251 }
1252 return NULL;
1253 }
1254
1255
1256
1257
1258
1259
1260
1261
1262 static struct fwnode_handle *
1263 acpi_node_get_parent(const struct fwnode_handle *fwnode)
1264 {
1265 if (is_acpi_data_node(fwnode)) {
1266
1267 return to_acpi_data_node(fwnode)->parent;
1268 }
1269 if (is_acpi_device_node(fwnode)) {
1270 struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
1271
1272 if (dev)
1273 return acpi_fwnode_handle(to_acpi_device(dev));
1274 }
1275
1276 return NULL;
1277 }
1278
1279
1280
1281
1282
1283 static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
1284 const char *str)
1285 {
1286 unsigned int len = strlen(str);
1287 const char *name;
1288
1289 if (!len || !is_acpi_data_node(fwnode))
1290 return false;
1291
1292 name = to_acpi_data_node(fwnode)->name;
1293
1294 return (fwnode_property_present(fwnode, "reg") &&
1295 !strncmp(name, str, len) && name[len] == '@') ||
1296 fwnode_property_present(fwnode, str);
1297 }
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308 static struct fwnode_handle *acpi_graph_get_next_endpoint(
1309 const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
1310 {
1311 struct fwnode_handle *port = NULL;
1312 struct fwnode_handle *endpoint;
1313
1314 if (!prev) {
1315 do {
1316 port = fwnode_get_next_child_node(fwnode, port);
1317
1318
1319
1320
1321
1322
1323
1324 if (is_acpi_graph_node(port, "port"))
1325 break;
1326 } while (port);
1327 } else {
1328 port = fwnode_get_parent(prev);
1329 }
1330
1331 if (!port)
1332 return NULL;
1333
1334 endpoint = fwnode_get_next_child_node(port, prev);
1335 while (!endpoint) {
1336 port = fwnode_get_next_child_node(fwnode, port);
1337 if (!port)
1338 break;
1339 if (is_acpi_graph_node(port, "port"))
1340 endpoint = fwnode_get_next_child_node(port, NULL);
1341 }
1342
1343
1344
1345
1346
1347
1348
1349
1350 if (!is_acpi_graph_node(endpoint, "endpoint"))
1351 return NULL;
1352
1353 return endpoint;
1354 }
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 static struct fwnode_handle *acpi_graph_get_child_prop_value(
1366 const struct fwnode_handle *fwnode, const char *prop_name,
1367 unsigned int val)
1368 {
1369 struct fwnode_handle *child;
1370
1371 fwnode_for_each_child_node(fwnode, child) {
1372 u32 nr;
1373
1374 if (fwnode_property_read_u32(child, prop_name, &nr))
1375 continue;
1376
1377 if (val == nr)
1378 return child;
1379 }
1380
1381 return NULL;
1382 }
1383
1384
1385
1386
1387
1388
1389
1390
1391 static struct fwnode_handle *
1392 acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
1393 {
1394 struct fwnode_handle *fwnode;
1395 unsigned int port_nr, endpoint_nr;
1396 struct fwnode_reference_args args;
1397 int ret;
1398
1399 memset(&args, 0, sizeof(args));
1400 ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
1401 &args);
1402 if (ret)
1403 return NULL;
1404
1405
1406 if (!is_acpi_device_node(args.fwnode))
1407 return args.nargs ? NULL : args.fwnode;
1408
1409
1410
1411
1412
1413 if (args.nargs != 2)
1414 return NULL;
1415
1416 fwnode = args.fwnode;
1417 port_nr = args.args[0];
1418 endpoint_nr = args.args[1];
1419
1420 fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
1421
1422 return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
1423 }
1424
1425 static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
1426 {
1427 if (!is_acpi_device_node(fwnode))
1428 return false;
1429
1430 return acpi_device_is_present(to_acpi_device_node(fwnode));
1431 }
1432
1433 static const void *
1434 acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
1435 const struct device *dev)
1436 {
1437 return acpi_device_get_match_data(dev);
1438 }
1439
1440 static bool acpi_fwnode_device_dma_supported(const struct fwnode_handle *fwnode)
1441 {
1442 return acpi_dma_supported(to_acpi_device_node(fwnode));
1443 }
1444
1445 static enum dev_dma_attr
1446 acpi_fwnode_device_get_dma_attr(const struct fwnode_handle *fwnode)
1447 {
1448 return acpi_get_dma_attr(to_acpi_device_node(fwnode));
1449 }
1450
1451 static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
1452 const char *propname)
1453 {
1454 return !acpi_node_prop_get(fwnode, propname, NULL);
1455 }
1456
1457 static int
1458 acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
1459 const char *propname,
1460 unsigned int elem_size, void *val,
1461 size_t nval)
1462 {
1463 enum dev_prop_type type;
1464
1465 switch (elem_size) {
1466 case sizeof(u8):
1467 type = DEV_PROP_U8;
1468 break;
1469 case sizeof(u16):
1470 type = DEV_PROP_U16;
1471 break;
1472 case sizeof(u32):
1473 type = DEV_PROP_U32;
1474 break;
1475 case sizeof(u64):
1476 type = DEV_PROP_U64;
1477 break;
1478 default:
1479 return -ENXIO;
1480 }
1481
1482 return acpi_node_prop_read(fwnode, propname, type, val, nval);
1483 }
1484
1485 static int
1486 acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
1487 const char *propname, const char **val,
1488 size_t nval)
1489 {
1490 return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
1491 val, nval);
1492 }
1493
1494 static int
1495 acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
1496 const char *prop, const char *nargs_prop,
1497 unsigned int args_count, unsigned int index,
1498 struct fwnode_reference_args *args)
1499 {
1500 return __acpi_node_get_property_reference(fwnode, prop, index,
1501 args_count, args);
1502 }
1503
1504 static const char *acpi_fwnode_get_name(const struct fwnode_handle *fwnode)
1505 {
1506 const struct acpi_device *adev;
1507 struct fwnode_handle *parent;
1508
1509
1510 parent = fwnode_get_parent(fwnode);
1511 if (!parent)
1512 return "\\";
1513
1514 fwnode_handle_put(parent);
1515
1516 if (is_acpi_data_node(fwnode)) {
1517 const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
1518
1519 return dn->name;
1520 }
1521
1522 adev = to_acpi_device_node(fwnode);
1523 if (WARN_ON(!adev))
1524 return NULL;
1525
1526 return acpi_device_bid(adev);
1527 }
1528
1529 static const char *
1530 acpi_fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
1531 {
1532 struct fwnode_handle *parent;
1533
1534
1535 parent = fwnode_get_parent(fwnode);
1536 if (!parent)
1537 return "";
1538
1539
1540 parent = fwnode_get_next_parent(parent);
1541 if (!parent)
1542 return "";
1543
1544 fwnode_handle_put(parent);
1545
1546
1547 return ".";
1548 }
1549
1550 static struct fwnode_handle *
1551 acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
1552 {
1553 return acpi_node_get_parent(fwnode);
1554 }
1555
1556 static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
1557 struct fwnode_endpoint *endpoint)
1558 {
1559 struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
1560
1561 endpoint->local_fwnode = fwnode;
1562
1563 if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
1564 fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
1565 if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
1566 fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
1567
1568 return 0;
1569 }
1570
1571 static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode,
1572 unsigned int index)
1573 {
1574 struct resource res;
1575 int ret;
1576
1577 ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
1578 if (ret)
1579 return ret;
1580
1581 return res.start;
1582 }
1583
1584 #define DECLARE_ACPI_FWNODE_OPS(ops) \
1585 const struct fwnode_operations ops = { \
1586 .device_is_available = acpi_fwnode_device_is_available, \
1587 .device_get_match_data = acpi_fwnode_device_get_match_data, \
1588 .device_dma_supported = \
1589 acpi_fwnode_device_dma_supported, \
1590 .device_get_dma_attr = acpi_fwnode_device_get_dma_attr, \
1591 .property_present = acpi_fwnode_property_present, \
1592 .property_read_int_array = \
1593 acpi_fwnode_property_read_int_array, \
1594 .property_read_string_array = \
1595 acpi_fwnode_property_read_string_array, \
1596 .get_parent = acpi_node_get_parent, \
1597 .get_next_child_node = acpi_get_next_subnode, \
1598 .get_named_child_node = acpi_fwnode_get_named_child_node, \
1599 .get_name = acpi_fwnode_get_name, \
1600 .get_name_prefix = acpi_fwnode_get_name_prefix, \
1601 .get_reference_args = acpi_fwnode_get_reference_args, \
1602 .graph_get_next_endpoint = \
1603 acpi_graph_get_next_endpoint, \
1604 .graph_get_remote_endpoint = \
1605 acpi_graph_get_remote_endpoint, \
1606 .graph_get_port_parent = acpi_fwnode_get_parent, \
1607 .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
1608 .irq_get = acpi_fwnode_irq_get, \
1609 }; \
1610 EXPORT_SYMBOL_GPL(ops)
1611
1612 DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
1613 DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
1614 const struct fwnode_operations acpi_static_fwnode_ops;
1615
1616 bool is_acpi_device_node(const struct fwnode_handle *fwnode)
1617 {
1618 return !IS_ERR_OR_NULL(fwnode) &&
1619 fwnode->ops == &acpi_device_fwnode_ops;
1620 }
1621 EXPORT_SYMBOL(is_acpi_device_node);
1622
1623 bool is_acpi_data_node(const struct fwnode_handle *fwnode)
1624 {
1625 return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
1626 }
1627 EXPORT_SYMBOL(is_acpi_data_node);