diff options
Diffstat (limited to 'drivers/usb/gadget/u_ether.c')
-rw-r--r-- | drivers/usb/gadget/u_ether.c | 87 |
1 files changed, 74 insertions, 13 deletions
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 2ac1d21..b0a56ee 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -97,16 +97,17 @@ struct eth_dev { static unsigned qmult = 5; module_param(qmult, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(qmult, "queue length multiplier at high speed"); +MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed"); #else /* full speed (low speed doesn't do bulk) */ #define qmult 1 #endif -/* for dual-speed hardware, use deeper queues at highspeed */ +/* for dual-speed hardware, use deeper queues at high/super speed */ static inline int qlen(struct usb_gadget *gadget) { - if (gadget_is_dualspeed(gadget) && gadget->speed == USB_SPEED_HIGH) + if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH || + gadget->speed == USB_SPEED_SUPER)) return qmult * DEFAULT_QLEN; else return DEFAULT_QLEN; @@ -242,8 +243,11 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) if (dev->port_usb->is_fixed) size = max_t(size_t, size, dev->port_usb->fixed_out_len); - +#ifdef CONFIG_USB_S3C_OTGD + skb = alloc_skb(size + NET_IP_ALIGN + 6, gfp_flags); +#else skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); +#endif if (skb == NULL) { DBG(dev, "no rx skb\n"); goto enomem; @@ -253,8 +257,11 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) * but on at least one, checksumming fails otherwise. Note: * RNDIS headers involve variable numbers of LE32 values. */ +#ifdef CONFIG_USB_S3C_OTGD + skb_reserve(skb, NET_IP_ALIGN + 6); +#else skb_reserve(skb, NET_IP_ALIGN); - +#endif req->buf = skb->data; req->length = size; req->complete = rx_complete; @@ -482,6 +489,11 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req) spin_lock(&dev->req_lock); list_add(&req->list, &dev->tx_reqs); spin_unlock(&dev->req_lock); + +#ifdef CONFIG_USB_S3C_OTGD + if (req->buf != skb->data) + kfree(req->buf); +#endif dev_kfree_skb_any(skb); atomic_dec(&dev->tx_qlen); @@ -577,7 +589,19 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, length = skb->len; } +#ifdef CONFIG_USB_S3C_OTGD + /* for double word align */ + req->buf = kmalloc(skb->len, GFP_ATOMIC | GFP_DMA); + + if (!req->buf) { + req->buf = skb->data; + ERROR(dev, "fail to kmalloc[req->buf = skb->data]\n"); + } else { + memcpy((void *)req->buf, (void *)skb->data, skb->len); + } +#else req->buf = skb->data; +#endif req->context = skb; req->complete = tx_complete; @@ -598,9 +622,10 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, req->length = length; - /* throttle highspeed IRQ rate back slightly */ + /* throttle high/super speed IRQ rate back slightly */ if (gadget_is_dualspeed(dev->gadget)) - req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) + req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH || + dev->gadget->speed == USB_SPEED_SUPER) ? ((atomic_read(&dev->tx_qlen) % qmult) != 0) : 0; @@ -615,9 +640,14 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, } if (retval) { +#ifdef CONFIG_USB_S3C_OTGD + if (req->buf != skb->data) + kfree(req->buf); +#endif dev_kfree_skb_any(skb); drop: dev->net->stats.tx_dropped++; + spin_lock_irqsave(&dev->req_lock, flags); if (list_empty(&dev->tx_reqs)) netif_start_queue(net); @@ -631,8 +661,7 @@ drop: static void eth_start(struct eth_dev *dev, gfp_t gfp_flags) { - DBG(dev, "%s\n", __func__); - + printk(KERN_DEBUG "usb: %s ++\n", __func__); /* fill the rx queue */ rx_fill(dev, gfp_flags); @@ -646,7 +675,7 @@ static int eth_open(struct net_device *net) struct eth_dev *dev = netdev_priv(net); struct gether *link; - DBG(dev, "%s\n", __func__); + printk(KERN_DEBUG "usb: %s ++\n", __func__); if (netif_carrier_ok(dev->net)) eth_start(dev, GFP_KERNEL); @@ -765,6 +794,26 @@ static struct device_type gadget_type = { */ int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) { + return gether_setup_name(g, ethaddr, "usb"); +} + +/** + * gether_setup_name - initialize one ethernet-over-usb link + * @g: gadget to associated with these links + * @ethaddr: NULL, or a buffer in which the ethernet address of the + * host side of the link is recorded + * @netname: name for network device (for example, "usb") + * Context: may sleep + * + * This sets up the single network link that may be exported by a + * gadget driver using this framework. The link layer addresses are + * set up using module parameters. + * + * Returns negative errno, or zero on success + */ +int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], + const char *netname) +{ struct eth_dev *dev; struct net_device *net; int status; @@ -787,17 +836,23 @@ int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) /* network device setup */ dev->net = net; - strcpy(net->name, "usb%d"); + snprintf(net->name, sizeof(net->name), "%s%%d", netname); if (get_ether_addr(dev_addr, net->dev_addr)) dev_warn(&g->dev, "using random %s ethernet address\n", "self"); + +#ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE + memcpy(dev->host_mac, ethaddr, ETH_ALEN); + printk(KERN_DEBUG "usb: set unique host mac\n"); +#else if (get_ether_addr(host_addr, dev->host_mac)) dev_warn(&g->dev, "using random %s ethernet address\n", "host"); if (ethaddr) memcpy(ethaddr, dev->host_mac, ETH_ALEN); +#endif net->netdev_ops = ð_netdev_ops; @@ -867,6 +922,7 @@ struct net_device *gether_connect(struct gether *link) struct eth_dev *dev = the_dev; int result = 0; + printk(KERN_DEBUG "usb: %s ++\n", __func__); if (!dev) return ERR_PTR(-EINVAL); @@ -886,12 +942,15 @@ struct net_device *gether_connect(struct gether *link) goto fail1; } + printk(KERN_DEBUG "usb: %s enable ep in/out\n", __func__); if (result == 0) result = alloc_requests(dev, link, qlen(dev->gadget)); if (result == 0) { dev->zlp = link->is_zlp_ok; DBG(dev, "qlen %d\n", qlen(dev->gadget)); + printk(KERN_DEBUG "usb: %s qlen=%d\n", + __func__, qlen(dev->gadget)); dev->header_len = link->header_len; dev->unwrap = link->unwrap; @@ -909,9 +968,12 @@ struct net_device *gether_connect(struct gether *link) } spin_unlock(&dev->lock); + printk(KERN_DEBUG "usb: %s netif_carrier_on\n", __func__); netif_carrier_on(dev->net); - if (netif_running(dev->net)) + if (netif_running(dev->net)) { + printk(KERN_DEBUG "usb: %s eth_start\n", __func__); eth_start(dev, GFP_ATOMIC); + } /* on error, disable any endpoints */ } else { @@ -943,7 +1005,6 @@ void gether_disconnect(struct gether *link) struct eth_dev *dev = link->ioport; struct usb_request *req; - WARN_ON(!dev); if (!dev) return; |