arm: tegra: comms: Enable autopm for RAW-IP network driver.
[linux-2.6.git] / drivers / net / 82596.c
index 97c5fc0..be1f197 100644 (file)
@@ -191,7 +191,7 @@ enum commands {
 #define         RX_SUSPEND     0x0030
 #define         RX_ABORT       0x0040
 
-#define TX_TIMEOUT     5
+#define TX_TIMEOUT     (HZ/20)
 
 
 struct i596_reg {
@@ -525,7 +525,21 @@ static irqreturn_t i596_error(int irq, void *dev_id)
 }
 #endif
 
-static inline void init_rx_bufs(struct net_device *dev)
+static inline void remove_rx_bufs(struct net_device *dev)
+{
+       struct i596_private *lp = dev->ml_priv;
+       struct i596_rbd *rbd;
+       int i;
+
+       for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
+               if (rbd->skb == NULL)
+                       break;
+               dev_kfree_skb(rbd->skb);
+               rbd->skb = NULL;
+       }
+}
+
+static inline int init_rx_bufs(struct net_device *dev)
 {
        struct i596_private *lp = dev->ml_priv;
        int i;
@@ -537,8 +551,11 @@ static inline void init_rx_bufs(struct net_device *dev)
        for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
                struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
 
-               if (skb == NULL)
-                       panic("82596: alloc_skb() failed");
+               if (skb == NULL) {
+                       remove_rx_bufs(dev);
+                       return -ENOMEM;
+               }
+
                skb->dev = dev;
                rbd->v_next = rbd+1;
                rbd->b_next = WSWAPrbd(virt_to_bus(rbd+1));
@@ -574,19 +591,8 @@ static inline void init_rx_bufs(struct net_device *dev)
        rfd->v_next = lp->rfds;
        rfd->b_next = WSWAPrfd(virt_to_bus(lp->rfds));
        rfd->cmd = CMD_EOL|CMD_FLEX;
-}
 
-static inline void remove_rx_bufs(struct net_device *dev)
-{
-       struct i596_private *lp = dev->ml_priv;
-       struct i596_rbd *rbd;
-       int i;
-
-       for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
-               if (rbd->skb == NULL)
-                       break;
-               dev_kfree_skb(rbd->skb);
-       }
+       return 0;
 }
 
 
@@ -1009,20 +1015,35 @@ static int i596_open(struct net_device *dev)
        }
 #ifdef ENABLE_MVME16x_NET
        if (MACH_IS_MVME16x) {
-               if (request_irq(0x56, i596_error, 0, "i82596_error", dev))
-                       return -EAGAIN;
+               if (request_irq(0x56, i596_error, 0, "i82596_error", dev)) {
+                       res = -EAGAIN;
+                       goto err_irq_dev;
+               }
        }
 #endif
-       init_rx_bufs(dev);
+       res = init_rx_bufs(dev);
+       if (res)
+               goto err_irq_56;
 
        netif_start_queue(dev);
 
-       /* Initialize the 82596 memory */
        if (init_i596_mem(dev)) {
                res = -EAGAIN;
-               free_irq(dev->irq, dev);
+               goto err_queue;
        }
 
+       return 0;
+
+err_queue:
+       netif_stop_queue(dev);
+       remove_rx_bufs(dev);
+err_irq_56:
+#ifdef ENABLE_MVME16x_NET
+       free_irq(0x56, dev);
+err_irq_dev:
+#endif
+       free_irq(dev->irq, dev);
+
        return res;
 }
 
@@ -1050,7 +1071,7 @@ static void i596_tx_timeout (struct net_device *dev)
                lp->last_restart = dev->stats.tx_packets;
        }
 
-       dev->trans_start = jiffies;
+       dev->trans_start = jiffies; /* prevent tx timeout */
        netif_wake_queue (dev);
 }
 
@@ -1060,7 +1081,6 @@ static netdev_tx_t i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct tx_cmd *tx_cmd;
        struct i596_tbd *tbd;
        short length = skb->len;
-       dev->trans_start = jiffies;
 
        DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%p) called\n",
                                dev->name, skb->len, skb->data));
@@ -1489,6 +1509,9 @@ static int i596_close(struct net_device *dev)
        }
 #endif
 
+#ifdef ENABLE_MVME16x_NET
+       free_irq(0x56, dev);
+#endif
        free_irq(dev->irq, dev);
        remove_rx_bufs(dev);