1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2020, Intel Corporation
6 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
9 #include <linux/acpi.h>
13 static acpi_status
tb_acpi_add_link(acpi_handle handle
, u32 level
, void *data
,
16 struct fwnode_reference_args args
;
17 struct fwnode_handle
*fwnode
;
18 struct tb_nhi
*nhi
= data
;
19 struct acpi_device
*adev
;
24 if (acpi_bus_get_device(handle
, &adev
))
27 fwnode
= acpi_fwnode_handle(adev
);
28 ret
= fwnode_property_get_reference_args(fwnode
, "usb4-host-interface",
33 /* It needs to reference this NHI */
34 if (nhi
->pdev
->dev
.fwnode
!= args
.fwnode
)
38 * Try to find physical device walking upwards to the hierarcy.
39 * We need to do this because the xHCI driver might not yet be
40 * bound so the USB3 SuperSpeed ports are not yet created.
42 dev
= acpi_get_first_physical_node(adev
);
47 dev
= acpi_get_first_physical_node(adev
);
54 * Check that the device is PCIe. This is because USB3
55 * SuperSpeed ports have this property and they are not power
56 * managed with the xHCI and the SuperSpeed hub so we create the
57 * link from xHCI instead.
59 while (!dev_is_pci(dev
))
66 * Check that this actually matches the type of device we
67 * expect. It should either be xHCI or PCIe root/downstream
70 pdev
= to_pci_dev(dev
);
71 if (pdev
->class == PCI_CLASS_SERIAL_USB_XHCI
||
73 (pci_pcie_type(pdev
) == PCI_EXP_TYPE_ROOT_PORT
||
74 pci_pcie_type(pdev
) == PCI_EXP_TYPE_DOWNSTREAM
))) {
75 const struct device_link
*link
;
77 link
= device_link_add(&pdev
->dev
, &nhi
->pdev
->dev
,
78 DL_FLAG_AUTOREMOVE_SUPPLIER
|
81 dev_dbg(&nhi
->pdev
->dev
, "created link from %s\n",
82 dev_name(&pdev
->dev
));
84 dev_warn(&nhi
->pdev
->dev
, "device link creation from %s failed\n",
85 dev_name(&pdev
->dev
));
90 fwnode_handle_put(args
.fwnode
);
95 * tb_acpi_add_links() - Add device links based on ACPI description
96 * @nhi: Pointer to NHI
98 * Goes over ACPI namespace finding tunneled ports that reference to
99 * @nhi ACPI node. For each reference a device link is added. The link
100 * is automatically removed by the driver core.
102 void tb_acpi_add_links(struct tb_nhi
*nhi
)
106 if (!has_acpi_companion(&nhi
->pdev
->dev
))
110 * Find all devices that have usb4-host-controller interface
111 * property that references to this NHI.
113 status
= acpi_walk_namespace(ACPI_TYPE_DEVICE
, ACPI_ROOT_OBJECT
, 32,
114 tb_acpi_add_link
, NULL
, nhi
, NULL
);
115 if (ACPI_FAILURE(status
))
116 dev_warn(&nhi
->pdev
->dev
, "failed to enumerate tunneled ports\n");