From 369d60bc21610167c5efa6cdf75ca0ea2fbcbcf6 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Mon, 28 Jan 2019 16:11:55 +0100 Subject: [PATCH] dde_linux: iterate over PCI devices in ascending BDF order On a Lenovo ThinkCentre M57p, the system locks up when the UHCI controller BIOS handoff (disabling bit 4 in the LEGSUP register) for the controller with PCI BDF 00:1d:2 is attempted before the handoff for the controller with BDF 00:1a:0. Fixes #3138 --- .../src/drivers/usb_host/spec/x86/platform.cc | 10 +++++++++- .../src/include/lx_kit/pci_dev_registry.h | 9 ++++++++- repos/dde_linux/src/lib/usb/spec/x86/pci_driver.cc | 14 +++++++++++--- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc b/repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc index e4f6302e80..9773e9ac15 100644 --- a/repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc +++ b/repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc @@ -71,7 +71,15 @@ class Pci_dev_list */ while (cap.valid()) { - _pci_caps.insert(new (Lx::Malloc::mem()) Element(cap)); + /* + * Keep PCI devices in natural bus order. Otherwise on a Lenovo + * ThinkCentre M57p, the system locks up when the UHCI + * controller BIOS handoff (disabling bit 4 in the LEGSUP + * register) for the controller with PCI BDF 00:1d:2 is + * attempted before the handoff for the controller with BDF + * 00:1a:0. + */ + _pci_caps.append(new (Lx::Malloc::mem()) Element(cap)); /* try next one. Upgrade session quota on demand.*/ Lx::pci()->with_upgrade([&] () { diff --git a/repos/dde_linux/src/include/lx_kit/pci_dev_registry.h b/repos/dde_linux/src/include/lx_kit/pci_dev_registry.h index 7cee6f736c..5dec03b893 100644 --- a/repos/dde_linux/src/include/lx_kit/pci_dev_registry.h +++ b/repos/dde_linux/src/include/lx_kit/pci_dev_registry.h @@ -45,7 +45,14 @@ class Lx::Pci_dev_registry void insert(Pci_dev *pci_dev) { - _devs.insert(pci_dev); + /* + * Keep PCI devices in natural bus order. Otherwise on a Lenovo + * ThinkCentre M57p, the system locks up when the UHCI controller + * BIOS handoff (disabling bit 4 in the LEGSUP register) for the + * controller with PCI BDF 00:1d:2 is attempted before the handoff + * for the controller with BDF 00:1a:0. + */ + _devs.append(pci_dev); } void remove(Pci_dev *pci_dev) diff --git a/repos/dde_linux/src/lib/usb/spec/x86/pci_driver.cc b/repos/dde_linux/src/lib/usb/spec/x86/pci_driver.cc index 17252159b8..814d587556 100644 --- a/repos/dde_linux/src/lib/usb/spec/x86/pci_driver.cc +++ b/repos/dde_linux/src/lib/usb/spec/x86/pci_driver.cc @@ -69,7 +69,15 @@ class Pci_dev_list */ while (cap.valid()) { - _pci_caps.insert(new (Lx::Malloc::mem()) Element(cap)); + /* + * Keep PCI devices in natural bus order. Otherwise on a Lenovo + * ThinkCentre M57p, the system locks up when the UHCI + * controller BIOS handoff (disabling bit 4 in the LEGSUP + * register) for the controller with PCI BDF 00:1d:2 is + * attempted before the handoff for the controller with BDF + * 00:1a:0. + */ + _pci_caps.append(new (Lx::Malloc::mem()) Element(cap)); /* try next one. Upgrade session quota on demand.*/ Lx::pci()->with_upgrade([&] () { @@ -105,7 +113,7 @@ extern "C" int pci_register_driver(struct pci_driver *driver) bool found = false; - auto lamda = [&] (Platform::Device_capability cap) { + auto lambda = [&] (Platform::Device_capability cap) { Platform::Device_client client(cap); @@ -164,7 +172,7 @@ extern "C" int pci_register_driver(struct pci_driver *driver) return true; }; - pci_dev_list()->for_each_pci_device(lamda); + pci_dev_list()->for_each_pci_device(lambda); return found ? 0 : -ENODEV; }