aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-eem14
-rw-r--r--drivers/usb/gadget/Kconfig15
-rw-r--r--drivers/usb/gadget/f_eem.c49
-rw-r--r--drivers/usb/gadget/u_eem.h9
4 files changed, 87 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-eem b/Documentation/ABI/testing/configfs-usb-gadget-eem
new file mode 100644
index 000000000000..10e87d67fa2e
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-usb-gadget-eem
@@ -0,0 +1,14 @@
1What: /config/usb-gadget/gadget/functions/eem.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 159393d58912..d5b0ffe26118 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -544,6 +544,21 @@ choice
544 544
545# this first set of drivers all depend on bulk-capable hardware. 545# this first set of drivers all depend on bulk-capable hardware.
546 546
547config USB_CONFIGFS_EEM
548 bool "Ethernet Emulation Model (EEM)"
549 depends on USB_CONFIGFS
550 depends on NET
551 select USB_U_ETHER
552 select USB_F_EEM
553 help
554 CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
555 and therefore can be supported by more hardware. Technically ECM and
556 EEM are designed for different applications. The ECM model extends
557 the network interface to the target (e.g. a USB cable modem), and the
558 EEM model is for mobile devices to communicate with hosts using
559 ethernet over USB. For Linux gadgets, however, the interface with
560 the host is the same (a usbX device), so the differences are minimal.
561
547config USB_CONFIGFS_PHONET 562config USB_CONFIGFS_PHONET
548 boolean "Phonet protocol" 563 boolean "Phonet protocol"
549 depends on USB_CONFIGFS 564 depends on USB_CONFIGFS
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index 31a2cb7ebe82..90ee8022e8d8 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -19,6 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20 20
21#include "u_ether.h" 21#include "u_ether.h"
22#include "u_ether_configfs.h"
22#include "u_eem.h" 23#include "u_eem.h"
23 24
24#define EEM_HLEN 2 25#define EEM_HLEN 2
@@ -263,8 +264,10 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
263 * with regard to eem_opts->bound access 264 * with regard to eem_opts->bound access
264 */ 265 */
265 if (!eem_opts->bound) { 266 if (!eem_opts->bound) {
267 mutex_lock(&eem_opts->lock);
266 gether_set_gadget(eem_opts->net, cdev->gadget); 268 gether_set_gadget(eem_opts->net, cdev->gadget);
267 status = gether_register_netdev(eem_opts->net); 269 status = gether_register_netdev(eem_opts->net);
270 mutex_unlock(&eem_opts->lock);
268 if (status) 271 if (status)
269 return status; 272 return status;
270 eem_opts->bound = true; 273 eem_opts->bound = true;
@@ -533,6 +536,41 @@ error:
533 return status; 536 return status;
534} 537}
535 538
539static inline struct f_eem_opts *to_f_eem_opts(struct config_item *item)
540{
541 return container_of(to_config_group(item), struct f_eem_opts,
542 func_inst.group);
543}
544
545/* f_eem_item_ops */
546USB_ETHERNET_CONFIGFS_ITEM(eem);
547
548/* f_eem_opts_dev_addr */
549USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(eem);
550
551/* f_eem_opts_host_addr */
552USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(eem);
553
554/* f_eem_opts_qmult */
555USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(eem);
556
557/* f_eem_opts_ifname */
558USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(eem);
559
560static struct configfs_attribute *eem_attrs[] = {
561 &f_eem_opts_dev_addr.attr,
562 &f_eem_opts_host_addr.attr,
563 &f_eem_opts_qmult.attr,
564 &f_eem_opts_ifname.attr,
565 NULL,
566};
567
568static struct config_item_type eem_func_type = {
569 .ct_item_ops = &eem_item_ops,
570 .ct_attrs = eem_attrs,
571 .ct_owner = THIS_MODULE,
572};
573
536static void eem_free_inst(struct usb_function_instance *f) 574static void eem_free_inst(struct usb_function_instance *f)
537{ 575{
538 struct f_eem_opts *opts; 576 struct f_eem_opts *opts;
@@ -552,20 +590,28 @@ static struct usb_function_instance *eem_alloc_inst(void)
552 opts = kzalloc(sizeof(*opts), GFP_KERNEL); 590 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
553 if (!opts) 591 if (!opts)
554 return ERR_PTR(-ENOMEM); 592 return ERR_PTR(-ENOMEM);
593 mutex_init(&opts->lock);
555 opts->func_inst.free_func_inst = eem_free_inst; 594 opts->func_inst.free_func_inst = eem_free_inst;
556 opts->net = gether_setup_default(); 595 opts->net = gether_setup_default();
557 if (IS_ERR(opts->net)) 596 if (IS_ERR(opts->net))
558 return ERR_CAST(opts->net); 597 return ERR_CAST(opts->net);
559 598
599 config_group_init_type_name(&opts->func_inst.group, "", &eem_func_type);
600
560 return &opts->func_inst; 601 return &opts->func_inst;
561} 602}
562 603
563static void eem_free(struct usb_function *f) 604static void eem_free(struct usb_function *f)
564{ 605{
565 struct f_eem *eem; 606 struct f_eem *eem;
607 struct f_eem_opts *opts;
566 608
567 eem = func_to_eem(f); 609 eem = func_to_eem(f);
610 opts = container_of(f->fi, struct f_eem_opts, func_inst);
568 kfree(eem); 611 kfree(eem);
612 mutex_lock(&opts->lock);
613 opts->refcnt--;
614 mutex_unlock(&opts->lock);
569} 615}
570 616
571static void eem_unbind(struct usb_configuration *c, struct usb_function *f) 617static void eem_unbind(struct usb_configuration *c, struct usb_function *f)
@@ -586,8 +632,11 @@ struct usb_function *eem_alloc(struct usb_function_instance *fi)
586 return ERR_PTR(-ENOMEM); 632 return ERR_PTR(-ENOMEM);
587 633
588 opts = container_of(fi, struct f_eem_opts, func_inst); 634 opts = container_of(fi, struct f_eem_opts, func_inst);
635 mutex_lock(&opts->lock);
636 opts->refcnt++;
589 637
590 eem->port.ioport = netdev_priv(opts->net); 638 eem->port.ioport = netdev_priv(opts->net);
639 mutex_unlock(&opts->lock);
591 eem->port.cdc_filter = DEFAULT_FILTER; 640 eem->port.cdc_filter = DEFAULT_FILTER;
592 641
593 eem->port.func.name = "cdc_eem"; 642 eem->port.func.name = "cdc_eem";
diff --git a/drivers/usb/gadget/u_eem.h b/drivers/usb/gadget/u_eem.h
index 8f432f2a5e57..e3ae97874c4f 100644
--- a/drivers/usb/gadget/u_eem.h
+++ b/drivers/usb/gadget/u_eem.h
@@ -22,6 +22,15 @@ struct f_eem_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_EEM_H */ 36#endif /* U_EEM_H */