Commit 04ab7a5e authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] PCI Scan all functions

From: Jake Moilanen <moilanen@austin.ibm.com>

On a ppc64 logically partitioned system, there can be a setup where function
0 of a PCI-PCI bridge is assigned to one partition and (for example) function
2 is assigned to a second partition.  On the second partition, it would
appear that function 0 does not exist, but function 2 does.  If all the
functions are not scanned, everything under function 2 would not be detected.

This patch allows devices that don't respond to function 0, but do respond to
other functions to be marked with a quirk and have all of their functions
scanned.
parent 48ceccc1
...@@ -721,3 +721,29 @@ pci_find_hose_for_OF_device(struct device_node *node) ...@@ -721,3 +721,29 @@ pci_find_hose_for_OF_device(struct device_node *node)
} }
return NULL; return NULL;
} }
/*
* ppc64 can have multifunction devices that do not respond to function 0.
* In this case we must scan all functions.
*/
int
pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
{
struct device_node *busdn, *dn;
if (bus->self)
busdn = pci_device_to_OF_node(bus->self);
else
busdn = bus->sysdata; /* must be a phb */
/*
* Check to see if there is any of the 8 functions are in the
* device tree. If they are then we need to scan all the
* functions of this slot.
*/
for (dn = busdn->child; dn; dn = dn->sibling)
if ((dn->devfn >> 3) == (devfn >> 3))
return 1;
return 0;
}
...@@ -620,6 +620,9 @@ pci_scan_single_device(struct pci_bus *bus, int devfn) ...@@ -620,6 +620,9 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
{ {
int func, nr = 0; int func, nr = 0;
int scan_all_fns;
scan_all_fns = pcibios_scan_all_fns(bus, devfn);
for (func = 0; func < 8; func++, devfn++) { for (func = 0; func < 8; func++, devfn++) {
struct pci_dev *dev; struct pci_dev *dev;
...@@ -640,7 +643,7 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) ...@@ -640,7 +643,7 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
} }
} }
} else { } else {
if (func == 0) if (func == 0 && !scan_all_fns)
break; break;
} }
} }
......
...@@ -51,6 +51,7 @@ struct pci_controller { ...@@ -51,6 +51,7 @@ struct pci_controller {
bus numbers. */ bus numbers. */
#define pcibios_assign_all_busses() 1 #define pcibios_assign_all_busses() 1
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO alpha_mv.min_io_address #define PCIBIOS_MIN_IO alpha_mv.min_io_address
#define PCIBIOS_MIN_MEM alpha_mv.min_mem_address #define PCIBIOS_MIN_MEM alpha_mv.min_mem_address
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#endif #endif
#define pcibios_scan_all_fns(a, b) 0
static inline void pcibios_set_master(struct pci_dev *dev) static inline void pcibios_set_master(struct pci_dev *dev)
{ {
/* No special bus mastering setup handling */ /* No special bus mastering setup handling */
......
...@@ -2,4 +2,5 @@ ...@@ -2,4 +2,5 @@
/* JMA 18.05.03 - is kinda needed, if only to tell it we don't have a PCI bus */ /* JMA 18.05.03 - is kinda needed, if only to tell it we don't have a PCI bus */
#define PCI_DMA_BUS_IS_PHYS 0 #define PCI_DMA_BUS_IS_PHYS 0
#define pcibios_scan_all_fns(a, b) 0
...@@ -22,4 +22,6 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, ...@@ -22,4 +22,6 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
region->end = res->end; region->end = res->end;
} }
#define pcibios_scan_all_fns(a, b) 0
#endif #endif
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
*/ */
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
extern inline void pcibios_set_master(struct pci_dev *dev) extern inline void pcibios_set_master(struct pci_dev *dev)
{ {
......
...@@ -15,6 +15,7 @@ extern unsigned int pcibios_assign_all_busses(void); ...@@ -15,6 +15,7 @@ extern unsigned int pcibios_assign_all_busses(void);
#else #else
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
#endif #endif
#define pcibios_scan_all_fns(a, b) 0
extern unsigned long pci_mem_start; extern unsigned long pci_mem_start;
#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_IO 0x1000
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* loader. * loader.
*/ */
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000 #define PCIBIOS_MIN_MEM 0x10000000
......
...@@ -36,6 +36,7 @@ struct pci_bus_info ...@@ -36,6 +36,7 @@ struct pci_bus_info
}; };
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
static inline void pcibios_set_master(struct pci_dev *dev) static inline void pcibios_set_master(struct pci_dev *dev)
{ {
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#define PCIBIOS_MIN_IO 0x100 #define PCIBIOS_MIN_IO 0x100
#define PCIBIOS_MIN_MEM 0x00010000 #define PCIBIOS_MIN_MEM 0x00010000
#define pcibios_scan_all_fns(a, b) 0
/* /*
* Return whether the given PCI device DMA address mask can * Return whether the given PCI device DMA address mask can
* be supported properly. For example, if your device can * be supported properly. For example, if your device can
......
...@@ -20,6 +20,7 @@ extern unsigned int pcibios_assign_all_busses(void); ...@@ -20,6 +20,7 @@ extern unsigned int pcibios_assign_all_busses(void);
#else #else
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
#endif #endif
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000 #define PCIBIOS_MIN_MEM 0x10000000
......
...@@ -174,6 +174,7 @@ extern inline void pcibios_register_hba(struct pci_hba_data *x) ...@@ -174,6 +174,7 @@ extern inline void pcibios_register_hba(struct pci_hba_data *x)
** to zero for legacy platforms and one for PAT platforms. ** to zero for legacy platforms and one for PAT platforms.
*/ */
#define pcibios_assign_all_busses() (pdc_type == PDC_TYPE_PAT) #define pcibios_assign_all_busses() (pdc_type == PDC_TYPE_PAT)
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0x10 #define PCIBIOS_MIN_IO 0x10
#define PCIBIOS_MIN_MEM 0x1000 /* NBPG - but pci/setup-res.c dies */ #define PCIBIOS_MIN_MEM 0x1000 /* NBPG - but pci/setup-res.c dies */
......
...@@ -26,6 +26,7 @@ struct pci_dev; ...@@ -26,6 +26,7 @@ struct pci_dev;
extern int pci_assign_all_busses; extern int pci_assign_all_busses;
#define pcibios_assign_all_busses() (pci_assign_all_busses) #define pcibios_assign_all_busses() (pci_assign_all_busses)
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000 #define PCIBIOS_MIN_MEM 0x10000000
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000 #define PCIBIOS_MIN_MEM 0x10000000
extern int pcibios_scan_all_fns(struct pci_bus *bus, int devfn);
static inline void pcibios_set_master(struct pci_dev *dev) static inline void pcibios_set_master(struct pci_dev *dev)
{ {
/* No special bus mastering setup handling */ /* No special bus mastering setup handling */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
or architectures with incomplete PCI setup by the loader */ or architectures with incomplete PCI setup by the loader */
#define pcibios_assign_all_busses() 1 #define pcibios_assign_all_busses() 1
#define pcibios_scan_all_fns(a, b) 0
/* /*
* A board can define one or more PCI channels that represent built-in (or * A board can define one or more PCI channels that represent built-in (or
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* or architectures with incomplete PCI setup by the loader. * or architectures with incomplete PCI setup by the loader.
*/ */
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0UL #define PCIBIOS_MIN_IO 0UL
#define PCIBIOS_MIN_MEM 0UL #define PCIBIOS_MIN_MEM 0UL
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* or architectures with incomplete PCI setup by the loader. * or architectures with incomplete PCI setup by the loader.
*/ */
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0UL #define PCIBIOS_MIN_IO 0UL
#define PCIBIOS_MIN_MEM 0UL #define PCIBIOS_MIN_MEM 0UL
......
...@@ -2,5 +2,6 @@ ...@@ -2,5 +2,6 @@
#define __UM_PCI_H #define __UM_PCI_H
#define PCI_DMA_BUS_IS_PHYS (1) #define PCI_DMA_BUS_IS_PHYS (1)
#define pcibios_scan_all_fns(a, b) 0
#endif #endif
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
/* Get any platform-dependent definitions. */ /* Get any platform-dependent definitions. */
#include <asm/machdep.h> #include <asm/machdep.h>
#define pcibios_scan_all_fns(a, b) 0
/* Generic declarations. */ /* Generic declarations. */
struct scatterlist; struct scatterlist;
......
...@@ -17,6 +17,7 @@ extern unsigned int pcibios_assign_all_busses(void); ...@@ -17,6 +17,7 @@ extern unsigned int pcibios_assign_all_busses(void);
#else #else
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
#endif #endif
#define pcibios_scan_all_fns(a, b) 0
extern int no_iommu, force_iommu; extern int no_iommu, force_iommu;
......
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