Subject: [PATCH] ACPI, PCI: add acpi_platform_notify_scan() Peter Hurley found irq nobody cared, and dmesg has [ 8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A [ 8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5 bisect to | commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4 | PCI: Put pci_dev in device tree as early as possible It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned. Add acpi_platform_notify_scan() to call acpi_pci_irq_add_prt later. Reported-and-tested-by: Peter Hurley Signed-off-by: Yinghai Lu --- drivers/acpi/glue.c | 12 ++++++++++++ drivers/base/core.c | 1 + drivers/pci/bus.c | 4 ++++ drivers/pci/pci-acpi.c | 27 +++++++++++++++++---------- include/acpi/acpi_bus.h | 1 + include/linux/device.h | 3 +-- 6 files changed, 36 insertions(+), 12 deletions(-) Index: linux-2.6/drivers/acpi/glue.c =================================================================== --- linux-2.6.orig/drivers/acpi/glue.c +++ linux-2.6/drivers/acpi/glue.c @@ -312,6 +312,17 @@ static int acpi_platform_notify(struct d return ret; } +static int acpi_platform_notify_scan(struct device *dev) +{ + struct acpi_bus_type *type; + + type = acpi_get_bus_type(dev->bus); + if (type && type->setup_scan) + type->setup_scan(dev); + + return 0; +} + static int acpi_platform_notify_remove(struct device *dev) { struct acpi_bus_type *type; @@ -331,6 +342,7 @@ int __init init_acpi_device_notify(void) return 0; } platform_notify = acpi_platform_notify; + platform_notify_scan = acpi_platform_notify_scan; platform_notify_remove = acpi_platform_notify_remove; return 0; } Index: linux-2.6/drivers/base/core.c =================================================================== --- linux-2.6.orig/drivers/base/core.c +++ linux-2.6/drivers/base/core.c @@ -44,6 +44,7 @@ early_param("sysfs.deprecated", sysfs_de #endif int (*platform_notify)(struct device *dev) = NULL; +int (*platform_notify_scan)(struct device *dev) = NULL; int (*platform_notify_remove)(struct device *dev) = NULL; static struct kobject *dev_kobj; struct kobject *sysfs_dev_char_kobj; Index: linux-2.6/drivers/pci/bus.c =================================================================== --- linux-2.6.orig/drivers/pci/bus.c +++ linux-2.6/drivers/pci/bus.c @@ -170,6 +170,10 @@ int pci_bus_add_device(struct pci_dev *d { int retval; + /* need to be called after bridge is scanned */ + if (platform_notify_scan) + platform_notify_scan(&dev->dev); + /* * Can not put in pci_device_add yet because resources * are not assigned yet for some devices. Index: linux-2.6/drivers/pci/pci-acpi.c =================================================================== --- linux-2.6.orig/drivers/pci/pci-acpi.c +++ linux-2.6/drivers/pci/pci-acpi.c @@ -307,6 +307,22 @@ static void pci_acpi_setup(struct device struct pci_dev *pci_dev = to_pci_dev(dev); acpi_handle handle = ACPI_HANDLE(dev); struct acpi_device *adev; + + if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) + return; + + device_set_wakeup_capable(dev, true); + acpi_pci_sleep_wake(pci_dev, false); + + pci_acpi_add_pm_notifier(adev, pci_dev); + if (adev->wakeup.flags.run_wake) + device_set_run_wake(dev, true); +} + +static void pci_acpi_setup_scan(struct device *dev) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + acpi_handle handle = ACPI_HANDLE(dev); acpi_status status; acpi_handle dummy; @@ -326,16 +342,6 @@ static void pci_acpi_setup(struct device pci_dev->subordinate->number : pci_dev->bus->number; acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus); } - - if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) - return; - - device_set_wakeup_capable(dev, true); - acpi_pci_sleep_wake(pci_dev, false); - - pci_acpi_add_pm_notifier(adev, pci_dev); - if (adev->wakeup.flags.run_wake) - device_set_run_wake(dev, true); } static void pci_acpi_cleanup(struct device *dev) @@ -359,6 +365,7 @@ static struct acpi_bus_type acpi_pci_bus .bus = &pci_bus_type, .find_device = acpi_pci_find_device, .setup = pci_acpi_setup, + .setup_scan = pci_acpi_setup_scan, .cleanup = pci_acpi_cleanup, }; Index: linux-2.6/include/acpi/acpi_bus.h =================================================================== --- linux-2.6.orig/include/acpi/acpi_bus.h +++ linux-2.6/include/acpi/acpi_bus.h @@ -440,6 +440,7 @@ struct acpi_bus_type { /* For bridges, such as PCI root bridge, IDE controller */ int (*find_bridge) (struct device *, acpi_handle *); void (*setup)(struct device *); + void (*setup_scan)(struct device *); void (*cleanup)(struct device *); }; int register_acpi_bus_type(struct acpi_bus_type *); Index: linux-2.6/include/linux/device.h =================================================================== --- linux-2.6.orig/include/linux/device.h +++ linux-2.6/include/linux/device.h @@ -897,10 +897,9 @@ extern void device_destroy(struct class */ /* Notify platform of device discovery */ extern int (*platform_notify)(struct device *dev); - +extern int (*platform_notify_scan)(struct device *dev); extern int (*platform_notify_remove)(struct device *dev); - /* * get_device - atomically increment the reference count for the device. *