diff options
-rw-r--r-- | drivers/pci/hotplug/Makefile | 3 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpadlpar_core.c | 110 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpaphp.h | 16 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpaphp_core.c | 77 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpaphp_pci.c | 15 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpaphp_slot.c | 9 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpaphp_vio.c | 129 |
7 files changed, 88 insertions, 271 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 246586a3d91a..3c71e3077ff1 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -41,8 +41,7 @@ acpiphp-objs := acpiphp_core.o \ 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 diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 86b384e42717..d7f1319f167a 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -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 @@ static DECLARE_MUTEX(rpadlpar_sem); #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 @@ static struct device_node *find_php_slot_pci_node(char *drc_name, 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 @@ static struct device_node *find_newly_added_node(char *drc_name, int *node_type) 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 @@ static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) 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 @@ static int dlpar_remove_phb(struct slot *slot) 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 @@ static int dlpar_add_phb(struct device_node *dn) 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 @@ int dlpar_add_slot(char *drc_name) { struct device_node *dn = NULL; int node_type; - int rc = 0; + int rc; if (down_interruptible(&rpadlpar_sem)) return -ERESTARTSYS; @@ -327,32 +339,39 @@ int dlpar_add_slot(char *drc_name) 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 @@ exit: * 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_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; 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: diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 25bea00b4f14..2d9f420dfa4f 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -61,10 +61,6 @@ extern int debug; #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 @@ 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 */ - 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_remove_slot(struct slot *slot); 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); diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 29117a3a3287..22ec0993cf89 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -152,17 +152,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) 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 @@ int rpaphp_add_slot(struct device_node *dn) 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 @@ exit: 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 void __exit cleanup_slots(void) 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 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) 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 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) 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); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index ab67d3d1a59c..30d10fcc24b2 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -265,11 +265,9 @@ static void print_slot_pci_funcs(struct slot *slot) { 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 @@ int rpaphp_unconfig_pci_adapter(struct slot *slot) 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 @@ static int setup_pci_slot(struct slot *slot) 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 @@ static int setup_pci_slot(struct slot *slot) 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 register_pci_slot(struct slot *slot) { int rc = -EINVAL; - slot->dev_type = PCI_DEV; if ((slot->type == EMBEDDED) || (slot->type == PHB)) slot->removable = 0; else diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index ff2cbf0652d8..80402027c015 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -220,13 +220,8 @@ int register_slot(struct slot *slot) __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; } diff --git a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c deleted file mode 100644 index 74df6a305e64..000000000000 --- a/drivers/pci/hotplug/rpaphp_vio.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * RPA Hot Plug Virtual I/O device functions - * Copyright (C) 2004 Linda Xie <lxie@us.ibm.com> - * - * 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 <lxie@us.ibm.com> - * - */ -#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; -} |