lkml.org 
[lkml]   [2007]   [Feb]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 2.6.21-rc1] ibmebus: Support dynamic addition and removal of adapters
    Date
    This patch will add two sysfs attributes to /sys/bus/ibmebus which can be used
    to notify the ebus driver of added / removed ebus devices in the OF device
    tree.

    Echoing the device's location code (as found in the OFDT "ibm,loc-code"
    property) into the "probe" attribute will notify ebus of addition of the device
    and cause the appropriate device driver's probe function to be called on the
    device.

    Likewise, echoing the location code into the "remove" attribute will cause
    the device to be removed from the system.

    Additionally, the uevent interface is now implemented in the driver.


    Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
    ---


    arch/powerpc/kernel/ibmebus.c | 121 +++++++++++++++++++++++++++++++++++++++---
    include/asm-powerpc/ibmebus.h | 2
    2 files changed, 114 insertions(+), 9 deletions(-)


    diff -wurp linux-2.6.20/arch/powerpc/kernel/ibmebus.c linux-2.6.20-ebus/arch/powerpc/kernel/ibmebus.c
    --- linux-2.6.20/arch/powerpc/kernel/ibmebus.c 2007-02-04 19:44:54.000000000 +0100
    +++ linux-2.6.20-ebus/arch/powerpc/kernel/ibmebus.c 2007-02-14 17:58:00.000000000 +0100
    @@ -2,6 +2,7 @@
    * IBM PowerPC IBM eBus Infrastructure Support.
    *
    * Copyright (c) 2005 IBM Corporation
    + * Joachim Fenkes <fenkes@de.ibm.com>
    * Heiko J Schick <schickhj@de.ibm.com>
    *
    * All rights reserved.
    @@ -44,7 +45,6 @@
    #include <asm/abs_addr.h>

    static struct ibmebus_dev ibmebus_bus_device = { /* fake "parent" device */
    - .name = ibmebus_bus_device.ofdev.dev.bus_id,
    .ofdev.dev.bus_id = "ibmebus",
    .ofdev.dev.bus = &ibmebus_bus_type,
    };
    @@ -161,7 +161,9 @@ static void __devinit ibmebus_dev_releas
    static ssize_t ibmebusdev_show_name(struct device *dev,
    struct device_attribute *attr, char *buf)
    {
    - return sprintf(buf, "%s\n", to_ibmebus_dev(dev)->name);
    + struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
    + char *name = (char*)get_property(ebus_dev->ofdev.node, "name", NULL);
    + return sprintf(buf, "%s\n", name);
    }
    static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name,
    NULL);
    @@ -171,7 +173,6 @@ static struct ibmebus_dev* __devinit ibm
    {
    int err = 0;

    - dev->name = name;
    dev->ofdev.dev.parent = &ibmebus_bus_device.ofdev.dev;
    dev->ofdev.dev.bus = &ibmebus_bus_type;
    dev->ofdev.dev.release = ibmebus_dev_release;
    @@ -262,11 +263,19 @@ static void ibmebus_add_devices_by_id(st
    return;
    }

    -static int ibmebus_match_helper(struct device *dev, void *data)
    +static int ibmebus_match_helper_name(struct device *dev, void *data)
    {
    - if (strcmp((char*)data, to_ibmebus_dev(dev)->name) == 0)
    - return 1;
    + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
    + char *name;

    + /* parent device has no of_device node, so skip it */
    + if (ebus_dev != &ibmebus_bus_device) {
    + name = (char*)get_property(
    + ebus_dev->ofdev.node, "name", NULL);
    +
    + if (name && (strcmp((char*)data, name) == 0))
    + return 1;
    + }
    return 0;
    }

    @@ -285,11 +294,10 @@ static void ibmebus_remove_devices_by_id
    while (strlen(idt->name) > 0) {
    while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
    (void*)idt->name,
    - ibmebus_match_helper))) {
    + ibmebus_match_helper_name))) {
    ibmebus_unregister_device(dev);
    }
    idt++;
    -
    }

    return;
    @@ -307,6 +315,9 @@ int ibmebus_register_driver(struct ibmeb
    if ((err = driver_register(&drv->driver) != 0))
    return err;

    + /* remove all supported devices first, in case someone
    + * probed them manually before registering the driver */
    + ibmebus_remove_devices_by_id(drv->id_table);
    ibmebus_add_devices_by_id(drv->id_table);

    return 0;
    @@ -361,12 +372,101 @@ static int ibmebus_bus_match(struct devi
    return 0;
    }

    +static int ibmebus_uevent(struct device *dev, char **envp, int num_envp,
    + char *buffer, int buffer_size)
    +{
    + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
    + char *name, *cp, *loc_code;
    + int length;
    +
    + if (!num_envp)
    + return -ENOMEM;
    +
    + if (!ebus_dev->ofdev.node)
    + return -ENODEV;
    +
    + name = (char *)get_property(ebus_dev->ofdev.node, "name", NULL);
    + cp = (char *)get_property(ebus_dev->ofdev.node, "compatible", NULL);
    + loc_code = (char *)get_property(ebus_dev->ofdev.node,
    + "ibm,loc-code", NULL);
    + if (!(name && cp && loc_code))
    + return -ENODEV;
    +
    + envp[0] = buffer;
    + length = scnprintf(buffer, buffer_size,
    + "MODALIAS=ibmebus:T%s:S%s:L%s",
    + name, cp, loc_code);
    + if (buffer_size - length <= 0)
    + return -ENOMEM;
    + envp[1] = NULL;
    +
    + return 0;
    +}
    +
    struct bus_type ibmebus_bus_type = {
    .name = "ibmebus",
    + .uevent = ibmebus_uevent,
    .match = ibmebus_bus_match,
    };
    EXPORT_SYMBOL(ibmebus_bus_type);

    +static int ibmebus_match_helper_loc_code(struct device *dev, void *data)
    +{
    + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
    + char *loc_code;
    +
    + /* parent device has no of_device node, so skip it */
    + if (ebus_dev != &ibmebus_bus_device) {
    + loc_code = (char*)get_property(
    + ebus_dev->ofdev.node, "ibm,loc-code", NULL);
    +
    + if (loc_code && (strcmp((char*)data, loc_code) == 0))
    + return 1;
    + }
    + return 0;
    +}
    +
    +static ssize_t ibmebus_store_probe(struct bus_type *dev,
    + const char *buf, size_t count)
    +{
    + struct device_node *dn = NULL;
    + char *loc_code;
    +
    + if (bus_find_device(&ibmebus_bus_type, NULL, (char*)buf,
    + ibmebus_match_helper_loc_code)) {
    + printk(KERN_WARNING "%s: loc_code %s has already been probed\n",
    + __FUNCTION__, buf);
    + return count;
    + }
    +
    + while ((dn = of_find_all_nodes(dn))) {
    + loc_code = (char *)get_property(dn, "ibm,loc-code", NULL);
    + if (loc_code && (strncmp(loc_code, buf, count) == 0)) {
    + if (ibmebus_register_device_node(dn) == NULL) {
    + of_node_put(dn);
    + break;
    + }
    + }
    + }
    +
    + return count;
    +}
    +static BUS_ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe);
    +
    +static ssize_t ibmebus_store_remove(struct bus_type *bus,
    + const char *buf, size_t count)
    +{
    + struct device *dev;
    +
    + while ((dev = bus_find_device(&ibmebus_bus_type, NULL, (char*)buf,
    + ibmebus_match_helper_loc_code))) {
    + ibmebus_unregister_device(dev);
    + }
    +
    + return count;
    +}
    +static BUS_ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove);
    +
    static int __init ibmebus_bus_init(void)
    {
    int err;
    @@ -389,6 +489,9 @@ static int __init ibmebus_bus_init(void)
    return err;
    }

    + bus_create_file(&ibmebus_bus_type, &bus_attr_probe);
    + bus_create_file(&ibmebus_bus_type, &bus_attr_remove);
    +
    return 0;
    }
    __initcall(ibmebus_bus_init);
    diff -wurp linux-2.6.20/include/asm-powerpc/ibmebus.h linux-2.6.20-ebus/include/asm-powerpc/ibmebus.h
    --- linux-2.6.20/include/asm-powerpc/ibmebus.h 2007-02-04 19:44:54.000000000 +0100
    +++ linux-2.6.20-ebus/include/asm-powerpc/ibmebus.h 2007-02-14 17:58:55.000000000 +0100
    @@ -2,6 +2,7 @@
    * IBM PowerPC eBus Infrastructure Support.
    *
    * Copyright (c) 2005 IBM Corporation
    + * Joachim Fenkes <fenkes@de.ibm.com>
    * Heiko J Schick <schickhj@de.ibm.com>
    *
    * All rights reserved.
    @@ -47,7 +48,6 @@
    extern struct bus_type ibmebus_bus_type;

    struct ibmebus_dev {
    - const char *name;
    struct of_device ofdev;
    };

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-02-15 17:55    [W:0.030 / U:0.308 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site