Subject: PCI Hotplug: rpaphp: Move VIO registration

From: John Rose <[email-masked]>
Date: Mon, 25 Jul 2005 10:16:42 -0500

Currently, rpaphp registers Virtual I/O slots as hotplug slots.  The
only purpose of this registration is to ensure that the VIO subsystem
is notified of new VIO buses during DLPAR adds.  Similarly, rpaphp
notifies the VIO subsystem when a VIO bus is DLPAR-removed.  The rpaphp
module has special case code to fake results for attributes like power,
adapter status, etc.  

The VIO register/unregister functions could just as easily be made from
the DLPAR module.  This patch moves the VIO registration calls to the
DLPAR module, and removes the VIO fluff from rpaphp altogether.

Signed-off-by: John Rose <[email-masked]>
Signed-off-by: Greg Kroah-Hartman <[email-masked]>

---
 drivers/pci/hotplug/Makefile        |    3 
 drivers/pci/hotplug/rpadlpar_core.c |  110 ++++++++++++++++++------------
 drivers/pci/hotplug/rpaphp.h        |   16 ----
 drivers/pci/hotplug/rpaphp_core.c   |   77 +++------------------
 drivers/pci/hotplug/rpaphp_pci.c    |   15 +---
 drivers/pci/hotplug/rpaphp_slot.c   |    9 --
 drivers/pci/hotplug/rpaphp_vio.c    |  129 ------------------------------------
 7 files changed, 88 insertions(+), 271 deletions(-)

--- gregkh-2.6.orig/drivers/pci/hotplug/rpadlpar_core.c	2005-06-17 12:48:29.000000000 -0700
+++ gregkh-2.6/drivers/pci/hotplug/rpadlpar_core.c	2005-07-26 16:10:01.000000000 -0700
@@ -19,6 +19,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/semaphore.h>
 #include <asm/rtas.h>
+#include <asm/vio.h>
 #include "../pci.h"
 #include "rpaphp.h"
 #include "rpadlpar.h"
@@ -29,23 +30,23 @@
 #define NODE_TYPE_SLOT 2
 #define NODE_TYPE_PHB  3
 
-static struct device_node *find_php_slot_vio_node(char *drc_name)
+static struct device_node *find_vio_slot_node(char *drc_name)
 {
-	struct device_node *child;
 	struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
-	char *loc_code;
+	struct device_node *dn = NULL;
+	char *name;
+	int rc;
 
 	if (!parent)
 		return NULL;
 
-	for (child = of_get_next_child(parent, NULL);
-		child; child = of_get_next_child(parent, child)) {
-		loc_code = get_property(child, "ibm,loc-code", NULL);
-		if (loc_code && !strncmp(loc_code, drc_name, strlen(drc_name)))
-			return child;
+	while ((dn = of_get_next_child(parent, dn))) {
+		rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
+		if ((rc == 0) && (!strcmp(drc_name, name)))
+			break;
 	}
 
-	return NULL;
+	return dn;
 }
 
 /* Find dlpar-capable pci node that contains the specified name and type */
@@ -67,7 +68,7 @@
 	return np;
 }
 
-static struct device_node *find_newly_added_node(char *drc_name, int *node_type)
+static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
 {
 	struct device_node *dn;
 
@@ -83,7 +84,7 @@
 		return dn;
 	}
 
-	dn = find_php_slot_vio_node(drc_name);
+	dn = find_vio_slot_node(drc_name);
 	if (dn) {
 		*node_type = NODE_TYPE_VIO;
 		return dn;
@@ -231,6 +232,12 @@
 		return -EIO;
 	}
 
+	/* Add hotplug slot */
+	if (rpaphp_add_slot(dn)) {
+		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+			__FUNCTION__, drc_name);
+		return -EIO;
+	}
 	return 0;
 }
 
@@ -288,7 +295,7 @@
 	return 0;
 }
 
-static int dlpar_add_phb(struct device_node *dn)
+static int dlpar_add_phb(char *drc_name, struct device_node *dn)
 {
 	struct pci_controller *phb;
 
@@ -296,6 +303,11 @@
 	if (!phb)
 		return -EINVAL;
 
+	if (rpaphp_add_slot(dn)) {
+		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+			__FUNCTION__, drc_name);
+		return -EIO;
+	}
 	return 0;
 }
 
@@ -316,7 +328,7 @@
 {
 	struct device_node *dn = NULL;
 	int node_type;
-	int rc = 0;
+	int rc;
 
 	if (down_interruptible(&rpadlpar_sem))
 		return -ERESTARTSYS;
@@ -327,32 +339,39 @@
 		goto exit;
 	}
 
-	dn = find_newly_added_node(drc_name, &node_type);
+	/* Find newly added node */
+	dn = find_dlpar_node(drc_name, &node_type);
 	if (!dn) {
 		rc = -ENODEV;
 		goto exit;
 	}
 
+	rc = -EIO;
 	switch (node_type) {
 		case NODE_TYPE_VIO:
-			/* Just add hotplug slot */
+			if (!vio_register_device_node(dn)) {
+				printk(KERN_ERR
+					"%s: failed to register vio node %s\n",
+					__FUNCTION__, drc_name);
+				goto exit;
+			}
 			break;
 		case NODE_TYPE_SLOT:
 			rc = dlpar_add_pci_slot(drc_name, dn);
+			if (rc)
+				goto exit;
 			break;
 		case NODE_TYPE_PHB:
-			rc = dlpar_add_phb(dn);
+			rc = dlpar_add_phb(drc_name, dn);
+			if (rc)
+				goto exit;
 			break;
 		default:
 			printk("%s: unexpected node type\n", __FUNCTION__);
-			return -EIO;
+			goto exit;
 	}
 
-	if (!rc && rpaphp_add_slot(dn)) {
-		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
-			__FUNCTION__, drc_name);
-		rc = -EIO;
-	}
+	rc = 0;
 exit:
 	up(&rpadlpar_sem);
 	return rc;
@@ -368,15 +387,18 @@
  * 0			Success
  * -EIO			Internal  Error
  */
-int dlpar_remove_vio_slot(struct slot *slot, char *drc_name)
+static int dlpar_remove_vio_slot(struct device_node *dn, char *drc_name)
 {
-	/* Remove hotplug slot */
+	struct vio_dev *vio_dev;
 
-	if (rpaphp_remove_slot(slot)) {
-		printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
-			__FUNCTION__, drc_name);
+	vio_dev = vio_find_node(dn);
+	if (!vio_dev) {
+		printk(KERN_ERR "%s: %s does not correspond to a vio dev\n",
+				__FUNCTION__, drc_name);
 		return -EIO;
 	}
+
+	vio_unregister_device(vio_dev);
 	return 0;
 }
 
@@ -434,36 +456,34 @@
  */
 int dlpar_remove_slot(char *drc_name)
 {
+	struct device_node *dn;
 	struct slot *slot;
+	int node_type;
 	int rc = 0;
 
 	if (down_interruptible(&rpadlpar_sem))
 		return -ERESTARTSYS;
 
-	if (!find_php_slot_vio_node(drc_name) &&
-	    !find_php_slot_pci_node(drc_name, "SLOT") &&
-	    !find_php_slot_pci_node(drc_name, "PHB")) {
+	dn = find_dlpar_node(drc_name, &node_type);
+	if (!dn) {
 		rc = -ENODEV;
 		goto exit;
 	}
 
-	slot = find_slot(drc_name);
-	if (!slot) {
-		rc = -EINVAL;
-		goto exit;
-	}
-	
-	if (slot->type == PHB) {
-		rc = dlpar_remove_phb(slot);
+	if (node_type == NODE_TYPE_VIO) {
+		rc = dlpar_remove_vio_slot(dn, drc_name);
 	} else {
-		switch (slot->dev_type) {
-			case PCI_DEV:
-				rc = dlpar_remove_pci_slot(slot, drc_name);
-				break;
+		slot = find_slot(drc_name);
+		if (!slot) {
+			rc = -EINVAL;
+			goto exit;
+		}
 
-			case VIO_DEV:
-				rc = dlpar_remove_vio_slot(slot, drc_name);
-				break;
+		if (node_type == NODE_TYPE_PHB)
+			rc = dlpar_remove_phb(slot);
+		else {
+			/* NODE_TYPE_SLOT */
+			rc = dlpar_remove_pci_slot(slot, drc_name);
 		}
 	}
 exit:
--- gregkh-2.6.orig/drivers/pci/hotplug/rpaphp_core.c	2005-06-17 12:48:29.000000000 -0700
+++ gregkh-2.6/drivers/pci/hotplug/rpaphp_core.c	2005-07-26 16:10:01.000000000 -0700
@@ -152,17 +152,7 @@
 	int retval = 0;
 
 	down(&rpaphp_sem);
-	/*  have to go through this */
-	switch (slot->dev_type) {
-	case PCI_DEV:
-		retval = rpaphp_get_pci_adapter_status(slot, 0, value);
-		break;
-	case VIO_DEV:
-		retval = rpaphp_get_vio_adapter_status(slot, 0, value);
-		break;
-	default:
-		retval = -EINVAL;
-	}
+	retval = rpaphp_get_pci_adapter_status(slot, 0, value);
 	up(&rpaphp_sem);
 	return retval;
 }
@@ -362,12 +352,6 @@
 
 	dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
 
-	if (dn->parent && is_vdevice_root(dn->parent)) {
-		/* register a VIO device */
-		retval = register_vio_slot(dn);
-		goto exit;
-	}
-
 	/* register PCI devices */
 	if (dn->name != 0 && strcmp(dn->name, "pci") == 0) {
 		if (is_php_dn(dn, &indexes, &names, &types, &power_domains))  
@@ -412,31 +396,6 @@
 	return retval;
 }
 
-/*
- * init_slots - initialize 'struct slot' structures for each slot
- *
- */
-static void init_slots(void)
-{
-	struct device_node *dn;
-
-	for (dn = find_all_nodes(); dn; dn = dn->next)
-		rpaphp_add_slot(dn);
-}
-
-static int __init init_rpa(void)
-{
-
-	init_MUTEX(&rpaphp_sem);
-
-	/* initialize internal data structure etc. */
-	init_slots();
-	if (!num_slots)
-		return -ENODEV;
-
-	return 0;
-}
-
 static void __exit cleanup_slots(void)
 {
 	struct list_head *tmp, *n;
@@ -458,10 +417,18 @@
 
 static int __init rpaphp_init(void)
 {
+	struct device_node *dn = NULL;
+
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	init_MUTEX(&rpaphp_sem);
+
+	while ((dn = of_find_node_by_type(dn, "pci")))
+		rpaphp_add_slot(dn);
+
+	if (!num_slots)
+		return -ENODEV;
 
-	/* read all the PRA info from the system */
-	return init_rpa();
+	return 0;
 }
 
 static void __exit rpaphp_exit(void)
@@ -481,16 +448,7 @@
 
 	dbg("ENABLING SLOT %s\n", slot->name);
 	down(&rpaphp_sem);
-	switch (slot->dev_type) {
-	case PCI_DEV:
-		retval = rpaphp_enable_pci_slot(slot);
-		break;
-	case VIO_DEV:
-		retval = rpaphp_enable_vio_slot(slot);
-		break;
-	default:
-		retval = -EINVAL;
-	}
+	retval = rpaphp_enable_pci_slot(slot);
 	up(&rpaphp_sem);
 exit:
 	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
@@ -511,16 +469,7 @@
 
 	dbg("DISABLING SLOT %s\n", slot->name);
 	down(&rpaphp_sem);
-	switch (slot->dev_type) {
-	case PCI_DEV:
-		retval = rpaphp_unconfig_pci_adapter(slot);
-		break;
-	case VIO_DEV:
-		retval = rpaphp_unconfig_vio_adapter(slot);
-		break;
-	default:
-		retval = -ENODEV;
-	}
+	retval = rpaphp_unconfig_pci_adapter(slot);
 	up(&rpaphp_sem);
 exit:
 	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
--- gregkh-2.6.orig/drivers/pci/hotplug/rpaphp_vio.c	2005-06-17 12:48:29.000000000 -0700
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,129 +0,0 @@
-/*
- * RPA Hot Plug Virtual I/O device functions 
- * Copyright (C) 2004 Linda Xie <[email-masked]>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email-masked]>
- *
- */
-#include <asm/vio.h>
-#include "rpaphp.h"
-
-/*
- * get_vio_adapter_status - get  the status of a slot
- * 
- * status:
- * 
- * 1-- adapter is configured
- * 2-- adapter is not configured
- * 3-- not valid
- */
-inline int rpaphp_get_vio_adapter_status(struct slot *slot, int is_init, u8 *value)
-{
-	*value = slot->state;
-	return 0;
-}
-
-int rpaphp_unconfig_vio_adapter(struct slot *slot)
-{
-	int retval = 0;
-
-	dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
-	if (!slot->dev.vio_dev) {
-		info("%s: no VIOA in slot[%s]\n", __FUNCTION__, slot->name);
-		retval = -EINVAL;
-		goto exit;
-	}
-	/* remove the device from the vio core */
-	vio_unregister_device(slot->dev.vio_dev);
-	slot->state = NOT_CONFIGURED;
-	info("%s: adapter in slot[%s] unconfigured.\n", __FUNCTION__, slot->name);
-exit:
-	dbg("Exit %s, rc=0x%x\n", __FUNCTION__, retval);
-	return retval;
-}
-
-static int setup_vio_hotplug_slot_info(struct slot *slot)
-{
-	slot->hotplug_slot->info->power_status = 1;
-	rpaphp_get_vio_adapter_status(slot, 1,
-		&slot->hotplug_slot->info->adapter_status); 
-	return 0;
-}
-
-int register_vio_slot(struct device_node *dn)
-{
-	u32 *index;
-	char *name;
-	int rc = -EINVAL;
-	struct slot *slot = NULL;
-	
-	rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
-	if (rc < 0)
-		goto exit_rc;
-	index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL);
-	if (!index)
-		goto exit_rc;
-	if (!(slot = alloc_slot_struct(dn, *index, name, 0))) {
-		rc = -ENOMEM;
-		goto exit_rc;
-	}
-	slot->dev_type = VIO_DEV;
-	slot->dev.vio_dev = vio_find_node(dn);
-	if (slot->dev.vio_dev) {
-		/*
-		 * rpaphp is the only owner of vio devices and
-		 * does not need extra reference taken by
-		 * vio_find_node
-		 */
-		put_device(&slot->dev.vio_dev->dev);
-	} else
-		slot->dev.vio_dev = vio_register_device_node(dn);
-	if (slot->dev.vio_dev)
-		slot->state = CONFIGURED;
-	else
-		slot->state = NOT_CONFIGURED;
-	if (setup_vio_hotplug_slot_info(slot))
-		goto exit_rc;
-	strcpy(slot->name, slot->dev.vio_dev->dev.bus_id);
-	info("%s: registered VIO device[name=%s vio_dev=%p]\n",
-		__FUNCTION__, slot->name, slot->dev.vio_dev); 
-	rc = register_slot(slot);
-exit_rc:
-	if (rc && slot)
-		dealloc_slot_struct(slot);
-	return (rc);
-}
-
-int rpaphp_enable_vio_slot(struct slot *slot)
-{
-	int retval = 0;
-
-	if ((slot->dev.vio_dev = vio_register_device_node(slot->dn))) {
-		info("%s: VIO adapter %s in slot[%s] has been configured\n",
-			__FUNCTION__, slot->dn->name, slot->name);
-		slot->state = CONFIGURED;
-	} else {
-		info("%s: no vio_dev struct for adapter in slot[%s]\n",
-			__FUNCTION__, slot->name);
-		slot->state = NOT_CONFIGURED;
-	}
-	
-	return retval;
-}
--- gregkh-2.6.orig/drivers/pci/hotplug/rpaphp.h	2005-07-26 16:09:58.000000000 -0700
+++ gregkh-2.6/drivers/pci/hotplug/rpaphp.h	2005-07-26 16:10:01.000000000 -0700
@@ -61,10 +61,6 @@
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 
-/* slot types */
-#define VIO_DEV	1
-#define PCI_DEV	2
-
 /* slot states */
 
 #define	NOT_VALID	3
@@ -84,14 +80,10 @@
 	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 */
-	union {
-		struct list_head *pci_devs; /* pci_devs in PCI slot */
-		struct vio_dev *vio_dev; /* vio_dev in VIO slot */
-	} dev;
+	struct list_head *pci_devs; /* pci_devs in PCI slot */
 	struct hotplug_slot *hotplug_slot;
 };
 
@@ -115,12 +107,6 @@
 extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
 		char **drc_name, char **drc_type, int *drc_power_domain);
 
-/* rpaphp_vio.c */
-extern int rpaphp_get_vio_adapter_status(struct slot *slot, int is_init, u8 * value);
-extern int rpaphp_unconfig_vio_adapter(struct slot *slot);
-extern int register_vio_slot(struct device_node *dn);
-extern int rpaphp_enable_vio_slot(struct slot *slot);
-
 /* rpaphp_slot.c */
 extern void dealloc_slot_struct(struct slot *slot);
 extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
--- gregkh-2.6.orig/drivers/pci/hotplug/rpaphp_pci.c	2005-07-26 16:09:58.000000000 -0700
+++ gregkh-2.6/drivers/pci/hotplug/rpaphp_pci.c	2005-07-26 16:10:01.000000000 -0700
@@ -265,11 +265,9 @@
 {
 	struct pci_dev *dev;
 
-	if (slot->dev_type == PCI_DEV) {
-		dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->name);
-		list_for_each_entry (dev, slot->dev.pci_devs, bus_list)
-			dbg("\t%s\n", pci_name(dev));
-	}
+	dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->name);
+	list_for_each_entry (dev, slot->pci_devs, bus_list)
+		dbg("\t%s\n", pci_name(dev));
 	return;
 }
 
@@ -328,7 +326,7 @@
 	struct pci_dev *dev;
 	int retval = 0;
 
-	list_for_each_entry(dev, slot->dev.pci_devs, bus_list)
+	list_for_each_entry(dev, slot->pci_devs, bus_list)
 		rpaphp_eeh_remove_bus_device(dev);
 
 	pci_remove_behind_bridge(slot->bridge);
@@ -401,7 +399,7 @@
 		bus = slot->bridge->subordinate;
 		if (!bus)
 			goto exit_rc;
-		slot->dev.pci_devs = &bus->devices;
+		slot->pci_devs = &bus->devices;
 
 		dbg("%s set slot->name to %s\n",  __FUNCTION__,
 				pci_name(slot->bridge));
@@ -434,7 +432,7 @@
 			goto exit_rc;
 		}
 		print_slot_pci_funcs(slot);
-		if (!list_empty(slot->dev.pci_devs)) {
+		if (!list_empty(slot->pci_devs)) {
 			slot->state = CONFIGURED;
 		} else {
 			/* DLPAR add as opposed to 
@@ -452,7 +450,6 @@
 {
 	int rc = -EINVAL;
 
-	slot->dev_type = PCI_DEV;
 	if ((slot->type == EMBEDDED) || (slot->type == PHB))
 		slot->removable = 0;
 	else
--- gregkh-2.6.orig/drivers/pci/hotplug/rpaphp_slot.c	2005-06-17 12:48:29.000000000 -0700
+++ gregkh-2.6/drivers/pci/hotplug/rpaphp_slot.c	2005-07-26 16:10:01.000000000 -0700
@@ -220,13 +220,8 @@
 	    __FUNCTION__, slot->name);
 
 	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
-
-	if (slot->dev_type == VIO_DEV)
-		info("Slot [%s](VIO location=%s) registered\n",
-		     slot->name, slot->location);
-	else
-		info("Slot [%s](PCI location=%s) registered\n",
-		     slot->name, slot->location);
+	info("Slot [%s](PCI location=%s) registered\n", slot->name,
+			slot->location);
 	num_slots++;
 	return 0;
 }
--- gregkh-2.6.orig/drivers/pci/hotplug/Makefile	2005-07-13 09:45:06.000000000 -0700
+++ gregkh-2.6/drivers/pci/hotplug/Makefile	2005-07-26 16:10:01.000000000 -0700
@@ -41,8 +41,7 @@
 
 rpaphp-objs		:=	rpaphp_core.o	\
 				rpaphp_pci.o	\
-				rpaphp_slot.o	\
-				rpaphp_vio.o
+				rpaphp_slot.o
 
 rpadlpar_io-objs	:=	rpadlpar_core.o \
 				rpadlpar_sysfs.o