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: Yuanquan Chen <Yuanquan.Chen@freescale.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Hiroo Matsumoto <matsumoto.hiroo@jp.fujitsu.com> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
This commit is contained in:
parent
55671f3cc2
commit
37f02195be
@ -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
|
||||||
*/
|
*/
|
||||||
@ -1055,6 +1043,23 @@ void pcibios_setup_bus_devices(struct pci_bus *bus)
|
|||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcibios_set_master(struct pci_dev *dev)
|
void pcibios_set_master(struct pci_dev *dev)
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user