Loading drivers/usb/gadget/function/f_qdss.c +102 −9 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include "usb_gadget_xport.h" #include "u_data_ipa.h" #include "u_rmnet.h" #include "u_ether.h" static unsigned int nr_qdss_ports; static unsigned int no_data_bam_ports; Loading @@ -41,6 +42,7 @@ static struct qdss_ports { struct f_qdss *port; struct gadget_ipa_port ipa_port; struct grmnet bam_dmux_port; struct gether gether_port; } qdss_ports[NR_QDSS_PORTS]; Loading Loading @@ -355,10 +357,14 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) struct usb_gadget *gadget = c->cdev->gadget; struct f_qdss *qdss = func_to_qdss(f); struct usb_ep *ep; int iface; int iface, ret = -ENOTSUPP; struct eth_dev *edev; enum transport_type dxport; pr_debug("qdss_bind\n"); dxport = qdss_ports[qdss->port_num].data_xport; if (!gadget_is_dualspeed(gadget) && !gadget_is_superspeed(gadget)) { pr_err("qdss_bind: full-speed is not supported\n"); return -ENOTSUPP; Loading Loading @@ -391,6 +397,14 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) goto fail; } qdss->port.data = ep; /* * Populate same for u_ether(gether_connect()) which uses * gether_port struct */ if (dxport == USB_GADGET_XPORT_ETHER) qdss_ports[qdss->port_num].gether_port.in_ep = ep; ep->driver_data = qdss; if (qdss->debug_inface_enabled) { Loading Loading @@ -444,11 +458,23 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) } } if (dxport == USB_GADGET_XPORT_ETHER) { pr_debug("USB_GADGET_XPORT_ETHER\n"); edev = gether_setup_name(c->cdev->gadget, NULL, NULL, NULL, QMULT_DEFAULT, "dpl_usb"); if (IS_ERR(edev)) { pr_err("%s: gether_setup failed\n", __func__); ret = PTR_ERR(edev); goto fail; } qdss_ports[qdss->port_num].gether_port.ioport = edev; } return 0; fail: clear_eps(f); clear_desc(gadget, f); return -ENOTSUPP; return ret; } Loading @@ -456,6 +482,7 @@ static void qdss_unbind(struct usb_configuration *c, struct usb_function *f) { struct f_qdss *qdss = func_to_qdss(f); struct usb_gadget *gadget = c->cdev->gadget; int i; pr_debug("qdss_unbind\n"); Loading @@ -463,11 +490,22 @@ static void qdss_unbind(struct usb_configuration *c, struct usb_function *f) clear_eps(f); clear_desc(gadget, f); for (i = 0; i < nr_qdss_ports; i++) { if (qdss_ports[i].data_xport == USB_GADGET_XPORT_ETHER) { gether_cleanup(qdss_ports[i].gether_port.ioport); qdss_ports[i].gether_port.ioport = NULL; } } } static void qdss_eps_disable(struct usb_function *f) { struct f_qdss *qdss = func_to_qdss(f); enum transport_type dxport; dxport = qdss_ports[qdss->port_num].data_xport; pr_debug("qdss_eps_disable\n"); Loading @@ -481,7 +519,14 @@ static void qdss_eps_disable(struct usb_function *f) qdss->ctrl_out_enabled = 0; } if (qdss->data_enabled) { /* * In case of data transport is uether, endpoint will be disabled * in gether_disconnect() too. This will lead to disabling of the * same endpoint twice and will print a warning message. * So for uether data transport disable endpoint only in * gether_disconnect() */ if (qdss->data_enabled && (dxport != USB_GADGET_XPORT_ETHER)) { usb_ep_disable(qdss->port.data); qdss->data_enabled = 0; } Loading Loading @@ -549,6 +594,10 @@ static void usb_qdss_disconnect_work(struct work_struct *work) pr_debug("usb_qdss_disconnect_work: HSIC transport\n"); ghsic_data_disconnect(&qdss->port, portno); break; case USB_GADGET_XPORT_ETHER: pr_debug("usb_qdss_disconnect_work: ETHER transport\n"); gether_disconnect(&qdss_ports[portno].gether_port); break; case USB_GADGET_XPORT_NONE: break; default: Loading Loading @@ -661,6 +710,7 @@ static void usb_qdss_connect_work(struct work_struct *work) unsigned char port_num; enum transport_type dxport; enum transport_type ctrl_xport; struct net_device *net; qdss = container_of(work, struct f_qdss, connect_w); dxport = qdss_ports[qdss->port_num].data_xport; Loading Loading @@ -745,6 +795,15 @@ static void usb_qdss_connect_work(struct work_struct *work) return; } break; case USB_GADGET_XPORT_ETHER: pr_debug("usb_qdss_connect_work: ETHER transport\n"); net = gether_connect(&qdss_ports[port_num].gether_port); if (IS_ERR(net)) { pr_err("%s: gether_connect failed: err:%ld\n", __func__, PTR_ERR(net)); return; } break; case USB_GADGET_XPORT_NONE: break; default: Loading Loading @@ -786,6 +845,13 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt) goto fail; } /* * In case of data transport is uether, endpoint will be enabled * in gether_connect() too. This will lead to enabling of the * same endpoint twice and will print a warning message. * So for uether data transport disable endpoint only in * gether_connect() */ if (dxport == USB_GADGET_XPORT_BAM2BAM_IPA || dxport == USB_GADGET_XPORT_BAM_DMUX) { qdss->usb_connected = 1; Loading @@ -793,9 +859,11 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt) return 0; } if (dxport != USB_GADGET_XPORT_ETHER) { ret = usb_ep_enable(qdss->port.data); if (ret) goto fail; } qdss->port.data->driver_data = qdss; qdss->data_enabled = 1; Loading Loading @@ -843,7 +911,8 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt) } } if (qdss->usb_connected && (ch->app_conn || (dxport == USB_GADGET_XPORT_HSIC))) { (dxport == USB_GADGET_XPORT_HSIC) || (dxport == USB_GADGET_XPORT_ETHER))) { queue_work(qdss->wq, &qdss->connect_w); } return 0; Loading @@ -863,6 +932,10 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) struct usb_qdss_ch *ch; unsigned long flags; char *name; enum transport_type dxport; struct usb_function *f; dxport = qdss_ports[portno].data_xport; pr_debug("qdss_bind_config\n"); if (portno >= nr_qdss_ports) { Loading @@ -887,10 +960,14 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) } } if (qdss_ports[portno].data_xport == USB_GADGET_XPORT_BAM2BAM) if (qdss_ports[portno].data_xport == USB_GADGET_XPORT_BAM2BAM) { name = kasprintf(GFP_ATOMIC, "qdss"); else } else if (dxport == USB_GADGET_XPORT_ETHER) { pr_debug("qdss_bind_config: USB_GADGET_XPORT_ETHER\n"); name = kasprintf(GFP_KERNEL, "qdss_dpl"); } else { name = kasprintf(GFP_ATOMIC, "qdss%d", portno); } if (!name) return -ENOMEM; Loading @@ -911,6 +988,7 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) spin_unlock_irqrestore(&qdss_lock, flags); qdss->wq = create_singlethread_workqueue(name); if (!qdss->wq) { kfree(name); kfree(qdss); return -ENOMEM; } Loading @@ -934,6 +1012,17 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) qdss->port.function.name = name; qdss->port.function.fs_descriptors = qdss_hs_desc; qdss->port.function.hs_descriptors = qdss_hs_desc; /* * Populate the gether_port->usb_function which is needed by * u_ether transport when the interface is brought 'down' by calling * eth_stop() */ if (dxport == USB_GADGET_XPORT_ETHER) { f = &qdss_ports[portno].gether_port.func; f->fs_descriptors = qdss_hs_data_only_desc; f->hs_descriptors = qdss_hs_data_only_desc; f->ss_descriptors = qdss_ss_data_only_desc; } qdss->port.function.strings = qdss_strings; qdss->port.function.bind = qdss_bind; qdss->port.function.unbind = qdss_unbind; Loading @@ -948,6 +1037,7 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) if (status) { pr_err("qdss usb_add_function failed\n"); ch->priv_usb = NULL; kfree(name); kfree(qdss); } Loading Loading @@ -1239,6 +1329,9 @@ static int qdss_init_port(const char *ctrl_name, const char *data_name, no_bam_dmux_ports++; pr_debug("USB_GADGET_XPORT_BAM_DMUX %u\n", no_bam_dmux_ports); break; case USB_GADGET_XPORT_ETHER: pr_debug("%s USB_GADGET_XPORT_ETHER\n", __func__); break; case USB_GADGET_XPORT_NONE: break; default: Loading drivers/usb/gadget/function/u_ether.c +107 −72 Original line number Diff line number Diff line Loading @@ -549,16 +549,29 @@ static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n) int status; spin_lock(&dev->req_lock); /* * u_ether driver always assumes that it has both in and out endpoints * and calls alloc_requests on both the endpoints, without checking if * the endpoint exits or not. In case of DPL, there is only one in_ep * and hence while trying to allocate meomory for out_ep, there will be * a NULL pointer exception. So to avoid this, allocate memory only if * the endpoints exists */ if (link->in_ep) { status = prealloc(&dev->tx_reqs, link->in_ep, n * tx_qmult, dev->sg_enabled, dev->header_len); if (status < 0) goto fail; } if (link->out_ep) { status = prealloc(&dev->rx_reqs, link->out_ep, n, dev->sg_enabled, dev->header_len); if (status < 0) goto fail; } goto done; fail: DBG(dev, "can't alloc requests\n"); Loading Loading @@ -1376,23 +1389,31 @@ static int eth_stop(struct net_device *net) * their own pace; the network stack can handle old packets. * For the moment we leave this here, since it works. */ if (link->in_ep) { in = link->in_ep->desc; out = link->out_ep->desc; usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); if (netif_carrier_ok(net)) { if (config_ep_by_speed(dev->gadget, &link->func, link->in_ep) || config_ep_by_speed(dev->gadget, &link->func, link->out_ep)) { if (netif_carrier_ok(net) && (config_ep_by_speed(dev->gadget, &link->func, link->in_ep))) { link->in_ep->desc = NULL; link->out_ep->desc = NULL; return -EINVAL; } DBG(dev, "host still using in/out endpoints\n"); DBG(dev, "host still using in endpoint\n"); link->in_ep->desc = in; link->out_ep->desc = out; usb_ep_enable(link->in_ep); } if (link->out_ep) { out = link->out_ep->desc; usb_ep_disable(link->out_ep); if ((netif_carrier_ok(net)) && (config_ep_by_speed(dev->gadget, &link->func, link->out_ep))) { link->out_ep->desc = NULL; return -EINVAL; } DBG(dev, "host still using out endpoint\n"); link->out_ep->desc = out; usb_ep_enable(link->out_ep); } } Loading Loading @@ -2043,6 +2064,13 @@ struct net_device *gether_connect(struct gether *link) } } if (!link->in_ep && !link->out_ep) { WARN_ON(1); result = -ENOTSUPP; goto fail0; } if (link->in_ep) { link->in_ep->driver_data = dev; result = usb_ep_enable(link->in_ep); if (result != 0) { Loading @@ -2050,7 +2078,9 @@ struct net_device *gether_connect(struct gether *link) link->in_ep->name, result); goto fail0; } } if (link->out_ep) { link->out_ep->driver_data = dev; result = usb_ep_enable(link->out_ep); if (result != 0) { Loading @@ -2058,6 +2088,7 @@ struct net_device *gether_connect(struct gether *link) link->out_ep->name, result); goto fail1; } } dev->header_len = link->header_len; dev->unwrap = link->unwrap; Loading Loading @@ -2150,6 +2181,7 @@ void gether_disconnect(struct gether *link) * of all pending i/o. then free the request objects * and forget about the endpoints. */ if (link->in_ep) { usb_ep_disable(link->in_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->tx_reqs)) { Loading Loading @@ -2182,7 +2214,9 @@ void gether_disconnect(struct gether *link) link->in_ep->driver_data = NULL; link->in_ep->desc = NULL; } if (link->out_ep) { usb_ep_disable(link->out_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->rx_reqs)) { Loading @@ -2203,6 +2237,7 @@ void gether_disconnect(struct gether *link) link->out_ep->driver_data = NULL; link->out_ep->desc = NULL; } pr_debug("%s(): tx_throttle count= %lu", __func__, dev->tx_throttle); Loading Loading
drivers/usb/gadget/function/f_qdss.c +102 −9 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include "usb_gadget_xport.h" #include "u_data_ipa.h" #include "u_rmnet.h" #include "u_ether.h" static unsigned int nr_qdss_ports; static unsigned int no_data_bam_ports; Loading @@ -41,6 +42,7 @@ static struct qdss_ports { struct f_qdss *port; struct gadget_ipa_port ipa_port; struct grmnet bam_dmux_port; struct gether gether_port; } qdss_ports[NR_QDSS_PORTS]; Loading Loading @@ -355,10 +357,14 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) struct usb_gadget *gadget = c->cdev->gadget; struct f_qdss *qdss = func_to_qdss(f); struct usb_ep *ep; int iface; int iface, ret = -ENOTSUPP; struct eth_dev *edev; enum transport_type dxport; pr_debug("qdss_bind\n"); dxport = qdss_ports[qdss->port_num].data_xport; if (!gadget_is_dualspeed(gadget) && !gadget_is_superspeed(gadget)) { pr_err("qdss_bind: full-speed is not supported\n"); return -ENOTSUPP; Loading Loading @@ -391,6 +397,14 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) goto fail; } qdss->port.data = ep; /* * Populate same for u_ether(gether_connect()) which uses * gether_port struct */ if (dxport == USB_GADGET_XPORT_ETHER) qdss_ports[qdss->port_num].gether_port.in_ep = ep; ep->driver_data = qdss; if (qdss->debug_inface_enabled) { Loading Loading @@ -444,11 +458,23 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) } } if (dxport == USB_GADGET_XPORT_ETHER) { pr_debug("USB_GADGET_XPORT_ETHER\n"); edev = gether_setup_name(c->cdev->gadget, NULL, NULL, NULL, QMULT_DEFAULT, "dpl_usb"); if (IS_ERR(edev)) { pr_err("%s: gether_setup failed\n", __func__); ret = PTR_ERR(edev); goto fail; } qdss_ports[qdss->port_num].gether_port.ioport = edev; } return 0; fail: clear_eps(f); clear_desc(gadget, f); return -ENOTSUPP; return ret; } Loading @@ -456,6 +482,7 @@ static void qdss_unbind(struct usb_configuration *c, struct usb_function *f) { struct f_qdss *qdss = func_to_qdss(f); struct usb_gadget *gadget = c->cdev->gadget; int i; pr_debug("qdss_unbind\n"); Loading @@ -463,11 +490,22 @@ static void qdss_unbind(struct usb_configuration *c, struct usb_function *f) clear_eps(f); clear_desc(gadget, f); for (i = 0; i < nr_qdss_ports; i++) { if (qdss_ports[i].data_xport == USB_GADGET_XPORT_ETHER) { gether_cleanup(qdss_ports[i].gether_port.ioport); qdss_ports[i].gether_port.ioport = NULL; } } } static void qdss_eps_disable(struct usb_function *f) { struct f_qdss *qdss = func_to_qdss(f); enum transport_type dxport; dxport = qdss_ports[qdss->port_num].data_xport; pr_debug("qdss_eps_disable\n"); Loading @@ -481,7 +519,14 @@ static void qdss_eps_disable(struct usb_function *f) qdss->ctrl_out_enabled = 0; } if (qdss->data_enabled) { /* * In case of data transport is uether, endpoint will be disabled * in gether_disconnect() too. This will lead to disabling of the * same endpoint twice and will print a warning message. * So for uether data transport disable endpoint only in * gether_disconnect() */ if (qdss->data_enabled && (dxport != USB_GADGET_XPORT_ETHER)) { usb_ep_disable(qdss->port.data); qdss->data_enabled = 0; } Loading Loading @@ -549,6 +594,10 @@ static void usb_qdss_disconnect_work(struct work_struct *work) pr_debug("usb_qdss_disconnect_work: HSIC transport\n"); ghsic_data_disconnect(&qdss->port, portno); break; case USB_GADGET_XPORT_ETHER: pr_debug("usb_qdss_disconnect_work: ETHER transport\n"); gether_disconnect(&qdss_ports[portno].gether_port); break; case USB_GADGET_XPORT_NONE: break; default: Loading Loading @@ -661,6 +710,7 @@ static void usb_qdss_connect_work(struct work_struct *work) unsigned char port_num; enum transport_type dxport; enum transport_type ctrl_xport; struct net_device *net; qdss = container_of(work, struct f_qdss, connect_w); dxport = qdss_ports[qdss->port_num].data_xport; Loading Loading @@ -745,6 +795,15 @@ static void usb_qdss_connect_work(struct work_struct *work) return; } break; case USB_GADGET_XPORT_ETHER: pr_debug("usb_qdss_connect_work: ETHER transport\n"); net = gether_connect(&qdss_ports[port_num].gether_port); if (IS_ERR(net)) { pr_err("%s: gether_connect failed: err:%ld\n", __func__, PTR_ERR(net)); return; } break; case USB_GADGET_XPORT_NONE: break; default: Loading Loading @@ -786,6 +845,13 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt) goto fail; } /* * In case of data transport is uether, endpoint will be enabled * in gether_connect() too. This will lead to enabling of the * same endpoint twice and will print a warning message. * So for uether data transport disable endpoint only in * gether_connect() */ if (dxport == USB_GADGET_XPORT_BAM2BAM_IPA || dxport == USB_GADGET_XPORT_BAM_DMUX) { qdss->usb_connected = 1; Loading @@ -793,9 +859,11 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt) return 0; } if (dxport != USB_GADGET_XPORT_ETHER) { ret = usb_ep_enable(qdss->port.data); if (ret) goto fail; } qdss->port.data->driver_data = qdss; qdss->data_enabled = 1; Loading Loading @@ -843,7 +911,8 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt) } } if (qdss->usb_connected && (ch->app_conn || (dxport == USB_GADGET_XPORT_HSIC))) { (dxport == USB_GADGET_XPORT_HSIC) || (dxport == USB_GADGET_XPORT_ETHER))) { queue_work(qdss->wq, &qdss->connect_w); } return 0; Loading @@ -863,6 +932,10 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) struct usb_qdss_ch *ch; unsigned long flags; char *name; enum transport_type dxport; struct usb_function *f; dxport = qdss_ports[portno].data_xport; pr_debug("qdss_bind_config\n"); if (portno >= nr_qdss_ports) { Loading @@ -887,10 +960,14 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) } } if (qdss_ports[portno].data_xport == USB_GADGET_XPORT_BAM2BAM) if (qdss_ports[portno].data_xport == USB_GADGET_XPORT_BAM2BAM) { name = kasprintf(GFP_ATOMIC, "qdss"); else } else if (dxport == USB_GADGET_XPORT_ETHER) { pr_debug("qdss_bind_config: USB_GADGET_XPORT_ETHER\n"); name = kasprintf(GFP_KERNEL, "qdss_dpl"); } else { name = kasprintf(GFP_ATOMIC, "qdss%d", portno); } if (!name) return -ENOMEM; Loading @@ -911,6 +988,7 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) spin_unlock_irqrestore(&qdss_lock, flags); qdss->wq = create_singlethread_workqueue(name); if (!qdss->wq) { kfree(name); kfree(qdss); return -ENOMEM; } Loading @@ -934,6 +1012,17 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) qdss->port.function.name = name; qdss->port.function.fs_descriptors = qdss_hs_desc; qdss->port.function.hs_descriptors = qdss_hs_desc; /* * Populate the gether_port->usb_function which is needed by * u_ether transport when the interface is brought 'down' by calling * eth_stop() */ if (dxport == USB_GADGET_XPORT_ETHER) { f = &qdss_ports[portno].gether_port.func; f->fs_descriptors = qdss_hs_data_only_desc; f->hs_descriptors = qdss_hs_data_only_desc; f->ss_descriptors = qdss_ss_data_only_desc; } qdss->port.function.strings = qdss_strings; qdss->port.function.bind = qdss_bind; qdss->port.function.unbind = qdss_unbind; Loading @@ -948,6 +1037,7 @@ static int qdss_bind_config(struct usb_configuration *c, unsigned char portno) if (status) { pr_err("qdss usb_add_function failed\n"); ch->priv_usb = NULL; kfree(name); kfree(qdss); } Loading Loading @@ -1239,6 +1329,9 @@ static int qdss_init_port(const char *ctrl_name, const char *data_name, no_bam_dmux_ports++; pr_debug("USB_GADGET_XPORT_BAM_DMUX %u\n", no_bam_dmux_ports); break; case USB_GADGET_XPORT_ETHER: pr_debug("%s USB_GADGET_XPORT_ETHER\n", __func__); break; case USB_GADGET_XPORT_NONE: break; default: Loading
drivers/usb/gadget/function/u_ether.c +107 −72 Original line number Diff line number Diff line Loading @@ -549,16 +549,29 @@ static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n) int status; spin_lock(&dev->req_lock); /* * u_ether driver always assumes that it has both in and out endpoints * and calls alloc_requests on both the endpoints, without checking if * the endpoint exits or not. In case of DPL, there is only one in_ep * and hence while trying to allocate meomory for out_ep, there will be * a NULL pointer exception. So to avoid this, allocate memory only if * the endpoints exists */ if (link->in_ep) { status = prealloc(&dev->tx_reqs, link->in_ep, n * tx_qmult, dev->sg_enabled, dev->header_len); if (status < 0) goto fail; } if (link->out_ep) { status = prealloc(&dev->rx_reqs, link->out_ep, n, dev->sg_enabled, dev->header_len); if (status < 0) goto fail; } goto done; fail: DBG(dev, "can't alloc requests\n"); Loading Loading @@ -1376,23 +1389,31 @@ static int eth_stop(struct net_device *net) * their own pace; the network stack can handle old packets. * For the moment we leave this here, since it works. */ if (link->in_ep) { in = link->in_ep->desc; out = link->out_ep->desc; usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); if (netif_carrier_ok(net)) { if (config_ep_by_speed(dev->gadget, &link->func, link->in_ep) || config_ep_by_speed(dev->gadget, &link->func, link->out_ep)) { if (netif_carrier_ok(net) && (config_ep_by_speed(dev->gadget, &link->func, link->in_ep))) { link->in_ep->desc = NULL; link->out_ep->desc = NULL; return -EINVAL; } DBG(dev, "host still using in/out endpoints\n"); DBG(dev, "host still using in endpoint\n"); link->in_ep->desc = in; link->out_ep->desc = out; usb_ep_enable(link->in_ep); } if (link->out_ep) { out = link->out_ep->desc; usb_ep_disable(link->out_ep); if ((netif_carrier_ok(net)) && (config_ep_by_speed(dev->gadget, &link->func, link->out_ep))) { link->out_ep->desc = NULL; return -EINVAL; } DBG(dev, "host still using out endpoint\n"); link->out_ep->desc = out; usb_ep_enable(link->out_ep); } } Loading Loading @@ -2043,6 +2064,13 @@ struct net_device *gether_connect(struct gether *link) } } if (!link->in_ep && !link->out_ep) { WARN_ON(1); result = -ENOTSUPP; goto fail0; } if (link->in_ep) { link->in_ep->driver_data = dev; result = usb_ep_enable(link->in_ep); if (result != 0) { Loading @@ -2050,7 +2078,9 @@ struct net_device *gether_connect(struct gether *link) link->in_ep->name, result); goto fail0; } } if (link->out_ep) { link->out_ep->driver_data = dev; result = usb_ep_enable(link->out_ep); if (result != 0) { Loading @@ -2058,6 +2088,7 @@ struct net_device *gether_connect(struct gether *link) link->out_ep->name, result); goto fail1; } } dev->header_len = link->header_len; dev->unwrap = link->unwrap; Loading Loading @@ -2150,6 +2181,7 @@ void gether_disconnect(struct gether *link) * of all pending i/o. then free the request objects * and forget about the endpoints. */ if (link->in_ep) { usb_ep_disable(link->in_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->tx_reqs)) { Loading Loading @@ -2182,7 +2214,9 @@ void gether_disconnect(struct gether *link) link->in_ep->driver_data = NULL; link->in_ep->desc = NULL; } if (link->out_ep) { usb_ep_disable(link->out_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->rx_reqs)) { Loading @@ -2203,6 +2237,7 @@ void gether_disconnect(struct gether *link) link->out_ep->driver_data = NULL; link->out_ep->desc = NULL; } pr_debug("%s(): tx_throttle count= %lu", __func__, dev->tx_throttle); Loading