patch-2.4.0-test12 linux/drivers/pci/pci.c
Next file: linux/drivers/pci/setup-bus.c
Previous file: linux/drivers/parport/parport_pc.c
Back to the patch index
Back to the overall index
- Lines: 225
- Date:
Mon Dec 11 13:46:26 2000
- Orig file:
v2.4.0-test11/linux/drivers/pci/pci.c
- Orig date:
Sun Nov 19 18:44:12 2000
diff -u --recursive --new-file v2.4.0-test11/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
@@ -300,18 +300,25 @@
pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
{
const struct pci_device_id *id;
+ int ret = 0;
if (drv->id_table) {
id = pci_match_device(drv->id_table, dev);
- if (!id)
- return 0;
+ if (!id) {
+ ret = 0;
+ goto out;
+ }
} else
id = NULL;
+
+ dev_probe_lock();
if (drv->probe(dev, id) >= 0) {
dev->driver = drv;
- return 1;
+ ret = 1;
}
- return 0;
+ dev_probe_unlock();
+out:
+ return ret;
}
int
@@ -354,16 +361,16 @@
run_sbin_hotplug(struct pci_dev *pdev, int insert)
{
int i;
- char *argv[3], *envp[7];
- char id[20], sub_id[24], bus_id[64], class_id[20];
+ char *argv[3], *envp[8];
+ char id[20], sub_id[24], bus_id[24], class_id[20];
if (!hotplug_path[0])
return;
- sprintf(class_id, "PCI_CLASS=%X", pdev->class >> 8);
- sprintf(id, "PCI_ID=%X/%X", pdev->vendor, pdev->device);
- sprintf(sub_id, "PCI_SUBSYS_ID=%X/%X", pdev->subsystem_vendor, pdev->subsystem_device);
- sprintf(bus_id, "PCI_BUS_ID=%s", pdev->slot_name);
+ sprintf(class_id, "PCI_CLASS=%04X", pdev->class);
+ sprintf(id, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device);
+ sprintf(sub_id, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, pdev->subsystem_device);
+ sprintf(bus_id, "PCI_SLOT_NAME=%s", pdev->slot_name);
i = 0;
argv[i++] = hotplug_path;
@@ -376,6 +383,7 @@
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
/* other stuff we want to pass to /sbin/hotplug */
+ envp[i++] = class_id;
envp[i++] = id;
envp[i++] = sub_id;
envp[i++] = bus_id;
@@ -539,15 +547,9 @@
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
{
unsigned int pos, reg, next;
- u32 l, sz, tmp;
- u16 cmd;
+ u32 l, sz;
struct resource *res;
- /* Disable IO and memory while we fiddle */
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
- pci_write_config_word(dev, PCI_COMMAND, tmp);
-
for(pos=0; pos<howmany; pos = next) {
next = pos+1;
res = &dev->resource[pos];
@@ -578,10 +580,11 @@
res->start |= ((unsigned long) l) << 32;
res->end = res->start + sz;
pci_write_config_dword(dev, reg+4, ~0);
- pci_read_config_dword(dev, reg+4, &tmp);
+ pci_read_config_dword(dev, reg+4, &sz);
pci_write_config_dword(dev, reg+4, l);
- if (l)
- res->end = res->start + (((unsigned long) ~l) << 32);
+ if (~sz)
+ res->end = res->start + 0xffffffff +
+ (((unsigned long) ~sz) << 32);
#else
if (l) {
printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", dev->slot_name);
@@ -610,7 +613,6 @@
}
res->name = dev->name;
}
- pci_write_config_word(dev, PCI_COMMAND, cmd);
}
void __init pci_read_bridge_bases(struct pci_bus *child)
@@ -710,6 +712,7 @@
static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
{
struct pci_bus *child;
+ int i;
/*
* Allocate a new bus, and inherit stuff from the parent..
@@ -731,6 +734,10 @@
child->primary = parent->secondary;
child->subordinate = 0xff;
+ /* Set up default resource pointers.. */
+ for (i = 0; i < 4; i++)
+ child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
+
return child;
}
@@ -755,7 +762,7 @@
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass);
- if ((buses & 0xffffff) && !pcibios_assign_all_busses()) {
+ if ((buses & 0xffff00) && !pcibios_assign_all_busses()) {
/*
* Bus already configured by firmware, process it in the first
* pass and just note the configuration.
@@ -771,9 +778,8 @@
unsigned int cmax = pci_do_scan_bus(child);
if (cmax > max) max = cmax;
} else {
- int i;
- for (i = 0; i < 4; i++)
- child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
+ unsigned int cmax = child->subordinate;
+ if (cmax > max) max = cmax;
}
} else {
/*
@@ -786,6 +792,7 @@
pci_read_config_word(dev, PCI_COMMAND, &cr);
pci_write_config_word(dev, PCI_COMMAND, 0x0000);
pci_write_config_word(dev, PCI_STATUS, 0xffff);
+
child = pci_add_new_bus(bus, dev, ++max);
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
@@ -799,15 +806,12 @@
/* Now we can scan all subordinate buses... */
max = pci_do_scan_bus(child);
} else {
- int i;
/*
* For CardBus bridges, we leave 4 bus numbers
* as cards with a PCI-to-PCI bridge can be
* inserted later.
*/
max += 3;
- for (i = 0; i < 4; i++)
- child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
}
/*
* Set the subordinate bus number to its real value.
@@ -1086,6 +1090,9 @@
return 0;
}
+
+/* take care to suspend/resume bridges only once */
+
static int pci_pm_suspend_bus(struct pci_bus *bus)
{
struct list_head *list;
@@ -1097,9 +1104,6 @@
/* Walk the device children list */
list_for_each(list, &bus->devices)
pci_pm_suspend_device(pci_dev_b(list));
-
- /* Suspend the bus controller.. */
- pci_pm_suspend_device(bus->self);
return 0;
}
@@ -1107,8 +1111,6 @@
{
struct list_head *list;
- pci_pm_resume_device(bus->self);
-
/* Walk the device children list */
list_for_each(list, &bus->devices)
pci_pm_resume_device(pci_dev_b(list));
@@ -1122,18 +1124,26 @@
static int pci_pm_suspend(void)
{
struct list_head *list;
+ struct pci_bus *bus;
- list_for_each(list, &pci_root_buses)
- pci_pm_suspend_bus(pci_bus_b(list));
+ list_for_each(list, &pci_root_buses) {
+ bus = pci_bus_b(list);
+ pci_pm_suspend_bus(bus);
+ pci_pm_suspend_device(bus->self);
+ }
return 0;
}
static int pci_pm_resume(void)
{
struct list_head *list;
+ struct pci_bus *bus;
- list_for_each(list, &pci_root_buses)
- pci_pm_resume_bus(pci_bus_b(list));
+ list_for_each(list, &pci_root_buses) {
+ bus = pci_bus_b(list);
+ pci_pm_resume_device(bus->self);
+ pci_pm_resume_bus(bus);
+ }
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)