|
@@ -1241,7 +1241,9 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
|
|
|
if (num_sgs == 1)
|
|
|
return 0;
|
|
|
|
|
|
- urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist), GFP_ATOMIC);
|
|
|
+ /* reserve one for zero packet */
|
|
|
+ urb->sg = kmalloc((num_sgs + 1) * sizeof(struct scatterlist),
|
|
|
+ GFP_ATOMIC);
|
|
|
if (!urb->sg)
|
|
|
return -ENOMEM;
|
|
|
|
|
@@ -1305,7 +1307,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|
|
if (build_dma_sg(skb, urb) < 0)
|
|
|
goto drop;
|
|
|
}
|
|
|
- entry->length = length = urb->transfer_buffer_length;
|
|
|
+ length = urb->transfer_buffer_length;
|
|
|
|
|
|
/* don't assume the hardware handles USB_ZERO_PACKET
|
|
|
* NOTE: strictly conforming cdc-ether devices should expect
|
|
@@ -1317,15 +1319,18 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|
|
if (length % dev->maxpacket == 0) {
|
|
|
if (!(info->flags & FLAG_SEND_ZLP)) {
|
|
|
if (!(info->flags & FLAG_MULTI_PACKET)) {
|
|
|
- urb->transfer_buffer_length++;
|
|
|
- if (skb_tailroom(skb)) {
|
|
|
+ length++;
|
|
|
+ if (skb_tailroom(skb) && !urb->num_sgs) {
|
|
|
skb->data[skb->len] = 0;
|
|
|
__skb_put(skb, 1);
|
|
|
- }
|
|
|
+ } else if (urb->num_sgs)
|
|
|
+ sg_set_buf(&urb->sg[urb->num_sgs++],
|
|
|
+ dev->padding_pkt, 1);
|
|
|
}
|
|
|
} else
|
|
|
urb->transfer_flags |= URB_ZERO_PACKET;
|
|
|
}
|
|
|
+ entry->length = urb->transfer_buffer_length = length;
|
|
|
|
|
|
spin_lock_irqsave(&dev->txq.lock, flags);
|
|
|
retval = usb_autopm_get_interface_async(dev->intf);
|
|
@@ -1509,6 +1514,7 @@ void usbnet_disconnect (struct usb_interface *intf)
|
|
|
|
|
|
usb_kill_urb(dev->interrupt);
|
|
|
usb_free_urb(dev->interrupt);
|
|
|
+ kfree(dev->padding_pkt);
|
|
|
|
|
|
free_netdev(net);
|
|
|
}
|
|
@@ -1679,9 +1685,16 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
|
|
|
/* initialize max rx_qlen and tx_qlen */
|
|
|
usbnet_update_max_qlen(dev);
|
|
|
|
|
|
+ if (dev->can_dma_sg && !(info->flags & FLAG_SEND_ZLP) &&
|
|
|
+ !(info->flags & FLAG_MULTI_PACKET)) {
|
|
|
+ dev->padding_pkt = kzalloc(1, GFP_KERNEL);
|
|
|
+ if (!dev->padding_pkt)
|
|
|
+ goto out4;
|
|
|
+ }
|
|
|
+
|
|
|
status = register_netdev (net);
|
|
|
if (status)
|
|
|
- goto out4;
|
|
|
+ goto out5;
|
|
|
netif_info(dev, probe, dev->net,
|
|
|
"register '%s' at usb-%s-%s, %s, %pM\n",
|
|
|
udev->dev.driver->name,
|
|
@@ -1699,6 +1712,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
+out5:
|
|
|
+ kfree(dev->padding_pkt);
|
|
|
out4:
|
|
|
usb_free_urb(dev->interrupt);
|
|
|
out3:
|