diff options
Diffstat (limited to 'drivers/net/usb/usbnet.c')
| -rw-r--r-- | drivers/net/usb/usbnet.c | 21 | 
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 449835f4331e..733f4feb2ef3 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1072,7 +1072,7 @@ static void __handle_set_rx_mode(struct usbnet *dev)   * especially now that control transfers can be queued.   */  static void -kevent (struct work_struct *work) +usbnet_deferred_kevent (struct work_struct *work)  {  	struct usbnet		*dev =  		container_of(work, struct usbnet, kevent); @@ -1188,8 +1188,7 @@ static void tx_complete (struct urb *urb)  	struct usbnet		*dev = entry->dev;  	if (urb->status == 0) { -		if (!(dev->driver_info->flags & FLAG_MULTI_PACKET)) -			dev->net->stats.tx_packets++; +		dev->net->stats.tx_packets += entry->packets;  		dev->net->stats.tx_bytes += entry->length;  	} else {  		dev->net->stats.tx_errors++; @@ -1347,7 +1346,19 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,  		} else  			urb->transfer_flags |= URB_ZERO_PACKET;  	} -	entry->length = urb->transfer_buffer_length = length; +	urb->transfer_buffer_length = length; + +	if (info->flags & FLAG_MULTI_PACKET) { +		/* Driver has set number of packets and a length delta. +		 * Calculate the complete length and ensure that it's +		 * positive. +		 */ +		entry->length += length; +		if (WARN_ON_ONCE(entry->length <= 0)) +			entry->length = length; +	} else { +		usbnet_set_skb_tx_stats(skb, 1, length); +	}  	spin_lock_irqsave(&dev->txq.lock, flags);  	retval = usb_autopm_get_interface_async(dev->intf); @@ -1615,7 +1626,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)  	skb_queue_head_init(&dev->rxq_pause);  	dev->bh.func = usbnet_bh;  	dev->bh.data = (unsigned long) dev; -	INIT_WORK (&dev->kevent, kevent); +	INIT_WORK (&dev->kevent, usbnet_deferred_kevent);  	init_usb_anchor(&dev->deferred);  	dev->delay.function = usbnet_bh;  	dev->delay.data = (unsigned long) dev;  |