Merge branch 'for_paulus' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc
[pandora-kernel.git] / drivers / net / mv643xx_eth.c
index 50ee085..ea62a3e 100644 (file)
@@ -132,25 +132,21 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
 }
 
 /*
- * mv643xx_eth_rx_task
+ * mv643xx_eth_rx_refill_descs
  *
  * Fills / refills RX queue on a certain gigabit ethernet port
  *
  * Input :     pointer to ethernet interface network device structure
  * Output :    N/A
  */
-static void mv643xx_eth_rx_task(void *data)
+static void mv643xx_eth_rx_refill_descs(struct net_device *dev)
 {
-       struct net_device *dev = (struct net_device *)data;
        struct mv643xx_private *mp = netdev_priv(dev);
        struct pkt_info pkt_info;
        struct sk_buff *skb;
        int unaligned;
 
-       if (test_and_set_bit(0, &mp->rx_task_busy))
-               panic("%s: Error in test_set_bit / clear_bit", dev->name);
-
-       while (mp->rx_desc_count < (mp->rx_ring_size - 5)) {
+       while (mp->rx_desc_count < mp->rx_ring_size) {
                skb = dev_alloc_skb(ETH_RX_SKB_SIZE + ETH_DMA_ALIGN);
                if (!skb)
                        break;
@@ -170,29 +166,19 @@ static void mv643xx_eth_rx_task(void *data)
                }
                skb_reserve(skb, ETH_HW_IP_ALIGN);
        }
-       clear_bit(0, &mp->rx_task_busy);
        /*
         * If RX ring is empty of SKB, set a timer to try allocating
-        * again in a later time .
+        * again at a later time.
         */
-       if ((mp->rx_desc_count == 0) && (mp->rx_timer_flag == 0)) {
+       if (mp->rx_desc_count == 0) {
                printk(KERN_INFO "%s: Rx ring is empty\n", dev->name);
-               /* After 100mSec */
-               mp->timeout.expires = jiffies + (HZ / 10);
+               mp->timeout.expires = jiffies + (HZ / 10);      /* 100 mSec */
                add_timer(&mp->timeout);
-               mp->rx_timer_flag = 1;
-       }
-#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
-       else {
-               /* Return interrupts */
-               mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num),
-                                                       INT_UNMASK_ALL);
        }
-#endif
 }
 
 /*
- * mv643xx_eth_rx_task_timer_wrapper
+ * mv643xx_eth_rx_refill_descs_timer_wrapper
  *
  * Timer routine to wake up RX queue filling task. This function is
  * used only in case the RX queue is empty, and all alloc_skb has
@@ -201,13 +187,9 @@ static void mv643xx_eth_rx_task(void *data)
  * Input :     pointer to ethernet interface network device structure
  * Output :    N/A
  */
-static void mv643xx_eth_rx_task_timer_wrapper(unsigned long data)
+static inline void mv643xx_eth_rx_refill_descs_timer_wrapper(unsigned long data)
 {
-       struct net_device *dev = (struct net_device *)data;
-       struct mv643xx_private *mp = netdev_priv(dev);
-
-       mp->rx_timer_flag = 0;
-       mv643xx_eth_rx_task((void *)data);
+       mv643xx_eth_rx_refill_descs((struct net_device *)data);
 }
 
 /*
@@ -299,10 +281,16 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
 {
        struct mv643xx_private *mp = netdev_priv(dev);
 
-       netif_device_detach(dev);
+       if (!netif_running(dev))
+               return;
+
+       netif_stop_queue(dev);
+
        eth_port_reset(mp->port_num);
        eth_port_start(dev);
-       netif_device_attach(dev);
+
+       if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
+               netif_wake_queue(dev);
 }
 
 /**
@@ -388,11 +376,7 @@ static void mv643xx_eth_free_all_tx_descs(struct net_device *dev)
  *
  * Output :    number of served packets
  */
-#ifdef MV643XX_NAPI
 static int mv643xx_eth_receive_queue(struct net_device *dev, int budget)
-#else
-static int mv643xx_eth_receive_queue(struct net_device *dev)
-#endif
 {
        struct mv643xx_private *mp = netdev_priv(dev);
        struct net_device_stats *stats = &mp->stats;
@@ -400,15 +384,14 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
        struct sk_buff *skb;
        struct pkt_info pkt_info;
 
-#ifdef MV643XX_NAPI
        while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) {
-#else
-       while (eth_port_receive(mp, &pkt_info) == ETH_OK) {
-#endif
                mp->rx_desc_count--;
                received_packets++;
 
-               /* Update statistics. Note byte count includes 4 byte CRC count */
+               /*
+                * Update statistics.
+                * Note byte count includes 4 byte CRC count
+                */
                stats->rx_packets++;
                stats->rx_bytes += pkt_info.byte_cnt;
                skb = pkt_info.return_info;
@@ -456,6 +439,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
                }
                dev->last_rx = jiffies;
        }
+       mv643xx_eth_rx_refill_descs(dev);       /* Fill RX ring with skb's */
 
        return received_packets;
 }
@@ -532,65 +516,16 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
        /* Read interrupt cause registers */
        eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
                                                ETH_INT_UNMASK_ALL;
-
-       if (eth_int_cause & BIT1)
+       if (eth_int_cause & ETH_INT_CAUSE_EXT) {
                eth_int_cause_ext = mv_read(
                        MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
                                                ETH_INT_UNMASK_ALL_EXT;
-
-#ifdef MV643XX_NAPI
-       if (!(eth_int_cause & 0x0007fffd)) {
-               /* Dont ack the Rx interrupt */
-#endif
-               /*
-                * Clear specific ethernet port intrerrupt registers by
-                * acknowleding relevant bits.
-                */
-               mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num),
-                                                       ~eth_int_cause);
-               if (eth_int_cause_ext != 0x0) {
-                       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG
-                                       (port_num), ~eth_int_cause_ext);
-                       /* UDP change : We may need this */
-                       if (eth_int_cause_ext & (BIT0 | BIT8))
-                               mv643xx_eth_free_completed_tx_descs(dev);
-               }
-#ifdef MV643XX_NAPI
-       } else {
-               if (netif_rx_schedule_prep(dev)) {
-                       /* Mask all the interrupts */
-                       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-                                                       ETH_INT_MASK_ALL);
-                       /* wait for previous write to complete */
-                       mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
-                       __netif_rx_schedule(dev);
-               }
-#else
-               if (eth_int_cause & (BIT2 | BIT11))
-                       mv643xx_eth_receive_queue(dev, 0);
-
-               /*
-                * After forwarded received packets to upper layer, add a task
-                * in an interrupts enabled context that refills the RX ring
-                * with skb's.
-                */
-#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
-               /* Mask all interrupts on ethernet port */
-               mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-                                                       INT_MASK_ALL);
-               /* wait for previous write to take effect */
-               mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
-
-               queue_task(&mp->rx_task, &tq_immediate);
-               mark_bh(IMMEDIATE_BH);
-#else
-               mp->rx_task.func(dev);
-#endif
-#endif
+               mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),
+                                                       ~eth_int_cause_ext);
        }
 
        /* PHY status changed */
-       if (eth_int_cause_ext & (BIT16 | BIT20)) {
+       if (eth_int_cause_ext & ETH_INT_CAUSE_PHY) {
                struct ethtool_cmd cmd;
 
                if (mii_link_ok(&mp->mii)) {
@@ -610,6 +545,23 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
                }
        }
 
+#ifdef MV643XX_NAPI
+       if (eth_int_cause & ETH_INT_CAUSE_RX) {
+               /* schedule the NAPI poll routine to maintain port */
+               mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+                                                       ETH_INT_MASK_ALL);
+               /* wait for previous write to complete */
+               mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
+               netif_rx_schedule(dev);
+       }
+#else
+       if (eth_int_cause & ETH_INT_CAUSE_RX)
+               mv643xx_eth_receive_queue(dev, INT_MAX);
+#endif
+       if (eth_int_cause_ext & ETH_INT_CAUSE_TX)
+               mv643xx_eth_free_completed_tx_descs(dev);
+
        /*
         * If no real interrupt occured, exit.
         * This can happen when using gigE interrupt coalescing mechanism.
@@ -835,15 +787,10 @@ static int mv643xx_eth_open(struct net_device *dev)
 
        eth_port_init(mp);
 
-       INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev);
-
        memset(&mp->timeout, 0, sizeof(struct timer_list));
-       mp->timeout.function = mv643xx_eth_rx_task_timer_wrapper;
+       mp->timeout.function = mv643xx_eth_rx_refill_descs_timer_wrapper;
        mp->timeout.data = (unsigned long)dev;
 
-       mp->rx_task_busy = 0;
-       mp->rx_timer_flag = 0;
-
        /* Allocate RX and TX skb rings */
        mp->rx_skb = kmalloc(sizeof(*mp->rx_skb) * mp->rx_ring_size,
                                                                GFP_KERNEL);
@@ -916,7 +863,7 @@ static int mv643xx_eth_open(struct net_device *dev)
 
        ether_init_rx_desc_ring(mp);
 
-       mv643xx_eth_rx_task(dev);       /* Fill RX ring with skb's */
+       mv643xx_eth_rx_refill_descs(dev);       /* Fill RX ring with skb's */
 
        /* Clear any pending ethernet port interrupts */
        mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
@@ -1068,7 +1015,6 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
                if (orig_budget > dev->quota)
                        orig_budget = dev->quota;
                work_done = mv643xx_eth_receive_queue(dev, orig_budget);
-               mp->rx_task.func(dev);
                *budget -= work_done;
                dev->quota -= work_done;
                if (work_done >= orig_budget)
@@ -1246,7 +1192,12 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        BUG_ON(netif_queue_stopped(dev));
        BUG_ON(skb == NULL);
-       BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB);
+
+       if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
+               printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
+               netif_stop_queue(dev);
+               return 1;
+       }
 
        if (has_tiny_unaligned_frags(skb)) {
                if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {