This adds a new sysfs root device to serve as a replacement for devices which are available only when a gadget is being bound. It is motivated by adding configfs support to USB Ethernet functions. When configfs is there, we would like to be able to mkdir some function directory, e.g.: $ mkdir functions/ecm.usb0 and have the usb0 available in the system (albeit in an unconfigured, or default state) at this very point, which is _way_ before the gadget is actually bound. However, this poses a chicken and egg problem. In order for the interface to appear in the system, it needs to be registered with register_netdev. But in order to register it, its parent device must be known and it becomes known only later during gadget's bind. This patch adds a /sys/devices/usb_gadget root device, which is registered during module_init of libcomposite, so it is available at any time for all libcomposite users and is used as a parent device for USB Ethernet devices instead of the gadget->dev. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- drivers/usb/gadget/configfs.c | 15 +++++++++++++++ drivers/usb/gadget/configfs.h | 18 ++++++++++++++++++ drivers/usb/gadget/u_ether.c | 17 +++++++++++------ 3 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/gadget/configfs.h diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index a34633a..9e24c0b 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -985,6 +985,9 @@ static struct configfs_subsystem gadget_subsys = { .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex), }; +struct device *gadget_sysfs_root; +EXPORT_SYMBOL(gadget_sysfs_root); + static int __init gadget_cfs_init(void) { int ret; @@ -992,12 +995,24 @@ static int __init gadget_cfs_init(void) config_group_init(&gadget_subsys.su_group); ret = configfs_register_subsystem(&gadget_subsys); + if (ret) + return ret; + + gadget_sysfs_root = root_device_register( + gadget_subsys.su_group.cg_item.ci_namebuf); + + if (IS_ERR_OR_NULL(gadget_sysfs_root)) { + ret = PTR_ERR(gadget_sysfs_root); + configfs_unregister_subsystem(&gadget_subsys); + } + return ret; } module_init(gadget_cfs_init); static void __exit gadget_cfs_exit(void) { + root_device_unregister(gadget_sysfs_root); configfs_unregister_subsystem(&gadget_subsys); } module_exit(gadget_cfs_exit); diff --git a/drivers/usb/gadget/configfs.h b/drivers/usb/gadget/configfs.h new file mode 100644 index 0000000..58362a6 --- /dev/null +++ b/drivers/usb/gadget/configfs.h @@ -0,0 +1,18 @@ +/* linux/drivers/usb/gadget/configfs.h + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef USB_GADGET_CONFIGFS_H +#define USB_GADGET_CONFIGFS_H + +extern struct device *gadget_sysfs_root; + +#endif /* USB_GADGET_CONFIGFS_H */ diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 5f9dacf..de9d84f 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -23,6 +23,7 @@ #include <linux/if_vlan.h> #include "u_ether.h" +#include "configfs.h" /* @@ -56,6 +57,7 @@ struct eth_dev { struct net_device *net; struct usb_gadget *gadget; + struct device *parent_dev; spinlock_t req_lock; /* guard {rx,tx}_reqs */ struct list_head tx_reqs, rx_reqs; @@ -160,8 +162,9 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) strlcpy(p->driver, "g_ether", sizeof(p->driver)); strlcpy(p->version, UETH__VERSION, sizeof(p->version)); - strlcpy(p->fw_version, dev->gadget->name, sizeof(p->fw_version)); - strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof(p->bus_info)); + strlcpy(p->fw_version, dev_name(dev->parent_dev), + sizeof(p->fw_version)); + strlcpy(p->bus_info, dev_name(dev->parent_dev), sizeof(p->bus_info)); } /* REVISIT can also support: @@ -768,12 +771,13 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, dev->net = net; dev->qmult = qmult; snprintf(net->name, sizeof(net->name), "%s%%d", netname); + dev->parent_dev = gadget_sysfs_root; if (get_ether_addr(dev_addr, net->dev_addr)) - dev_warn(&g->dev, + dev_warn(dev->parent_dev, "using random %s ethernet address\n", "self"); if (get_ether_addr(host_addr, dev->host_mac)) - dev_warn(&g->dev, + dev_warn(dev->parent_dev, "using random %s ethernet address\n", "host"); if (ethaddr) @@ -784,12 +788,13 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, SET_ETHTOOL_OPS(net, &ops); dev->gadget = g; - SET_NETDEV_DEV(net, &g->dev); + SET_NETDEV_DEV(net, dev->parent_dev); SET_NETDEV_DEVTYPE(net, &gadget_type); status = register_netdev(net); if (status < 0) { - dev_dbg(&g->dev, "register_netdev failed, %d\n", status); + dev_dbg(dev->parent_dev, "register_netdev failed, %d\n", + status); free_netdev(net); dev = ERR_PTR(status); } else { -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html