aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Nyman2017-06-02 08:36:26 -0500
committerGreg Kroah-Hartman2017-08-24 19:02:36 -0500
commit6b45092236817efd713e92beab934fe404393324 (patch)
tree95b7da9eafcd130cae1f948477790d24c3b35816
parentce1b98a30571b1022d6ce86d9876a7a7dbf9aed5 (diff)
downloadkernel-omap-6b45092236817efd713e92beab934fe404393324.tar.gz
kernel-omap-6b45092236817efd713e92beab934fe404393324.tar.xz
kernel-omap-6b45092236817efd713e92beab934fe404393324.zip
usb: optimize acpi companion search for usb port devices
commit ed18c5fa945768a9bec994e786edbbbc7695acf6 upstream. This optimization significantly reduces xhci driver load time. In ACPI tables the acpi companion port devices are children of the hub device. The port devices are identified by their port number returned by the ACPI _ADR method. _ADR 0 is reserved for the root hub device. The current implementation to find a acpi companion port device loops through all acpi port devices under that parent hub, evaluating their _ADR method each time a new port device is added. for a xHC controller with 25 ports under its roothub it will end up invoking ACPI bytecode 625 times before all ports are ready, making it really slow. The _ADR values are already read and cached earler. So instead of running the bytecode again we can check the cached _ADR value first, and then fall back to the old way. As one of the more significant changes, the xhci load time on Intel kabylake reduced by 70%, (28ms) from initcall xhci_pci_init+0x0/0x49 returned 0 after 39537 usecs to initcall xhci_pci_init+0x0/0x49 returned 0 after 11270 usecs Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/usb-acpi.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index 2776cfe64c09..ef9cf4a21afe 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -127,6 +127,22 @@ out:
127 */ 127 */
128#define USB_ACPI_LOCATION_VALID (1 << 31) 128#define USB_ACPI_LOCATION_VALID (1 << 31)
129 129
130static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent,
131 int raw)
132{
133 struct acpi_device *adev;
134
135 if (!parent)
136 return NULL;
137
138 list_for_each_entry(adev, &parent->children, node) {
139 if (acpi_device_adr(adev) == raw)
140 return adev;
141 }
142
143 return acpi_find_child_device(parent, raw, false);
144}
145
130static struct acpi_device *usb_acpi_find_companion(struct device *dev) 146static struct acpi_device *usb_acpi_find_companion(struct device *dev)
131{ 147{
132 struct usb_device *udev; 148 struct usb_device *udev;
@@ -174,8 +190,10 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev)
174 int raw; 190 int raw;
175 191
176 raw = usb_hcd_find_raw_port_number(hcd, port1); 192 raw = usb_hcd_find_raw_port_number(hcd, port1);
177 adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev), 193
178 raw, false); 194 adev = usb_acpi_find_port(ACPI_COMPANION(&udev->dev),
195 raw);
196
179 if (!adev) 197 if (!adev)
180 return NULL; 198 return NULL;
181 } else { 199 } else {
@@ -186,7 +204,9 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev)
186 return NULL; 204 return NULL;
187 205
188 acpi_bus_get_device(parent_handle, &adev); 206 acpi_bus_get_device(parent_handle, &adev);
189 adev = acpi_find_child_device(adev, port1, false); 207
208 adev = usb_acpi_find_port(adev, port1);
209
190 if (!adev) 210 if (!adev)
191 return NULL; 211 return NULL;
192 } 212 }