Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/multi.c | 41 +++++++++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index fd0451a..aebdc14 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -948,6 +948,7 @@ config USB_G_MULTI select USB_U_RNDIS select USB_F_ACM select USB_F_MASS_STORAGE + select USB_F_ECM help The Multifunction Composite Gadget provides Ethernet (RNDIS and/or CDC Ethernet), mass storage and ACM serial link diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index c52ec0f..2371084 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -43,8 +43,7 @@ MODULE_LICENSE("GPL"); */ #include "f_mass_storage.h" -#define USB_FECM_INCLUDED -#include "f_ecm.c" +#include "u_ecm.h" #include "f_subset.c" #ifdef USB_ETH_RNDIS # include "f_rndis.c" @@ -141,6 +140,8 @@ static struct eth_dev *the_dev; static struct usb_function_instance *fi_fsg; +static struct usb_function_instance *fi_ecm; + /********** RNDIS **********/ #ifdef USB_ETH_RNDIS @@ -217,9 +218,11 @@ static int rndis_config_register(struct usb_composite_dev *cdev) #ifdef CONFIG_USB_G_MULTI_CDC static struct usb_function *f_acm_multi; static struct usb_function *f_fsg_multi; +static struct usb_function *f_ecm_multi; static __init int cdc_do_config(struct usb_configuration *c) { + struct f_ecm_opts *ecm_opts; int ret; if (gadget_is_otg(c->cdev->gadget)) { @@ -227,9 +230,17 @@ static __init int cdc_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - ret = ecm_bind_config(c, hostaddr, the_dev); - if (ret < 0) - return ret; + ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); + ecm_opts->ethaddr = hostaddr; + ecm_opts->dev = the_dev; + + f_ecm_multi = usb_get_function(fi_ecm); + if (IS_ERR(f_ecm_multi)) + return PTR_ERR(f_ecm_multi); + + ret = usb_add_function(c, f_ecm_multi); + if (ret) + goto err_func_ecm; /* implicit port_num is zero */ f_acm_multi = usb_get_function(fi_acm); @@ -258,6 +269,9 @@ err_fsg: err_conf: usb_put_function(f_acm_multi); err_func_acm: + usb_remove_function(c, f_ecm_multi); +err_func_ecm: + usb_put_function(f_ecm_multi); return ret; } @@ -304,6 +318,12 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) if (IS_ERR(the_dev)) return PTR_ERR(the_dev); + fi_ecm = usb_get_function_instance("ecm"); + if (IS_ERR(fi_ecm)) { + status = PTR_ERR(fi_ecm); + goto fail; + } + /* set up serial link layer */ fi_acm = usb_get_function_instance("acm"); if (IS_ERR(fi_acm)) { @@ -338,7 +358,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) status = cdc_config_register(cdev); if (unlikely(status < 0)) - goto fail3; + goto fail4; usb_composite_overwrite_options(cdev, &coverwrite); /* we're done */ @@ -348,6 +368,11 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) /* error recovery */ +fail4: +#ifdef USB_ETH_RNDIS + usb_put_function(f_acm_rndis); + usb_put_function(f_fsg_rndis); +#endif fail3: fsg_common_put(fsg_common); fail2: @@ -355,6 +380,8 @@ fail2: fail1: usb_put_function_instance(fi_acm); fail0: + usb_put_function_instance(fi_ecm); +fail: gether_cleanup(the_dev); return status; } @@ -364,6 +391,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev) #ifdef CONFIG_USB_G_MULTI_CDC usb_put_function(f_acm_multi); usb_put_function(f_fsg_multi); + usb_put_function(f_ecm_multi); #endif #ifdef USB_ETH_RNDIS usb_put_function(f_acm_rndis); @@ -371,6 +399,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev) #endif usb_put_function_instance(fi_acm); usb_put_function_instance(fi_fsg); + usb_put_function_instance(fi_ecm); gether_cleanup(the_dev); return 0; } -- 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