lkml.org 
[lkml]   [2008]   [Mar]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH 3/4] Introduce pci_slot
    Acked-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>

    Thanks,
    Kenji Kaneshige


    Alex Chiang wrote:
    > Currently, /sys/bus/pci/slots/ only exposes hotplug attributes
    > when a hotplug driver is loaded, but PCI slots have attributes
    > such as address, speed, width, etc. that are not related to
    > hotplug at all.
    >
    > Introduce pci_slot as the primary data structure and kobject
    > model. Hotplug attributes described in hotplug_slot become a
    > secondary structure associated with the pci_slot.
    >
    > This patch only creates the infrastructure that allows the
    > separation of PCI slot attributes and hotplug attributes.
    > In this patch, the PCI hotplug core remains the only user of this
    > infrastructure, and thus, /sys/bus/pci/slots/ will still only
    > become populated when a hotplug driver is loaded.
    >
    > A later patch in this series will add a second user of this new
    > infrastructure and demonstrate splitting the task of exposing
    > pci_slot attributes from hotplug_slot attributes.
    >
    > - Make pci_slot the primary sysfs entity. hotplug_slot becomes a
    > subsidiary structure.
    > o pci_create_slot() creates and registers a slot with the PCI core
    > o pci_slot_add_hotplug() gives it hotplug capability
    >
    > - Change the prototype of pci_hp_register() to take the bus and
    > slot number (on parent bus) as parameters.
    >
    > - Remove all the ->get_address methods since this functionality is
    > now handled by pci_slot directly.
    >
    > v10 -> v11:
    > Thanks to Kenji Kanishige for the following updates
    > - Add missing semaphore for slot release
    > - Use list_head for pci slot list
    > - Replace dbg with pr_debug
    > - Remove useless release handler
    > - Use .default_attrs for address file
    > - Fix return value of pci_create_slot()
    > - Change return value of pci_destroy_slot()
    > - Trivial cleanups for slot.c
    > - add missing lock for hotplug slot list
    >
    > v9 -> v10:
    > No change
    >
    > v8 -> v9:
    > Fixed printk output, changed to American spelling of
    > "initialization"
    >
    > v7 -> v8:
    > Removed externs from C files.
    >
    > Taught sn_hp_destroy and sn_hotplug_slot_register about
    > struct pci_slot.
    >
    > v6 -> v7:
    > Refresh to new kobject model.
    >
    > v5 -> v6:
    > Add debugging information.
    >
    > v4 -> v5:
    > Add refcounting for pci_slot objects.
    >
    > Return -EBUSY if an hp driver attempts to register a slot
    > that is already registered to another driver. Do not consider
    > that to be an error condition in acpiphp and pciehp.
    >
    > v3 -> v4:
    > Fixed bug with pciehp and rpaphp registering slots
    >
    > v2 -> v3:
    > Separated slot creation and slot hotplug ability into two
    > interfaces. Fixed bugs in pci_destroy_slot(), and now
    > properly calling from pci_hp_deregister.
    >
    > v1 -> v2:
    > No change
    >
    > Signed-off-by: Alex Chiang <achiang@hp.com>
    > Signed-off-by: Matthew Wilcox <matthew@wil.cx>
    > ---
    > drivers/pci/Makefile | 2 +-
    > drivers/pci/hotplug/acpiphp.h | 1 -
    > drivers/pci/hotplug/acpiphp_core.c | 25 +---
    > drivers/pci/hotplug/acpiphp_glue.c | 23 +--
    > drivers/pci/hotplug/acpiphp_ibm.c | 6 +-
    > drivers/pci/hotplug/cpci_hotplug_core.c | 2 +-
    > drivers/pci/hotplug/cpqphp_core.c | 4 +-
    > drivers/pci/hotplug/fakephp.c | 2 +-
    > drivers/pci/hotplug/ibmphp_ebda.c | 3 +-
    > drivers/pci/hotplug/pci_hotplug_core.c | 257 ++++++++++++-------------------
    > drivers/pci/hotplug/pciehp_core.c | 31 ++--
    > drivers/pci/hotplug/rpadlpar_sysfs.c | 5 +-
    > drivers/pci/hotplug/rpaphp_slot.c | 3 +-
    > drivers/pci/hotplug/sgi_hotplug.c | 10 +-
    > drivers/pci/hotplug/shpchp_core.c | 17 +--
    > drivers/pci/pci.h | 13 ++
    > drivers/pci/probe.c | 1 +
    > drivers/pci/slot.c | 147 ++++++++++++++++++
    > include/linux/pci.h | 14 ++
    > include/linux/pci_hotplug.h | 12 +-
    > 20 files changed, 325 insertions(+), 253 deletions(-)
    > create mode 100644 drivers/pci/slot.c
    >
    > diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
    > index 4d1ce2e..7d63f8c 100644
    > --- a/drivers/pci/Makefile
    > +++ b/drivers/pci/Makefile
    > @@ -2,7 +2,7 @@
    > # Makefile for the PCI bus specific drivers.
    > #
    >
    > -obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \
    > +obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
    > pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
    > obj-$(CONFIG_PROC_FS) += proc.o
    >
    > diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
    > index 7a29164..eecf7cb 100644
    > --- a/drivers/pci/hotplug/acpiphp.h
    > +++ b/drivers/pci/hotplug/acpiphp.h
    > @@ -215,7 +215,6 @@ extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
    > extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
    > extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
    > extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
    > -extern u32 acpiphp_get_address (struct acpiphp_slot *slot);
    >
    > /* variables */
    > extern int acpiphp_debug;
    > diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
    > index 9279d5b..57319e6 100644
    > --- a/drivers/pci/hotplug/acpiphp_core.c
    > +++ b/drivers/pci/hotplug/acpiphp_core.c
    > @@ -70,7 +70,6 @@ static int disable_slot (struct hotplug_slot *slot);
    > static int set_attention_status (struct hotplug_slot *slot, u8 value);
    > static int get_power_status (struct hotplug_slot *slot, u8 *value);
    > static int get_attention_status (struct hotplug_slot *slot, u8 *value);
    > -static int get_address (struct hotplug_slot *slot, u32 *value);
    > static int get_latch_status (struct hotplug_slot *slot, u8 *value);
    > static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
    >
    > @@ -83,7 +82,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
    > .get_attention_status = get_attention_status,
    > .get_latch_status = get_latch_status,
    > .get_adapter_status = get_adapter_status,
    > - .get_address = get_address,
    > };
    >
    >
    > @@ -274,23 +272,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
    > return 0;
    > }
    >
    > -
    > -/**
    > - * get_address - get pci address of a slot
    > - * @hotplug_slot: slot to get status
    > - * @value: pointer to struct pci_busdev (seg, bus, dev)
    > - */
    > -static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
    > -{
    > - struct slot *slot = hotplug_slot->private;
    > -
    > - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
    > -
    > - *value = acpiphp_get_address(slot->acpi_slot);
    > -
    > - return 0;
    > -}
    > -
    > static int __init init_acpi(void)
    > {
    > int retval;
    > @@ -357,7 +338,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
    > acpiphp_slot->slot = slot;
    > snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun);
    >
    > - retval = pci_hp_register(slot->hotplug_slot);
    > + retval = pci_hp_register(slot->hotplug_slot,
    > + acpiphp_slot->bridge->pci_bus,
    > + acpiphp_slot->device);
    > + if (retval == -EBUSY)
    > + goto error_hpslot;
    > if (retval) {
    > err("pci_hp_register failed with error %d\n", retval);
    > goto error_hpslot;
    > diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
    > index 5e50008..b8039eb 100644
    > --- a/drivers/pci/hotplug/acpiphp_glue.c
    > +++ b/drivers/pci/hotplug/acpiphp_glue.c
    > @@ -258,7 +258,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
    > bridge->pci_bus->number, slot->device);
    > retval = acpiphp_register_hotplug_slot(slot);
    > if (retval) {
    > - warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval);
    > + if (retval == -EBUSY)
    > + warn("Slot %d already registered by another "
    > + "hotplug driver\n", slot->sun);
    > + else
    > + warn("acpiphp_register_hotplug_slot failed "
    > + "(err code = 0x%x)\n", retval);
    > goto err_exit;
    > }
    > }
    > @@ -1867,19 +1872,3 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
    >
    > return (sta == 0) ? 0 : 1;
    > }
    > -
    > -
    > -/*
    > - * pci address (seg/bus/dev)
    > - */
    > -u32 acpiphp_get_address(struct acpiphp_slot *slot)
    > -{
    > - u32 address;
    > - struct pci_bus *pci_bus = slot->bridge->pci_bus;
    > -
    > - address = (pci_domain_nr(pci_bus) << 16) |
    > - (pci_bus->number << 8) |
    > - slot->device;
    > -
    > - return address;
    > -}
    > diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
    > index b0a22b9..34a708f 100644
    > --- a/drivers/pci/hotplug/acpiphp_ibm.c
    > +++ b/drivers/pci/hotplug/acpiphp_ibm.c
    > @@ -33,8 +33,10 @@
    > #include <linux/kobject.h>
    > #include <asm/uaccess.h>
    > #include <linux/moduleparam.h>
    > +#include <linux/pci.h>
    >
    > #include "acpiphp.h"
    > +#include "../pci.h"
    >
    > #define DRIVER_VERSION "1.0.1"
    > #define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
    > @@ -430,7 +432,7 @@ static int __init ibm_acpiphp_init(void)
    > int retval = 0;
    > acpi_status status;
    > struct acpi_device *device;
    > - struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
    > + struct kobject *sysdir = &pci_slots_kset->kobj;
    >
    > dbg("%s\n", __FUNCTION__);
    >
    > @@ -477,7 +479,7 @@ init_return:
    > static void __exit ibm_acpiphp_exit(void)
    > {
    > acpi_status status;
    > - struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
    > + struct kobject *sysdir = &pci_slots_kset->kobj;
    >
    > dbg("%s\n", __FUNCTION__);
    >
    > diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
    > index ed4d44e..aa47b80 100644
    > --- a/drivers/pci/hotplug/cpci_hotplug_core.c
    > +++ b/drivers/pci/hotplug/cpci_hotplug_core.c
    > @@ -285,7 +285,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
    > info->attention_status = cpci_get_attention_status(slot);
    >
    > dbg("registering slot %s", slot->hotplug_slot->name);
    > - status = pci_hp_register(slot->hotplug_slot);
    > + status = pci_hp_register(slot->hotplug_slot, bus, i);
    > if (status) {
    > err("pci_hp_register failed with error %d", status);
    > goto error_name;
    > diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
    > index 7417887..2e0392e 100644
    > --- a/drivers/pci/hotplug/cpqphp_core.c
    > +++ b/drivers/pci/hotplug/cpqphp_core.c
    > @@ -434,7 +434,9 @@ static int ctrl_slot_setup(struct controller *ctrl,
    > slot->bus, slot->device,
    > slot->number, ctrl->slot_device_offset,
    > slot_number);
    > - result = pci_hp_register(hotplug_slot);
    > + result = pci_hp_register(hotplug_slot,
    > + ctrl->pci_dev->subordinate,
    > + slot->device);
    > if (result) {
    > err("pci_hp_register failed with error %d\n", result);
    > goto error_name;
    > diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
    > index 6c14b4d..2d84755 100644
    > --- a/drivers/pci/hotplug/fakephp.c
    > +++ b/drivers/pci/hotplug/fakephp.c
    > @@ -127,7 +127,7 @@ static int add_slot(struct pci_dev *dev)
    > slot->release = &dummy_release;
    > slot->private = dslot;
    >
    > - retval = pci_hp_register(slot);
    > + retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn));
    > if (retval) {
    > err("pci_hp_register failed with error %d\n", retval);
    > goto error_dslot;
    > diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
    > index bbccde9..17a5cfe 100644
    > --- a/drivers/pci/hotplug/ibmphp_ebda.c
    > +++ b/drivers/pci/hotplug/ibmphp_ebda.c
    > @@ -1001,7 +1001,8 @@ static int __init ebda_rsrc_controller (void)
    > tmp_slot = list_entry (list, struct slot, ibm_slot_list);
    >
    > snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot));
    > - pci_hp_register (tmp_slot->hotplug_slot);
    > + pci_hp_register(tmp_slot->hotplug_slot,
    > + pci_find_bus(0, tmp_slot->bus), tmp_slot->device);
    > }
    >
    > print_ebda_hpc ();
    > diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
    > index dd59a05..5208786 100644
    > --- a/drivers/pci/hotplug/pci_hotplug_core.c
    > +++ b/drivers/pci/hotplug/pci_hotplug_core.c
    > @@ -40,6 +40,7 @@
    > #include <linux/pci.h>
    > #include <linux/pci_hotplug.h>
    > #include <asm/uaccess.h>
    > +#include "../pci.h"
    >
    > #define MY_NAME "pci_hotplug"
    >
    > @@ -60,41 +61,7 @@ static int debug;
    > //////////////////////////////////////////////////////////////////
    >
    > static LIST_HEAD(pci_hotplug_slot_list);
    > -
    > -struct kset *pci_hotplug_slots_kset;
    > -
    > -static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
    > - struct attribute *attr, char *buf)
    > -{
    > - struct hotplug_slot *slot = to_hotplug_slot(kobj);
    > - struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
    > - return attribute->show ? attribute->show(slot, buf) : -EIO;
    > -}
    > -
    > -static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
    > - struct attribute *attr, const char *buf, size_t len)
    > -{
    > - struct hotplug_slot *slot = to_hotplug_slot(kobj);
    > - struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
    > - return attribute->store ? attribute->store(slot, buf, len) : -EIO;
    > -}
    > -
    > -static struct sysfs_ops hotplug_slot_sysfs_ops = {
    > - .show = hotplug_slot_attr_show,
    > - .store = hotplug_slot_attr_store,
    > -};
    > -
    > -static void hotplug_slot_release(struct kobject *kobj)
    > -{
    > - struct hotplug_slot *slot = to_hotplug_slot(kobj);
    > - if (slot->release)
    > - slot->release(slot);
    > -}
    > -
    > -static struct kobj_type hotplug_slot_ktype = {
    > - .sysfs_ops = &hotplug_slot_sysfs_ops,
    > - .release = &hotplug_slot_release,
    > -};
    > +static DEFINE_SPINLOCK(pci_hotplug_slot_list_lock);
    >
    > /* these strings match up with the values in pci_bus_speed */
    > static char *pci_bus_speed_strings[] = {
    > @@ -149,16 +116,15 @@ GET_STATUS(power_status, u8)
    > GET_STATUS(attention_status, u8)
    > GET_STATUS(latch_status, u8)
    > GET_STATUS(adapter_status, u8)
    > -GET_STATUS(address, u32)
    > GET_STATUS(max_bus_speed, enum pci_bus_speed)
    > GET_STATUS(cur_bus_speed, enum pci_bus_speed)
    >
    > -static ssize_t power_read_file (struct hotplug_slot *slot, char *buf)
    > +static ssize_t power_read_file(struct pci_slot *slot, char *buf)
    > {
    > int retval;
    > u8 value;
    >
    > - retval = get_power_status (slot, &value);
    > + retval = get_power_status(slot->hotplug, &value);
    > if (retval)
    > goto exit;
    > retval = sprintf (buf, "%d\n", value);
    > @@ -166,9 +132,10 @@ exit:
    > return retval;
    > }
    >
    > -static ssize_t power_write_file (struct hotplug_slot *slot, const char *buf,
    > +static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf,
    > size_t count)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > unsigned long lpower;
    > u8 power;
    > int retval = 0;
    > @@ -204,29 +171,30 @@ exit:
    > return count;
    > }
    >
    > -static struct hotplug_slot_attribute hotplug_slot_attr_power = {
    > +static struct pci_slot_attribute hotplug_slot_attr_power = {
    > .attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR},
    > .show = power_read_file,
    > .store = power_write_file
    > };
    >
    > -static ssize_t attention_read_file (struct hotplug_slot *slot, char *buf)
    > +static ssize_t attention_read_file(struct pci_slot *slot, char *buf)
    > {
    > int retval;
    > u8 value;
    >
    > - retval = get_attention_status (slot, &value);
    > + retval = get_attention_status(slot->hotplug, &value);
    > if (retval)
    > goto exit;
    > - retval = sprintf (buf, "%d\n", value);
    > + retval = sprintf(buf, "%d\n", value);
    >
    > exit:
    > return retval;
    > }
    >
    > -static ssize_t attention_write_file (struct hotplug_slot *slot, const char *buf,
    > +static ssize_t attention_write_file(struct pci_slot *slot, const char *buf,
    > size_t count)
    > {
    > + struct hotplug_slot_ops *ops = slot->hotplug->ops;
    > unsigned long lattention;
    > u8 attention;
    > int retval = 0;
    > @@ -235,13 +203,13 @@ static ssize_t attention_write_file (struct hotplug_slot *slot, const char *buf,
    > attention = (u8)(lattention & 0xff);
    > dbg (" - attention = %d\n", attention);
    >
    > - if (!try_module_get(slot->ops->owner)) {
    > + if (!try_module_get(ops->owner)) {
    > retval = -ENODEV;
    > goto exit;
    > }
    > - if (slot->ops->set_attention_status)
    > - retval = slot->ops->set_attention_status(slot, attention);
    > - module_put(slot->ops->owner);
    > + if (ops->set_attention_status)
    > + retval = ops->set_attention_status(slot->hotplug, attention);
    > + module_put(ops->owner);
    >
    > exit:
    > if (retval)
    > @@ -249,18 +217,18 @@ exit:
    > return count;
    > }
    >
    > -static struct hotplug_slot_attribute hotplug_slot_attr_attention = {
    > +static struct pci_slot_attribute hotplug_slot_attr_attention = {
    > .attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR},
    > .show = attention_read_file,
    > .store = attention_write_file
    > };
    >
    > -static ssize_t latch_read_file (struct hotplug_slot *slot, char *buf)
    > +static ssize_t latch_read_file(struct pci_slot *slot, char *buf)
    > {
    > int retval;
    > u8 value;
    >
    > - retval = get_latch_status (slot, &value);
    > + retval = get_latch_status(slot->hotplug, &value);
    > if (retval)
    > goto exit;
    > retval = sprintf (buf, "%d\n", value);
    > @@ -269,17 +237,17 @@ exit:
    > return retval;
    > }
    >
    > -static struct hotplug_slot_attribute hotplug_slot_attr_latch = {
    > +static struct pci_slot_attribute hotplug_slot_attr_latch = {
    > .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO},
    > .show = latch_read_file,
    > };
    >
    > -static ssize_t presence_read_file (struct hotplug_slot *slot, char *buf)
    > +static ssize_t presence_read_file(struct pci_slot *slot, char *buf)
    > {
    > int retval;
    > u8 value;
    >
    > - retval = get_adapter_status (slot, &value);
    > + retval = get_adapter_status(slot->hotplug, &value);
    > if (retval)
    > goto exit;
    > retval = sprintf (buf, "%d\n", value);
    > @@ -288,42 +256,20 @@ exit:
    > return retval;
    > }
    >
    > -static struct hotplug_slot_attribute hotplug_slot_attr_presence = {
    > +static struct pci_slot_attribute hotplug_slot_attr_presence = {
    > .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO},
    > .show = presence_read_file,
    > };
    >
    > -static ssize_t address_read_file (struct hotplug_slot *slot, char *buf)
    > -{
    > - int retval;
    > - u32 address;
    > -
    > - retval = get_address (slot, &address);
    > - if (retval)
    > - goto exit;
    > - retval = sprintf (buf, "%04x:%02x:%02x\n",
    > - (address >> 16) & 0xffff,
    > - (address >> 8) & 0xff,
    > - address & 0xff);
    > -
    > -exit:
    > - return retval;
    > -}
    > -
    > -static struct hotplug_slot_attribute hotplug_slot_attr_address = {
    > - .attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
    > - .show = address_read_file,
    > -};
    > -
    > static char *unknown_speed = "Unknown bus speed";
    >
    > -static ssize_t max_bus_speed_read_file (struct hotplug_slot *slot, char *buf)
    > +static ssize_t max_bus_speed_read_file(struct pci_slot *slot, char *buf)
    > {
    > char *speed_string;
    > int retval;
    > enum pci_bus_speed value;
    >
    > - retval = get_max_bus_speed (slot, &value);
    > + retval = get_max_bus_speed(slot->hotplug, &value);
    > if (retval)
    > goto exit;
    >
    > @@ -338,18 +284,18 @@ exit:
    > return retval;
    > }
    >
    > -static struct hotplug_slot_attribute hotplug_slot_attr_max_bus_speed = {
    > +static struct pci_slot_attribute hotplug_slot_attr_max_bus_speed = {
    > .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO},
    > .show = max_bus_speed_read_file,
    > };
    >
    > -static ssize_t cur_bus_speed_read_file (struct hotplug_slot *slot, char *buf)
    > +static ssize_t cur_bus_speed_read_file(struct pci_slot *slot, char *buf)
    > {
    > char *speed_string;
    > int retval;
    > enum pci_bus_speed value;
    >
    > - retval = get_cur_bus_speed (slot, &value);
    > + retval = get_cur_bus_speed(slot->hotplug, &value);
    > if (retval)
    > goto exit;
    >
    > @@ -364,14 +310,15 @@ exit:
    > return retval;
    > }
    >
    > -static struct hotplug_slot_attribute hotplug_slot_attr_cur_bus_speed = {
    > +static struct pci_slot_attribute hotplug_slot_attr_cur_bus_speed = {
    > .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO},
    > .show = cur_bus_speed_read_file,
    > };
    >
    > -static ssize_t test_write_file (struct hotplug_slot *slot, const char *buf,
    > +static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf,
    > size_t count)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > unsigned long ltest;
    > u32 test;
    > int retval = 0;
    > @@ -394,13 +341,14 @@ exit:
    > return count;
    > }
    >
    > -static struct hotplug_slot_attribute hotplug_slot_attr_test = {
    > +static struct pci_slot_attribute hotplug_slot_attr_test = {
    > .attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR},
    > .store = test_write_file
    > };
    >
    > -static int has_power_file (struct hotplug_slot *slot)
    > +static int has_power_file(struct pci_slot *pci_slot)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > if ((!slot) || (!slot->ops))
    > return -ENODEV;
    > if ((slot->ops->enable_slot) ||
    > @@ -410,8 +358,9 @@ static int has_power_file (struct hotplug_slot *slot)
    > return -ENOENT;
    > }
    >
    > -static int has_attention_file (struct hotplug_slot *slot)
    > +static int has_attention_file(struct pci_slot *pci_slot)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > if ((!slot) || (!slot->ops))
    > return -ENODEV;
    > if ((slot->ops->set_attention_status) ||
    > @@ -420,8 +369,9 @@ static int has_attention_file (struct hotplug_slot *slot)
    > return -ENOENT;
    > }
    >
    > -static int has_latch_file (struct hotplug_slot *slot)
    > +static int has_latch_file(struct pci_slot *pci_slot)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > if ((!slot) || (!slot->ops))
    > return -ENODEV;
    > if (slot->ops->get_latch_status)
    > @@ -429,8 +379,9 @@ static int has_latch_file (struct hotplug_slot *slot)
    > return -ENOENT;
    > }
    >
    > -static int has_adapter_file (struct hotplug_slot *slot)
    > +static int has_adapter_file(struct pci_slot *pci_slot)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > if ((!slot) || (!slot->ops))
    > return -ENODEV;
    > if (slot->ops->get_adapter_status)
    > @@ -438,17 +389,9 @@ static int has_adapter_file (struct hotplug_slot *slot)
    > return -ENOENT;
    > }
    >
    > -static int has_address_file (struct hotplug_slot *slot)
    > -{
    > - if ((!slot) || (!slot->ops))
    > - return -ENODEV;
    > - if (slot->ops->get_address)
    > - return 0;
    > - return -ENOENT;
    > -}
    > -
    > -static int has_max_bus_speed_file (struct hotplug_slot *slot)
    > +static int has_max_bus_speed_file(struct pci_slot *pci_slot)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > if ((!slot) || (!slot->ops))
    > return -ENODEV;
    > if (slot->ops->get_max_bus_speed)
    > @@ -456,8 +399,9 @@ static int has_max_bus_speed_file (struct hotplug_slot *slot)
    > return -ENOENT;
    > }
    >
    > -static int has_cur_bus_speed_file (struct hotplug_slot *slot)
    > +static int has_cur_bus_speed_file(struct pci_slot *pci_slot)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > if ((!slot) || (!slot->ops))
    > return -ENODEV;
    > if (slot->ops->get_cur_bus_speed)
    > @@ -465,8 +409,9 @@ static int has_cur_bus_speed_file (struct hotplug_slot *slot)
    > return -ENOENT;
    > }
    >
    > -static int has_test_file (struct hotplug_slot *slot)
    > +static int has_test_file(struct pci_slot *pci_slot)
    > {
    > + struct hotplug_slot *slot = pci_slot->hotplug;
    > if ((!slot) || (!slot->ops))
    > return -ENODEV;
    > if (slot->ops->hardware_test)
    > @@ -474,7 +419,7 @@ static int has_test_file (struct hotplug_slot *slot)
    > return -ENOENT;
    > }
    >
    > -static int fs_add_slot (struct hotplug_slot *slot)
    > +static int fs_add_slot(struct pci_slot *slot)
    > {
    > int retval = 0;
    >
    > @@ -505,13 +450,6 @@ static int fs_add_slot (struct hotplug_slot *slot)
    > goto exit_adapter;
    > }
    >
    > - if (has_address_file(slot) == 0) {
    > - retval = sysfs_create_file(&slot->kobj,
    > - &hotplug_slot_attr_address.attr);
    > - if (retval)
    > - goto exit_address;
    > - }
    > -
    > if (has_max_bus_speed_file(slot) == 0) {
    > retval = sysfs_create_file(&slot->kobj,
    > &hotplug_slot_attr_max_bus_speed.attr);
    > @@ -544,10 +482,6 @@ exit_cur_speed:
    > sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
    >
    > exit_max_speed:
    > - if (has_address_file(slot) == 0)
    > - sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr);
    > -
    > -exit_address:
    > if (has_adapter_file(slot) == 0)
    > sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
    >
    > @@ -567,7 +501,7 @@ exit:
    > return retval;
    > }
    >
    > -static void fs_remove_slot (struct hotplug_slot *slot)
    > +static void fs_remove_slot(struct pci_slot *slot)
    > {
    > if (has_power_file(slot) == 0)
    > sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
    > @@ -581,9 +515,6 @@ static void fs_remove_slot (struct hotplug_slot *slot)
    > if (has_adapter_file(slot) == 0)
    > sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
    >
    > - if (has_address_file(slot) == 0)
    > - sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr);
    > -
    > if (has_max_bus_speed_file(slot) == 0)
    > sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
    >
    > @@ -599,12 +530,16 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
    > struct hotplug_slot *slot;
    > struct list_head *tmp;
    >
    > + spin_lock(&pci_hotplug_slot_list_lock);
    > list_for_each (tmp, &pci_hotplug_slot_list) {
    > slot = list_entry (tmp, struct hotplug_slot, slot_list);
    > if (strcmp(slot->name, name) == 0)
    > - return slot;
    > + goto out;
    > }
    > - return NULL;
    > + slot = NULL;
    > +out:
    > + spin_unlock(&pci_hotplug_slot_list_lock);
    > + return slot;
    > }
    >
    > /**
    > @@ -616,9 +551,10 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
    > *
    > * Returns 0 if successful, anything else for an error.
    > */
    > -int pci_hp_register (struct hotplug_slot *slot)
    > +int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr)
    > {
    > int result;
    > + struct pci_slot *pci_slot;
    >
    > if (slot == NULL)
    > return -ENODEV;
    > @@ -630,20 +566,26 @@ int pci_hp_register (struct hotplug_slot *slot)
    > return -EINVAL;
    > }
    >
    > - /* this can fail if we have already registered a slot with the same name */
    > - slot->kobj.kset = pci_hotplug_slots_kset;
    > - result = kobject_init_and_add(&slot->kobj, &hotplug_slot_ktype, NULL,
    > - "%s", slot->name);
    > - if (result) {
    > - err("Unable to register kobject '%s'", slot->name);
    > - return -EINVAL;
    > + pci_slot = pci_create_slot(bus, slot_nr, slot->name);
    > + if (IS_ERR(pci_slot))
    > + return PTR_ERR(pci_slot);
    > +
    > + if (pci_slot->hotplug) {
    > + dbg("%s: already claimed\n", __func__);
    > + pci_destroy_slot(pci_slot);
    > + return -EBUSY;
    > }
    >
    > - list_add (&slot->slot_list, &pci_hotplug_slot_list);
    > + slot->pci_slot = pci_slot;
    > + pci_slot->hotplug = slot;
    > +
    > + spin_lock(&pci_hotplug_slot_list_lock);
    > + list_add(&slot->slot_list, &pci_hotplug_slot_list);
    > + spin_unlock(&pci_hotplug_slot_list_lock);
    >
    > - result = fs_add_slot (slot);
    > - kobject_uevent(&slot->kobj, KOBJ_ADD);
    > - dbg ("Added slot %s to the list\n", slot->name);
    > + result = fs_add_slot(pci_slot);
    > + kobject_uevent(&pci_slot->kobj, KOBJ_ADD);
    > + dbg("Added slot %s to the list\n", slot->name);
    > return result;
    > }
    >
    > @@ -656,22 +598,30 @@ int pci_hp_register (struct hotplug_slot *slot)
    > *
    > * Returns 0 if successful, anything else for an error.
    > */
    > -int pci_hp_deregister (struct hotplug_slot *slot)
    > +int pci_hp_deregister(struct hotplug_slot *hotplug)
    > {
    > struct hotplug_slot *temp;
    > + struct pci_slot *slot;
    >
    > - if (slot == NULL)
    > + if (!hotplug)
    > return -ENODEV;
    >
    > - temp = get_slot_from_name (slot->name);
    > - if (temp != slot) {
    > + temp = get_slot_from_name(hotplug->name);
    > + if (temp != hotplug)
    > return -ENODEV;
    > - }
    > - list_del (&slot->slot_list);
    >
    > - fs_remove_slot (slot);
    > - dbg ("Removed slot %s from the list\n", slot->name);
    > - kobject_put(&slot->kobj);
    > + spin_lock(&pci_hotplug_slot_list_lock);
    > + list_del(&hotplug->slot_list);
    > + spin_unlock(&pci_hotplug_slot_list_lock);
    > +
    > + slot = hotplug->pci_slot;
    > + fs_remove_slot(slot);
    > + dbg("Removed slot %s from the list\n", hotplug->name);
    > +
    > + hotplug->release(hotplug);
    > + slot->hotplug = NULL;
    > + pci_destroy_slot(slot);
    > +
    > return 0;
    > }
    >
    > @@ -685,13 +635,15 @@ int pci_hp_deregister (struct hotplug_slot *slot)
    > *
    > * Returns 0 if successful, anything else for an error.
    > */
    > -int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
    > +int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug,
    > struct hotplug_slot_info *info)
    > {
    > - if ((slot == NULL) || (info == NULL))
    > + struct pci_slot *slot;
    > + if (!hotplug || !info)
    > return -ENODEV;
    > + slot = hotplug->pci_slot;
    >
    > - memcpy (slot->info, info, sizeof (struct hotplug_slot_info));
    > + memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info));
    >
    > return 0;
    > }
    > @@ -699,36 +651,22 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
    > static int __init pci_hotplug_init (void)
    > {
    > int result;
    > - struct kset *pci_bus_kset;
    >
    > - pci_bus_kset = bus_get_kset(&pci_bus_type);
    > -
    > - pci_hotplug_slots_kset = kset_create_and_add("slots", NULL,
    > - &pci_bus_kset->kobj);
    > - if (!pci_hotplug_slots_kset) {
    > - result = -ENOMEM;
    > - err("Register subsys error\n");
    > - goto exit;
    > - }
    > result = cpci_hotplug_init(debug);
    > if (result) {
    > err ("cpci_hotplug_init with error %d\n", result);
    > - goto err_subsys;
    > + goto err_cpci;
    > }
    >
    > info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
    > - goto exit;
    >
    > -err_subsys:
    > - kset_unregister(pci_hotplug_slots_kset);
    > -exit:
    > +err_cpci:
    > return result;
    > }
    >
    > static void __exit pci_hotplug_exit (void)
    > {
    > cpci_hotplug_exit();
    > - kset_unregister(pci_hotplug_slots_kset);
    > }
    >
    > module_init(pci_hotplug_init);
    > @@ -740,7 +678,6 @@ MODULE_LICENSE("GPL");
    > module_param(debug, bool, 0644);
    > MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
    >
    > -EXPORT_SYMBOL_GPL(pci_hotplug_slots_kset);
    > EXPORT_SYMBOL_GPL(pci_hp_register);
    > EXPORT_SYMBOL_GPL(pci_hp_deregister);
    > EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
    > diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
    > index 5fa4ba0..e6d3d4d 100644
    > --- a/drivers/pci/hotplug/pciehp_core.c
    > +++ b/drivers/pci/hotplug/pciehp_core.c
    > @@ -69,7 +69,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
    > static int get_attention_status (struct hotplug_slot *slot, u8 *value);
    > static int get_latch_status (struct hotplug_slot *slot, u8 *value);
    > static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
    > -static int get_address (struct hotplug_slot *slot, u32 *value);
    > static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
    > static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
    >
    > @@ -82,7 +81,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
    > .get_attention_status = get_attention_status,
    > .get_latch_status = get_latch_status,
    > .get_adapter_status = get_adapter_status,
    > - .get_address = get_address,
    > .get_max_bus_speed = get_max_bus_speed,
    > .get_cur_bus_speed = get_cur_bus_speed,
    > };
    > @@ -245,14 +243,18 @@ static int init_slots(struct controller *ctrl)
    > dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
    > "slot_device_offset=%x\n", slot->bus, slot->device,
    > slot->hp_slot, slot->number, ctrl->slot_device_offset);
    > - retval = pci_hp_register(hotplug_slot);
    > + retval = pci_hp_register(hotplug_slot,
    > + ctrl->pci_dev->subordinate,
    > + slot->device);
    > + if (retval == -EBUSY)
    > + goto error_info;
    > if (retval) {
    > err ("pci_hp_register failed with error %d\n", retval);
    > goto error_info;
    > }
    > /* create additional sysfs entries */
    > if (EMI(ctrl->ctrlcap)) {
    > - retval = sysfs_create_file(&hotplug_slot->kobj,
    > + retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
    > &hotplug_slot_attr_lock.attr);
    > if (retval) {
    > pci_hp_deregister(hotplug_slot);
    > @@ -285,7 +287,7 @@ static void cleanup_slots(struct controller *ctrl)
    > slot = list_entry(tmp, struct slot, slot_list);
    > list_del(&slot->slot_list);
    > if (EMI(ctrl->ctrlcap))
    > - sysfs_remove_file(&slot->hotplug_slot->kobj,
    > + sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
    > &hotplug_slot_attr_lock.attr);
    > cancel_delayed_work(&slot->work);
    > flush_scheduled_work();
    > @@ -387,18 +389,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
    > return 0;
    > }
    >
    > -static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
    > -{
    > - struct slot *slot = hotplug_slot->private;
    > - struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
    > -
    > - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
    > -
    > - *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
    > -
    > - return 0;
    > -}
    > -
    > static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
    > {
    > struct slot *slot = hotplug_slot->private;
    > @@ -460,7 +450,12 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
    > /* Setup the slot information structures */
    > rc = init_slots(ctrl);
    > if (rc) {
    > - err("%s: slot initialization failed\n", PCIE_MODULE_NAME);
    > + if (rc == -EBUSY)
    > + warn("%s: slot already registered by another "
    > + "hotplug driver\n", PCIE_MODULE_NAME);
    > + else
    > + err("%s: slot initialization failed\n",
    > + PCIE_MODULE_NAME);
    > goto err_out_release_ctlr;
    > }
    >
    > diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
    > index e32148a..399b196 100644
    > --- a/drivers/pci/hotplug/rpadlpar_sysfs.c
    > +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
    > @@ -14,8 +14,10 @@
    > */
    > #include <linux/kobject.h>
    > #include <linux/string.h>
    > +#include <linux/pci.h>
    > #include <linux/pci_hotplug.h>
    > #include "rpadlpar.h"
    > +#include "../pcih."
    >
    > #define DLPAR_KOBJ_NAME "control"
    > #define ADD_SLOT_ATTR_NAME "add_slot"
    > @@ -23,7 +25,6 @@
    >
    > #define MAX_DRC_NAME_LEN 64
    >
    > -
    > static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
    > const char *buf, size_t nbytes)
    > {
    > @@ -108,7 +109,7 @@ int dlpar_sysfs_init(void)
    > int error;
    >
    > dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME,
    > - &pci_hotplug_slots_kset->kobj);
    > + &pci_slots_kset->kobj);
    > if (!dlpar_kobj)
    > return -EINVAL;
    >
    > diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
    > index 8ad3deb..8e5fff0 100644
    > --- a/drivers/pci/hotplug/rpaphp_slot.c
    > +++ b/drivers/pci/hotplug/rpaphp_slot.c
    > @@ -162,7 +162,8 @@ int rpaphp_register_slot(struct slot *slot)
    > return -EAGAIN;
    > }
    >
    > - retval = pci_hp_register(php_slot);
    > + retval = pci_hp_register(php_slot, slot->bus,
    > + PCI_SLOT(PCI_DN(slot->dn->child)->devfn));
    > if (retval) {
    > err("pci_hp_register failed with error %d\n", retval);
    > return retval;
    > diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
    > index ef07c36..8908834 100644
    > --- a/drivers/pci/hotplug/sgi_hotplug.c
    > +++ b/drivers/pci/hotplug/sgi_hotplug.c
    > @@ -197,13 +197,15 @@ 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 pci_slot *pci_slot;
    > struct hotplug_slot *bss_hotplug_slot = NULL;
    >
    > list_for_each_entry(slot, &sn_hp_list, hp_list) {
    > bss_hotplug_slot = slot->hotplug_slot;
    > + pci_slot = bss_hotplug_slot->pci_slot;
    > list_del(&((struct slot *)bss_hotplug_slot->private)->
    > hp_list);
    > - sysfs_remove_file(&bss_hotplug_slot->kobj,
    > + sysfs_remove_file(&pci_slot->kobj,
    > &sn_slot_path_attr.attr);
    > break;
    > }
    > @@ -614,6 +616,7 @@ static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
    > static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
    > {
    > int device;
    > + struct pci_slot *pci_slot;
    > struct hotplug_slot *bss_hotplug_slot;
    > int rc = 0;
    >
    > @@ -650,11 +653,12 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
    > bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
    > bss_hotplug_slot->release = &sn_release_slot;
    >
    > - rc = pci_hp_register(bss_hotplug_slot);
    > + rc = pci_hp_register(bss_hotplug_slot, pci_bus, device);
    > if (rc)
    > goto register_err;
    >
    > - rc = sysfs_create_file(&bss_hotplug_slot->kobj,
    > + pci_slot = bss_hotplug_slot->pci_slot;
    > + rc = sysfs_create_file(&pci_slot->kobj,
    > &sn_slot_path_attr.attr);
    > if (rc)
    > goto register_err;
    > diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
    > index 80dec97..22c4d2e 100644
    > --- a/drivers/pci/hotplug/shpchp_core.c
    > +++ b/drivers/pci/hotplug/shpchp_core.c
    > @@ -65,7 +65,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
    > static int get_attention_status (struct hotplug_slot *slot, u8 *value);
    > static int get_latch_status (struct hotplug_slot *slot, u8 *value);
    > static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
    > -static int get_address (struct hotplug_slot *slot, u32 *value);
    > static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
    > static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
    >
    > @@ -78,7 +77,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
    > .get_attention_status = get_attention_status,
    > .get_latch_status = get_latch_status,
    > .get_adapter_status = get_adapter_status,
    > - .get_address = get_address,
    > .get_max_bus_speed = get_max_bus_speed,
    > .get_cur_bus_speed = get_cur_bus_speed,
    > };
    > @@ -152,7 +150,8 @@ static int init_slots(struct controller *ctrl)
    > dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
    > "slot_device_offset=%x\n", slot->bus, slot->device,
    > slot->hp_slot, slot->number, ctrl->slot_device_offset);
    > - retval = pci_hp_register(slot->hotplug_slot);
    > + retval = pci_hp_register(slot->hotplug_slot,
    > + ctrl->pci_dev->subordinate, slot->device);
    > if (retval) {
    > err("pci_hp_register failed with error %d\n", retval);
    > goto error_info;
    > @@ -277,18 +276,6 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
    > return 0;
    > }
    >
    > -static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
    > -{
    > - struct slot *slot = get_slot(hotplug_slot);
    > - struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
    > -
    > - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
    > -
    > - *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
    > -
    > - return 0;
    > -}
    > -
    > static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
    > {
    > struct slot *slot = get_slot(hotplug_slot);
    > diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
    > index eabeb1f..61bb743 100644
    > --- a/drivers/pci/pci.h
    > +++ b/drivers/pci/pci.h
    > @@ -87,3 +87,16 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
    > }
    >
    > struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
    > +
    > +/* PCI slot sysfs helper code */
    > +#define to_pci_slot(s) container_of(s, struct pci_slot, kobj)
    > +
    > +extern struct kset *pci_slots_kset;
    > +
    > +struct pci_slot_attribute {
    > + struct attribute attr;
    > + ssize_t (*show)(struct pci_slot *, char *);
    > + ssize_t (*store)(struct pci_slot *, const char *, size_t);
    > +};
    > +#define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr)
    > +
    > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
    > index 2db2e4b..3ee2c8a 100644
    > --- a/drivers/pci/probe.c
    > +++ b/drivers/pci/probe.c
    > @@ -384,6 +384,7 @@ static struct pci_bus * pci_alloc_bus(void)
    > INIT_LIST_HEAD(&b->node);
    > INIT_LIST_HEAD(&b->children);
    > INIT_LIST_HEAD(&b->devices);
    > + INIT_LIST_HEAD(&b->slots);
    > }
    > return b;
    > }
    > diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
    > new file mode 100644
    > index 0000000..86fc8d9
    > --- /dev/null
    > +++ b/drivers/pci/slot.c
    > @@ -0,0 +1,147 @@
    > +/*
    > + * drivers/pci/slot.c
    > + * Copyright (C) 2006 Matthew Wilcox <matthew@wil.cx>
    > + * Copyright (C) 2006,2007 Hewlett-Packard Development Company, L.P.
    > + * Copyright (C) 2007 Alex Chiang <achiang@hp.com>
    > + */
    > +
    > +#include <linux/kobject.h>
    > +#include <linux/pci.h>
    > +#include "pci.h"
    > +
    > +struct kset *pci_slots_kset;
    > +EXPORT_SYMBOL_GPL(pci_slots_kset);
    > +
    > +static ssize_t pci_slot_attr_show(struct kobject *kobj,
    > + struct attribute *attr, char *buf)
    > +{
    > + struct pci_slot *slot = to_pci_slot(kobj);
    > + struct pci_slot_attribute *attribute = to_pci_slot_attr(attr);
    > + return attribute->show ? attribute->show(slot, buf) : -EIO;
    > +}
    > +
    > +static ssize_t pci_slot_attr_store(struct kobject *kobj,
    > + struct attribute *attr, const char *buf, size_t len)
    > +{
    > + struct pci_slot *slot = to_pci_slot(kobj);
    > + struct pci_slot_attribute *attribute = to_pci_slot_attr(attr);
    > + return attribute->store ? attribute->store(slot, buf, len) : -EIO;
    > +}
    > +
    > +static struct sysfs_ops pci_slot_sysfs_ops = {
    > + .show = pci_slot_attr_show,
    > + .store = pci_slot_attr_store,
    > +};
    > +
    > +static ssize_t address_read_file(struct pci_slot *slot, char *buf)
    > +{
    > + return sprintf(buf, "%04x:%02x:%02x\n", pci_domain_nr(slot->bus),
    > + slot->bus->number, slot->number);
    > +}
    > +
    > +static void pci_slot_release(struct kobject *kobj)
    > +{
    > + struct pci_slot *slot = to_pci_slot(kobj);
    > +
    > + pr_debug("%s: releasing pci_slot on %x:%d\n", __func__,
    > + slot->bus->number, slot->number);
    > +
    > + list_del(&slot->list);
    > +
    > + kfree(slot);
    > +}
    > +
    > +static struct pci_slot_attribute pci_slot_attr_address =
    > + __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL);
    > +
    > +static struct attribute *pci_slot_default_attrs[] = {
    > + &pci_slot_attr_address.attr,
    > + NULL,
    > +};
    > +
    > +static struct kobj_type pci_slot_ktype = {
    > + .sysfs_ops = &pci_slot_sysfs_ops,
    > + .release = &pci_slot_release,
    > + .default_attrs = pci_slot_default_attrs,
    > +};
    > +
    > +struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
    > + const char *name)
    > +{
    > + struct pci_slot *slot;
    > + int err;
    > +
    > + down_write(&pci_bus_sem);
    > +
    > + /* If we've already created this slot, bump refcount and return. */
    > + list_for_each_entry(slot, &parent->slots, list) {
    > + if (slot->number == slot_nr) {
    > + kobject_get(&slot->kobj);
    > + pr_debug("%s: bumped refcount to %d on %x:%d\n",
    > + __func__,
    > + atomic_read(&slot->kobj.kref.refcount),
    > + parent->number, slot_nr);
    > + goto out;
    > + }
    > + }
    > +
    > + slot = kzalloc(sizeof(*slot), GFP_KERNEL);
    > + if (!slot) {
    > + slot = ERR_PTR(-ENOMEM);
    > + goto out;
    > + }
    > +
    > + slot->bus = parent;
    > + slot->number = slot_nr;
    > +
    > + slot->kobj.kset = pci_slots_kset;
    > + err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
    > + "%s", name);
    > + if (err) {
    > + printk(KERN_ERR "Unable to register kobject %s\n", name);
    > + goto err;
    > + }
    > +
    > + INIT_LIST_HEAD(&slot->list);
    > + list_add(&slot->list, &parent->slots);
    > +
    > + pr_debug("%s: created pci_slot on %x:%d\n",
    > + __func__, parent->number, slot_nr);
    > +
    > + out:
    > + up_write(&pci_bus_sem);
    > + return slot;
    > + err:
    > + kfree(slot);
    > + slot = ERR_PTR(err);
    > + goto out;
    > +}
    > +EXPORT_SYMBOL_GPL(pci_create_slot);
    > +
    > +void pci_destroy_slot(struct pci_slot *slot)
    > +{
    > + pr_debug("%s: decreased refcount to %d on %x:%d\n", __func__,
    > + atomic_read(&slot->kobj.kref.refcount) - 1, slot->bus->number,
    > + slot->number);
    > +
    > + down_write(&pci_bus_sem);
    > + kobject_put(&slot->kobj);
    > + up_write(&pci_bus_sem);
    > +}
    > +EXPORT_SYMBOL_GPL(pci_destroy_slot);
    > +
    > +static int pci_slot_init(void)
    > +{
    > + struct kset *pci_bus_kset;
    > +
    > + pci_bus_kset = bus_get_kset(&pci_bus_type);
    > + pci_slots_kset = kset_create_and_add("slots", NULL,
    > + &pci_bus_kset->kobj);
    > + if (!pci_slots_kset) {
    > + printk(KERN_ERR "PCI: Slot initialization failure\n");
    > + return -ENOMEM;
    > + }
    > + return 0;
    > +}
    > +
    > +subsys_initcall(pci_slot_init);
    > diff --git a/include/linux/pci.h b/include/linux/pci.h
    > index b7e4b63..69c0862 100644
    > --- a/include/linux/pci.h
    > +++ b/include/linux/pci.h
    > @@ -128,6 +128,15 @@ struct pci_cap_saved_state {
    > u32 data[0];
    > };
    >
    > +/* pci_slot represents a physical slot */
    > +struct pci_slot {
    > + struct pci_bus *bus; /* The bus this slot is on */
    > + struct list_head list; /* node in list of slots on this bus */
    > + struct hotplug_slot *hotplug; /* Hotplug info (migrate over time) */
    > + unsigned char number; /* PCI_SLOT(pci_dev->devfn) */
    > + struct kobject kobj;
    > +};
    > +
    > /*
    > * The pci_dev structure is used to describe PCI devices.
    > */
    > @@ -139,6 +148,7 @@ struct pci_dev {
    >
    > void *sysdata; /* hook for sys-specific extension */
    > struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
    > + struct pci_slot *slot; /* Physical slot this device is in */
    >
    > unsigned int devfn; /* encoded device & function index */
    > unsigned short vendor;
    > @@ -258,6 +268,7 @@ struct pci_bus {
    > struct list_head children; /* list of child buses */
    > struct list_head devices; /* list of devices on this bus */
    > struct pci_dev *self; /* bridge device as seen by parent */
    > + struct list_head slots; /* list of slots on this bus */
    > struct resource *resource[PCI_BUS_NUM_RESOURCES];
    > /* address space routed to this bus */
    >
    > @@ -481,6 +492,9 @@ struct pci_bus *pci_create_bus(struct device *parent, int bus,
    > struct pci_ops *ops, void *sysdata);
    > struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
    > int busnr);
    > +struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
    > + const char *name);
    > +void pci_destroy_slot(struct pci_slot *slot);
    > int pci_scan_slot(struct pci_bus *bus, int devfn);
    > struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn);
    > void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
    > diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
    > index 8f67e8f..bb36c59 100644
    > --- a/include/linux/pci_hotplug.h
    > +++ b/include/linux/pci_hotplug.h
    > @@ -95,9 +95,6 @@ struct hotplug_slot_attribute {
    > * @get_adapter_status: Called to get see if an adapter is present in the slot or not.
    > * If this field is NULL, the value passed in the struct hotplug_slot_info
    > * will be used when this value is requested by a user.
    > - * @get_address: Called to get pci address of a slot.
    > - * If this field is NULL, the value passed in the struct hotplug_slot_info
    > - * will be used when this value is requested by a user.
    > * @get_max_bus_speed: Called to get the max bus speed for a slot.
    > * If this field is NULL, the value passed in the struct hotplug_slot_info
    > * will be used when this value is requested by a user.
    > @@ -120,7 +117,6 @@ struct hotplug_slot_ops {
    > int (*get_attention_status) (struct hotplug_slot *slot, u8 *value);
    > int (*get_latch_status) (struct hotplug_slot *slot, u8 *value);
    > int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value);
    > - int (*get_address) (struct hotplug_slot *slot, u32 *value);
    > int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value);
    > int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value);
    > };
    > @@ -140,7 +136,6 @@ struct hotplug_slot_info {
    > u8 attention_status;
    > u8 latch_status;
    > u8 adapter_status;
    > - u32 address;
    > enum pci_bus_speed max_bus_speed;
    > enum pci_bus_speed cur_bus_speed;
    > };
    > @@ -166,15 +161,14 @@ struct hotplug_slot {
    >
    > /* Variables below this are for use only by the hotplug pci core. */
    > struct list_head slot_list;
    > - struct kobject kobj;
    > + struct pci_slot *pci_slot;
    > };
    > #define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj)
    >
    > -extern int pci_hp_register (struct hotplug_slot *slot);
    > -extern int pci_hp_deregister (struct hotplug_slot *slot);
    > +extern int pci_hp_register(struct hotplug_slot *, struct pci_bus *, int nr);
    > +extern int pci_hp_deregister(struct hotplug_slot *slot);
    > extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot,
    > struct hotplug_slot_info *info);
    > -extern struct kset *pci_hotplug_slots_kset;
    >
    > /* PCI Setting Record (Type 0) */
    > struct hpp_type0 {




    \
     
     \ /
      Last update: 2008-03-25 05:53    [W:0.143 / U:3.764 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site