Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== Here's the main bluetooth-next pull request for the 5.1 kernel. - Fixes & improvements to mediatek, hci_qca, btrtl, and btmrvl HCI drivers - Fixes to parsing invalid L2CAP config option sizes - Locking fix to bt_accept_enqueue() - Add support for new Marvel sd8977 chipset - Various other smaller fixes & cleanups ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -139,85 +139,122 @@ static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent,
|
||||
return acpi_find_child_device(parent, raw, false);
|
||||
}
|
||||
|
||||
static struct acpi_device *usb_acpi_find_companion(struct device *dev)
|
||||
static struct acpi_device *
|
||||
usb_acpi_get_companion_for_port(struct usb_port *port_dev)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
struct acpi_device *adev;
|
||||
acpi_handle *parent_handle;
|
||||
int port1;
|
||||
|
||||
/* Get the struct usb_device point of port's hub */
|
||||
udev = to_usb_device(port_dev->dev.parent->parent);
|
||||
|
||||
/*
|
||||
* In the ACPI DSDT table, only usb root hub and usb ports are
|
||||
* acpi device nodes. The hierarchy like following.
|
||||
* The root hub ports' parent is the root hub. The non-root-hub
|
||||
* ports' parent is the parent hub port which the hub is
|
||||
* connected to.
|
||||
*/
|
||||
if (!udev->parent) {
|
||||
adev = ACPI_COMPANION(&udev->dev);
|
||||
port1 = usb_hcd_find_raw_port_number(bus_to_hcd(udev->bus),
|
||||
port_dev->portnum);
|
||||
} else {
|
||||
parent_handle = usb_get_hub_port_acpi_handle(udev->parent,
|
||||
udev->portnum);
|
||||
if (!parent_handle)
|
||||
return NULL;
|
||||
|
||||
acpi_bus_get_device(parent_handle, &adev);
|
||||
port1 = port_dev->portnum;
|
||||
}
|
||||
|
||||
return usb_acpi_find_port(adev, port1);
|
||||
}
|
||||
|
||||
static struct acpi_device *
|
||||
usb_acpi_find_companion_for_port(struct usb_port *port_dev)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
struct acpi_pld_info *pld;
|
||||
acpi_handle *handle;
|
||||
acpi_status status;
|
||||
|
||||
adev = usb_acpi_get_companion_for_port(port_dev);
|
||||
if (!adev)
|
||||
return NULL;
|
||||
|
||||
handle = adev->handle;
|
||||
status = acpi_get_physical_device_location(handle, &pld);
|
||||
if (!ACPI_FAILURE(status) && pld) {
|
||||
port_dev->location = USB_ACPI_LOCATION_VALID
|
||||
| pld->group_token << 8 | pld->group_position;
|
||||
port_dev->connect_type = usb_acpi_get_connect_type(handle, pld);
|
||||
ACPI_FREE(pld);
|
||||
}
|
||||
|
||||
return adev;
|
||||
}
|
||||
|
||||
static struct acpi_device *
|
||||
usb_acpi_find_companion_for_device(struct usb_device *udev)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
struct usb_port *port_dev;
|
||||
struct usb_hub *hub;
|
||||
|
||||
if (!udev->parent) {
|
||||
/* root hub is only child (_ADR=0) under its parent, the HC */
|
||||
adev = ACPI_COMPANION(udev->dev.parent);
|
||||
return acpi_find_child_device(adev, 0, false);
|
||||
}
|
||||
|
||||
hub = usb_hub_to_struct_hub(udev->parent);
|
||||
if (!hub)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* This is an embedded USB device connected to a port and such
|
||||
* devices share port's ACPI companion.
|
||||
*/
|
||||
port_dev = hub->ports[udev->portnum - 1];
|
||||
return usb_acpi_get_companion_for_port(port_dev);
|
||||
}
|
||||
|
||||
static struct acpi_device *usb_acpi_find_companion(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* The USB hierarchy like following:
|
||||
*
|
||||
* Device (EHC1)
|
||||
* Device (HUBN)
|
||||
* Device (PR01)
|
||||
* Device (PR11)
|
||||
* Device (PR12)
|
||||
* Device (FN12)
|
||||
* Device (FN13)
|
||||
* Device (PR13)
|
||||
* ...
|
||||
* So all binding process is divided into two parts. binding
|
||||
* root hub and usb ports.
|
||||
* where HUBN is root hub, and PRNN are USB ports and devices
|
||||
* connected to them, and FNNN are individualk functions for
|
||||
* connected composite USB devices. PRNN and FNNN may contain
|
||||
* _CRS and other methods describing sideband resources for
|
||||
* the connected device.
|
||||
*
|
||||
* On the kernel side both root hub and embedded USB devices are
|
||||
* represented as instances of usb_device structure, and ports
|
||||
* are represented as usb_port structures, so the whole process
|
||||
* is split into 2 parts: finding companions for devices and
|
||||
* finding companions for ports.
|
||||
*
|
||||
* Note that we do not handle individual functions of composite
|
||||
* devices yet, for that we would need to assign companions to
|
||||
* devices corresponding to USB interfaces.
|
||||
*/
|
||||
if (is_usb_device(dev)) {
|
||||
udev = to_usb_device(dev);
|
||||
if (udev->parent)
|
||||
return NULL;
|
||||
|
||||
/* root hub is only child (_ADR=0) under its parent, the HC */
|
||||
adev = ACPI_COMPANION(dev->parent);
|
||||
return acpi_find_child_device(adev, 0, false);
|
||||
} else if (is_usb_port(dev)) {
|
||||
struct usb_port *port_dev = to_usb_port(dev);
|
||||
int port1 = port_dev->portnum;
|
||||
struct acpi_pld_info *pld;
|
||||
acpi_handle *handle;
|
||||
acpi_status status;
|
||||
|
||||
/* Get the struct usb_device point of port's hub */
|
||||
udev = to_usb_device(dev->parent->parent);
|
||||
|
||||
/*
|
||||
* The root hub ports' parent is the root hub. The non-root-hub
|
||||
* ports' parent is the parent hub port which the hub is
|
||||
* connected to.
|
||||
*/
|
||||
if (!udev->parent) {
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
int raw;
|
||||
|
||||
raw = usb_hcd_find_raw_port_number(hcd, port1);
|
||||
|
||||
adev = usb_acpi_find_port(ACPI_COMPANION(&udev->dev),
|
||||
raw);
|
||||
|
||||
if (!adev)
|
||||
return NULL;
|
||||
} else {
|
||||
parent_handle =
|
||||
usb_get_hub_port_acpi_handle(udev->parent,
|
||||
udev->portnum);
|
||||
if (!parent_handle)
|
||||
return NULL;
|
||||
|
||||
acpi_bus_get_device(parent_handle, &adev);
|
||||
|
||||
adev = usb_acpi_find_port(adev, port1);
|
||||
|
||||
if (!adev)
|
||||
return NULL;
|
||||
}
|
||||
handle = adev->handle;
|
||||
status = acpi_get_physical_device_location(handle, &pld);
|
||||
if (ACPI_FAILURE(status) || !pld)
|
||||
return adev;
|
||||
|
||||
port_dev->location = USB_ACPI_LOCATION_VALID
|
||||
| pld->group_token << 8 | pld->group_position;
|
||||
port_dev->connect_type = usb_acpi_get_connect_type(handle, pld);
|
||||
ACPI_FREE(pld);
|
||||
|
||||
return adev;
|
||||
}
|
||||
if (is_usb_device(dev))
|
||||
return usb_acpi_find_companion_for_device(to_usb_device(dev));
|
||||
else if (is_usb_port(dev))
|
||||
return usb_acpi_find_companion_for_port(to_usb_port(dev));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
Reference in New Issue
Block a user