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)
}
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)
int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
{
int func, nr = 0;
int scan_all_fns;
scan_all_fns = pcibios_scan_all_fns(bus, devfn);
for (func = 0; func < 8; func++, devfn++) {
struct pci_dev *dev;
......@@ -640,7 +643,7 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
}
}
} else {
if (func == 0)
if (func == 0 && !scan_all_fns)
break;
}
}
......
......@@ -51,6 +51,7 @@ struct pci_controller {
bus numbers. */
#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_MEM alpha_mv.min_mem_address
......
......@@ -20,6 +20,8 @@
#endif
#define pcibios_scan_all_fns(a, b) 0
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
......
/* Should not be needed. IDE stupidity */
/* 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,
region->end = res->end;
}
#define pcibios_scan_all_fns(a, b) 0
#endif
......@@ -8,6 +8,7 @@
*/
#define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
extern inline void pcibios_set_master(struct pci_dev *dev)
{
......
......@@ -15,6 +15,7 @@ extern unsigned int pcibios_assign_all_busses(void);
#else
#define pcibios_assign_all_busses() 0
#endif
#define pcibios_scan_all_fns(a, b) 0
extern unsigned long pci_mem_start;
#define PCIBIOS_MIN_IO 0x1000
......
......@@ -16,6 +16,7 @@
* loader.
*/
#define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000
......
......@@ -36,6 +36,7 @@ struct pci_bus_info
};
#define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
static inline void pcibios_set_master(struct pci_dev *dev)
{
......
......@@ -11,6 +11,8 @@
#define PCIBIOS_MIN_IO 0x100
#define PCIBIOS_MIN_MEM 0x00010000
#define pcibios_scan_all_fns(a, b) 0
/*
* Return whether the given PCI device DMA address mask can
* be supported properly. For example, if your device can
......
......@@ -20,6 +20,7 @@ extern unsigned int pcibios_assign_all_busses(void);
#else
#define pcibios_assign_all_busses() 0
#endif
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000
......
......@@ -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.
*/
#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_MEM 0x1000 /* NBPG - but pci/setup-res.c dies */
......
......@@ -26,6 +26,7 @@ struct pci_dev;
extern int 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_MEM 0x10000000
......
......@@ -19,6 +19,8 @@
#define PCIBIOS_MIN_IO 0x1000
#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)
{
/* No special bus mastering setup handling */
......
......@@ -12,6 +12,7 @@
or architectures with incomplete PCI setup by the loader */
#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
......
......@@ -8,6 +8,7 @@
* or architectures with incomplete PCI setup by the loader.
*/
#define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0UL
#define PCIBIOS_MIN_MEM 0UL
......
......@@ -11,6 +11,7 @@
* or architectures with incomplete PCI setup by the loader.
*/
#define pcibios_assign_all_busses() 0
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO 0UL
#define PCIBIOS_MIN_MEM 0UL
......
......@@ -2,5 +2,6 @@
#define __UM_PCI_H
#define PCI_DMA_BUS_IS_PHYS (1)
#define pcibios_scan_all_fns(a, b) 0
#endif
......@@ -17,6 +17,8 @@
/* Get any platform-dependent definitions. */
#include <asm/machdep.h>
#define pcibios_scan_all_fns(a, b) 0
/* Generic declarations. */
struct scatterlist;
......
......@@ -17,6 +17,7 @@ extern unsigned int pcibios_assign_all_busses(void);
#else
#define pcibios_assign_all_busses() 0
#endif
#define pcibios_scan_all_fns(a, b) 0
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