lkml.org 
[lkml]   [2007]   [Sep]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3/5] ibmebus: Add device creation and bus probing based on of_device
    Date
    The devtree root is now searched for devices matching a built-in whitelist
    during boot, so these devices appear on the bus from the beginning. It is
    still possible to manually add/remove devices to/from the bus by using the
    probe/remove sysfs interface. Also, when a device driver registers itself,
    the devtree is matched against its matchlist.

    Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
    ---
    arch/powerpc/kernel/ibmebus.c | 100 +++++++++++++++++++++++++++++++++-------
    1 files changed, 82 insertions(+), 18 deletions(-)

    diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
    index cc80f84..43d4764 100644
    --- a/arch/powerpc/kernel/ibmebus.c
    +++ b/arch/powerpc/kernel/ibmebus.c
    @@ -51,6 +51,13 @@ static struct device ibmebus_bus_device = { /* fake "parent" device */

    struct bus_type ibmebus_bus_type;

    +/* These devices will automatically be added to the bus during init */
    +static struct of_device_id builtin_matches[] = {
    + { .compatible = "IBM,lhca" },
    + { .compatible = "IBM,lhea" },
    + {},
    +};
    +
    static void *ibmebus_alloc_coherent(struct device *dev,
    size_t size,
    dma_addr_t *dma_handle,
    @@ -124,6 +131,67 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
    .dma_supported = ibmebus_dma_supported,
    };

    +static int ibmebus_match_path(struct device *dev, void *data)
    +{
    + struct device_node *dn = to_of_device(dev)->node;
    + return (dn->full_name &&
    + (strcasecmp((char *)data, dn->full_name) == 0));
    +}
    +
    +static int ibmebus_match_node(struct device *dev, void *data)
    +{
    + return to_of_device(dev)->node == data;
    +}
    +
    +static int ibmebus_create_device(struct device_node *dn)
    +{
    + struct of_device *dev;
    + int ret;
    +
    + dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
    + if (!dev)
    + return -ENOMEM;
    +
    + dev->dev.bus = &ibmebus_bus_type;
    + dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
    +
    + ret = of_device_register(dev);
    + if (ret) {
    + of_device_free(dev);
    + return ret;
    + }
    +
    + return 0;
    +}
    +
    +static int ibmebus_create_devices(const struct of_device_id *matches)
    +{
    + struct device_node *root, *child;
    + int ret = 0;
    +
    + root = of_find_node_by_path("/");
    +
    + for (child = NULL; (child = of_get_next_child(root, child)); ) {
    + if (!of_match_node(matches, child))
    + continue;
    +
    + if (bus_find_device(&ibmebus_bus_type, NULL, child,
    + ibmebus_match_node))
    + continue;
    +
    + ret = ibmebus_create_device(child);
    + if (ret) {
    + printk(KERN_ERR "%s: failed to create device (%i)",
    + __FUNCTION__, ret);
    + of_node_put(child);
    + break;
    + }
    + }
    +
    + of_node_put(root);
    + return ret;
    +}
    +
    int ibmebus_register_driver(struct ibmebus_driver *drv)
    {
    return 0;
    @@ -172,18 +240,6 @@ static struct device_attribute ibmebus_dev_attrs[] = {
    __ATTR_NULL
    };

    -static int ibmebus_match_path(struct device *dev, void *data)
    -{
    - int rc;
    - struct device_node *dn =
    - of_node_get(to_ibmebus_dev(dev)->ofdev.node);
    -
    - rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0));
    -
    - of_node_put(dn);
    - return rc;
    -}
    -
    static char *ibmebus_chomp(const char *in, size_t count)
    {
    char *out = (char*)kmalloc(count + 1, GFP_KERNEL);
    @@ -202,9 +258,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
    const char *buf, size_t count)
    {
    struct device_node *dn = NULL;
    - struct ibmebus_dev *dev;
    char *path;
    - ssize_t rc;
    + ssize_t rc = 0;

    path = ibmebus_chomp(buf, count);
    if (!path)
    @@ -219,9 +274,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
    }

    if ((dn = of_find_node_by_path(path))) {
    -/* dev = ibmebus_register_device_node(dn); */
    + rc = ibmebus_create_device(dn);
    of_node_put(dn);
    - rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
    } else {
    printk(KERN_WARNING "%s: no such device node: %s\n",
    __FUNCTION__, path);
    @@ -230,7 +284,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,

    out:
    kfree(path);
    - return rc;
    + if (rc)
    + return rc;
    + return count;
    }

    static ssize_t ibmebus_store_remove(struct bus_type *bus,
    @@ -245,7 +301,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,

    if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
    ibmebus_match_path))) {
    -/* ibmebus_unregister_device(dev); */
    + of_device_unregister(to_of_device(dev));

    kfree(path);
    return count;
    @@ -265,6 +321,7 @@ static struct bus_attribute ibmebus_bus_attrs[] = {
    };

    struct bus_type ibmebus_bus_type = {
    + .uevent = of_device_uevent,
    .dev_attrs = ibmebus_dev_attrs,
    .bus_attrs = ibmebus_bus_attrs
    };
    @@ -292,6 +349,13 @@ static int __init ibmebus_bus_init(void)
    return err;
    }

    + err = ibmebus_create_devices(builtin_matches);
    + if (err) {
    + device_unregister(&ibmebus_bus_device);
    + bus_unregister(&ibmebus_bus_type);
    + return err;
    + }
    +
    return 0;
    }
    postcore_initcall(ibmebus_bus_init);
    --
    1.5.2

    -
    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-09-26 11:55    [W:0.027 / U:66.000 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site