property.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /*
  2. * ACPI device specific properties support.
  3. *
  4. * Copyright (C) 2014, Intel Corporation
  5. * All rights reserved.
  6. *
  7. * Authors: Mika Westerberg <[email protected]>
  8. * Darren Hart <[email protected]>
  9. * Rafael J. Wysocki <[email protected]>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. */
  15. #include <linux/acpi.h>
  16. #include <linux/device.h>
  17. #include <linux/export.h>
  18. #include "internal.h"
  19. static int acpi_data_get_property_array(struct acpi_device_data *data,
  20. const char *name,
  21. acpi_object_type type,
  22. const union acpi_object **obj);
  23. /* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
  24. static const u8 prp_uuid[16] = {
  25. 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
  26. 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
  27. };
  28. /* ACPI _DSD data subnodes UUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
  29. static const u8 ads_uuid[16] = {
  30. 0xe6, 0xe3, 0xb8, 0xdb, 0x86, 0x58, 0xa6, 0x4b,
  31. 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b
  32. };
  33. static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
  34. const union acpi_object *desc,
  35. struct acpi_device_data *data);
  36. static bool acpi_extract_properties(const union acpi_object *desc,
  37. struct acpi_device_data *data);
  38. static bool acpi_nondev_subnode_ok(acpi_handle scope,
  39. const union acpi_object *link,
  40. struct list_head *list)
  41. {
  42. struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
  43. struct acpi_data_node *dn;
  44. acpi_handle handle;
  45. acpi_status status;
  46. dn = kzalloc(sizeof(*dn), GFP_KERNEL);
  47. if (!dn)
  48. return false;
  49. dn->name = link->package.elements[0].string.pointer;
  50. dn->fwnode.type = FWNODE_ACPI_DATA;
  51. INIT_LIST_HEAD(&dn->data.subnodes);
  52. status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
  53. &handle);
  54. if (ACPI_FAILURE(status))
  55. goto fail;
  56. status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
  57. ACPI_TYPE_PACKAGE);
  58. if (ACPI_FAILURE(status))
  59. goto fail;
  60. if (acpi_extract_properties(buf.pointer, &dn->data))
  61. dn->handle = handle;
  62. /*
  63. * The scope for the subnode object lookup is the one of the namespace
  64. * node (device) containing the object that has returned the package.
  65. * That is, it's the scope of that object's parent.
  66. */
  67. status = acpi_get_parent(handle, &scope);
  68. if (ACPI_SUCCESS(status)
  69. && acpi_enumerate_nondev_subnodes(scope, buf.pointer, &dn->data))
  70. dn->handle = handle;
  71. if (dn->handle) {
  72. dn->data.pointer = buf.pointer;
  73. list_add_tail(&dn->sibling, list);
  74. return true;
  75. }
  76. acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
  77. fail:
  78. ACPI_FREE(buf.pointer);
  79. kfree(dn);
  80. return false;
  81. }
  82. static int acpi_add_nondev_subnodes(acpi_handle scope,
  83. const union acpi_object *links,
  84. struct list_head *list)
  85. {
  86. bool ret = false;
  87. int i;
  88. for (i = 0; i < links->package.count; i++) {
  89. const union acpi_object *link;
  90. link = &links->package.elements[i];
  91. /* Only two elements allowed, both must be strings. */
  92. if (link->package.count == 2
  93. && link->package.elements[0].type == ACPI_TYPE_STRING
  94. && link->package.elements[1].type == ACPI_TYPE_STRING
  95. && acpi_nondev_subnode_ok(scope, link, list))
  96. ret = true;
  97. }
  98. return ret;
  99. }
  100. static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
  101. const union acpi_object *desc,
  102. struct acpi_device_data *data)
  103. {
  104. int i;
  105. /* Look for the ACPI data subnodes UUID. */
  106. for (i = 0; i < desc->package.count; i += 2) {
  107. const union acpi_object *uuid, *links;
  108. uuid = &desc->package.elements[i];
  109. links = &desc->package.elements[i + 1];
  110. /*
  111. * The first element must be a UUID and the second one must be
  112. * a package.
  113. */
  114. if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
  115. || links->type != ACPI_TYPE_PACKAGE)
  116. break;
  117. if (memcmp(uuid->buffer.pointer, ads_uuid, sizeof(ads_uuid)))
  118. continue;
  119. return acpi_add_nondev_subnodes(scope, links, &data->subnodes);
  120. }
  121. return false;
  122. }
  123. static bool acpi_property_value_ok(const union acpi_object *value)
  124. {
  125. int j;
  126. /*
  127. * The value must be an integer, a string, a reference, or a package
  128. * whose every element must be an integer, a string, or a reference.
  129. */
  130. switch (value->type) {
  131. case ACPI_TYPE_INTEGER:
  132. case ACPI_TYPE_STRING:
  133. case ACPI_TYPE_LOCAL_REFERENCE:
  134. return true;
  135. case ACPI_TYPE_PACKAGE:
  136. for (j = 0; j < value->package.count; j++)
  137. switch (value->package.elements[j].type) {
  138. case ACPI_TYPE_INTEGER:
  139. case ACPI_TYPE_STRING:
  140. case ACPI_TYPE_LOCAL_REFERENCE:
  141. continue;
  142. default:
  143. return false;
  144. }
  145. return true;
  146. }
  147. return false;
  148. }
  149. static bool acpi_properties_format_valid(const union acpi_object *properties)
  150. {
  151. int i;
  152. for (i = 0; i < properties->package.count; i++) {
  153. const union acpi_object *property;
  154. property = &properties->package.elements[i];
  155. /*
  156. * Only two elements allowed, the first one must be a string and
  157. * the second one has to satisfy certain conditions.
  158. */
  159. if (property->package.count != 2
  160. || property->package.elements[0].type != ACPI_TYPE_STRING
  161. || !acpi_property_value_ok(&property->package.elements[1]))
  162. return false;
  163. }
  164. return true;
  165. }
  166. static void acpi_init_of_compatible(struct acpi_device *adev)
  167. {
  168. const union acpi_object *of_compatible;
  169. int ret;
  170. ret = acpi_data_get_property_array(&adev->data, "compatible",
  171. ACPI_TYPE_STRING, &of_compatible);
  172. if (ret) {
  173. ret = acpi_dev_get_property(adev, "compatible",
  174. ACPI_TYPE_STRING, &of_compatible);
  175. if (ret) {
  176. if (adev->parent
  177. && adev->parent->flags.of_compatible_ok)
  178. goto out;
  179. return;
  180. }
  181. }
  182. adev->data.of_compatible = of_compatible;
  183. out:
  184. adev->flags.of_compatible_ok = 1;
  185. }
  186. static bool acpi_extract_properties(const union acpi_object *desc,
  187. struct acpi_device_data *data)
  188. {
  189. int i;
  190. if (desc->package.count % 2)
  191. return false;
  192. /* Look for the device properties UUID. */
  193. for (i = 0; i < desc->package.count; i += 2) {
  194. const union acpi_object *uuid, *properties;
  195. uuid = &desc->package.elements[i];
  196. properties = &desc->package.elements[i + 1];
  197. /*
  198. * The first element must be a UUID and the second one must be
  199. * a package.
  200. */
  201. if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
  202. || properties->type != ACPI_TYPE_PACKAGE)
  203. break;
  204. if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
  205. continue;
  206. /*
  207. * We found the matching UUID. Now validate the format of the
  208. * package immediately following it.
  209. */
  210. if (!acpi_properties_format_valid(properties))
  211. break;
  212. data->properties = properties;
  213. return true;
  214. }
  215. return false;
  216. }
  217. void acpi_init_properties(struct acpi_device *adev)
  218. {
  219. struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
  220. struct acpi_hardware_id *hwid;
  221. acpi_status status;
  222. bool acpi_of = false;
  223. INIT_LIST_HEAD(&adev->data.subnodes);
  224. /*
  225. * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
  226. * Device Tree compatible properties for this device.
  227. */
  228. list_for_each_entry(hwid, &adev->pnp.ids, list) {
  229. if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
  230. acpi_of = true;
  231. break;
  232. }
  233. }
  234. status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
  235. ACPI_TYPE_PACKAGE);
  236. if (ACPI_FAILURE(status))
  237. goto out;
  238. if (acpi_extract_properties(buf.pointer, &adev->data)) {
  239. adev->data.pointer = buf.pointer;
  240. if (acpi_of)
  241. acpi_init_of_compatible(adev);
  242. }
  243. if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer, &adev->data))
  244. adev->data.pointer = buf.pointer;
  245. if (!adev->data.pointer) {
  246. acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
  247. ACPI_FREE(buf.pointer);
  248. }
  249. out:
  250. if (acpi_of && !adev->flags.of_compatible_ok)
  251. acpi_handle_info(adev->handle,
  252. ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
  253. }
  254. static void acpi_destroy_nondev_subnodes(struct list_head *list)
  255. {
  256. struct acpi_data_node *dn, *next;
  257. if (list_empty(list))
  258. return;
  259. list_for_each_entry_safe_reverse(dn, next, list, sibling) {
  260. acpi_destroy_nondev_subnodes(&dn->data.subnodes);
  261. wait_for_completion(&dn->kobj_done);
  262. list_del(&dn->sibling);
  263. ACPI_FREE((void *)dn->data.pointer);
  264. kfree(dn);
  265. }
  266. }
  267. void acpi_free_properties(struct acpi_device *adev)
  268. {
  269. acpi_destroy_nondev_subnodes(&adev->data.subnodes);
  270. ACPI_FREE((void *)adev->data.pointer);
  271. adev->data.of_compatible = NULL;
  272. adev->data.pointer = NULL;
  273. adev->data.properties = NULL;
  274. }
  275. /**
  276. * acpi_data_get_property - return an ACPI property with given name
  277. * @data: ACPI device deta object to get the property from
  278. * @name: Name of the property
  279. * @type: Expected property type
  280. * @obj: Location to store the property value (if not %NULL)
  281. *
  282. * Look up a property with @name and store a pointer to the resulting ACPI
  283. * object at the location pointed to by @obj if found.
  284. *
  285. * Callers must not attempt to free the returned objects. These objects will be
  286. * freed by the ACPI core automatically during the removal of @data.
  287. *
  288. * Return: %0 if property with @name has been found (success),
  289. * %-EINVAL if the arguments are invalid,
  290. * %-EINVAL if the property doesn't exist,
  291. * %-EPROTO if the property value type doesn't match @type.
  292. */
  293. static int acpi_data_get_property(struct acpi_device_data *data,
  294. const char *name, acpi_object_type type,
  295. const union acpi_object **obj)
  296. {
  297. const union acpi_object *properties;
  298. int i;
  299. if (!data || !name)
  300. return -EINVAL;
  301. if (!data->pointer || !data->properties)
  302. return -EINVAL;
  303. properties = data->properties;
  304. for (i = 0; i < properties->package.count; i++) {
  305. const union acpi_object *propname, *propvalue;
  306. const union acpi_object *property;
  307. property = &properties->package.elements[i];
  308. propname = &property->package.elements[0];
  309. propvalue = &property->package.elements[1];
  310. if (!strcmp(name, propname->string.pointer)) {
  311. if (type != ACPI_TYPE_ANY && propvalue->type != type)
  312. return -EPROTO;
  313. if (obj)
  314. *obj = propvalue;
  315. return 0;
  316. }
  317. }
  318. return -EINVAL;
  319. }
  320. /**
  321. * acpi_dev_get_property - return an ACPI property with given name.
  322. * @adev: ACPI device to get the property from.
  323. * @name: Name of the property.
  324. * @type: Expected property type.
  325. * @obj: Location to store the property value (if not %NULL).
  326. */
  327. int acpi_dev_get_property(struct acpi_device *adev, const char *name,
  328. acpi_object_type type, const union acpi_object **obj)
  329. {
  330. return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
  331. }
  332. EXPORT_SYMBOL_GPL(acpi_dev_get_property);
  333. static struct acpi_device_data *acpi_device_data_of_node(struct fwnode_handle *fwnode)
  334. {
  335. if (fwnode->type == FWNODE_ACPI) {
  336. struct acpi_device *adev = to_acpi_device_node(fwnode);
  337. return &adev->data;
  338. } else if (fwnode->type == FWNODE_ACPI_DATA) {
  339. struct acpi_data_node *dn = to_acpi_data_node(fwnode);
  340. return &dn->data;
  341. }
  342. return NULL;
  343. }
  344. /**
  345. * acpi_node_prop_get - return an ACPI property with given name.
  346. * @fwnode: Firmware node to get the property from.
  347. * @propname: Name of the property.
  348. * @valptr: Location to store a pointer to the property value (if not %NULL).
  349. */
  350. int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname,
  351. void **valptr)
  352. {
  353. return acpi_data_get_property(acpi_device_data_of_node(fwnode),
  354. propname, ACPI_TYPE_ANY,
  355. (const union acpi_object **)valptr);
  356. }
  357. /**
  358. * acpi_data_get_property_array - return an ACPI array property with given name
  359. * @adev: ACPI data object to get the property from
  360. * @name: Name of the property
  361. * @type: Expected type of array elements
  362. * @obj: Location to store a pointer to the property value (if not NULL)
  363. *
  364. * Look up an array property with @name and store a pointer to the resulting
  365. * ACPI object at the location pointed to by @obj if found.
  366. *
  367. * Callers must not attempt to free the returned objects. Those objects will be
  368. * freed by the ACPI core automatically during the removal of @data.
  369. *
  370. * Return: %0 if array property (package) with @name has been found (success),
  371. * %-EINVAL if the arguments are invalid,
  372. * %-EINVAL if the property doesn't exist,
  373. * %-EPROTO if the property is not a package or the type of its elements
  374. * doesn't match @type.
  375. */
  376. static int acpi_data_get_property_array(struct acpi_device_data *data,
  377. const char *name,
  378. acpi_object_type type,
  379. const union acpi_object **obj)
  380. {
  381. const union acpi_object *prop;
  382. int ret, i;
  383. ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
  384. if (ret)
  385. return ret;
  386. if (type != ACPI_TYPE_ANY) {
  387. /* Check that all elements are of correct type. */
  388. for (i = 0; i < prop->package.count; i++)
  389. if (prop->package.elements[i].type != type)
  390. return -EPROTO;
  391. }
  392. if (obj)
  393. *obj = prop;
  394. return 0;
  395. }
  396. /**
  397. * __acpi_node_get_property_reference - returns handle to the referenced object
  398. * @fwnode: Firmware node to get the property from
  399. * @propname: Name of the property
  400. * @index: Index of the reference to return
  401. * @num_args: Maximum number of arguments after each reference
  402. * @args: Location to store the returned reference with optional arguments
  403. *
  404. * Find property with @name, verifify that it is a package containing at least
  405. * one object reference and if so, store the ACPI device object pointer to the
  406. * target object in @args->adev. If the reference includes arguments, store
  407. * them in the @args->args[] array.
  408. *
  409. * If there's more than one reference in the property value package, @index is
  410. * used to select the one to return.
  411. *
  412. * It is possible to leave holes in the property value set like in the
  413. * example below:
  414. *
  415. * Package () {
  416. * "cs-gpios",
  417. * Package () {
  418. * ^GPIO, 19, 0, 0,
  419. * ^GPIO, 20, 0, 0,
  420. * 0,
  421. * ^GPIO, 21, 0, 0,
  422. * }
  423. * }
  424. *
  425. * Calling this function with index %2 return %-ENOENT and with index %3
  426. * returns the last entry. If the property does not contain any more values
  427. * %-ENODATA is returned. The NULL entry must be single integer and
  428. * preferably contain value %0.
  429. *
  430. * Return: %0 on success, negative error code on failure.
  431. */
  432. int __acpi_node_get_property_reference(struct fwnode_handle *fwnode,
  433. const char *propname, size_t index, size_t num_args,
  434. struct acpi_reference_args *args)
  435. {
  436. const union acpi_object *element, *end;
  437. const union acpi_object *obj;
  438. struct acpi_device_data *data;
  439. struct acpi_device *device;
  440. int ret, idx = 0;
  441. data = acpi_device_data_of_node(fwnode);
  442. if (!data)
  443. return -EINVAL;
  444. ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
  445. if (ret)
  446. return ret;
  447. /*
  448. * The simplest case is when the value is a single reference. Just
  449. * return that reference then.
  450. */
  451. if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
  452. if (index)
  453. return -EINVAL;
  454. ret = acpi_bus_get_device(obj->reference.handle, &device);
  455. if (ret)
  456. return ret;
  457. args->adev = device;
  458. args->nargs = 0;
  459. return 0;
  460. }
  461. /*
  462. * If it is not a single reference, then it is a package of
  463. * references followed by number of ints as follows:
  464. *
  465. * Package () { REF, INT, REF, INT, INT }
  466. *
  467. * The index argument is then used to determine which reference
  468. * the caller wants (along with the arguments).
  469. */
  470. if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
  471. return -EPROTO;
  472. element = obj->package.elements;
  473. end = element + obj->package.count;
  474. while (element < end) {
  475. u32 nargs, i;
  476. if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
  477. ret = acpi_bus_get_device(element->reference.handle,
  478. &device);
  479. if (ret)
  480. return -ENODEV;
  481. nargs = 0;
  482. element++;
  483. /* assume following integer elements are all args */
  484. for (i = 0; element + i < end && i < num_args; i++) {
  485. int type = element[i].type;
  486. if (type == ACPI_TYPE_INTEGER)
  487. nargs++;
  488. else if (type == ACPI_TYPE_LOCAL_REFERENCE)
  489. break;
  490. else
  491. return -EPROTO;
  492. }
  493. if (nargs > MAX_ACPI_REFERENCE_ARGS)
  494. return -EPROTO;
  495. if (idx == index) {
  496. args->adev = device;
  497. args->nargs = nargs;
  498. for (i = 0; i < nargs; i++)
  499. args->args[i] = element[i].integer.value;
  500. return 0;
  501. }
  502. element += nargs;
  503. } else if (element->type == ACPI_TYPE_INTEGER) {
  504. if (idx == index)
  505. return -ENOENT;
  506. element++;
  507. } else {
  508. return -EPROTO;
  509. }
  510. idx++;
  511. }
  512. return -ENODATA;
  513. }
  514. EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
  515. static int acpi_data_prop_read_single(struct acpi_device_data *data,
  516. const char *propname,
  517. enum dev_prop_type proptype, void *val)
  518. {
  519. const union acpi_object *obj;
  520. int ret;
  521. if (!val)
  522. return -EINVAL;
  523. if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
  524. ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
  525. if (ret)
  526. return ret;
  527. switch (proptype) {
  528. case DEV_PROP_U8:
  529. if (obj->integer.value > U8_MAX)
  530. return -EOVERFLOW;
  531. *(u8 *)val = obj->integer.value;
  532. break;
  533. case DEV_PROP_U16:
  534. if (obj->integer.value > U16_MAX)
  535. return -EOVERFLOW;
  536. *(u16 *)val = obj->integer.value;
  537. break;
  538. case DEV_PROP_U32:
  539. if (obj->integer.value > U32_MAX)
  540. return -EOVERFLOW;
  541. *(u32 *)val = obj->integer.value;
  542. break;
  543. default:
  544. *(u64 *)val = obj->integer.value;
  545. break;
  546. }
  547. } else if (proptype == DEV_PROP_STRING) {
  548. ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
  549. if (ret)
  550. return ret;
  551. *(char **)val = obj->string.pointer;
  552. } else {
  553. ret = -EINVAL;
  554. }
  555. return ret;
  556. }
  557. int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
  558. enum dev_prop_type proptype, void *val)
  559. {
  560. return adev ? acpi_data_prop_read_single(&adev->data, propname, proptype, val) : -EINVAL;
  561. }
  562. static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
  563. size_t nval)
  564. {
  565. int i;
  566. for (i = 0; i < nval; i++) {
  567. if (items[i].type != ACPI_TYPE_INTEGER)
  568. return -EPROTO;
  569. if (items[i].integer.value > U8_MAX)
  570. return -EOVERFLOW;
  571. val[i] = items[i].integer.value;
  572. }
  573. return 0;
  574. }
  575. static int acpi_copy_property_array_u16(const union acpi_object *items,
  576. u16 *val, size_t nval)
  577. {
  578. int i;
  579. for (i = 0; i < nval; i++) {
  580. if (items[i].type != ACPI_TYPE_INTEGER)
  581. return -EPROTO;
  582. if (items[i].integer.value > U16_MAX)
  583. return -EOVERFLOW;
  584. val[i] = items[i].integer.value;
  585. }
  586. return 0;
  587. }
  588. static int acpi_copy_property_array_u32(const union acpi_object *items,
  589. u32 *val, size_t nval)
  590. {
  591. int i;
  592. for (i = 0; i < nval; i++) {
  593. if (items[i].type != ACPI_TYPE_INTEGER)
  594. return -EPROTO;
  595. if (items[i].integer.value > U32_MAX)
  596. return -EOVERFLOW;
  597. val[i] = items[i].integer.value;
  598. }
  599. return 0;
  600. }
  601. static int acpi_copy_property_array_u64(const union acpi_object *items,
  602. u64 *val, size_t nval)
  603. {
  604. int i;
  605. for (i = 0; i < nval; i++) {
  606. if (items[i].type != ACPI_TYPE_INTEGER)
  607. return -EPROTO;
  608. val[i] = items[i].integer.value;
  609. }
  610. return 0;
  611. }
  612. static int acpi_copy_property_array_string(const union acpi_object *items,
  613. char **val, size_t nval)
  614. {
  615. int i;
  616. for (i = 0; i < nval; i++) {
  617. if (items[i].type != ACPI_TYPE_STRING)
  618. return -EPROTO;
  619. val[i] = items[i].string.pointer;
  620. }
  621. return 0;
  622. }
  623. static int acpi_data_prop_read(struct acpi_device_data *data,
  624. const char *propname,
  625. enum dev_prop_type proptype,
  626. void *val, size_t nval)
  627. {
  628. const union acpi_object *obj;
  629. const union acpi_object *items;
  630. int ret;
  631. if (val && nval == 1) {
  632. ret = acpi_data_prop_read_single(data, propname, proptype, val);
  633. if (!ret)
  634. return ret;
  635. }
  636. ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
  637. if (ret)
  638. return ret;
  639. if (!val)
  640. return obj->package.count;
  641. if (nval > obj->package.count)
  642. return -EOVERFLOW;
  643. else if (nval <= 0)
  644. return -EINVAL;
  645. items = obj->package.elements;
  646. switch (proptype) {
  647. case DEV_PROP_U8:
  648. ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
  649. break;
  650. case DEV_PROP_U16:
  651. ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
  652. break;
  653. case DEV_PROP_U32:
  654. ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
  655. break;
  656. case DEV_PROP_U64:
  657. ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
  658. break;
  659. case DEV_PROP_STRING:
  660. ret = acpi_copy_property_array_string(items, (char **)val, nval);
  661. break;
  662. default:
  663. ret = -EINVAL;
  664. break;
  665. }
  666. return ret;
  667. }
  668. int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
  669. enum dev_prop_type proptype, void *val, size_t nval)
  670. {
  671. return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
  672. }
  673. /**
  674. * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
  675. * @fwnode: Firmware node to get the property from.
  676. * @propname: Name of the property.
  677. * @proptype: Expected property type.
  678. * @val: Location to store the property value (if not %NULL).
  679. * @nval: Size of the array pointed to by @val.
  680. *
  681. * If @val is %NULL, return the number of array elements comprising the value
  682. * of the property. Otherwise, read at most @nval values to the array at the
  683. * location pointed to by @val.
  684. */
  685. int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname,
  686. enum dev_prop_type proptype, void *val, size_t nval)
  687. {
  688. return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
  689. propname, proptype, val, nval);
  690. }
  691. /**
  692. * acpi_get_next_subnode - Return the next child node handle for a device.
  693. * @dev: Device to find the next child node for.
  694. * @child: Handle to one of the device's child nodes or a null handle.
  695. */
  696. struct fwnode_handle *acpi_get_next_subnode(struct device *dev,
  697. struct fwnode_handle *child)
  698. {
  699. struct acpi_device *adev = ACPI_COMPANION(dev);
  700. struct list_head *head, *next;
  701. if (!adev)
  702. return NULL;
  703. if (!child || child->type == FWNODE_ACPI) {
  704. head = &adev->children;
  705. if (list_empty(head))
  706. goto nondev;
  707. if (child) {
  708. adev = to_acpi_device_node(child);
  709. next = adev->node.next;
  710. if (next == head) {
  711. child = NULL;
  712. adev = ACPI_COMPANION(dev);
  713. goto nondev;
  714. }
  715. adev = list_entry(next, struct acpi_device, node);
  716. } else {
  717. adev = list_first_entry(head, struct acpi_device, node);
  718. }
  719. return acpi_fwnode_handle(adev);
  720. }
  721. nondev:
  722. if (!child || child->type == FWNODE_ACPI_DATA) {
  723. struct acpi_data_node *dn;
  724. head = &adev->data.subnodes;
  725. if (list_empty(head))
  726. return NULL;
  727. if (child) {
  728. dn = to_acpi_data_node(child);
  729. next = dn->sibling.next;
  730. if (next == head)
  731. return NULL;
  732. dn = list_entry(next, struct acpi_data_node, sibling);
  733. } else {
  734. dn = list_first_entry(head, struct acpi_data_node, sibling);
  735. }
  736. return &dn->fwnode;
  737. }
  738. return NULL;
  739. }