[PATCH 3/9] usb/gadget: change sysfs parent device for USB Ethernet

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux