diff options
author | Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 2013-05-28 03:15:56 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-06-10 10:58:08 -0400 |
commit | 02832e56f88a981474ee4c7c141f46fc1b4454f4 (patch) | |
tree | 9d69ab395696bb866ec54f17f2ecc4c67dbda84d /drivers | |
parent | 74bf963d1d230b0cedbcbc46f6f15f20c2e3ee55 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/Kconfig | 10 | ||||
-rw-r--r-- | drivers/usb/gadget/f_subset.c | 46 | ||||
-rw-r--r-- | drivers/usb/gadget/u_gether.h | 9 |
3 files changed, 64 insertions, 1 deletions
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 | ||
550 | config 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 | |||
550 | config USB_CONFIGFS_EEM | 560 | config 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 | ||
451 | static 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 */ | ||
458 | USB_ETHERNET_CONFIGFS_ITEM(gether); | ||
459 | |||
460 | /* f_gether_opts_dev_addr */ | ||
461 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(gether); | ||
462 | |||
463 | /* f_gether_opts_host_addr */ | ||
464 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(gether); | ||
465 | |||
466 | /* f_gether_opts_qmult */ | ||
467 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(gether); | ||
468 | |||
469 | /* f_gether_opts_ifname */ | ||
470 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(gether); | ||
471 | |||
472 | static 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 | |||
480 | static 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 | |||
448 | static void geth_free_inst(struct usb_function_instance *f) | 486 | static 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 */ |