Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5eeb8c63 authored by John Rose's avatar John Rose Committed by Greg Kroah-Hartman
Browse files

[PATCH] PCI Hotplug: rpaphp: Move VIO registration



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: default avatarJohn Rose <johnrose@austin.ibm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent bde16841
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -41,8 +41,7 @@ acpiphp-objs := acpiphp_core.o \


rpaphp-objs		:=	rpaphp_core.o	\
rpaphp-objs		:=	rpaphp_core.o	\
				rpaphp_pci.o	\
				rpaphp_pci.o	\
				rpaphp_slot.o	\
				rpaphp_slot.o
				rpaphp_vio.o


rpadlpar_io-objs	:=	rpadlpar_core.o \
rpadlpar_io-objs	:=	rpadlpar_core.o \
				rpadlpar_sysfs.o
				rpadlpar_sysfs.o
+65 −45
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <asm/pci-bridge.h>
#include <asm/pci-bridge.h>
#include <asm/semaphore.h>
#include <asm/semaphore.h>
#include <asm/rtas.h>
#include <asm/rtas.h>
#include <asm/vio.h>
#include "../pci.h"
#include "../pci.h"
#include "rpaphp.h"
#include "rpaphp.h"
#include "rpadlpar.h"
#include "rpadlpar.h"
@@ -29,23 +30,23 @@ static DECLARE_MUTEX(rpadlpar_sem);
#define NODE_TYPE_SLOT 2
#define NODE_TYPE_SLOT 2
#define NODE_TYPE_PHB  3
#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");
	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)
	if (!parent)
		return NULL;
		return NULL;


	for (child = of_get_next_child(parent, NULL);
	while ((dn = of_get_next_child(parent, dn))) {
		child; child = of_get_next_child(parent, child)) {
		rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
		loc_code = get_property(child, "ibm,loc-code", NULL);
		if ((rc == 0) && (!strcmp(drc_name, name)))
		if (loc_code && !strncmp(loc_code, drc_name, strlen(drc_name)))
			break;
			return child;
	}
	}


	return NULL;
	return dn;
}
}


/* Find dlpar-capable pci node that contains the specified name and type */
/* Find dlpar-capable pci node that contains the specified name and type */
@@ -67,7 +68,7 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
	return np;
	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;
	struct device_node *dn;


@@ -83,7 +84,7 @@ static struct device_node *find_newly_added_node(char *drc_name, int *node_type)
		return dn;
		return dn;
	}
	}


	dn = find_php_slot_vio_node(drc_name);
	dn = find_vio_slot_node(drc_name);
	if (dn) {
	if (dn) {
		*node_type = NODE_TYPE_VIO;
		*node_type = NODE_TYPE_VIO;
		return dn;
		return dn;
@@ -231,6 +232,12 @@ static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
		return -EIO;
		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;
	return 0;
}
}


@@ -288,7 +295,7 @@ static int dlpar_remove_phb(struct slot *slot)
	return 0;
	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;
	struct pci_controller *phb;


@@ -296,6 +303,11 @@ static int dlpar_add_phb(struct device_node *dn)
	if (!phb)
	if (!phb)
		return -EINVAL;
		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;
	return 0;
}
}


@@ -316,7 +328,7 @@ int dlpar_add_slot(char *drc_name)
{
{
	struct device_node *dn = NULL;
	struct device_node *dn = NULL;
	int node_type;
	int node_type;
	int rc = 0;
	int rc;


	if (down_interruptible(&rpadlpar_sem))
	if (down_interruptible(&rpadlpar_sem))
		return -ERESTARTSYS;
		return -ERESTARTSYS;
@@ -327,32 +339,39 @@ int dlpar_add_slot(char *drc_name)
		goto exit;
		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) {
	if (!dn) {
		rc = -ENODEV;
		rc = -ENODEV;
		goto exit;
		goto exit;
	}
	}


	rc = -EIO;
	switch (node_type) {
	switch (node_type) {
		case NODE_TYPE_VIO:
		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;
			break;
		case NODE_TYPE_SLOT:
		case NODE_TYPE_SLOT:
			rc = dlpar_add_pci_slot(drc_name, dn);
			rc = dlpar_add_pci_slot(drc_name, dn);
			if (rc)
				goto exit;
			break;
			break;
		case NODE_TYPE_PHB:
		case NODE_TYPE_PHB:
			rc = dlpar_add_phb(dn);
			rc = dlpar_add_phb(drc_name, dn);
			if (rc)
				goto exit;
			break;
			break;
		default:
		default:
			printk("%s: unexpected node type\n", __FUNCTION__);
			printk("%s: unexpected node type\n", __FUNCTION__);
			return -EIO;
			goto exit;
	}
	}


	if (!rc && rpaphp_add_slot(dn)) {
	rc = 0;
		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
			__FUNCTION__, drc_name);
		rc = -EIO;
	}
exit:
exit:
	up(&rpadlpar_sem);
	up(&rpadlpar_sem);
	return rc;
	return rc;
@@ -368,15 +387,18 @@ int dlpar_add_slot(char *drc_name)
 * 0			Success
 * 0			Success
 * -EIO			Internal  Error
 * -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)) {
	vio_dev = vio_find_node(dn);
		printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
	if (!vio_dev) {
		printk(KERN_ERR "%s: %s does not correspond to a vio dev\n",
				__FUNCTION__, drc_name);
				__FUNCTION__, drc_name);
		return -EIO;
		return -EIO;
	}
	}

	vio_unregister_device(vio_dev);
	return 0;
	return 0;
}
}


@@ -434,36 +456,34 @@ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
 */
 */
int dlpar_remove_slot(char *drc_name)
int dlpar_remove_slot(char *drc_name)
{
{
	struct device_node *dn;
	struct slot *slot;
	struct slot *slot;
	int node_type;
	int rc = 0;
	int rc = 0;


	if (down_interruptible(&rpadlpar_sem))
	if (down_interruptible(&rpadlpar_sem))
		return -ERESTARTSYS;
		return -ERESTARTSYS;


	if (!find_php_slot_vio_node(drc_name) &&
	dn = find_dlpar_node(drc_name, &node_type);
	    !find_php_slot_pci_node(drc_name, "SLOT") &&
	if (!dn) {
	    !find_php_slot_pci_node(drc_name, "PHB")) {
		rc = -ENODEV;
		rc = -ENODEV;
		goto exit;
		goto exit;
	}
	}


	if (node_type == NODE_TYPE_VIO) {
		rc = dlpar_remove_vio_slot(dn, drc_name);
	} else {
		slot = find_slot(drc_name);
		slot = find_slot(drc_name);
		if (!slot) {
		if (!slot) {
			rc = -EINVAL;
			rc = -EINVAL;
			goto exit;
			goto exit;
		}
		}


	if (slot->type == PHB) {
		if (node_type == NODE_TYPE_PHB)
			rc = dlpar_remove_phb(slot);
			rc = dlpar_remove_phb(slot);
	} else {
		else {
		switch (slot->dev_type) {
			/* NODE_TYPE_SLOT */
			case PCI_DEV:
			rc = dlpar_remove_pci_slot(slot, drc_name);
			rc = dlpar_remove_pci_slot(slot, drc_name);
				break;

			case VIO_DEV:
				rc = dlpar_remove_vio_slot(slot, drc_name);
				break;
		}
		}
	}
	}
exit:
exit:
+1 −15
Original line number Original line Diff line number Diff line
@@ -61,10 +61,6 @@ extern int debug;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%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 */
/* slot states */


#define	NOT_VALID	3
#define	NOT_VALID	3
@@ -84,14 +80,10 @@ struct slot {
	char *name;
	char *name;
	char *location;
	char *location;
	u8 removable;
	u8 removable;
	u8 dev_type;		/* VIO or PCI */
	struct device_node *dn;	/* slot's device_node in OFDT */
	struct device_node *dn;	/* slot's device_node in OFDT */
				/* dn has phb info */
				/* dn has phb info */
	struct pci_dev *bridge;	/* slot's pci_dev in pci_devices */
	struct pci_dev *bridge;	/* slot's pci_dev in pci_devices */
	union {
	struct list_head *pci_devs; /* pci_devs in PCI slot */
	struct list_head *pci_devs; /* pci_devs in PCI slot */
		struct vio_dev *vio_dev; /* vio_dev in VIO slot */
	} dev;
	struct hotplug_slot *hotplug_slot;
	struct hotplug_slot *hotplug_slot;
};
};


@@ -115,12 +107,6 @@ extern int rpaphp_remove_slot(struct slot *slot);
extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
		char **drc_name, char **drc_type, int *drc_power_domain);
		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 */
/* rpaphp_slot.c */
extern void dealloc_slot_struct(struct slot *slot);
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);
extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
+13 −64
Original line number Original line Diff line number Diff line
@@ -152,17 +152,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
	int retval = 0;
	int retval = 0;


	down(&rpaphp_sem);
	down(&rpaphp_sem);
	/*  have to go through this */
	switch (slot->dev_type) {
	case PCI_DEV:
	retval = rpaphp_get_pci_adapter_status(slot, 0, value);
	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;
	}
	up(&rpaphp_sem);
	up(&rpaphp_sem);
	return retval;
	return retval;
}
}
@@ -362,12 +352,6 @@ int rpaphp_add_slot(struct device_node *dn)


	dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
	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 */
	/* register PCI devices */
	if (dn->name != 0 && strcmp(dn->name, "pci") == 0) {
	if (dn->name != 0 && strcmp(dn->name, "pci") == 0) {
		if (is_php_dn(dn, &indexes, &names, &types, &power_domains))  
		if (is_php_dn(dn, &indexes, &names, &types, &power_domains))  
@@ -412,31 +396,6 @@ int rpaphp_add_slot(struct device_node *dn)
	return retval;
	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)
static void __exit cleanup_slots(void)
{
{
	struct list_head *tmp, *n;
	struct list_head *tmp, *n;
@@ -458,10 +417,18 @@ static void __exit cleanup_slots(void)


static int __init rpaphp_init(void)
static int __init rpaphp_init(void)
{
{
	struct device_node *dn = NULL;

	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
	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 0;
	return init_rpa();
}
}


static void __exit rpaphp_exit(void)
static void __exit rpaphp_exit(void)
@@ -481,16 +448,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)


	dbg("ENABLING SLOT %s\n", slot->name);
	dbg("ENABLING SLOT %s\n", slot->name);
	down(&rpaphp_sem);
	down(&rpaphp_sem);
	switch (slot->dev_type) {
	case PCI_DEV:
	retval = rpaphp_enable_pci_slot(slot);
	retval = rpaphp_enable_pci_slot(slot);
		break;
	case VIO_DEV:
		retval = rpaphp_enable_vio_slot(slot);
		break;
	default:
		retval = -EINVAL;
	}
	up(&rpaphp_sem);
	up(&rpaphp_sem);
exit:
exit:
	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
@@ -511,16 +469,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)


	dbg("DISABLING SLOT %s\n", slot->name);
	dbg("DISABLING SLOT %s\n", slot->name);
	down(&rpaphp_sem);
	down(&rpaphp_sem);
	switch (slot->dev_type) {
	case PCI_DEV:
	retval = rpaphp_unconfig_pci_adapter(slot);
	retval = rpaphp_unconfig_pci_adapter(slot);
		break;
	case VIO_DEV:
		retval = rpaphp_unconfig_vio_adapter(slot);
		break;
	default:
		retval = -ENODEV;
	}
	up(&rpaphp_sem);
	up(&rpaphp_sem);
exit:
exit:
	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
+6 −9
Original line number Original line Diff line number Diff line
@@ -265,11 +265,9 @@ static void print_slot_pci_funcs(struct slot *slot)
{
{
	struct pci_dev *dev;
	struct pci_dev *dev;


	if (slot->dev_type == PCI_DEV) {
	dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->name);
	dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->name);
		list_for_each_entry (dev, slot->dev.pci_devs, bus_list)
	list_for_each_entry (dev, slot->pci_devs, bus_list)
		dbg("\t%s\n", pci_name(dev));
		dbg("\t%s\n", pci_name(dev));
	}
	return;
	return;
}
}


@@ -328,7 +326,7 @@ int rpaphp_unconfig_pci_adapter(struct slot *slot)
	struct pci_dev *dev;
	struct pci_dev *dev;
	int retval = 0;
	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);
		rpaphp_eeh_remove_bus_device(dev);


	pci_remove_behind_bridge(slot->bridge);
	pci_remove_behind_bridge(slot->bridge);
@@ -401,7 +399,7 @@ static int setup_pci_slot(struct slot *slot)
		bus = slot->bridge->subordinate;
		bus = slot->bridge->subordinate;
		if (!bus)
		if (!bus)
			goto exit_rc;
			goto exit_rc;
		slot->dev.pci_devs = &bus->devices;
		slot->pci_devs = &bus->devices;


		dbg("%s set slot->name to %s\n",  __FUNCTION__,
		dbg("%s set slot->name to %s\n",  __FUNCTION__,
				pci_name(slot->bridge));
				pci_name(slot->bridge));
@@ -434,7 +432,7 @@ static int setup_pci_slot(struct slot *slot)
			goto exit_rc;
			goto exit_rc;
		}
		}
		print_slot_pci_funcs(slot);
		print_slot_pci_funcs(slot);
		if (!list_empty(slot->dev.pci_devs)) {
		if (!list_empty(slot->pci_devs)) {
			slot->state = CONFIGURED;
			slot->state = CONFIGURED;
		} else {
		} else {
			/* DLPAR add as opposed to 
			/* DLPAR add as opposed to 
@@ -452,7 +450,6 @@ int register_pci_slot(struct slot *slot)
{
{
	int rc = -EINVAL;
	int rc = -EINVAL;


	slot->dev_type = PCI_DEV;
	if ((slot->type == EMBEDDED) || (slot->type == PHB))
	if ((slot->type == EMBEDDED) || (slot->type == PHB))
		slot->removable = 0;
		slot->removable = 0;
	else
	else
Loading