[PATCH] Virtual IO devices don't have bridges

linas at austin.ibm.com linas at austin.ibm.com
Thu Jun 24 04:49:18 EST 2004


Hi Linda, Greg,

Below follows a set of patches to the ppc64 pci hotplug code.
If there are no objections from Linda or the other pSeries
hotplug maintainers, then Greg, please apply to your sources.

The three fixes are:
-- Virtual I/O (VIO) devices do not have PCI bridges associated
   with them.  Thus, performing a loop over all devices, when
   a VIO device was in the list caused a null-pointer deref.
   Appearently, no one ever tried to hot-unplug a pci slot
   on a system that had VIO devices on it before.

-- slot-remove ordering problem. EEH remove should be done last,
   after the pci slot remove.  This caused certain oddball but
   mostly harmless trouble in certain obscure hardware-failure
   testing scenarios.

-- Minor performance tweak to the struct slot structure.
   Putting the two u8 members of the struct will shrink the
   total struct size by 8 bytes.  Moving the struct list_head
   from last place to first place in the struct will avoid
   an add-immediate instruction generated by the compiler,
   without adversly afecting ofther member access.

Linas
-------------- next part --------------
--- drivers/pci/hotplug/rpaphp_pci.c.orig	2004-06-23 11:55:37.000000000 -0500
+++ drivers/pci/hotplug/rpaphp_pci.c	2004-06-23 13:22:01.000000000 -0500
@@ -376,8 +376,8 @@ int rpaphp_unconfig_pci_adapter(struct s

 		func = list_entry(ln, struct rpaphp_pci_func, sibling);
 		if (func->pci_dev) {
-			rpaphp_eeh_remove_bus_device(func->pci_dev);
 			pci_remove_bus_device(func->pci_dev);
+			rpaphp_eeh_remove_bus_device(func->pci_dev);
 		}
 		kfree(func);
 	}
@@ -513,9 +513,18 @@ struct hotplug_slot *rpaphp_find_hotplug
 		struct list_head *ln;

 		slot = list_entry(tmp, struct slot, rpaphp_slot_list);
+		if (slot->bridge == NULL) {
+			if (slot->dev_type == PCI_DEV) {
+				printk (KERN_WARNING "PCI slot missing bridge %s %s \n",
+				                    slot->name, slot->location);
+			}
+			continue;
+		}
+
 		bus = slot->bridge->subordinate;
-		if (!bus)
-			return NULL; /* shouldn't be here */
+		if (!bus) {
+			continue;  /* should never happen? */
+		}
 		for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
                                 struct pci_dev *pdev = pci_dev_b(ln);
 				if (pdev == dev)
--- drivers/pci/hotplug/rpaphp.h.orig	2004-06-18 16:10:47.000000000 -0500
+++ drivers/pci/hotplug/rpaphp.h	2004-06-23 13:28:20.000000000 -0500
@@ -85,6 +85,7 @@ struct rpaphp_pci_func {
  * struct slot - slot information for each *physical* slot
  */
 struct slot {
+	struct list_head rpaphp_slot_list;
 	int state;
 	u32 index;
 	u32 type;
@@ -92,6 +93,7 @@ struct slot {
 	char *name;
 	char *location;
 	u8 removable;
+	u8 dev_type;		/* VIO or PCI */
 	struct device_node *dn;	/* slot's device_node in OFDT */
 				/* dn has phb info */
 	struct pci_dev *bridge;	/* slot's pci_dev in pci_devices */
@@ -99,9 +101,7 @@ struct slot {
 		struct list_head pci_funcs; /* pci_devs in PCI slot */
 		struct vio_dev *vio_dev; /* vio_dev in VIO slot */
 	} dev;
-	u8 dev_type;		/* VIO or PCI */
 	struct hotplug_slot *hotplug_slot;
-	struct list_head rpaphp_slot_list;
 };

 extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops;


More information about the Linuxppc64-dev mailing list