aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/pci/hotplug/rpadlpar_core.c
diff options
context:
space:
mode:
authorJohn Rose <johnrose@austin.ibm.com>2005-07-25 10:17:03 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 14:57:23 -0700
commit56d8456b06ad1316bff3c75caed5e06e786f20d8 (patch)
treef7a17c2e66c548b5172bebd07a01437ff78a9447 /drivers/pci/hotplug/rpadlpar_core.c
parent[PATCH] PCI Hotplug: rpaphp: Export slot enable (diff)
downloadwireguard-linux-56d8456b06ad1316bff3c75caed5e06e786f20d8.tar.xz
wireguard-linux-56d8456b06ad1316bff3c75caed5e06e786f20d8.zip
[PATCH] PCI Hotplug: rpaphp: Purify hotplug
Currently rpaphp registers the following bus types as hotplug slots: 1) Actual PCI Hotplug slots 2) Embedded/Internal PCI slots 3) PCI Host Bridges The second and third bus types are not actually direct parents of removable adapters. As such, the rpaphp has special case code to fake results for attributes like power, adapter status, etc. This patch removes types 2 and 3 from the rpaphp module. This patch also changes the DLPAR module so that slots can be DLPAR-added/removed without having been designated as hotplug-capable. Signed-off-by: John Rose <johnrose@austin.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/rpadlpar_core.c')
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c154
1 files changed, 78 insertions, 76 deletions
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index f2a73f70e58c..4ada15111af0 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -26,6 +26,8 @@
static DECLARE_MUTEX(rpadlpar_sem);
+#define DLPAR_MODULE_NAME "rpadlpar_io"
+
#define NODE_TYPE_VIO 1
#define NODE_TYPE_SLOT 2
#define NODE_TYPE_PHB 3
@@ -93,14 +95,14 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
return NULL;
}
-static struct slot *find_slot(char *drc_name)
+static struct slot *find_slot(struct device_node *dn)
{
struct list_head *tmp, *n;
struct slot *slot;
list_for_each_safe(tmp, n, &rpaphp_slot_head) {
slot = list_entry(tmp, struct slot, rpaphp_slot_list);
- if (strcmp(slot->location, drc_name) == 0)
+ if (slot->dn == dn)
return slot;
}
@@ -214,6 +216,9 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
struct pci_dev *dev;
int rc;
+ if (rpaphp_find_pci_bus(dn))
+ return -EINVAL;
+
/* Add pci bus */
dev = dlpar_pci_add_bus(dn);
if (!dev) {
@@ -261,36 +266,32 @@ static int dlpar_remove_root_bus(struct pci_controller *phb)
return 0;
}
-static int dlpar_remove_phb(struct slot *slot)
+static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
{
- struct pci_controller *phb;
- struct device_node *dn;
+ struct slot *slot;
int rc = 0;
- dn = slot->dn;
- if (!dn) {
- printk(KERN_ERR "%s: unexpected NULL slot device node\n",
- __FUNCTION__);
- return -EIO;
- }
-
- phb = dn->phb;
- if (!phb) {
- printk(KERN_ERR "%s: unexpected NULL phb pointer\n",
- __FUNCTION__);
- return -EIO;
- }
+ if (!rpaphp_find_pci_bus(dn))
+ return -EINVAL;
- if (rpaphp_remove_slot(slot)) {
- printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
- __FUNCTION__, slot->location);
- return -EIO;
+ slot = find_slot(dn);
+ if (slot) {
+ /* Remove hotplug slot */
+ if (rpaphp_remove_slot(slot)) {
+ printk(KERN_ERR
+ "%s: unable to remove hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
}
- rc = dlpar_remove_root_bus(phb);
+ BUG_ON(!dn->phb);
+ rc = dlpar_remove_root_bus(dn->phb);
if (rc < 0)
return rc;
+ dn->phb = NULL;
+
return 0;
}
@@ -298,9 +299,14 @@ static int dlpar_add_phb(char *drc_name, struct device_node *dn)
{
struct pci_controller *phb;
+ if (dn->phb) {
+ /* PHB already exists */
+ return -EINVAL;
+ }
+
phb = init_phb_dynamic(dn);
if (!phb)
- return -EINVAL;
+ return -EIO;
if (rpaphp_add_slot(dn)) {
printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
@@ -310,6 +316,20 @@ static int dlpar_add_phb(char *drc_name, struct device_node *dn)
return 0;
}
+static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
+{
+ if (vio_find_node(dn))
+ return -EINVAL;
+
+ if (!vio_register_device_node(dn)) {
+ printk(KERN_ERR
+ "%s: failed to register vio node %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
+ return 0;
+}
+
/**
* dlpar_add_slot - DLPAR add an I/O Slot
* @drc_name: drc-name of newly added slot
@@ -327,17 +347,11 @@ int dlpar_add_slot(char *drc_name)
{
struct device_node *dn = NULL;
int node_type;
- int rc;
+ int rc = -EIO;
if (down_interruptible(&rpadlpar_sem))
return -ERESTARTSYS;
- /* Check for existing hotplug slot */
- if (find_slot(drc_name)) {
- rc = -EINVAL;
- goto exit;
- }
-
/* Find newly added node */
dn = find_dlpar_node(drc_name, &node_type);
if (!dn) {
@@ -345,32 +359,19 @@ int dlpar_add_slot(char *drc_name)
goto exit;
}
- rc = -EIO;
switch (node_type) {
case NODE_TYPE_VIO:
- if (!vio_register_device_node(dn)) {
- printk(KERN_ERR
- "%s: failed to register vio node %s\n",
- __FUNCTION__, drc_name);
- goto exit;
- }
+ rc = dlpar_add_vio_slot(drc_name, dn);
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(drc_name, dn);
- if (rc)
- goto exit;
break;
- default:
- printk("%s: unexpected node type\n", __FUNCTION__);
- goto exit;
}
- rc = 0;
+ printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name);
exit:
up(&rpadlpar_sem);
return rc;
@@ -384,18 +385,15 @@ exit:
* of an I/O Slot.
* Return Codes:
* 0 Success
- * -EIO Internal Error
+ * -EINVAL Vio dev doesn't exist
*/
-static int dlpar_remove_vio_slot(struct device_node *dn, char *drc_name)
+static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
{
struct vio_dev *vio_dev;
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;
- }
+ if (!vio_dev)
+ return -EINVAL;
vio_unregister_device(vio_dev);
return 0;
@@ -412,15 +410,24 @@ static int dlpar_remove_vio_slot(struct device_node *dn, char *drc_name)
* -ENODEV Not a valid drc_name
* -EIO Internal PCI Error
*/
-int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
+int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
{
- struct pci_bus *bus = slot->bus;
+ struct pci_bus *bus;
+ struct slot *slot;
- /* Remove hotplug slot */
- if (rpaphp_remove_slot(slot)) {
- printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
- __FUNCTION__, drc_name);
- return -EIO;
+ bus = rpaphp_find_pci_bus(dn);
+ if (!bus)
+ return -EINVAL;
+
+ slot = find_slot(dn);
+ if (slot) {
+ /* Remove hotplug slot */
+ if (rpaphp_remove_slot(slot)) {
+ printk(KERN_ERR
+ "%s: unable to remove hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
}
if (unmap_bus_range(bus)) {
@@ -450,7 +457,6 @@ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
int dlpar_remove_slot(char *drc_name)
{
struct device_node *dn;
- struct slot *slot;
int node_type;
int rc = 0;
@@ -463,22 +469,18 @@ int dlpar_remove_slot(char *drc_name)
goto exit;
}
- if (node_type == NODE_TYPE_VIO) {
- rc = dlpar_remove_vio_slot(dn, drc_name);
- } else {
- slot = find_slot(drc_name);
- if (!slot) {
- rc = -EINVAL;
- goto exit;
- }
-
- if (node_type == NODE_TYPE_PHB)
- rc = dlpar_remove_phb(slot);
- else {
- /* NODE_TYPE_SLOT */
- rc = dlpar_remove_pci_slot(slot, drc_name);
- }
+ switch (node_type) {
+ case NODE_TYPE_VIO:
+ rc = dlpar_remove_vio_slot(drc_name, dn);
+ break;
+ case NODE_TYPE_PHB:
+ rc = dlpar_remove_phb(drc_name, dn);
+ break;
+ case NODE_TYPE_SLOT:
+ rc = dlpar_remove_pci_slot(drc_name, dn);
+ break;
}
+ printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name);
exit:
up(&rpadlpar_sem);
return rc;