Skip to content

Commit b4dfbbd

Browse files
dtorholtmann
authored andcommitted
usb: assign ACPI companions for embedded USB devices
USB devices permanently connected to USB ports may be described in ACPI tables and share ACPI devices with ports they are connected to. See [1] for details. This will allow us to describe sideband resources for devices, such as, for example, hard reset line for BT USB controllers. [1] https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/other-acpi-namespace-objects#acpi-namespace-hierarchy-and-adr-for-embedded-usb-devices Signed-off-by: Dmitry Torokhov <[email protected]> Signed-off-by: Rajat Jain <[email protected]> (changed how we get the usb_port) Acked-by: Greg Kroah-Hartman <[email protected]> Tested-by: Sukumar Ghorai <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent bcfcd40 commit b4dfbbd

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

drivers/usb/core/usb-acpi.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,30 +200,56 @@ static struct acpi_device *
200200
usb_acpi_find_companion_for_device(struct usb_device *udev)
201201
{
202202
struct acpi_device *adev;
203+
struct usb_port *port_dev;
204+
struct usb_hub *hub;
205+
206+
if (!udev->parent) {
207+
/* root hub is only child (_ADR=0) under its parent, the HC */
208+
adev = ACPI_COMPANION(udev->dev.parent);
209+
return acpi_find_child_device(adev, 0, false);
210+
}
203211

204-
if (!udev->parent)
212+
hub = usb_hub_to_struct_hub(udev->parent);
213+
if (!hub)
205214
return NULL;
206215

207-
/* root hub is only child (_ADR=0) under its parent, the HC */
208-
adev = ACPI_COMPANION(udev->dev.parent);
209-
return acpi_find_child_device(adev, 0, false);
216+
/*
217+
* This is an embedded USB device connected to a port and such
218+
* devices share port's ACPI companion.
219+
*/
220+
port_dev = hub->ports[udev->portnum - 1];
221+
return usb_acpi_get_companion_for_port(port_dev);
210222
}
211223

212-
213224
static struct acpi_device *usb_acpi_find_companion(struct device *dev)
214225
{
215226
/*
216-
* In the ACPI DSDT table, only usb root hub and usb ports are
217-
* acpi device nodes. The hierarchy like following.
227+
* The USB hierarchy like following:
228+
*
218229
* Device (EHC1)
219230
* Device (HUBN)
220231
* Device (PR01)
221232
* Device (PR11)
222233
* Device (PR12)
234+
* Device (FN12)
235+
* Device (FN13)
223236
* Device (PR13)
224237
* ...
225-
* So all binding process is divided into two parts. binding
226-
* root hub and usb ports.
238+
* where HUBN is root hub, and PRNN are USB ports and devices
239+
* connected to them, and FNNN are individualk functions for
240+
* connected composite USB devices. PRNN and FNNN may contain
241+
* _CRS and other methods describing sideband resources for
242+
* the connected device.
243+
*
244+
* On the kernel side both root hub and embedded USB devices are
245+
* represented as instances of usb_device structure, and ports
246+
* are represented as usb_port structures, so the whole process
247+
* is split into 2 parts: finding companions for devices and
248+
* finding companions for ports.
249+
*
250+
* Note that we do not handle individual functions of composite
251+
* devices yet, for that we would need to assign companions to
252+
* devices corresponding to USB interfaces.
227253
*/
228254
if (is_usb_device(dev))
229255
return usb_acpi_find_companion_for_device(to_usb_device(dev));

0 commit comments

Comments
 (0)