aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>2013-05-28 03:15:56 -0400
committerFelipe Balbi <balbi@ti.com>2013-06-10 10:58:08 -0400
commit02832e56f88a981474ee4c7c141f46fc1b4454f4 (patch)
tree9d69ab395696bb866ec54f17f2ecc4c67dbda84d
parent74bf963d1d230b0cedbcbc46f6f15f20c2e3ee55 (diff)
usb: gadget: f_subset: add configfs support
f_subset learns about configfs so we can, eventually, remove in-kernel gadget drivers. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-subset14
-rw-r--r--drivers/usb/gadget/Kconfig10
-rw-r--r--drivers/usb/gadget/f_subset.c46
-rw-r--r--drivers/usb/gadget/u_gether.h9
4 files changed, 78 insertions, 1 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-subset b/Documentation/ABI/testing/configfs-usb-gadget-subset
new file mode 100644
index 000000000000..f47170a2f7dc
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-usb-gadget-subset
@@ -0,0 +1,14 @@
1What: /config/usb-gadget/gadget/functions/geth.name
2Date: May 2013
3KenelVersion: 3.11
4Description:
5 The attributes:
6
7 ifname - network device interface name associated with
8 this function instance
9 qmult - queue length multiplier for high and
10 super speed
11 host_addr - MAC address of host's end of this
12 Ethernet over USB link
13 dev_addr - MAC address of device's end of this
14 Ethernet over USB link
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 0a444f39109f..3a72b9dbf7f0 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -547,6 +547,16 @@ choice
547 547
548# this first set of drivers all depend on bulk-capable hardware. 548# this first set of drivers all depend on bulk-capable hardware.
549 549
550config USB_CONFIGFS_ECM_SUBSET
551 boolean "Ethernet Control Model (CDC ECM) subset"
552 depends on USB_CONFIGFS
553 depends on NET
554 select USB_U_ETHER
555 select USB_F_SUBSET
556 help
557 On hardware that can't implement the full protocol,
558 a simple CDC subset is used, placing fewer demands on USB.
559
550config USB_CONFIGFS_EEM 560config USB_CONFIGFS_EEM
551 bool "Ethernet Emulation Model (EEM)" 561 bool "Ethernet Emulation Model (EEM)"
552 depends on USB_CONFIGFS 562 depends on USB_CONFIGFS
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index 089881a530d5..fbc7a24942e4 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -17,6 +17,7 @@
17#include <linux/etherdevice.h> 17#include <linux/etherdevice.h>
18 18
19#include "u_ether.h" 19#include "u_ether.h"
20#include "u_ether_configfs.h"
20#include "u_gether.h" 21#include "u_gether.h"
21 22
22/* 23/*
@@ -313,8 +314,10 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
313 * with regard to gether_opts->bound access 314 * with regard to gether_opts->bound access
314 */ 315 */
315 if (!gether_opts->bound) { 316 if (!gether_opts->bound) {
317 mutex_lock(&gether_opts->lock);
316 gether_set_gadget(gether_opts->net, cdev->gadget); 318 gether_set_gadget(gether_opts->net, cdev->gadget);
317 status = gether_register_netdev(gether_opts->net); 319 status = gether_register_netdev(gether_opts->net);
320 mutex_unlock(&gether_opts->lock);
318 if (status) 321 if (status)
319 return status; 322 return status;
320 gether_opts->bound = true; 323 gether_opts->bound = true;
@@ -445,6 +448,41 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
445 448
446#else 449#else
447 450
451static inline struct f_gether_opts *to_f_gether_opts(struct config_item *item)
452{
453 return container_of(to_config_group(item), struct f_gether_opts,
454 func_inst.group);
455}
456
457/* f_gether_item_ops */
458USB_ETHERNET_CONFIGFS_ITEM(gether);
459
460/* f_gether_opts_dev_addr */
461USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(gether);
462
463/* f_gether_opts_host_addr */
464USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(gether);
465
466/* f_gether_opts_qmult */
467USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(gether);
468
469/* f_gether_opts_ifname */
470USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(gether);
471
472static struct configfs_attribute *gether_attrs[] = {
473 &f_gether_opts_dev_addr.attr,
474 &f_gether_opts_host_addr.attr,
475 &f_gether_opts_qmult.attr,
476 &f_gether_opts_ifname.attr,
477 NULL,
478};
479
480static struct config_item_type gether_func_type = {
481 .ct_item_ops = &gether_item_ops,
482 .ct_attrs = gether_attrs,
483 .ct_owner = THIS_MODULE,
484};
485
448static void geth_free_inst(struct usb_function_instance *f) 486static void geth_free_inst(struct usb_function_instance *f)
449{ 487{
450 struct f_gether_opts *opts; 488 struct f_gether_opts *opts;
@@ -464,12 +502,15 @@ static struct usb_function_instance *geth_alloc_inst(void)
464 opts = kzalloc(sizeof(*opts), GFP_KERNEL); 502 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
465 if (!opts) 503 if (!opts)
466 return ERR_PTR(-ENOMEM); 504 return ERR_PTR(-ENOMEM);
467 505 mutex_init(&opts->lock);
468 opts->func_inst.free_func_inst = geth_free_inst; 506 opts->func_inst.free_func_inst = geth_free_inst;
469 opts->net = gether_setup_default(); 507 opts->net = gether_setup_default();
470 if (IS_ERR(opts->net)) 508 if (IS_ERR(opts->net))
471 return ERR_CAST(opts->net); 509 return ERR_CAST(opts->net);
472 510
511 config_group_init_type_name(&opts->func_inst.group, "",
512 &gether_func_type);
513
473 return &opts->func_inst; 514 return &opts->func_inst;
474} 515}
475 516
@@ -500,6 +541,8 @@ static struct usb_function *geth_alloc(struct usb_function_instance *fi)
500 541
501 opts = container_of(fi, struct f_gether_opts, func_inst); 542 opts = container_of(fi, struct f_gether_opts, func_inst);
502 543
544 mutex_lock(&opts->lock);
545 opts->refcnt++;
503 /* export host's Ethernet address in CDC format */ 546 /* export host's Ethernet address in CDC format */
504 status = gether_get_host_addr_cdc(opts->net, geth->ethaddr, 547 status = gether_get_host_addr_cdc(opts->net, geth->ethaddr,
505 sizeof(geth->ethaddr)); 548 sizeof(geth->ethaddr));
@@ -510,6 +553,7 @@ static struct usb_function *geth_alloc(struct usb_function_instance *fi)
510 geth_string_defs[1].s = geth->ethaddr; 553 geth_string_defs[1].s = geth->ethaddr;
511 554
512 geth->port.ioport = netdev_priv(opts->net); 555 geth->port.ioport = netdev_priv(opts->net);
556 mutex_unlock(&opts->lock);
513 geth->port.cdc_filter = DEFAULT_FILTER; 557 geth->port.cdc_filter = DEFAULT_FILTER;
514 558
515 geth->port.func.name = "cdc_subset"; 559 geth->port.func.name = "cdc_subset";
diff --git a/drivers/usb/gadget/u_gether.h b/drivers/usb/gadget/u_gether.h
index 3a4a2bf61cdc..d4078426ba5d 100644
--- a/drivers/usb/gadget/u_gether.h
+++ b/drivers/usb/gadget/u_gether.h
@@ -22,6 +22,15 @@ struct f_gether_opts {
22 struct usb_function_instance func_inst; 22 struct usb_function_instance func_inst;
23 struct net_device *net; 23 struct net_device *net;
24 bool bound; 24 bool bound;
25
26 /*
27 * Read/write access to configfs attributes is handled by configfs.
28 *
29 * This is to protect the data from concurrent access by read/write
30 * and create symlink/remove symlink.
31 */
32 struct mutex lock;
33 int refcnt;
25}; 34};
26 35
27#endif /* U_GETHER_H */ 36#endif /* U_GETHER_H */