Commit 7c3db3a8 authored by Russell King's avatar Russell King Committed by Linus Torvalds

[PATCH] Eliminate stack allocation of struct pci_dev...

- Eliminate the stack allocation of a struct pci_dev, and make
  pci_scan_slot() take a bus and a devfn argument.
- Add "dev->multifunction" to indicate whether this is a multifunction
  device.
- Run header fixups before inserting the new pci device into any
  device lists or announcing it to the drivers.
- Convert some more stuff to use the list_for_each* macro(s).
parent f2820e1d
...@@ -801,7 +801,7 @@ static int power_off_slot (struct acpiphp_slot *slot) ...@@ -801,7 +801,7 @@ static int power_off_slot (struct acpiphp_slot *slot)
static int enable_device (struct acpiphp_slot *slot) static int enable_device (struct acpiphp_slot *slot)
{ {
u8 bus; u8 bus;
struct pci_dev dev0, *dev; struct pci_dev *dev;
struct pci_bus *child; struct pci_bus *child;
struct list_head *l; struct list_head *l;
struct acpiphp_func *func; struct acpiphp_func *func;
...@@ -824,16 +824,8 @@ static int enable_device (struct acpiphp_slot *slot) ...@@ -824,16 +824,8 @@ static int enable_device (struct acpiphp_slot *slot)
if (retval) if (retval)
goto err_exit; goto err_exit;
memset(&dev0, 0, sizeof (struct pci_dev));
dev0.bus = slot->bridge->pci_bus;
dev0.devfn = PCI_DEVFN(slot->device, 0);
dev0.sysdata = dev0.bus->sysdata;
dev0.dev.parent = dev0.bus->dev;
dev0.dev.bus = &pci_bus_type;
/* returned `dev' is the *first function* only! */ /* returned `dev' is the *first function* only! */
dev = pci_scan_slot (&dev0); dev = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
if (!dev) { if (!dev) {
err("No new device found\n"); err("No new device found\n");
......
...@@ -574,19 +574,13 @@ int cpci_configure_slot(struct slot* slot) ...@@ -574,19 +574,13 @@ int cpci_configure_slot(struct slot* slot)
/* Still NULL? Well then scan for it! */ /* Still NULL? Well then scan for it! */
if(slot->dev == NULL) { if(slot->dev == NULL) {
struct pci_dev dev0;
dbg("pci_dev still null"); dbg("pci_dev still null");
memset(&dev0, 0, sizeof (struct pci_dev));
dev0.bus = slot->bus;
dev0.devfn = slot->devfn;
dev0.sysdata = slot->bus->self->sysdata;
/* /*
* This will generate pci_dev structures for all functions, but * This will generate pci_dev structures for all functions, but
* we will only call this case when lookup fails. * we will only call this case when lookup fails.
*/ */
slot->dev = pci_scan_slot(&dev0); slot->dev = pci_scan_slot(slot->bus, slot->devfn);
if(slot->dev == NULL) { if(slot->dev == NULL) {
err("Could not find PCI device for slot %02x", slot->number); err("Could not find PCI device for slot %02x", slot->number);
return 0; return 0;
......
...@@ -84,24 +84,19 @@ static void *detect_HRT_floating_pointer(void *begin, void *end) ...@@ -84,24 +84,19 @@ static void *detect_HRT_floating_pointer(void *begin, void *end)
int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
{ {
unsigned char bus; unsigned char bus;
struct pci_dev dev0;
struct pci_bus *child; struct pci_bus *child;
int rc = 0; int rc = 0;
memset(&dev0, 0, sizeof(struct pci_dev));
if (func->pci_dev == NULL) if (func->pci_dev == NULL)
func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7)); func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7));
//Still NULL ? Well then scan for it ! //Still NULL ? Well then scan for it !
if (func->pci_dev == NULL) { if (func->pci_dev == NULL) {
dbg("INFO: pci_dev still null\n"); dbg("INFO: pci_dev still null\n");
dev0.bus = ctrl->pci_dev->bus;
dev0.devfn = (func->device << 3) + (func->function & 0x7);
dev0.sysdata = ctrl->pci_dev->sysdata;
//this will generate pci_dev structures for all functions, but we will only call this case when lookup fails //this will generate pci_dev structures for all functions, but we will only call this case when lookup fails
func->pci_dev = pci_scan_slot(&dev0); func->pci_dev = pci_scan_slot(ctrl->pci_dev->bus,
(func->device << 3) + (func->function & 0x7));
if (func->pci_dev == NULL) { if (func->pci_dev == NULL) {
dbg("ERROR: pci_dev still null\n"); dbg("ERROR: pci_dev still null\n");
return 0; return 0;
......
...@@ -845,26 +845,22 @@ static u8 bus_structure_fixup (u8 busno) ...@@ -845,26 +845,22 @@ static u8 bus_structure_fixup (u8 busno)
static int ibm_configure_device (struct pci_func *func) static int ibm_configure_device (struct pci_func *func)
{ {
unsigned char bus; unsigned char bus;
struct pci_dev dev0;
struct pci_bus *child; struct pci_bus *child;
int rc = 0; int rc = 0;
int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */
memset (&dev0, 0, sizeof (struct pci_dev));
if (!(bus_structure_fixup (func->busno))) if (!(bus_structure_fixup (func->busno)))
flag = 1; flag = 1;
if (func->dev == NULL) if (func->dev == NULL)
func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7)); func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7));
if (func->dev == NULL) { if (func->dev == NULL) {
dev0.bus = ibmphp_find_bus (func->busno); struct pci_bus *bus = ibmphp_find_bus (func->busno);
if (!dev0.bus) if (!bus)
return 0; return 0;
dev0.devfn = ((func->device << 3) + (func->function & 0x7));
dev0.sysdata = dev0.bus->sysdata;
func->dev = pci_scan_slot (&dev0); func->dev = pci_scan_slot(bus,
(func->device << 3) + (func->function & 0x7));
if (func->dev == NULL) { if (func->dev == NULL) {
err ("ERROR... : pci_dev still NULL \n"); err ("ERROR... : pci_dev still NULL \n");
......
...@@ -374,7 +374,8 @@ int pci_setup_device(struct pci_dev * dev) ...@@ -374,7 +374,8 @@ int pci_setup_device(struct pci_dev * dev)
dev->class = class; dev->class = class;
class >>= 8; class >>= 8;
DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, class, dev->hdr_type); DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn,
dev->vendor, dev->device, class, dev->hdr_type);
/* "Unknown power state" */ /* "Unknown power state" */
dev->current_state = 4; dev->current_state = 4;
...@@ -427,23 +428,35 @@ int pci_setup_device(struct pci_dev * dev) ...@@ -427,23 +428,35 @@ int pci_setup_device(struct pci_dev * dev)
* Read the config data for a PCI device, sanity-check it * Read the config data for a PCI device, sanity-check it
* and fill in the dev structure... * and fill in the dev structure...
*/ */
struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp) static struct pci_dev * __devinit
pci_scan_device(struct pci_bus *bus, int devfn)
{ {
struct pci_dev *dev; struct pci_dev *dev;
u32 l; u32 l;
u8 hdr_type;
if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
return NULL;
if (pci_read_config_dword(temp, PCI_VENDOR_ID, &l)) if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
return NULL; return NULL;
/* some broken boards return 0 or ~0 if a slot is empty: */ /* some broken boards return 0 or ~0 if a slot is empty: */
if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000)
return NULL; return NULL;
dev = kmalloc(sizeof(*dev), GFP_KERNEL); dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
if (!dev) if (!dev)
return NULL; return NULL;
memcpy(dev, temp, sizeof(*dev)); memset(dev, 0, sizeof(struct pci_dev));
dev->bus = bus;
dev->sysdata = bus->sysdata;
dev->dev.parent = bus->dev;
dev->dev.bus = &pci_bus_type;
dev->devfn = devfn;
dev->hdr_type = hdr_type & 0x7f;
dev->multifunction = !!(hdr_type & 0x80);
dev->vendor = l & 0xffff; dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff; dev->device = (l >> 16) & 0xffff;
...@@ -461,42 +474,44 @@ struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp) ...@@ -461,42 +474,44 @@ struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp)
strcpy(dev->dev.bus_id,dev->slot_name); strcpy(dev->dev.bus_id,dev->slot_name);
dev->dev.dma_mask = &dev->dma_mask; dev->dev.dma_mask = &dev->dma_mask;
device_register(&dev->dev);
return dev; return dev;
} }
struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp) struct pci_dev * __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
{ {
struct pci_bus *bus = temp->bus;
struct pci_dev *dev;
struct pci_dev *first_dev = NULL; struct pci_dev *first_dev = NULL;
int func = 0; int func;
int is_multi = 0;
u8 hdr_type;
for (func = 0; func < 8; func++, temp->devfn++) { for (func = 0; func < 8; func++, devfn++) {
if (func && !is_multi) /* not a multi-function device */ struct pci_dev *dev;
continue;
if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type))
continue;
temp->hdr_type = hdr_type & 0x7f;
dev = pci_scan_device(temp); dev = pci_scan_device(bus, devfn);
if (!dev) if (!dev)
continue; continue;
if (!func) {
is_multi = hdr_type & 0x80; if (func == 0) {
first_dev = dev; first_dev = dev;
} else {
dev->multifunction = 1;
} }
/* Fix up broken headers */
pci_fixup_device(PCI_FIXUP_HEADER, dev);
/* /*
* Link the device to both the global PCI device chain and * Link the device to both the global PCI device chain and
* the per-bus list of devices and add the /proc entry. * the per-bus list of devices and add the /proc entry.
* Note: this also runs the hotplug notifiers (bad!) --rmk
*/ */
device_register(&dev->dev);
pci_insert_device (dev, bus); pci_insert_device (dev, bus);
/* Fix up broken headers */ /*
pci_fixup_device(PCI_FIXUP_HEADER, dev); * If this is a single function device,
* don't scan past the first function.
*/
if (!dev->multifunction)
break;
} }
return first_dev; return first_dev;
} }
...@@ -507,28 +522,12 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) ...@@ -507,28 +522,12 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
struct list_head *ln; struct list_head *ln;
struct pci_dev *dev; struct pci_dev *dev;
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
return 0;
}
DBG("Scanning bus %02x\n", bus->number); DBG("Scanning bus %02x\n", bus->number);
max = bus->secondary; max = bus->secondary;
/* Create a device template */
memset(dev, 0, sizeof(*dev));
dev->bus = bus;
dev->sysdata = bus->sysdata;
dev->dev.parent = bus->dev;
dev->dev.bus = &pci_bus_type;
/* Go find them, Rover! */ /* Go find them, Rover! */
for (devfn = 0; devfn < 0x100; devfn += 8) { for (devfn = 0; devfn < 0x100; devfn += 8)
dev->devfn = devfn; pci_scan_slot(bus, devfn);
pci_scan_slot(dev);
}
kfree(dev);
/* /*
* After performing arch-dependent fixup of the bus, look behind * After performing arch-dependent fixup of the bus, look behind
...@@ -537,9 +536,9 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) ...@@ -537,9 +536,9 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
DBG("Fixups for bus %02x\n", bus->number); DBG("Fixups for bus %02x\n", bus->number);
pcibios_fixup_bus(bus); pcibios_fixup_bus(bus);
for (pass=0; pass < 2; pass++) for (pass=0; pass < 2; pass++)
for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { list_for_each_entry(dev, &bus->devices, bus_list) {
dev = pci_dev_b(ln); if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
max = pci_scan_bridge(bus, dev, max, pass); max = pci_scan_bridge(bus, dev, max, pass);
} }
......
...@@ -413,6 +413,7 @@ struct pci_dev { ...@@ -413,6 +413,7 @@ struct pci_dev {
/* These fields are used by common fixups */ /* These fields are used by common fixups */
unsigned int transparent:1; /* Transparent PCI bridge */ unsigned int transparent:1; /* Transparent PCI bridge */
unsigned int multifunction:1;/* Part of multi-function device */
}; };
#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
...@@ -548,7 +549,7 @@ static inline struct pci_bus *pci_alloc_primary_bus(int bus) ...@@ -548,7 +549,7 @@ static inline struct pci_bus *pci_alloc_primary_bus(int bus)
{ {
return pci_alloc_primary_bus_parented(NULL, bus); return pci_alloc_primary_bus_parented(NULL, bus);
} }
struct pci_dev *pci_scan_slot(struct pci_dev *temp); struct pci_dev *pci_scan_slot(struct pci_bus *bus, int devfn);
int pci_proc_attach_device(struct pci_dev *dev); int pci_proc_attach_device(struct pci_dev *dev);
int pci_proc_detach_device(struct pci_dev *dev); int pci_proc_detach_device(struct pci_dev *dev);
int pci_proc_attach_bus(struct pci_bus *bus); int pci_proc_attach_bus(struct pci_bus *bus);
......
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