Commit 37f02195 authored by Yuanquan Chen's avatar Yuanquan Chen Committed by Michael Ellerman

powerpc/pci: fix PCI-e devices rescan issue on powerpc platform

Powerpc initializes the DMA and IRQ information in pci_scan_child_bus()->
pcibios_fixup_bus()->pcibios_setup_bus_devices(). But for the devices
which are hotpluged, bus->is added has been set for the first scan of the
PCI-e bus, so the initialization code won't be called. Then the hotpluged
devices' driver will fail to load.

For example :
The PCI-e device 0001:03:00.0 is the Intel PCI-e e1000e network card, remove
it from the system:

    # echo 1 > /sys/bus/pci/devices/0001\:03\:00.0/remove
    # e1000e 0001:03:00.0 eth0: removed PHC

Rescan it from it's bus:

    # echo 1 > /sys/bus/pci/devices/0001\:02\:00.0/rescan
    ...
    e1000e 0001:03:00.0: Disabling ASPM L0s L1
    e1000e 0001:03:00.0: No usable DMA configuration, aborting
    e1000e: probe of 0001:03:00.0 failed with error -5

So we move the DMA & IRQ initialization code from pcibios_setup_devices() and
construct a new function pcibios_enable_device. We call this function in
pcibios_enable_device, which will be called by PCI-e rescan code. At the
meanwhile, we avoid the the impact on cardbus. I also validate this patch with
silicon's PCIe-sata which encounters the IRQ issue.
Signed-off-by: default avatarYuanquan Chen <Yuanquan.Chen@freescale.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Hiroo Matsumoto <matsumoto.hiroo@jp.fujitsu.com>
Signed-off-by: default avatarMichael Ellerman <michael@ellerman.id.au>
parent 55671f3c
...@@ -1023,20 +1023,8 @@ void pcibios_setup_bus_self(struct pci_bus *bus) ...@@ -1023,20 +1023,8 @@ void pcibios_setup_bus_self(struct pci_bus *bus)
ppc_md.pci_dma_bus_setup(bus); ppc_md.pci_dma_bus_setup(bus);
} }
void pcibios_setup_bus_devices(struct pci_bus *bus) void pcibios_setup_device(struct pci_dev *dev)
{ {
struct pci_dev *dev;
pr_debug("PCI: Fixup bus devices %d (%s)\n",
bus->number, bus->self ? pci_name(bus->self) : "PHB");
list_for_each_entry(dev, &bus->devices, bus_list) {
/* Cardbus can call us to add new devices to a bus, so ignore
* those who are already fully discovered
*/
if (dev->is_added)
continue;
/* Fixup NUMA node as it may not be setup yet by the generic /* Fixup NUMA node as it may not be setup yet by the generic
* code and is needed by the DMA init * code and is needed by the DMA init
*/ */
...@@ -1054,6 +1042,23 @@ void pcibios_setup_bus_devices(struct pci_bus *bus) ...@@ -1054,6 +1042,23 @@ void pcibios_setup_bus_devices(struct pci_bus *bus)
pci_read_irq_line(dev); pci_read_irq_line(dev);
if (ppc_md.pci_irq_fixup) if (ppc_md.pci_irq_fixup)
ppc_md.pci_irq_fixup(dev); ppc_md.pci_irq_fixup(dev);
}
void pcibios_setup_bus_devices(struct pci_bus *bus)
{
struct pci_dev *dev;
pr_debug("PCI: Fixup bus devices %d (%s)\n",
bus->number, bus->self ? pci_name(bus->self) : "PHB");
list_for_each_entry(dev, &bus->devices, bus_list) {
/* Cardbus can call us to add new devices to a bus, so ignore
* those who are already fully discovered
*/
if (dev->is_added)
continue;
pcibios_setup_device(dev);
} }
} }
...@@ -1494,6 +1499,10 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) ...@@ -1494,6 +1499,10 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
if (ppc_md.pcibios_enable_device_hook(dev)) if (ppc_md.pcibios_enable_device_hook(dev))
return -EINVAL; return -EINVAL;
/* avoid pcie irq fix up impact on cardbus */
if (dev->hdr_type != PCI_HEADER_TYPE_CARDBUS)
pcibios_setup_device(dev);
return pci_enable_resources(dev, mask); return pci_enable_resources(dev, mask);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment