Merge remote-tracking branch 'usb-gadget/next'
[deliverable/linux.git] / drivers / usb / gadget / function / u_ether.c
index 5f562c1ec795718900e5e33de6d6e051eb2bb2ae..8cb08033b7c152b388a291d03499f7f180566d4b 100644 (file)
@@ -82,6 +82,7 @@ struct eth_dev {
 #define        WORK_RX_MEMORY          0
 
        bool                    zlp;
+       bool                    no_skb_reserve;
        u8                      host_mac[ETH_ALEN];
        u8                      dev_mac[ETH_ALEN];
 };
@@ -233,7 +234,8 @@ 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.
         */
-       skb_reserve(skb, NET_IP_ALIGN);
+       if (likely(!dev->no_skb_reserve))
+               skb_reserve(skb, NET_IP_ALIGN);
 
        req->buf = skb->data;
        req->length = size;
@@ -551,14 +553,16 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
                spin_lock_irqsave(&dev->lock, flags);
                if (dev->port_usb)
                        skb = dev->wrap(dev->port_usb, skb);
-               spin_unlock_irqrestore(&dev->lock, flags);
                if (!skb) {
                        /* Multi frame CDC protocols may store the frame for
                         * later which is not a dropped frame.
                         */
                        if (dev->port_usb &&
-                                       dev->port_usb->supports_multi_frame)
+                                       dev->port_usb->supports_multi_frame) {
+                               spin_unlock_irqrestore(&dev->lock, flags);
                                goto multiframe;
+                       }
+                       spin_unlock_irqrestore(&dev->lock, flags);
                        goto drop;
                }
        }
@@ -569,12 +573,14 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
        req->complete = tx_complete;
 
        /* NCM requires no zlp if transfer is dwNtbInMaxSize */
-       if (dev->port_usb->is_fixed &&
+       if (dev->port_usb &&
+           dev->port_usb->is_fixed &&
            length == dev->port_usb->fixed_in_len &&
            (length % in->maxpacket) == 0)
                req->zero = 0;
        else
                req->zero = 1;
+       spin_unlock_irqrestore(&dev->lock, flags);
 
        /* use zlp framing on tx for strict CDC-Ether conformance,
         * though any robust network rx path ignores extra padding.
@@ -1063,6 +1069,7 @@ struct net_device *gether_connect(struct gether *link)
 
        if (result == 0) {
                dev->zlp = link->is_zlp_ok;
+               dev->no_skb_reserve = link->no_skb_reserve;
                DBG(dev, "qlen %d\n", qlen(dev->gadget, dev->qmult));
 
                dev->header_len = link->header_len;
This page took 0.025089 seconds and 5 git commands to generate.