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

Merge branches 'acpi-resources' and 'acpi-docs'

* acpi-resources:
Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources walks"
resource: provide meaningful MODULE_LICENSE() in test suite
ASoC: Intel: catpt: Replace open coded variant of resource_intersection()
ACPI: watchdog: Replace open coded variant of resource_union()
PCI/ACPI: Replace open coded variant of resource_union()
resource: Add test cases for new resource API
resource: Introduce resource_intersection() for overlapping resources
resource: Introduce resource_union() for overlapping resources
resource: Group resource_overlaps() with other inline helpers
resource: Simplify region_intersects() by reducing conditionals

* acpi-docs:
Documentation: ACPI: enumeration: add PCI hierarchy representation
Documentation: ACPI: _DSD: enable hyperlink in final references
Documentation: ACPI: explain how to use gpio-line-names

+414 -39
+4 -4
Documentation/firmware-guide/acpi/dsd/leds.rst
··· 90 90 References 91 91 ========== 92 92 93 - [1] Device tree. <URL:https://www.devicetree.org>, referenced 2019-02-21. 93 + [1] Device tree. https://www.devicetree.org, referenced 2019-02-21. 94 94 95 95 [2] Advanced Configuration and Power Interface Specification. 96 - <URL:https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf>, 96 + https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf, 97 97 referenced 2019-02-21. 98 98 99 99 [3] Documentation/devicetree/bindings/leds/common.txt ··· 101 101 [4] Documentation/devicetree/bindings/media/video-interfaces.txt 102 102 103 103 [5] Device Properties UUID For _DSD. 104 - <URL:https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf>, 104 + https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf, 105 105 referenced 2019-02-21. 106 106 107 107 [6] Hierarchical Data Extension UUID For _DSD. 108 - <URL:https://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf>, 108 + https://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf, 109 109 referenced 2019-02-21. 110 110 111 111 [7] Documentation/firmware-guide/acpi/dsd/data-node-references.rst
+154
Documentation/firmware-guide/acpi/enumeration.rst
··· 461 461 property returned by it is meaningless. 462 462 463 463 Refer to :doc:`DSD-properties-rules` for more information. 464 + 465 + PCI hierarchy representation 466 + ============================ 467 + 468 + Sometimes could be useful to enumerate a PCI device, knowing its position on the 469 + PCI bus. 470 + 471 + For example, some systems use PCI devices soldered directly on the mother board, 472 + in a fixed position (ethernet, Wi-Fi, serial ports, etc.). In this conditions it 473 + is possible to refer to these PCI devices knowing their position on the PCI bus 474 + topology. 475 + 476 + To identify a PCI device, a complete hierarchical description is required, from 477 + the chipset root port to the final device, through all the intermediate 478 + bridges/switches of the board. 479 + 480 + For example, let us assume to have a system with a PCIe serial port, an 481 + Exar XR17V3521, soldered on the main board. This UART chip also includes 482 + 16 GPIOs and we want to add the property ``gpio-line-names`` [1] to these pins. 483 + In this case, the ``lspci`` output for this component is:: 484 + 485 + 07:00.0 Serial controller: Exar Corp. XR17V3521 Dual PCIe UART (rev 03) 486 + 487 + The complete ``lspci`` output (manually reduced in length) is:: 488 + 489 + 00:00.0 Host bridge: Intel Corp... Host Bridge (rev 0d) 490 + ... 491 + 00:13.0 PCI bridge: Intel Corp... PCI Express Port A #1 (rev fd) 492 + 00:13.1 PCI bridge: Intel Corp... PCI Express Port A #2 (rev fd) 493 + 00:13.2 PCI bridge: Intel Corp... PCI Express Port A #3 (rev fd) 494 + 00:14.0 PCI bridge: Intel Corp... PCI Express Port B #1 (rev fd) 495 + 00:14.1 PCI bridge: Intel Corp... PCI Express Port B #2 (rev fd) 496 + ... 497 + 05:00.0 PCI bridge: Pericom Semiconductor Device 2404 (rev 05) 498 + 06:01.0 PCI bridge: Pericom Semiconductor Device 2404 (rev 05) 499 + 06:02.0 PCI bridge: Pericom Semiconductor Device 2404 (rev 05) 500 + 06:03.0 PCI bridge: Pericom Semiconductor Device 2404 (rev 05) 501 + 07:00.0 Serial controller: Exar Corp. XR17V3521 Dual PCIe UART (rev 03) <-- Exar 502 + ... 503 + 504 + The bus topology is:: 505 + 506 + -[0000:00]-+-00.0 507 + ... 508 + +-13.0-[01]----00.0 509 + +-13.1-[02]----00.0 510 + +-13.2-[03]-- 511 + +-14.0-[04]----00.0 512 + +-14.1-[05-09]----00.0-[06-09]--+-01.0-[07]----00.0 <-- Exar 513 + | +-02.0-[08]----00.0 514 + | \-03.0-[09]-- 515 + ... 516 + \-1f.1 517 + 518 + To describe this Exar device on the PCI bus, we must start from the ACPI name 519 + of the chipset bridge (also called "root port") with address:: 520 + 521 + Bus: 0 - Device: 14 - Function: 1 522 + 523 + To find this information is necessary disassemble the BIOS ACPI tables, in 524 + particular the DSDT (see also [2]):: 525 + 526 + mkdir ~/tables/ 527 + cd ~/tables/ 528 + acpidump > acpidump 529 + acpixtract -a acpidump 530 + iasl -e ssdt?.* -d dsdt.dat 531 + 532 + Now, in the dsdt.dsl, we have to search the device whose address is related to 533 + 0x14 (device) and 0x01 (function). In this case we can find the following 534 + device:: 535 + 536 + Scope (_SB.PCI0) 537 + { 538 + ... other definitions follow ... 539 + Device (RP02) 540 + { 541 + Method (_ADR, 0, NotSerialized) // _ADR: Address 542 + { 543 + If ((RPA2 != Zero)) 544 + { 545 + Return (RPA2) /* \RPA2 */ 546 + } 547 + Else 548 + { 549 + Return (0x00140001) 550 + } 551 + } 552 + ... other definitions follow ... 553 + 554 + and the _ADR method [3] returns exactly the device/function couple that 555 + we are looking for. With this information and analyzing the above ``lspci`` 556 + output (both the devices list and the devices tree), we can write the following 557 + ACPI description for the Exar PCIe UART, also adding the list of its GPIO line 558 + names:: 559 + 560 + Scope (_SB.PCI0.RP02) 561 + { 562 + Device (BRG1) //Bridge 563 + { 564 + Name (_ADR, 0x0000) 565 + 566 + Device (BRG2) //Bridge 567 + { 568 + Name (_ADR, 0x00010000) 569 + 570 + Device (EXAR) 571 + { 572 + Name (_ADR, 0x0000) 573 + 574 + Name (_DSD, Package () 575 + { 576 + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 577 + Package () 578 + { 579 + Package () 580 + { 581 + "gpio-line-names", 582 + Package () 583 + { 584 + "mode_232", 585 + "mode_422", 586 + "mode_485", 587 + "misc_1", 588 + "misc_2", 589 + "misc_3", 590 + "", 591 + "", 592 + "aux_1", 593 + "aux_2", 594 + "aux_3", 595 + } 596 + } 597 + } 598 + }) 599 + } 600 + } 601 + } 602 + } 603 + 604 + The location "_SB.PCI0.RP02" is obtained by the above investigation in the 605 + dsdt.dsl table, whereas the device names "BRG1", "BRG2" and "EXAR" are 606 + created analyzing the position of the Exar UART in the PCI bus topology. 607 + 608 + References 609 + ========== 610 + 611 + [1] Documentation/firmware-guide/acpi/gpio-properties.rst 612 + 613 + [2] Documentation/admin-guide/acpi/initrd_table_override.rst 614 + 615 + [3] ACPI Specifications, Version 6.3 - Paragraph 6.1.1 _ADR Address) 616 + https://uefi.org/sites/default/files/resources/ACPI_6_3_May16.pdf, 617 + referenced 2020-11-18
+55 -1
Documentation/firmware-guide/acpi/gpio-properties.rst
··· 133 133 134 134 - gpio-line-names 135 135 136 - Example:: 136 + The ``gpio-line-names`` declaration is a list of strings ("names"), which 137 + describes each line/pin of a GPIO controller/expander. This list, contained in 138 + a package, must be inserted inside the GPIO controller declaration of an ACPI 139 + table (typically inside the DSDT). The ``gpio-line-names`` list must respect the 140 + following rules (see also the examples): 141 + 142 + - the first name in the list corresponds with the first line/pin of the GPIO 143 + controller/expander 144 + - the names inside the list must be consecutive (no "holes" are permitted) 145 + - the list can be incomplete and can end before the last GPIO line: in 146 + other words, it is not mandatory to fill all the GPIO lines 147 + - empty names are allowed (two quotation marks ``""`` correspond to an empty 148 + name) 149 + 150 + Example of a GPIO controller of 16 lines, with an incomplete list with two 151 + empty names:: 152 + 153 + Package () { 154 + "gpio-line-names", 155 + Package () { 156 + "pin_0", 157 + "pin_1", 158 + "", 159 + "", 160 + "pin_3", 161 + "pin_4_push_button", 162 + } 163 + } 164 + 165 + At runtime, the above declaration produces the following result (using the 166 + "libgpiod" tools):: 167 + 168 + root@debian:~# gpioinfo gpiochip4 169 + gpiochip4 - 16 lines: 170 + line 0: "pin_0" unused input active-high 171 + line 1: "pin_1" unused input active-high 172 + line 2: unnamed unused input active-high 173 + line 3: unnamed unused input active-high 174 + line 4: "pin_3" unused input active-high 175 + line 5: "pin_4_push_button" unused input active-high 176 + line 6: unnamed unused input active-high 177 + line 7 unnamed unused input active-high 178 + line 8: unnamed unused input active-high 179 + line 9: unnamed unused input active-high 180 + line 10: unnamed unused input active-high 181 + line 11: unnamed unused input active-high 182 + line 12: unnamed unused input active-high 183 + line 13: unnamed unused input active-high 184 + line 14: unnamed unused input active-high 185 + line 15: unnamed unused input active-high 186 + root@debian:~# gpiofind pin_4_push_button 187 + gpiochip4 5 188 + root@debian:~# 189 + 190 + Another example:: 137 191 138 192 Package () { 139 193 "gpio-line-names",
+1 -5
drivers/acpi/acpi_watchdog.c
··· 151 151 found = false; 152 152 resource_list_for_each_entry(rentry, &resource_list) { 153 153 if (rentry->res->flags == res.flags && 154 - resource_overlaps(rentry->res, &res)) { 155 - if (res.start < rentry->res->start) 156 - rentry->res->start = res.start; 157 - if (res.end > rentry->res->end) 158 - rentry->res->end = res.end; 154 + resource_union(rentry->res, &res, rentry->res)) { 159 155 found = true; 160 156 break; 161 157 }
+1 -3
drivers/acpi/pci_root.c
··· 722 722 * our resources no longer match the ACPI _CRS, but 723 723 * the kernel resource tree doesn't allow overlaps. 724 724 */ 725 - if (resource_overlaps(res1, res2)) { 726 - res2->start = min(res1->start, res2->start); 727 - res2->end = max(res1->end, res2->end); 725 + if (resource_union(res1, res2, res2)) { 728 726 dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n", 729 727 res2, res1); 730 728 free = true;
+1 -1
drivers/acpi/resource.c
··· 541 541 ret = c->preproc(ares, c->preproc_data); 542 542 if (ret < 0) { 543 543 c->error = ret; 544 - return AE_CTRL_TERMINATE; 544 + return AE_ABORT_METHOD; 545 545 } else if (ret > 0) { 546 546 return AE_OK; 547 547 }
+28 -8
include/linux/ioport.h
··· 10 10 #define _LINUX_IOPORT_H 11 11 12 12 #ifndef __ASSEMBLY__ 13 - #include <linux/compiler.h> 14 - #include <linux/types.h> 15 13 #include <linux/bits.h> 14 + #include <linux/compiler.h> 15 + #include <linux/minmax.h> 16 + #include <linux/types.h> 16 17 /* 17 18 * Resources are tree-like, allowing 18 19 * nesting etc.. ··· 230 229 return r1->start <= r2->start && r1->end >= r2->end; 231 230 } 232 231 232 + /* True if any part of r1 overlaps r2 */ 233 + static inline bool resource_overlaps(struct resource *r1, struct resource *r2) 234 + { 235 + return r1->start <= r2->end && r1->end >= r2->start; 236 + } 237 + 238 + static inline bool 239 + resource_intersection(struct resource *r1, struct resource *r2, struct resource *r) 240 + { 241 + if (!resource_overlaps(r1, r2)) 242 + return false; 243 + r->start = max(r1->start, r2->start); 244 + r->end = min(r1->end, r2->end); 245 + return true; 246 + } 247 + 248 + static inline bool 249 + resource_union(struct resource *r1, struct resource *r2, struct resource *r) 250 + { 251 + if (!resource_overlaps(r1, r2)) 252 + return false; 253 + r->start = min(r1->start, r2->start); 254 + r->end = max(r1->end, r2->end); 255 + return true; 256 + } 233 257 234 258 /* Convenience shorthand with allocation */ 235 259 #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) ··· 321 295 extern int 322 296 walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end, 323 297 void *arg, int (*func)(struct resource *, void *)); 324 - 325 - /* True if any part of r1 overlaps r2 */ 326 - static inline bool resource_overlaps(struct resource *r1, struct resource *r2) 327 - { 328 - return (r1->start <= r2->end && r1->end >= r2->start); 329 - } 330 298 331 299 struct resource *devm_request_free_mem_region(struct device *dev, 332 300 struct resource *base, unsigned long size);
+1
kernel/Makefile
··· 123 123 obj-$(CONFIG_RSEQ) += rseq.o 124 124 obj-$(CONFIG_WATCH_QUEUE) += watch_queue.o 125 125 126 + obj-$(CONFIG_RESOURCE_KUNIT_TEST) += resource_kunit.o 126 127 obj-$(CONFIG_SYSCTL_KUNIT_TEST) += sysctl-test.o 127 128 128 129 CFLAGS_stackleak.o += $(DISABLE_STACKLEAK_PLUGIN)
+5 -5
kernel/resource.c
··· 557 557 } 558 558 read_unlock(&resource_lock); 559 559 560 + if (type == 0) 561 + return REGION_DISJOINT; 562 + 560 563 if (other == 0) 561 - return type ? REGION_INTERSECTS : REGION_DISJOINT; 564 + return REGION_INTERSECTS; 562 565 563 - if (type) 564 - return REGION_MIXED; 565 - 566 - return REGION_DISJOINT; 566 + return REGION_MIXED; 567 567 } 568 568 EXPORT_SYMBOL_GPL(region_intersects); 569 569
+152
kernel/resource_kunit.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Test cases for API provided by resource.c and ioport.h 4 + */ 5 + 6 + #include <kunit/test.h> 7 + #include <linux/ioport.h> 8 + #include <linux/kernel.h> 9 + #include <linux/string.h> 10 + 11 + #define R0_START 0x0000 12 + #define R0_END 0xffff 13 + #define R1_START 0x1234 14 + #define R1_END 0x2345 15 + #define R2_START 0x4567 16 + #define R2_END 0x5678 17 + #define R3_START 0x6789 18 + #define R3_END 0x789a 19 + #define R4_START 0x2000 20 + #define R4_END 0x7000 21 + 22 + static struct resource r0 = { .start = R0_START, .end = R0_END }; 23 + static struct resource r1 = { .start = R1_START, .end = R1_END }; 24 + static struct resource r2 = { .start = R2_START, .end = R2_END }; 25 + static struct resource r3 = { .start = R3_START, .end = R3_END }; 26 + static struct resource r4 = { .start = R4_START, .end = R4_END }; 27 + 28 + struct result { 29 + struct resource *r1; 30 + struct resource *r2; 31 + struct resource r; 32 + bool ret; 33 + }; 34 + 35 + static struct result results_for_union[] = { 36 + { 37 + .r1 = &r1, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true, 38 + }, { 39 + .r1 = &r2, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true, 40 + }, { 41 + .r1 = &r3, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true, 42 + }, { 43 + .r1 = &r4, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true, 44 + }, { 45 + .r1 = &r2, .r2 = &r1, .ret = false, 46 + }, { 47 + .r1 = &r3, .r2 = &r1, .ret = false, 48 + }, { 49 + .r1 = &r4, .r2 = &r1, .r.start = R1_START, .r.end = R4_END, .ret = true, 50 + }, { 51 + .r1 = &r2, .r2 = &r3, .ret = false, 52 + }, { 53 + .r1 = &r2, .r2 = &r4, .r.start = R4_START, .r.end = R4_END, .ret = true, 54 + }, { 55 + .r1 = &r3, .r2 = &r4, .r.start = R4_START, .r.end = R3_END, .ret = true, 56 + }, 57 + }; 58 + 59 + static struct result results_for_intersection[] = { 60 + { 61 + .r1 = &r1, .r2 = &r0, .r.start = R1_START, .r.end = R1_END, .ret = true, 62 + }, { 63 + .r1 = &r2, .r2 = &r0, .r.start = R2_START, .r.end = R2_END, .ret = true, 64 + }, { 65 + .r1 = &r3, .r2 = &r0, .r.start = R3_START, .r.end = R3_END, .ret = true, 66 + }, { 67 + .r1 = &r4, .r2 = &r0, .r.start = R4_START, .r.end = R4_END, .ret = true, 68 + }, { 69 + .r1 = &r2, .r2 = &r1, .ret = false, 70 + }, { 71 + .r1 = &r3, .r2 = &r1, .ret = false, 72 + }, { 73 + .r1 = &r4, .r2 = &r1, .r.start = R4_START, .r.end = R1_END, .ret = true, 74 + }, { 75 + .r1 = &r2, .r2 = &r3, .ret = false, 76 + }, { 77 + .r1 = &r2, .r2 = &r4, .r.start = R2_START, .r.end = R2_END, .ret = true, 78 + }, { 79 + .r1 = &r3, .r2 = &r4, .r.start = R3_START, .r.end = R4_END, .ret = true, 80 + }, 81 + }; 82 + 83 + static void resource_do_test(struct kunit *test, bool ret, struct resource *r, 84 + bool exp_ret, struct resource *exp_r, 85 + struct resource *r1, struct resource *r2) 86 + { 87 + KUNIT_EXPECT_EQ_MSG(test, ret, exp_ret, "Resources %pR %pR", r1, r2); 88 + KUNIT_EXPECT_EQ_MSG(test, r->start, exp_r->start, "Start elements are not equal"); 89 + KUNIT_EXPECT_EQ_MSG(test, r->end, exp_r->end, "End elements are not equal"); 90 + } 91 + 92 + static void resource_do_union_test(struct kunit *test, struct result *r) 93 + { 94 + struct resource result; 95 + bool ret; 96 + 97 + memset(&result, 0, sizeof(result)); 98 + ret = resource_union(r->r1, r->r2, &result); 99 + resource_do_test(test, ret, &result, r->ret, &r->r, r->r1, r->r2); 100 + 101 + memset(&result, 0, sizeof(result)); 102 + ret = resource_union(r->r2, r->r1, &result); 103 + resource_do_test(test, ret, &result, r->ret, &r->r, r->r2, r->r1); 104 + } 105 + 106 + static void resource_test_union(struct kunit *test) 107 + { 108 + struct result *r = results_for_union; 109 + unsigned int i = 0; 110 + 111 + do { 112 + resource_do_union_test(test, &r[i]); 113 + } while (++i < ARRAY_SIZE(results_for_union)); 114 + } 115 + 116 + static void resource_do_intersection_test(struct kunit *test, struct result *r) 117 + { 118 + struct resource result; 119 + bool ret; 120 + 121 + memset(&result, 0, sizeof(result)); 122 + ret = resource_intersection(r->r1, r->r2, &result); 123 + resource_do_test(test, ret, &result, r->ret, &r->r, r->r1, r->r2); 124 + 125 + memset(&result, 0, sizeof(result)); 126 + ret = resource_intersection(r->r2, r->r1, &result); 127 + resource_do_test(test, ret, &result, r->ret, &r->r, r->r2, r->r1); 128 + } 129 + 130 + static void resource_test_intersection(struct kunit *test) 131 + { 132 + struct result *r = results_for_intersection; 133 + unsigned int i = 0; 134 + 135 + do { 136 + resource_do_intersection_test(test, &r[i]); 137 + } while (++i < ARRAY_SIZE(results_for_intersection)); 138 + } 139 + 140 + static struct kunit_case resource_test_cases[] = { 141 + KUNIT_CASE(resource_test_union), 142 + KUNIT_CASE(resource_test_intersection), 143 + {} 144 + }; 145 + 146 + static struct kunit_suite resource_test_suite = { 147 + .name = "resource", 148 + .test_cases = resource_test_cases, 149 + }; 150 + kunit_test_suite(resource_test_suite); 151 + 152 + MODULE_LICENSE("GPL");
+11
lib/Kconfig.debug
··· 2226 2226 2227 2227 If unsure, say N. 2228 2228 2229 + config RESOURCE_KUNIT_TEST 2230 + tristate "KUnit test for resource API" 2231 + depends on KUNIT 2232 + help 2233 + This builds the resource API unit test. 2234 + Tests the logic of API provided by resource.c and ioport.h. 2235 + For more information on KUnit and unit tests in general please refer 2236 + to the KUnit documentation in Documentation/dev-tools/kunit/. 2237 + 2238 + If unsure, say N. 2239 + 2229 2240 config SYSCTL_KUNIT_TEST 2230 2241 tristate "KUnit test for sysctl" if !KUNIT_ALL_TESTS 2231 2242 depends on KUNIT
-11
sound/soc/intel/catpt/core.h
··· 22 22 struct resource * 23 23 catpt_request_region(struct resource *root, resource_size_t size); 24 24 25 - static inline bool catpt_resource_overlapping(struct resource *r1, 26 - struct resource *r2, 27 - struct resource *ret) 28 - { 29 - if (!resource_overlaps(r1, r2)) 30 - return false; 31 - ret->start = max(r1->start, r2->start); 32 - ret->end = min(r1->end, r2->end); 33 - return true; 34 - } 35 - 36 25 struct catpt_ipc_msg { 37 26 union { 38 27 u32 header;
+1 -1
sound/soc/intel/catpt/loader.c
··· 267 267 r2.start = off; 268 268 r2.end = r2.start + info->size - 1; 269 269 270 - if (!catpt_resource_overlapping(&r2, &r1, &common)) 270 + if (!resource_intersection(&r2, &r1, &common)) 271 271 continue; 272 272 /* calculate start offset of common data area */ 273 273 off = common.start - r1.start;