thunderbolt: Log a warning if device links are not found

The software connection manager needs the device links in order to
establish the tunnels before the native protocols so log a warning if
they are not found.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
Mika Westerberg 2022-12-27 09:17:48 +02:00
parent 6dacc6db46
commit 408e1d965a
3 changed files with 32 additions and 14 deletions

View File

@ -12,7 +12,7 @@
#include "tb.h" #include "tb.h"
static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data,
void **return_value) void **ret)
{ {
struct acpi_device *adev = acpi_fetch_acpi_dev(handle); struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
struct fwnode_handle *fwnode; struct fwnode_handle *fwnode;
@ -84,6 +84,7 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data,
if (link) { if (link) {
dev_dbg(&nhi->pdev->dev, "created link from %s\n", dev_dbg(&nhi->pdev->dev, "created link from %s\n",
dev_name(&pdev->dev)); dev_name(&pdev->dev));
*(bool *)ret = true;
} else { } else {
dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n",
dev_name(&pdev->dev)); dev_name(&pdev->dev));
@ -104,22 +105,29 @@ out_put:
* Goes over ACPI namespace finding tunneled ports that reference to * Goes over ACPI namespace finding tunneled ports that reference to
* @nhi ACPI node. For each reference a device link is added. The link * @nhi ACPI node. For each reference a device link is added. The link
* is automatically removed by the driver core. * is automatically removed by the driver core.
*
* Returns %true if at least one link was created.
*/ */
void tb_acpi_add_links(struct tb_nhi *nhi) bool tb_acpi_add_links(struct tb_nhi *nhi)
{ {
acpi_status status; acpi_status status;
bool ret = false;
if (!has_acpi_companion(&nhi->pdev->dev)) if (!has_acpi_companion(&nhi->pdev->dev))
return; return false;
/* /*
* Find all devices that have usb4-host-controller interface * Find all devices that have usb4-host-controller interface
* property that references to this NHI. * property that references to this NHI.
*/ */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 32, status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 32,
tb_acpi_add_link, NULL, nhi, NULL); tb_acpi_add_link, NULL, nhi, (void **)&ret);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status)) {
dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n"); dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n");
return false;
}
return ret;
} }
/** /**

View File

@ -2366,12 +2366,13 @@ static const struct tb_cm_ops tb_cm_ops = {
* downstream ports and the NHI so that the device core will make sure * downstream ports and the NHI so that the device core will make sure
* NHI is resumed first before the rest. * NHI is resumed first before the rest.
*/ */
static void tb_apple_add_links(struct tb_nhi *nhi) static bool tb_apple_add_links(struct tb_nhi *nhi)
{ {
struct pci_dev *upstream, *pdev; struct pci_dev *upstream, *pdev;
bool ret;
if (!x86_apple_machine) if (!x86_apple_machine)
return; return false;
switch (nhi->pdev->device) { switch (nhi->pdev->device) {
case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE: case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE:
@ -2380,26 +2381,27 @@ static void tb_apple_add_links(struct tb_nhi *nhi)
case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI: case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI:
break; break;
default: default:
return; return false;
} }
upstream = pci_upstream_bridge(nhi->pdev); upstream = pci_upstream_bridge(nhi->pdev);
while (upstream) { while (upstream) {
if (!pci_is_pcie(upstream)) if (!pci_is_pcie(upstream))
return; return false;
if (pci_pcie_type(upstream) == PCI_EXP_TYPE_UPSTREAM) if (pci_pcie_type(upstream) == PCI_EXP_TYPE_UPSTREAM)
break; break;
upstream = pci_upstream_bridge(upstream); upstream = pci_upstream_bridge(upstream);
} }
if (!upstream) if (!upstream)
return; return false;
/* /*
* For each hotplug downstream port, create add device link * For each hotplug downstream port, create add device link
* back to NHI so that PCIe tunnels can be re-established after * back to NHI so that PCIe tunnels can be re-established after
* sleep. * sleep.
*/ */
ret = false;
for_each_pci_bridge(pdev, upstream->subordinate) { for_each_pci_bridge(pdev, upstream->subordinate) {
const struct device_link *link; const struct device_link *link;
@ -2415,11 +2417,14 @@ static void tb_apple_add_links(struct tb_nhi *nhi)
if (link) { if (link) {
dev_dbg(&nhi->pdev->dev, "created link from %s\n", dev_dbg(&nhi->pdev->dev, "created link from %s\n",
dev_name(&pdev->dev)); dev_name(&pdev->dev));
ret = true;
} else { } else {
dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n",
dev_name(&pdev->dev)); dev_name(&pdev->dev));
} }
} }
return ret;
} }
struct tb *tb_probe(struct tb_nhi *nhi) struct tb *tb_probe(struct tb_nhi *nhi)
@ -2446,8 +2451,13 @@ struct tb *tb_probe(struct tb_nhi *nhi)
tb_dbg(tb, "using software connection manager\n"); tb_dbg(tb, "using software connection manager\n");
tb_apple_add_links(nhi); /*
tb_acpi_add_links(nhi); * Device links are needed to make sure we establish tunnels
* before the PCIe/USB stack is resumed so complain here if we
* found them missing.
*/
if (!tb_apple_add_links(nhi) && !tb_acpi_add_links(nhi))
tb_warn(tb, "device links to tunneled native ports are missing!\n");
return tb; return tb;
} }

View File

@ -1333,7 +1333,7 @@ static inline bool usb4_port_device_is_offline(const struct usb4_port *usb4)
void tb_check_quirks(struct tb_switch *sw); void tb_check_quirks(struct tb_switch *sw);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
void tb_acpi_add_links(struct tb_nhi *nhi); bool tb_acpi_add_links(struct tb_nhi *nhi);
bool tb_acpi_is_native(void); bool tb_acpi_is_native(void);
bool tb_acpi_may_tunnel_usb3(void); bool tb_acpi_may_tunnel_usb3(void);
@ -1346,7 +1346,7 @@ void tb_acpi_exit(void);
int tb_acpi_power_on_retimers(struct tb_port *port); int tb_acpi_power_on_retimers(struct tb_port *port);
int tb_acpi_power_off_retimers(struct tb_port *port); int tb_acpi_power_off_retimers(struct tb_port *port);
#else #else
static inline void tb_acpi_add_links(struct tb_nhi *nhi) { } static inline bool tb_acpi_add_links(struct tb_nhi *nhi) { return false; }
static inline bool tb_acpi_is_native(void) { return true; } static inline bool tb_acpi_is_native(void) { return true; }
static inline bool tb_acpi_may_tunnel_usb3(void) { return true; } static inline bool tb_acpi_may_tunnel_usb3(void) { return true; }