]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/net/catc.c
Merge git://git.infradead.org/mtd-2.6
[linux-2.6-omap-h63xx.git] / drivers / usb / net / catc.c
index 4852012735f66c207030abb7676136ff43a0f3cd..86e90c59d55156473058e9ae6a2a6137da8e5283 100644 (file)
@@ -255,7 +255,6 @@ static void catc_rx_done(struct urb *urb)
                if (!(skb = dev_alloc_skb(pkt_len)))
                        return;
 
-               skb->dev = catc->netdev;
                eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
                skb_put(skb, pkt_len);
 
@@ -356,7 +355,7 @@ resubmit:
  * Transmit routines.
  */
 
-static void catc_tx_run(struct catc *catc)
+static int catc_tx_run(struct catc *catc)
 {
        int status;
 
@@ -374,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.");
@@ -398,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);
 
@@ -412,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);
@@ -419,11 +424,14 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
        catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
        tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
        *((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
-       memcpy(tx_buf + 2, skb->data, skb->len);
+       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))))
@@ -431,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);