diff options
author | hayeswang <hayeswang@realtek.com> | 2013-11-20 04:30:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-20 15:09:41 -0500 |
commit | 61598788582cafad52816d5d1db879334d8bd561 (patch) | |
tree | 241c6444ab2a86e87d6c483266d7a627c30fcf18 /drivers/net/usb | |
parent | 7937f9e5141c9d4864d399d91325605a35cd5831 (diff) |
r8152: modify the tx flow
Remove the code for sending the packet in the rtl8152_start_xmit().
Let rtl8152_start_xmit() to queue the packet only, and schedule a
tasklet to send the queued packets. This simplify the code and make
sure all the packet would be sent by the original order.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/r8152.c | 46 |
1 files changed, 3 insertions, 43 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 428600d5c056..8a786b65d883 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
@@ -1388,53 +1388,13 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, | |||
1388 | struct net_device *netdev) | 1388 | struct net_device *netdev) |
1389 | { | 1389 | { |
1390 | struct r8152 *tp = netdev_priv(netdev); | 1390 | struct r8152 *tp = netdev_priv(netdev); |
1391 | struct net_device_stats *stats = rtl8152_get_stats(netdev); | ||
1392 | unsigned long flags; | ||
1393 | struct tx_agg *agg = NULL; | ||
1394 | struct tx_desc *tx_desc; | ||
1395 | unsigned int len; | ||
1396 | u8 *tx_data; | ||
1397 | int res; | ||
1398 | 1391 | ||
1399 | skb_tx_timestamp(skb); | 1392 | skb_tx_timestamp(skb); |
1400 | 1393 | ||
1401 | /* If tx_queue is not empty, it means at least one previous packt */ | 1394 | skb_queue_tail(&tp->tx_queue, skb); |
1402 | /* is waiting for sending. Don't send current one before it. */ | ||
1403 | if (skb_queue_empty(&tp->tx_queue)) | ||
1404 | agg = r8152_get_tx_agg(tp); | ||
1405 | |||
1406 | if (!agg) { | ||
1407 | skb_queue_tail(&tp->tx_queue, skb); | ||
1408 | return NETDEV_TX_OK; | ||
1409 | } | ||
1410 | |||
1411 | tx_desc = (struct tx_desc *)agg->head; | ||
1412 | tx_data = agg->head + sizeof(*tx_desc); | ||
1413 | agg->skb_num = agg->skb_len = 0; | ||
1414 | 1395 | ||
1415 | len = skb->len; | 1396 | if (!list_empty(&tp->tx_free)) |
1416 | r8152_tx_csum(tp, tx_desc, skb); | 1397 | tasklet_schedule(&tp->tl); |
1417 | memcpy(tx_data, skb->data, len); | ||
1418 | dev_kfree_skb_any(skb); | ||
1419 | agg->skb_num++; | ||
1420 | agg->skb_len += len; | ||
1421 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), | ||
1422 | agg->head, len + sizeof(*tx_desc), | ||
1423 | (usb_complete_t)write_bulk_callback, agg); | ||
1424 | res = usb_submit_urb(agg->urb, GFP_ATOMIC); | ||
1425 | if (res) { | ||
1426 | /* Can we get/handle EPIPE here? */ | ||
1427 | if (res == -ENODEV) { | ||
1428 | netif_device_detach(tp->netdev); | ||
1429 | } else { | ||
1430 | netif_warn(tp, tx_err, netdev, | ||
1431 | "failed tx_urb %d\n", res); | ||
1432 | stats->tx_dropped++; | ||
1433 | spin_lock_irqsave(&tp->tx_lock, flags); | ||
1434 | list_add_tail(&agg->list, &tp->tx_free); | ||
1435 | spin_unlock_irqrestore(&tp->tx_lock, flags); | ||
1436 | } | ||
1437 | } | ||
1438 | 1398 | ||
1439 | return NETDEV_TX_OK; | 1399 | return NETDEV_TX_OK; |
1440 | } | 1400 | } |