From bde168412440084e649e7e04938bd1ab6e7bf978 Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 25 Jul 2005 10:16:37 -0500 Subject: [PATCH] PCI Hotplug: rpaphp: Remove unused stuff Subject line says it all :) Signed-off-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp.h | 6 --- drivers/pci/hotplug/rpaphp_pci.c | 98 +++++++++++++--------------------------- 2 files changed, 31 insertions(+), 73 deletions(-) (limited to 'drivers/pci/hotplug') diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 81746e6e0e0f..25bea00b4f14 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -72,11 +72,6 @@ extern int debug; #define CONFIGURED 1 #define EMPTY 0 -struct rpaphp_pci_func { - struct pci_dev *pci_dev; - struct list_head sibling; -}; - /* * struct slot - slot information for each *physical* slot */ @@ -113,7 +108,6 @@ extern int rpaphp_enable_pci_slot(struct slot *slot); extern int register_pci_slot(struct slot *slot); extern int rpaphp_unconfig_pci_adapter(struct slot *slot); extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); -extern struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev); /* rpaphp_core.c */ extern int rpaphp_add_slot(struct device_node *dn); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index d8305a935aab..ab67d3d1a59c 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -186,39 +186,6 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) } } -static int rpaphp_pci_config_bridge(struct pci_dev *dev); - -/***************************************************************************** - rpaphp_pci_config_slot() will configure all devices under the - given slot->dn and return the the first pci_dev. - *****************************************************************************/ -static struct pci_dev * -rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus) -{ - struct device_node *eads_first_child = dn->child; - struct pci_dev *dev = NULL; - int num; - - dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); - - if (eads_first_child) { - /* pci_scan_slot should find all children of EADs */ - num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0)); - if (num) { - rpaphp_fixup_new_pci_devices(bus, 1); - pci_bus_add_devices(bus); - } - dev = rpaphp_find_pci_dev(eads_first_child); - if (!dev) { - err("No new device found\n"); - return NULL; - } - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) - rpaphp_pci_config_bridge(dev); - } - return dev; -} - static int rpaphp_pci_config_bridge(struct pci_dev *dev) { u8 sec_busno; @@ -252,6 +219,37 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev) return 0; } +/***************************************************************************** + rpaphp_pci_config_slot() will configure all devices under the + given slot->dn and return the the first pci_dev. + *****************************************************************************/ +static struct pci_dev * +rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus) +{ + struct device_node *eads_first_child = dn->child; + struct pci_dev *dev = NULL; + int num; + + dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); + + if (eads_first_child) { + /* pci_scan_slot should find all children of EADs */ + num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0)); + if (num) { + rpaphp_fixup_new_pci_devices(bus, 1); + pci_bus_add_devices(bus); + } + dev = rpaphp_find_pci_dev(eads_first_child); + if (!dev) { + err("No new device found\n"); + return NULL; + } + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) + rpaphp_pci_config_bridge(dev); + } + return dev; +} + static void enable_eeh(struct device_node *dn) { struct device_node *sib; @@ -502,37 +500,3 @@ exit: dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; } - -struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev) -{ - struct list_head *tmp, *n; - struct slot *slot; - - list_for_each_safe(tmp, n, &rpaphp_slot_head) { - struct pci_bus *bus; - 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) { - 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) - return slot->hotplug_slot; - } - } - - return NULL; -} - -EXPORT_SYMBOL_GPL(rpaphp_find_hotplug_slot); -- cgit v1.2.3 From 5eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14 Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 25 Jul 2005 10:16:42 -0500 Subject: [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: John Rose Signed-off-by: Greg Kroah-Hartman --- 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(-) delete mode 100644 drivers/pci/hotplug/rpaphp_vio.c (limited to 'drivers/pci/hotplug') 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 #include #include +#include #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 - * - * 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 - * - */ -#include -#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; -} -- cgit v1.2.3 From 9c209c919df95f83aa042b3352c43841ad15a02b Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 25 Jul 2005 11:13:38 -0500 Subject: [PATCH] PCI Hotplug: rpaphp: Change slot pci reference The slot structure in the rpaphp module currently references the PCI contents of the slot using the PCI device of the parent bridge. This is unnecessary, since the module is actually interested in the subordinate bus of the bridge. The dependency on a PCI bridge device also prohibits the module from registering hotplug slots that have a root bridge as a parent, since root bridges on PPC64 don't have PCI devices. This patch changes struct slot to reference the PCI subsystem using a pci_bus rather than a pci_dev. Signed-off-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 44 ++--------- drivers/pci/hotplug/rpaphp.h | 7 +- drivers/pci/hotplug/rpaphp_pci.c | 141 ++++++++++++++++-------------------- 3 files changed, 75 insertions(+), 117 deletions(-) (limited to 'drivers/pci/hotplug') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index d7f1319f167a..7f868edaa72d 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -198,28 +198,6 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) return dev; } -static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev) -{ - struct pci_bus *secondary_bus; - - if (!bridge_dev) { - printk(KERN_ERR "%s: unexpected null device\n", - __FUNCTION__); - return -EINVAL; - } - - secondary_bus = bridge_dev->subordinate; - - if (unmap_bus_range(secondary_bus)) { - printk(KERN_ERR "%s: failed to unmap bus range\n", - __FUNCTION__); - return -ERANGE; - } - - pci_remove_bus_device(bridge_dev); - return 0; -} - static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) { struct pci_dev *dev; @@ -415,14 +393,7 @@ static int dlpar_remove_vio_slot(struct device_node *dn, char *drc_name) */ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name) { - struct pci_dev *bridge_dev; - - bridge_dev = slot->bridge; - if (!bridge_dev) { - printk(KERN_ERR "%s: unexpected null bridge device\n", - __FUNCTION__); - return -EIO; - } + struct pci_bus *bus = slot->bus; /* Remove hotplug slot */ if (rpaphp_remove_slot(slot)) { @@ -431,13 +402,14 @@ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name) return -EIO; } - /* Remove pci bus */ - - if (dlpar_pci_remove_bus(bridge_dev)) { - printk(KERN_ERR "%s: unable to remove pci bus %s\n", - __FUNCTION__, drc_name); - return -EIO; + if (unmap_bus_range(bus)) { + printk(KERN_ERR "%s: failed to unmap bus range\n", + __FUNCTION__); + return -ERANGE; } + + BUG_ON(!bus->self); + pci_remove_bus_device(bus->self); return 0; } diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 2d9f420dfa4f..9f050fde80c2 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -80,10 +80,9 @@ struct slot { char *name; char *location; u8 removable; - 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 */ - struct list_head *pci_devs; /* pci_devs in PCI slot */ + struct device_node *dn; + struct pci_bus *bus; + struct list_head *pci_devs; struct hotplug_slot *hotplug_slot; }; diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 30d10fcc24b2..54fff5fb0094 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -45,6 +45,32 @@ struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn) return dev; } +struct pci_bus *find_bus_among_children(struct pci_bus *bus, + struct device_node *dn) +{ + struct pci_bus *child = NULL; + struct list_head *tmp; + struct device_node *busdn; + + busdn = pci_bus_to_OF_node(bus); + if (busdn == dn) + return bus; + + list_for_each(tmp, &bus->children) { + child = find_bus_among_children(pci_bus_b(tmp), dn); + if (child) + break; + } + return child; +} + +struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn) +{ + BUG_ON(!dn->phb || !dn->phb->bus); + + return find_bus_among_children(dn->phb->bus, dn); +} + EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev); int rpaphp_claim_resource(struct pci_dev *dev, int resource) @@ -69,11 +95,6 @@ int rpaphp_claim_resource(struct pci_dev *dev, int resource) EXPORT_SYMBOL_GPL(rpaphp_claim_resource); -static struct pci_dev *rpaphp_find_bridge_pdev(struct slot *slot) -{ - return rpaphp_find_pci_dev(slot->dn); -} - static int rpaphp_get_sensor_state(struct slot *slot, int *state) { int rc; @@ -226,20 +247,22 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev) static struct pci_dev * rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus) { - struct device_node *eads_first_child = dn->child; struct pci_dev *dev = NULL; + int slotno; int num; dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); - if (eads_first_child) { - /* pci_scan_slot should find all children of EADs */ - num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0)); + if (dn->child) { + slotno = PCI_SLOT(dn->child->devfn); + + /* pci_scan_slot should find all children */ + num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); if (num) { rpaphp_fixup_new_pci_devices(bus, 1); pci_bus_add_devices(bus); } - dev = rpaphp_find_pci_dev(eads_first_child); + dev = rpaphp_find_pci_dev(dn->child); if (!dev) { err("No new device found\n"); return NULL; @@ -273,31 +296,19 @@ static void print_slot_pci_funcs(struct slot *slot) static int rpaphp_config_pci_adapter(struct slot *slot) { - struct pci_bus *pci_bus; struct pci_dev *dev; int rc = -ENODEV; dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name); - if (slot->bridge) { - - pci_bus = slot->bridge->subordinate; - if (!pci_bus) { - err("%s: can't find bus structure\n", __FUNCTION__); - goto exit; - } - enable_eeh(slot->dn); - dev = rpaphp_pci_config_slot(slot->dn, pci_bus); - if (!dev) { - err("%s: can't find any devices.\n", __FUNCTION__); - goto exit; - } - print_slot_pci_funcs(slot); - rc = 0; - } else { - /* slot is not enabled */ - err("slot doesn't have pci_dev structure\n"); + enable_eeh(slot->dn); + dev = rpaphp_pci_config_slot(slot->dn, slot->bus); + if (!dev) { + err("%s: can't find any devices.\n", __FUNCTION__); + goto exit; } + print_slot_pci_funcs(slot); + rc = 0; exit: dbg("Exit %s: rc=%d\n", __FUNCTION__, rc); return rc; @@ -323,13 +334,14 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev) int rpaphp_unconfig_pci_adapter(struct slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *tmp; int retval = 0; - list_for_each_entry(dev, slot->pci_devs, bus_list) + list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) { rpaphp_eeh_remove_bus_device(dev); + pci_remove_bus_device(dev); + } - pci_remove_behind_bridge(slot->bridge); slot->state = NOT_CONFIGURED; info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__, slot->name); @@ -352,66 +364,41 @@ static int setup_pci_hotplug_slot_info(struct slot *slot) return 0; } -static int set_phb_slot_name(struct slot *slot) +static void set_slot_name(struct slot *slot) { - struct device_node *dn; - struct pci_controller *phb; - struct pci_bus *bus; - - dn = slot->dn; - if (!dn) { - return -EINVAL; - } - phb = dn->phb; - if (!phb) { - return -EINVAL; - } - bus = phb->bus; - if (!bus) { - return -EINVAL; - } + struct pci_bus *bus = slot->bus; + struct pci_dev *bridge; - sprintf(slot->name, "%04x:%02x:%02x.%x", pci_domain_nr(bus), - bus->number, 0, 0); - return 0; + bridge = bus->self; + if (bridge) + strcpy(slot->name, pci_name(bridge)); + else + sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus), + bus->number); } static int setup_pci_slot(struct slot *slot) { + struct device_node *dn = slot->dn; struct pci_bus *bus; - int rc; - if (slot->type == PHB) { - rc = set_phb_slot_name(slot); - if (rc < 0) { - err("%s: failed to set phb slot name\n", __FUNCTION__); - goto exit_rc; - } - } else { - slot->bridge = rpaphp_find_bridge_pdev(slot); - if (!slot->bridge) { - /* slot being added doesn't have pci_dev yet */ - err("%s: no pci_dev for bridge dn %s\n", - __FUNCTION__, slot->name); - goto exit_rc; - } - - bus = slot->bridge->subordinate; - if (!bus) - goto exit_rc; - slot->pci_devs = &bus->devices; - - dbg("%s set slot->name to %s\n", __FUNCTION__, - pci_name(slot->bridge)); - strcpy(slot->name, pci_name(slot->bridge)); + BUG_ON(!dn); + bus = rpaphp_find_pci_bus(dn); + if (!bus) { + err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name); + goto exit_rc; } + slot->bus = bus; + slot->pci_devs = &bus->devices; + set_slot_name(slot); + /* find slot's pci_dev if it's not empty */ if (slot->hotplug_slot->info->adapter_status == EMPTY) { slot->state = EMPTY; /* slot is empty */ } else { /* slot is occupied */ - if (!(slot->dn->child)) { + if (!dn->child) { /* non-empty slot has to have child */ err("%s: slot[%s]'s device_node doesn't have child for adapter\n", __FUNCTION__, slot->name); -- cgit v1.2.3 From 0945cd5f908a09ad99bf42d7ded16f26f24f317d Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 25 Jul 2005 10:16:53 -0500 Subject: [PATCH] PCI Hotplug: rpaphp: Remove rpaphp_find_pci The rpaphp module currently uses a fragile method to find a pci device by its device node. This function is unnecessary, so this patch scraps it. Signed-off-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 35 +++++++++++------- drivers/pci/hotplug/rpaphp.h | 1 - drivers/pci/hotplug/rpaphp_pci.c | 72 +++++++++++++------------------------ 3 files changed, 47 insertions(+), 61 deletions(-) (limited to 'drivers/pci/hotplug') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 7f868edaa72d..2ee7eb513e6c 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -165,6 +165,20 @@ static int pci_add_secondary_bus(struct device_node *dn, return 0; } +static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, + struct device_node *dev_dn) +{ + struct pci_dev *tmp = NULL; + struct device_node *child_dn; + + list_for_each_entry(tmp, &parent->devices, bus_list) { + child_dn = pci_device_to_OF_node(tmp); + if (child_dn == dev_dn) + return tmp; + } + return NULL; +} + static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) { struct pci_controller *hose = dn->phb; @@ -180,21 +194,18 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) pci_bus_add_devices(hose->bus); /* Confirm new bridge dev was created */ - dev = rpaphp_find_pci_dev(dn); - if (!dev) { - printk(KERN_ERR "%s: failed to add pci device\n", __FUNCTION__); - return NULL; - } + dev = dlpar_find_new_dev(hose->bus, dn); + if (dev) { + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { + printk(KERN_ERR "%s: unexpected header type %d\n", + __FUNCTION__, dev->hdr_type); + return NULL; + } - if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { - printk(KERN_ERR "%s: unexpected header type %d\n", - __FUNCTION__, dev->hdr_type); - return NULL; + if (pci_add_secondary_bus(dn, dev)) + return NULL; } - if (pci_add_secondary_bus(dn, dev)) - return NULL; - return dev; } diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 9f050fde80c2..8ecff0b950e8 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -93,7 +93,6 @@ extern int num_slots; /* function prototypes */ /* rpaphp_pci.c */ -extern struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn); extern int rpaphp_claim_resource(struct pci_dev *dev, int resource); extern int rpaphp_enable_pci_slot(struct slot *slot); extern int register_pci_slot(struct slot *slot); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 54fff5fb0094..30a892ca4b37 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -30,22 +30,7 @@ #include "rpaphp.h" -struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn) -{ - struct pci_dev *dev = NULL; - char bus_id[BUS_ID_SIZE]; - - sprintf(bus_id, "%04x:%02x:%02x.%d", dn->phb->global_number, - dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn)); - for_each_pci_dev(dev) { - if (!strcmp(pci_name(dev), bus_id)) { - break; - } - } - return dev; -} - -struct pci_bus *find_bus_among_children(struct pci_bus *bus, +static struct pci_bus *find_bus_among_children(struct pci_bus *bus, struct device_node *dn) { struct pci_bus *child = NULL; @@ -64,15 +49,14 @@ struct pci_bus *find_bus_among_children(struct pci_bus *bus, return child; } -struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn) +static struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn) { - BUG_ON(!dn->phb || !dn->phb->bus); + if (!dn->phb || !dn->phb->bus) + return NULL; return find_bus_among_children(dn->phb->bus, dn); } -EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev); - int rpaphp_claim_resource(struct pci_dev *dev, int resource) { struct resource *res = &dev->resource[resource]; @@ -137,9 +121,8 @@ static int rpaphp_get_sensor_state(struct slot *slot, int *state) */ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) { + struct pci_bus *bus; int state, rc; - struct device_node *child_dn; - struct pci_dev *child_dev = NULL; *value = NOT_VALID; rc = rpaphp_get_sensor_state(slot, &state); @@ -156,20 +139,11 @@ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) /* config/unconfig adapter */ *value = slot->state; } else { - child_dn = slot->dn->child; - if (child_dn) - child_dev = rpaphp_find_pci_dev(child_dn); - - if (child_dev) - *value = CONFIGURED; - else if (!child_dn) - dbg("%s: %s is not valid OFDT node\n", - __FUNCTION__, slot->dn->full_name); - else { - err("%s: can't find pdev of adapter in slot[%s]\n", - __FUNCTION__, slot->dn->full_name); + bus = rpaphp_find_pci_bus(slot->dn); + if (bus && !list_empty(&bus->devices)) + *value = CONFIGURED; + else *value = NOT_CONFIGURED; - } } } exit: @@ -252,24 +226,26 @@ rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus) int num; dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); + if (!dn->child) + return NULL; - if (dn->child) { - slotno = PCI_SLOT(dn->child->devfn); + slotno = PCI_SLOT(dn->child->devfn); - /* pci_scan_slot should find all children */ - num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); - if (num) { - rpaphp_fixup_new_pci_devices(bus, 1); - pci_bus_add_devices(bus); - } - dev = rpaphp_find_pci_dev(dn->child); - if (!dev) { - err("No new device found\n"); - return NULL; - } + /* pci_scan_slot should find all children */ + num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); + if (num) { + rpaphp_fixup_new_pci_devices(bus, 1); + pci_bus_add_devices(bus); + } + if (list_empty(&bus->devices)) { + err("%s: No new device found\n", __FUNCTION__); + return NULL; + } + list_for_each_entry(dev, &bus->devices, bus_list) { if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) rpaphp_pci_config_bridge(dev); } + return dev; } -- cgit v1.2.3 From 940903c5a5a906c622a79b3101586deb1a1b3480 Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 25 Jul 2005 10:16:58 -0500 Subject: [PATCH] PCI Hotplug: rpaphp: Export slot enable This patch exports rpaphp_config_pci_adapter() for use by the rpadlpar module. It also changes this function by removing any dependencies on struct slot. The patch also changes the RPA DLPAR-add path to enable newly-added slots in a separate step from that which registers them as hotplug slots. Signed-off-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 12 +++++++++++- drivers/pci/hotplug/rpaphp.h | 1 + drivers/pci/hotplug/rpaphp_pci.c | 36 +++++++++++++++++++++++------------- 3 files changed, 35 insertions(+), 14 deletions(-) (limited to 'drivers/pci/hotplug') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 2ee7eb513e6c..f2a73f70e58c 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -209,9 +209,10 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) return dev; } -static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) +static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) { struct pci_dev *dev; + int rc; /* Add pci bus */ dev = dlpar_pci_add_bus(dn); @@ -221,6 +222,15 @@ static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) return -EIO; } + if (dn->child) { + rc = rpaphp_config_pci_adapter(dev->subordinate); + if (rc < 0) { + printk(KERN_ERR "%s: unable to enable slot %s\n", + __FUNCTION__, drc_name); + return -EIO; + } + } + /* Add hotplug slot */ if (rpaphp_add_slot(dn)) { printk(KERN_ERR "%s: unable to add hotplug slot %s\n", diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 8ecff0b950e8..064a0d66e3c5 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -98,6 +98,7 @@ extern int rpaphp_enable_pci_slot(struct slot *slot); extern int register_pci_slot(struct slot *slot); extern int rpaphp_unconfig_pci_adapter(struct slot *slot); extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); +extern int rpaphp_config_pci_adapter(struct pci_bus *bus); /* rpaphp_core.c */ extern int rpaphp_add_slot(struct device_node *dn); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 30a892ca4b37..f2f1cd0f941a 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -219,14 +219,15 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev) given slot->dn and return the the first pci_dev. *****************************************************************************/ static struct pci_dev * -rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus) +rpaphp_pci_config_slot(struct pci_bus *bus) { + struct device_node *dn = pci_bus_to_OF_node(bus); struct pci_dev *dev = NULL; int slotno; int num; dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); - if (!dn->child) + if (!dn || !dn->child) return NULL; slotno = PCI_SLOT(dn->child->devfn); @@ -260,35 +261,44 @@ static void enable_eeh(struct device_node *dn) } -static void print_slot_pci_funcs(struct slot *slot) +static void print_slot_pci_funcs(struct pci_bus *bus) { + struct device_node *dn; struct pci_dev *dev; - dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->name); - list_for_each_entry (dev, slot->pci_devs, bus_list) + dn = pci_bus_to_OF_node(bus); + if (!dn) + return; + + dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name); + list_for_each_entry (dev, &bus->devices, bus_list) dbg("\t%s\n", pci_name(dev)); return; } -static int rpaphp_config_pci_adapter(struct slot *slot) +int rpaphp_config_pci_adapter(struct pci_bus *bus) { + struct device_node *dn = pci_bus_to_OF_node(bus); struct pci_dev *dev; int rc = -ENODEV; - dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name); + dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name); + if (!dn) + goto exit; - enable_eeh(slot->dn); - dev = rpaphp_pci_config_slot(slot->dn, slot->bus); + enable_eeh(dn); + dev = rpaphp_pci_config_slot(bus); if (!dev) { err("%s: can't find any devices.\n", __FUNCTION__); goto exit; } - print_slot_pci_funcs(slot); + print_slot_pci_funcs(bus); rc = 0; exit: dbg("Exit %s: rc=%d\n", __FUNCTION__, rc); return rc; } +EXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter); static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev) { @@ -384,7 +394,7 @@ static int setup_pci_slot(struct slot *slot) if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { dbg("%s CONFIGURING pci adapter in slot[%s]\n", __FUNCTION__, slot->name); - if (rpaphp_config_pci_adapter(slot)) { + if (rpaphp_config_pci_adapter(slot->bus)) { err("%s: CONFIG pci adapter failed\n", __FUNCTION__); goto exit_rc; } @@ -394,7 +404,7 @@ static int setup_pci_slot(struct slot *slot) __FUNCTION__, slot->name); goto exit_rc; } - print_slot_pci_funcs(slot); + print_slot_pci_funcs(slot->bus); if (!list_empty(slot->pci_devs)) { slot->state = CONFIGURED; } else { @@ -437,7 +447,7 @@ int rpaphp_enable_pci_slot(struct slot *slot) /* if slot is not empty, enable the adapter */ if (state == PRESENT) { dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name); - retval = rpaphp_config_pci_adapter(slot); + retval = rpaphp_config_pci_adapter(slot->bus); if (!retval) { slot->state = CONFIGURED; dbg("%s: PCI devices in slot[%s] has been configured\n", -- cgit v1.2.3 From 56d8456b06ad1316bff3c75caed5e06e786f20d8 Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 25 Jul 2005 10:17:03 -0500 Subject: [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 Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 154 ++++++++++++++++++------------------ drivers/pci/hotplug/rpaphp.h | 6 +- drivers/pci/hotplug/rpaphp_core.c | 69 +++------------- drivers/pci/hotplug/rpaphp_pci.c | 11 +-- drivers/pci/hotplug/rpaphp_slot.c | 57 +++---------- 5 files changed, 104 insertions(+), 193 deletions(-) (limited to 'drivers/pci/hotplug') 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; diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 064a0d66e3c5..61d94d1e29cb 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -30,10 +30,6 @@ #include #include "pci_hotplug.h" -#define PHB 2 -#define HOTPLUG 1 -#define EMBEDDED 0 - #define DR_INDICATOR 9002 #define DR_ENTITY_SENSE 9003 @@ -79,7 +75,6 @@ struct slot { u32 power_domain; char *name; char *location; - u8 removable; struct device_node *dn; struct pci_bus *bus; struct list_head *pci_devs; @@ -93,6 +88,7 @@ extern int num_slots; /* function prototypes */ /* rpaphp_pci.c */ +extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn); extern int rpaphp_claim_resource(struct pci_dev *dev, int resource); extern int rpaphp_enable_pci_slot(struct slot *slot); extern int register_pci_slot(struct slot *slot); diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 22ec0993cf89..c830ff0acdc3 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -307,34 +307,6 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names, return 0; } -static int is_dr_dn(struct device_node *dn, int **indexes, int **names, - int **types, int **power_domains, int **my_drc_index) -{ - int rc; - - *my_drc_index = (int *) get_property(dn, "ibm,my-drc-index", NULL); - if(!*my_drc_index) - return (0); - - if (!dn->parent) - return (0); - - rc = get_children_props(dn->parent, indexes, names, types, - power_domains); - return (rc >= 0); -} - -static inline int is_vdevice_root(struct device_node *dn) -{ - return !strcmp(dn->name, "vdevice"); -} - -int is_dlpar_type(const char *type_str) -{ - /* Only register DLPAR-capable nodes of drc-type PHB or SLOT */ - return (!strcmp(type_str, "PHB") || !strcmp(type_str, "SLOT")); -} - /**************************************************************** * rpaphp not only registers PCI hotplug slots(HOTPLUG), * but also logical DR slots(EMBEDDED). @@ -346,7 +318,7 @@ int rpaphp_add_slot(struct device_node *dn) { struct slot *slot; int retval = 0; - int i, *my_drc_index, slot_type; + int i; int *indexes, *names, *types, *power_domains; char *name, *type; @@ -354,40 +326,25 @@ int rpaphp_add_slot(struct device_node *dn) /* register PCI devices */ if (dn->name != 0 && strcmp(dn->name, "pci") == 0) { - if (is_php_dn(dn, &indexes, &names, &types, &power_domains)) - slot_type = HOTPLUG; - else if (is_dr_dn(dn, &indexes, &names, &types, &power_domains, &my_drc_index)) - slot_type = EMBEDDED; - else goto exit; + if (!is_php_dn(dn, &indexes, &names, &types, &power_domains)) + goto exit; name = (char *) &names[1]; type = (char *) &types[1]; for (i = 0; i < indexes[0]; i++, - name += (strlen(name) + 1), type += (strlen(type) + 1)) { - - if (slot_type == HOTPLUG || - (slot_type == EMBEDDED && - indexes[i + 1] == my_drc_index[0] && - is_dlpar_type(type))) { - if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name, - power_domains[i + 1]))) { - retval = -ENOMEM; - goto exit; - } - if (!strcmp(type, "PHB")) - slot->type = PHB; - else if (slot_type == EMBEDDED) - slot->type = EMBEDDED; - else - slot->type = simple_strtoul(type, NULL, 10); + name += (strlen(name) + 1), type += (strlen(type) + 1)) { + + if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name, + power_domains[i + 1]))) { + retval = -ENOMEM; + goto exit; + } + slot->type = simple_strtoul(type, NULL, 10); - dbg(" Found drc-index:0x%x drc-name:%s drc-type:%s\n", + dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", indexes[i + 1], name, type); - retval = register_pci_slot(slot); - if (slot_type == EMBEDDED) - goto exit; - } + retval = register_pci_slot(slot); } } exit: diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index f2f1cd0f941a..17a0279ebcb9 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -49,13 +49,14 @@ static struct pci_bus *find_bus_among_children(struct pci_bus *bus, return child; } -static struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn) +struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn) { if (!dn->phb || !dn->phb->bus) return NULL; return find_bus_among_children(dn->phb->bus, dn); } +EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus); int rpaphp_claim_resource(struct pci_dev *dev, int resource) { @@ -129,10 +130,8 @@ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) if (rc) goto exit; - if ((state == EMPTY) || (slot->type == PHB)) { - dbg("slot is empty\n"); + if (state == EMPTY) *value = EMPTY; - } else if (state == PRESENT) { if (!is_init) { /* at run-time slot->state can be changed by */ @@ -423,10 +422,6 @@ int register_pci_slot(struct slot *slot) { int rc = -EINVAL; - if ((slot->type == EMBEDDED) || (slot->type == PHB)) - slot->removable = 0; - else - slot->removable = 1; if (setup_pci_hotplug_slot_info(slot)) goto exit_rc; if (setup_pci_slot(slot)) diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 80402027c015..0e8815495083 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -30,35 +30,6 @@ #include #include "rpaphp.h" -static ssize_t removable_read_file (struct hotplug_slot *php_slot, char *buf) -{ - u8 value; - int retval = -ENOENT; - struct slot *slot = (struct slot *)php_slot->private; - - if (!slot) - return retval; - - value = slot->removable; - retval = sprintf (buf, "%d\n", value); - return retval; -} - -static struct hotplug_slot_attribute hotplug_slot_attr_removable = { - .attr = {.name = "phy_removable", .mode = S_IFREG | S_IRUGO}, - .show = removable_read_file, -}; - -static void rpaphp_sysfs_add_attr_removable (struct hotplug_slot *slot) -{ - sysfs_create_file(&slot->kobj, &hotplug_slot_attr_removable.attr); -} - -static void rpaphp_sysfs_remove_attr_removable (struct hotplug_slot *slot) -{ - sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_removable.attr); -} - static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf) { char *value; @@ -176,9 +147,6 @@ int deregister_slot(struct slot *slot) /* remove "phy_location" file */ rpaphp_sysfs_remove_attr_location(php_slot); - /* remove "phy_removable" file */ - rpaphp_sysfs_remove_attr_removable(php_slot); - retval = pci_hp_deregister(php_slot); if (retval) err("Problem unregistering a slot %s\n", slot->name); @@ -212,9 +180,6 @@ int register_slot(struct slot *slot) /* create "phy_locatoin" file */ rpaphp_sysfs_add_attr_location(slot->hotplug_slot); - /* create "phy_removable" file */ - rpaphp_sysfs_add_attr_removable(slot->hotplug_slot); - /* add slot to our internal list */ dbg("%s adding slot[%s] to rpaphp_slot_list\n", __FUNCTION__, slot->name); @@ -230,21 +195,17 @@ int rpaphp_get_power_status(struct slot *slot, u8 * value) { int rc = 0, level; - if (slot->type == HOTPLUG) { - rc = rtas_get_power_level(slot->power_domain, &level); - if (!rc) { - dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n", - __FUNCTION__, slot->name, slot->power_domain, level); - *value = level; - } else - err("failed to get power-level for slot(%s), rc=0x%x\n", - slot->location, rc); - } else { - dbg("%s report POWER_ON for EMBEDDED or PHB slot %s\n", - __FUNCTION__, slot->location); - *value = (u8) POWER_ON; + rc = rtas_get_power_level(slot->power_domain, &level); + if (rc < 0) { + err("failed to get power-level for slot(%s), rc=0x%x\n", + slot->location, rc); + return rc; } + dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n", + __FUNCTION__, slot->name, slot->power_domain, level); + *value = level; + return rc; } -- cgit v1.2.3 From 1248d636122e4ec9d7802b850904e3bb48a0da23 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Fri, 5 Aug 2005 12:16:06 -0700 Subject: [PATCH] PCI Hotplug: use bus_slot number for name For systems with multiple hotplug controllers, you need to use more than just the slot number to uniquely name the slot. Without a unique slot name, the pci_hp_register() will fail. This patch adds the bus number to the name. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 2 +- drivers/pci/hotplug/shpchp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/pci/hotplug') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 2b92b9e8c910..061ead21ef14 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -302,7 +302,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) { - snprintf(buffer, buffer_size, "%d", slot->number); + snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number); } enum php_ctlr_type { diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index fe4d653da188..b7d1c61d6bbb 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -411,7 +411,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) { - snprintf(buffer, buffer_size, "%d", slot->number); + snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number); } enum php_ctlr_type { -- cgit v1.2.3 From 1d2450a4a6eb656798c6282b5ffc8e5f9f52ac14 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Fri, 12 Aug 2005 10:13:34 -0400 Subject: [PATCH] PCI Hotplug: SGI hotplug driver fixes These fixes were suggested by pcihpd-discuss, but were dropped in the initial checkin of the code. These fixes include cleaning up the hotplug driver sysfs filename, and some minor code cleanups. The driver also requires at least PROM 4.30, not 4.20. Signed-off-by: Prarit Bhargava Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/sgi_hotplug.c | 195 ++++++++++++++++++-------------------- 1 file changed, 91 insertions(+), 104 deletions(-) (limited to 'drivers/pci/hotplug') diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 323041fd41dc..b1409441c1cd 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -32,14 +32,15 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver"); -#define PCIIO_ASIC_TYPE_TIOCA 4 -#define PCI_SLOT_ALREADY_UP 2 /* slot already up */ -#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */ -#define PCI_L1_ERR 7 /* L1 console command error */ -#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */ -#define PCI_L1_QSIZE 128 /* our L1 message buffer size */ -#define SN_MAX_HP_SLOTS 32 /* max number of hotplug slots */ -#define SGI_HOTPLUG_PROM_REV 0x0420 /* Min. required PROM version */ +#define PCIIO_ASIC_TYPE_TIOCA 4 +#define PCI_SLOT_ALREADY_UP 2 /* slot already up */ +#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */ +#define PCI_L1_ERR 7 /* L1 console command error */ +#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */ +#define PCI_L1_QSIZE 128 /* our L1 message buffer size */ +#define SN_MAX_HP_SLOTS 32 /* max hotplug slots */ +#define SGI_HOTPLUG_PROM_REV 0x0430 /* Min. required PROM version */ +#define SN_SLOT_NAME_SIZE 33 /* size of name string */ /* internal list head */ static struct list_head sn_hp_list; @@ -51,6 +52,7 @@ struct slot { /* this struct for glue internal only */ struct hotplug_slot *hotplug_slot; struct list_head hp_list; + char physical_path[SN_SLOT_NAME_SIZE]; }; struct pcibr_slot_enable_resp { @@ -70,7 +72,7 @@ enum sn_pci_req_e { static int enable_slot(struct hotplug_slot *slot); static int disable_slot(struct hotplug_slot *slot); -static int get_power_status(struct hotplug_slot *slot, u8 *value); +static inline int get_power_status(struct hotplug_slot *slot, u8 *value); static struct hotplug_slot_ops sn_hotplug_slot_ops = { .owner = THIS_MODULE, @@ -81,6 +83,21 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = { static DECLARE_MUTEX(sn_hotplug_sem); +static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot, + char *buf) +{ + int retval = -ENOENT; + struct slot *slot = bss_hotplug_slot->private; + + if (!slot) + return retval; + + retval = sprintf (buf, "%s\n", slot->physical_path); + return retval; +} + +static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path); + static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) { struct pcibus_info *pcibus_info; @@ -120,15 +137,15 @@ static int sn_pci_bus_valid(struct pci_bus *pci_bus) /* Only register slots in I/O Bricks that support hotplug */ bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); switch (bricktype) { - case L1_BRICKTYPE_IX: - case L1_BRICKTYPE_PX: - case L1_BRICKTYPE_IA: - case L1_BRICKTYPE_PA: - return 1; - break; - default: - return -EPERM; - break; + case L1_BRICKTYPE_IX: + case L1_BRICKTYPE_PX: + case L1_BRICKTYPE_IA: + case L1_BRICKTYPE_PA: + return 1; + break; + default: + return -EPERM; + break; } return -EIO; @@ -142,13 +159,12 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); - bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot), - GFP_KERNEL); - if (!bss_hotplug_slot->private) + slot = kcalloc(1, sizeof(*slot), GFP_KERNEL); + if (!slot) return -ENOMEM; - slot = (struct slot *)bss_hotplug_slot->private; + bss_hotplug_slot->private = slot; - bss_hotplug_slot->name = kmalloc(33, GFP_KERNEL); + bss_hotplug_slot->name = kmalloc(SN_SLOT_NAME_SIZE, GFP_KERNEL); if (!bss_hotplug_slot->name) { kfree(bss_hotplug_slot->private); return -ENOMEM; @@ -156,16 +172,16 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, slot->device_num = device; slot->pci_bus = pci_bus; - - sprintf(bss_hotplug_slot->name, "module_%c%c%c%c%.2d_b_%d_s_%d", + sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x", + pci_domain_nr(pci_bus), + ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf, + device + 1); + sprintf(slot->physical_path, "module_%c%c%c%c%.2d", '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid), - MODULE_GET_BPOS(pcibus_info->pbi_moduleid), - ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf, - device + 1); - + MODULE_GET_BPOS(pcibus_info->pbi_moduleid)); slot->hotplug_slot = bss_hotplug_slot; list_add(&slot->hp_list, &sn_hp_list); @@ -175,14 +191,14 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, static struct hotplug_slot * sn_hp_destroy(void) { struct slot *slot; - struct list_head *list; struct hotplug_slot *bss_hotplug_slot = NULL; - list_for_each(list, &sn_hp_list) { - slot = list_entry(list, struct slot, hp_list); + list_for_each_entry(slot, &sn_hp_list, hp_list) { bss_hotplug_slot = slot->hotplug_slot; list_del(&((struct slot *)bss_hotplug_slot->private)-> hp_list); + sysfs_remove_file(&bss_hotplug_slot->kobj, + &sn_slot_path_attr.attr); break; } return bss_hotplug_slot; @@ -190,7 +206,6 @@ static struct hotplug_slot * sn_hp_destroy(void) static void sn_bus_alloc_data(struct pci_dev *dev) { - struct list_head *node; struct pci_bus *subordinate_bus; struct pci_dev *child; @@ -199,66 +214,29 @@ static void sn_bus_alloc_data(struct pci_dev *dev) /* Recursively sets up the sn_irq_info structs */ if (dev->subordinate) { subordinate_bus = dev->subordinate; - list_for_each(node, &subordinate_bus->devices) { - child = list_entry(node, struct pci_dev, bus_list); + list_for_each_entry(child, &subordinate_bus->devices, bus_list) sn_bus_alloc_data(child); - } } } static void sn_bus_free_data(struct pci_dev *dev) { - struct list_head *node; struct pci_bus *subordinate_bus; struct pci_dev *child; /* Recursively clean up sn_irq_info structs */ if (dev->subordinate) { subordinate_bus = dev->subordinate; - list_for_each(node, &subordinate_bus->devices) { - child = list_entry(node, struct pci_dev, bus_list); + list_for_each_entry(child, &subordinate_bus->devices, bus_list) sn_bus_free_data(child); - } } sn_pci_unfixup_slot(dev); } -static u8 sn_power_status_get(struct hotplug_slot *bss_hotplug_slot) -{ - struct slot *slot = (struct slot *)bss_hotplug_slot->private; - struct pcibus_info *pcibus_info; - u8 retval; - - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); - retval = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); - - return retval ? 1 : 0; -} - -static void sn_slot_mark_enable(struct hotplug_slot *bss_hotplug_slot, - int device_num) -{ - struct slot *slot = (struct slot *)bss_hotplug_slot->private; - struct pcibus_info *pcibus_info; - - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); - pcibus_info->pbi_enabled_devices |= (1 << device_num); -} - -static void sn_slot_mark_disable(struct hotplug_slot *bss_hotplug_slot, - int device_num) -{ - struct slot *slot = (struct slot *)bss_hotplug_slot->private; - struct pcibus_info *pcibus_info; - - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); - pcibus_info->pbi_enabled_devices &= ~(1 << device_num); -} - static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, int device_num) { - struct slot *slot = (struct slot *)bss_hotplug_slot->private; + struct slot *slot = bss_hotplug_slot->private; struct pcibus_info *pcibus_info; struct pcibr_slot_enable_resp resp; int rc; @@ -273,7 +251,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, if (rc == PCI_SLOT_ALREADY_UP) { dev_dbg(slot->pci_bus->self, "is already active\n"); - return -EPERM; + return 1; /* return 1 to user */ } if (rc == PCI_L1_ERR) { @@ -290,7 +268,8 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, return -EIO; } - sn_slot_mark_enable(bss_hotplug_slot, device_num); + pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); + pcibus_info->pbi_enabled_devices |= (1 << device_num); return 0; } @@ -298,7 +277,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, int device_num, int action) { - struct slot *slot = (struct slot *)bss_hotplug_slot->private; + struct slot *slot = bss_hotplug_slot->private; struct pcibus_info *pcibus_info; struct pcibr_slot_disable_resp resp; int rc; @@ -307,43 +286,44 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp); - if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_SLOT_ALREADY_DOWN) { + if ((action == PCI_REQ_SLOT_ELIGIBLE) && + (rc == PCI_SLOT_ALREADY_DOWN)) { dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n"); - return -ENODEV; + return 1; /* return 1 to user */ } - if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_EMPTY_33MHZ) { + if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) { dev_dbg(slot->pci_bus->self, "Cannot remove last 33MHz card\n"); return -EPERM; } - if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_L1_ERR) { + if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) { dev_dbg(slot->pci_bus->self, "L1 failure %d with message \n%s\n", resp.resp_sub_errno, resp.resp_l1_msg); return -EPERM; } - if (action == PCI_REQ_SLOT_ELIGIBLE && rc) { + if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) { dev_dbg(slot->pci_bus->self, "remove failed with error %d sub-error %d\n", rc, resp.resp_sub_errno); return -EIO; } - if (action == PCI_REQ_SLOT_ELIGIBLE && !rc) + if ((action == PCI_REQ_SLOT_ELIGIBLE) && !rc) return 0; - if (action == PCI_REQ_SLOT_DISABLE && !rc) { - sn_slot_mark_disable(bss_hotplug_slot, device_num); + if ((action == PCI_REQ_SLOT_DISABLE) && !rc) { + pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); + pcibus_info->pbi_enabled_devices &= ~(1 << device_num); dev_dbg(slot->pci_bus->self, "remove successful\n"); return 0; } - if (action == PCI_REQ_SLOT_DISABLE && rc) { + if ((action == PCI_REQ_SLOT_DISABLE) && rc) { dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc); - return rc; } return rc; @@ -351,7 +331,7 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, static int enable_slot(struct hotplug_slot *bss_hotplug_slot) { - struct slot *slot = (struct slot *)bss_hotplug_slot->private; + struct slot *slot = bss_hotplug_slot->private; struct pci_bus *new_bus = NULL; struct pci_dev *dev; int func, num_funcs; @@ -371,8 +351,8 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) return rc; } - num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1, - PCI_FUNC(0))); + num_funcs = pci_scan_slot(slot->pci_bus, + PCI_DEVFN(slot->device_num + 1, 0)); if (!num_funcs) { dev_dbg(slot->pci_bus->self, "no device in slot\n"); up(&sn_hotplug_sem); @@ -391,8 +371,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) dev = pci_get_slot(slot->pci_bus, PCI_DEVFN(slot->device_num + 1, PCI_FUNC(func))); - - if (dev) { if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { unsigned char sec_bus; @@ -431,7 +409,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) static int disable_slot(struct hotplug_slot *bss_hotplug_slot) { - struct slot *slot = (struct slot *)bss_hotplug_slot->private; + struct slot *slot = bss_hotplug_slot->private; struct pci_dev *dev; int func; int rc; @@ -448,7 +426,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) /* Free the SN resources assigned to the Linux device.*/ for (func = 0; func < 8; func++) { dev = pci_get_slot(slot->pci_bus, - PCI_DEVFN(slot->device_num+1, + PCI_DEVFN(slot->device_num + 1, PCI_FUNC(func))); if (dev) { /* @@ -477,10 +455,15 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) return rc; } -static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value) +static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot, + u8 *value) { + struct slot *slot = bss_hotplug_slot->private; + struct pcibus_info *pcibus_info; + + pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); down(&sn_hotplug_sem); - *value = sn_power_status_get(bss_hotplug_slot); + *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); up(&sn_hotplug_sem); return 0; } @@ -508,7 +491,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) if (sn_pci_slot_valid(pci_bus, device) != 1) continue; - bss_hotplug_slot = kcalloc(1,sizeof(struct hotplug_slot), + bss_hotplug_slot = kcalloc(1, sizeof(*bss_hotplug_slot), GFP_KERNEL); if (!bss_hotplug_slot) { rc = -ENOMEM; @@ -516,7 +499,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) } bss_hotplug_slot->info = - kcalloc(1,sizeof(struct hotplug_slot_info), + kcalloc(1, sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!bss_hotplug_slot->info) { rc = -ENOMEM; @@ -535,6 +518,11 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) rc = pci_hp_register(bss_hotplug_slot); if (rc) goto register_err; + + rc = sysfs_create_file(&bss_hotplug_slot->kobj, + &sn_slot_path_attr.attr); + if (rc) + goto register_err; } dev_dbg(pci_bus->self, "Registered bus with hotplug\n"); return rc; @@ -564,14 +552,14 @@ static int sn_pci_hotplug_init(void) int rc; int registered = 0; - INIT_LIST_HEAD(&sn_hp_list); - if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) { - printk(KERN_ERR "%s: PROM version must be greater than 4.05\n", + printk(KERN_ERR "%s: PROM version must be greater than 4.30\n", __FUNCTION__); return -EPERM; } + INIT_LIST_HEAD(&sn_hp_list); + while ((pci_bus = pci_find_next_bus(pci_bus))) { if (!pci_bus->sysdata) continue; @@ -584,9 +572,9 @@ static int sn_pci_hotplug_init(void) dev_dbg(pci_bus->self, "valid hotplug bus\n"); rc = sn_hotplug_slot_register(pci_bus); - if (!rc) + if (!rc) { registered = 1; - else { + } else { registered = 0; break; } @@ -599,9 +587,8 @@ static void sn_pci_hotplug_exit(void) { struct hotplug_slot *bss_hotplug_slot; - while ((bss_hotplug_slot = sn_hp_destroy())) { + while ((bss_hotplug_slot = sn_hp_destroy())) pci_hp_deregister(bss_hotplug_slot); - } if (!list_empty(&sn_hp_list)) printk(KERN_ERR "%s: internal list is not empty\n", __FILE__); -- cgit v1.2.3