diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c index ffec2e01b896f27f11241403cc5ae6f4c504c24e..86e90c59d55156473058e9ae6a2a6137da8e5283 100644 --- a/drivers/usb/net/catc.c +++ b/drivers/usb/net/catc.c @@ -355,7 +355,7 @@ static void catc_irq_done(struct urb *urb) * Transmit routines. */ -static void catc_tx_run(struct catc *catc) +static int catc_tx_run(struct catc *catc) { int status; @@ -373,12 +373,14 @@ static void catc_tx_run(struct catc *catc) catc->tx_ptr = 0; catc->netdev->trans_start = jiffies; + return status; } static void catc_tx_done(struct urb *urb) { struct catc *catc = urb->context; unsigned long flags; + int r; if (urb->status == -ECONNRESET) { dbg("Tx Reset."); @@ -397,10 +399,13 @@ static void catc_tx_done(struct urb *urb) spin_lock_irqsave(&catc->tx_lock, flags); - if (catc->tx_ptr) - catc_tx_run(catc); - else + if (catc->tx_ptr) { + r = catc_tx_run(catc); + if (unlikely(r < 0)) + clear_bit(TX_RUNNING, &catc->flags); + } else { clear_bit(TX_RUNNING, &catc->flags); + } netif_wake_queue(catc->netdev); @@ -411,6 +416,7 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct catc *catc = netdev_priv(netdev); unsigned long flags; + int r = 0; char *tx_buf; spin_lock_irqsave(&catc->tx_lock, flags); @@ -421,8 +427,11 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) skb_copy_from_linear_data(skb, tx_buf + 2, skb->len); catc->tx_ptr += skb->len + 2; - if (!test_and_set_bit(TX_RUNNING, &catc->flags)) - catc_tx_run(catc); + if (!test_and_set_bit(TX_RUNNING, &catc->flags)) { + r = catc_tx_run(catc); + if (r < 0) + clear_bit(TX_RUNNING, &catc->flags); + } if ((catc->is_f5u011 && catc->tx_ptr) || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))) @@ -430,8 +439,10 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) spin_unlock_irqrestore(&catc->tx_lock, flags); - catc->stats.tx_bytes += skb->len; - catc->stats.tx_packets++; + if (r >= 0) { + catc->stats.tx_bytes += skb->len; + catc->stats.tx_packets++; + } dev_kfree_skb(skb);