We have observed the following on Power systems with SR-IOV capable adapters: lpfc 0002:01:00.0: device not available because of BAR 7 [0x000000-0x00ffff] collisions The issue is that on Power systems, PCI BARs cannot be remapped and VF BARs might have values that collide. As far as I can tell, the current SR-IOV code cannot be supported on Power and so it seems like we could provide a hook for an architecture that might set CONFIG_PCI_IOV to disable SR-IOV support (potentially at run-time). I defined a weak version of this function that returns true if CONFIG_PCI_IOV is set (which I think should reflect the current setup that CONFIG_PCI_IOV represents an unconditional support of SR-IOV) and false otherwise. The only architecture that implements the hook is powerpc, which uses a machine callback to decide if a platform supports SR-IOV or not. I only defined one such callback, for the pseries platform, and return false unconditionally there. This was tested to not result in BAR collisions against 3.1.0-rc9-00012-g6367f17. Signed-off-by: Nishanth Aravamudan <nacc@xxxxxxxxxx> --- Bjorn, FWIW, this also fixes the issue I was seeing, independent of the other change, as now the BARs aren't even touched. This is probably a "safer" change, too, as it doesn't assume that the path I was changing in the other patches was the only one to be touched for SR-IOV. diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 47cacdd..c11618e 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -211,6 +211,8 @@ struct machdep_calls { * allow assignment/enabling of the device. */ int (*pcibios_enable_device_hook)(struct pci_dev *); + bool (*pcibios_supports_sriov)(struct pci_dev *); + /* Called to shutdown machine specific hardware not already controlled * by other drivers. */ diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index 49c3de5..03dd50f 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h @@ -192,6 +192,8 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file, unsigned long size, pgprot_t prot); +extern bool pcibios_supports_sriov(struct pci_dev *); + #define HAVE_ARCH_PCI_RESOURCE_TO_USER extern void pci_resource_to_user(const struct pci_dev *dev, int bar, const struct resource *rsrc, diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 32656f1..aefc8a7 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1732,6 +1732,17 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); } +bool pcibios_supports_sriov(struct pci_dev *dev) +{ +#ifdef CONFIG_PCI_IOV + if (ppc_md.pcibios_supports_sriov) + return ppc_md.pcibios_supports_sriov(dev); + return true; +#else + return false; +#endif +} + static void fixup_hide_host_resource_fsl(struct pci_dev *dev) { int i, class = dev->class >> 8; diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 2c6ded2..3d75308 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -76,6 +76,11 @@ void __init pSeries_final_fixup(void) pci_addr_cache_build(); } +bool pSeries_supports_sriov(struct pci_dev *dev) +{ + return false; +} + /* * Assume the winbond 82c105 is the IDE controller on a * p610/p615/p630. We should probably be more careful in case diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 24c7162..9aeb176 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -43,6 +43,7 @@ static inline void setup_kexec_cpu_down_mpic(void) { } #endif extern void pSeries_final_fixup(void); +extern bool pSeries_supports_sriov(struct pci_dev *); /* Poweron flag used for enabling auto ups restart */ extern unsigned long rtas_poweron_auto; diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 0969fd9..f0e9f8f 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -697,6 +697,10 @@ static void pSeries_power_off(void) #ifndef CONFIG_PCI void pSeries_final_fixup(void) { } +bool pSeries_supports_sriov(struct pci_dev *) +{ + return false; +} #endif define_machine(pseries) { @@ -707,6 +711,7 @@ define_machine(pseries) { .show_cpuinfo = pSeries_show_cpuinfo, .log_error = pSeries_log_error, .pcibios_fixup = pSeries_final_fixup, + .pcibios_supports_sriov = pSeries_supports_sriov, .pci_probe_mode = pSeries_pci_probe_mode, .restart = rtas_restart, .power_off = pSeries_power_off, diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 42fae47..8f800bd 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -557,6 +557,9 @@ int pci_iov_init(struct pci_dev *dev) { int pos; + if (!pcibios_supports_sriov(dev)) + return -ENODEV; + if (!pci_is_pcie(dev)) return -ENODEV; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e9651f0..22c7416 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3330,6 +3330,15 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) return 0; } +bool __attribute__((weak)) pcibios_supports_sriov(struct pci_dev *dev) +{ +#ifdef CONFIG_PCI_IOV + return true; +#else + return false; +#endif +} + /* Some architectures require additional programming to enable VGA */ static arch_set_vga_state_t arch_set_vga_state; -- Nishanth Aravamudan <nacc@xxxxxxxxxx> IBM Linux Technology Center -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html