aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/u_ether.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/u_ether.c')
-rw-r--r--drivers/usb/gadget/u_ether.c87
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 = &eth_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;