[patch, resent] Softnet changes for arch/ppc/8xx_io/enet.c

From: Daniel Marmier (daniel.marmier@lightning.ch)
Date: Wed Apr 12 2000 - 01:13:11 EST


Alan Cox wrote:
>
> The diff is corrupt. Looks like your mailer trashed it

Yes, it did (forgot to disable text wrapping). Here is a hopefully better one.

                                Daniel Marmier

diff -urN linux-2.3.99-pre3/arch/ppc/8xx_io/enet.c linux-2.3.99-pre3-dm/arch/ppc/8xx_io/enet.c
--- linux-2.3.99-pre3/arch/ppc/8xx_io/enet.c Tue Dec 14 15:06:03 1999
+++ linux-2.3.99-pre3-dm/arch/ppc/8xx_io/enet.c Mon Apr 10 09:17:49 2000
@@ -37,6 +37,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/spinlock.h>
 
 #include <asm/8xx_immap.h>
 #include <asm/pgtable.h>
@@ -108,6 +109,10 @@
  * Port C, 9 (CTS2) - SCC Ethernet Collision
  */
 
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT (200*HZ/1000)
+
 /* The number of Tx and Rx buffers. These are allocated from the page
  * pool. The code may assume these are power of two, so it is best
  * to keep them that size.
@@ -149,8 +154,8 @@
         cbd_t *dirty_tx; /* The ring entries to be free()ed. */
         scc_t *sccp;
         struct net_device_stats stats;
- char tx_full;
- unsigned long lock;
+ int tx_full;
+ spinlock_t lock;
 };
 
 static int cpm_enet_open(struct net_device *dev);
@@ -190,9 +195,7 @@
          * a simple way to do that.
          */
 
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
 
         return 0; /* Always succeed */
 }
@@ -202,55 +205,6 @@
 {
         struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
         volatile cbd_t *bdp;
- unsigned long flags;
-
- /* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 200)
- return 1;
- printk("%s: transmit timed out.\n", dev->name);
- cep->stats.tx_errors++;
-#ifndef final_version
- {
- int i;
- cbd_t *bdp;
- printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
- cep->cur_tx, cep->tx_full ? " (full)" : "",
- cep->cur_rx);
- bdp = cep->tx_bd_base;
- for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
- printk("%04x %04x %08x\n",
- bdp->cbd_sc,
- bdp->cbd_datlen,
- bdp->cbd_bufaddr);
- bdp = cep->rx_bd_base;
- for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
- printk("%04x %04x %08x\n",
- bdp->cbd_sc,
- bdp->cbd_datlen,
- bdp->cbd_bufaddr);
- }
-#endif
-
- dev->tbusy=0;
- dev->trans_start = jiffies;
-
- return 0;
- }
-
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
-
- if (test_and_set_bit(0, (void*)&cep->lock) != 0) {
- printk("%s: tx queue lock!.\n", dev->name);
- /* don't clear dev->tbusy flag. */
- return 1;
- }
 
         /* Fill in a Tx ring entry */
         bdp = cep->cur_tx;
@@ -261,7 +215,6 @@
                  * This should not happen, since dev->tbusy should be set.
                  */
                 printk("%s: tx queue full!.\n", dev->name);
- cep->lock = 0;
                 return 1;
         }
 #endif
@@ -292,7 +245,9 @@
         /* Push the data cache so the CPM does not get stale memory
          * data.
          */
- flush_dcache_range(skb->data, skb->data + skb->len);
+ flush_dcache_range((unsigned long)skb->data, (unsigned long)skb->data + skb->len);
+
+ spin_lock_irq(cep->lock);
 
         /* Send it on its way. Tell CPM its ready, interrupt when done,
          * its the last BD of the frame, and to put the CRC on the end.
@@ -308,20 +263,48 @@
         else
                 bdp++;
 
- save_flags(flags);
- cli();
- cep->lock = 0;
- if (bdp->cbd_sc & BD_ENET_TX_READY)
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
                 cep->tx_full = 1;
- else
- dev->tbusy=0;
- restore_flags(flags);
+ netif_stop_queue(dev);
+ }
 
         cep->cur_tx = (cbd_t *)bdp;
 
+ spin_unlock_irq(cep->lock);
         return 0;
 }
 
+static void cpm_enet_timeout(struct net_device *dev)
+{
+ struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ cep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+ cep->cur_tx, cep->tx_full ? " (full)" : "",
+ cep->cur_rx);
+ bdp = cep->tx_bd_base;
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = cep->rx_bd_base;
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+ if (!cep->tx_full)
+ netif_wake_queue(dev);
+}
+
 /* The interrupt handler.
  * This is called from the CPM handler, not the MPC core interrupt.
  */
@@ -335,10 +318,6 @@
         int must_restart;
 
         cep = (struct cpm_enet_private *)dev->priv;
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
- dev->interrupt = 1;
 
         /* Get the interrupt events that caused us to be here.
         */
@@ -363,6 +342,8 @@
         /* Transmit OK, or non-fatal error. Update the buffer descriptors.
         */
         if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+ spin_lock(&cep->lock);
+
             bdp = cep->dirty_tx;
             while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
                 if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
@@ -394,12 +375,13 @@
                 /* Deferred means some collisions occurred during transmit,
                  * but we eventually sent the packet OK.
                  */
- if (bdp->cbd_sc & BD_ENET_TX_DEF)
- cep->stats.collisions++;
+ if (bdp->cbd_sc & BD_ENET_TX_DEF) {
+ cep->stats.collisions++;
+ }
 
                 /* Free the sk buffer associated with this last transmit.
                 */
- dev_kfree_skb(cep->tx_skbuff[cep->skb_dirty]/*, FREE_WRITE*/);
+ dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
                 cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
 
                 /* Update pointer to next buffer descriptor to be transmitted.
@@ -409,6 +391,15 @@
                 else
                         bdp++;
 
+ /* Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (cep->tx_full) {
+ cep->tx_full = 0;
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ }
+
                 /* I don't know if we can be held off from processing these
                  * interrupts for more than one frame time. I really hope
                  * not. In such a case, we would now want to check the
@@ -418,15 +409,6 @@
                  * does not have BD_ENET_TX_READY set.
                  */
 
- /* Since we have freed up a buffer, the ring is no longer
- * full.
- */
- if (cep->tx_full && dev->tbusy) {
- cep->tx_full = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
-
                 cep->dirty_tx = (cbd_t *)bdp;
             }
 
@@ -444,6 +426,8 @@
                     mk_cr_cmd(CPM_CR_ENET, CPM_CR_RESTART_TX) | CPM_CR_FLG;
                 while (cp->cp_cpcr & CPM_CR_FLG);
             }
+
+ spin_unlock(&cep->lock);
         }
 
         /* Check for receive busy, i.e. packets coming but no place to
@@ -454,10 +438,6 @@
                 cep->stats.rx_dropped++;
                 printk("CPM ENET: BSY can't happen.\n");
         }
-
- dev->interrupt = 0;
-
- return;
 }
 
 /* During a receive, the cur_rx points to the current incoming buffer.
@@ -562,8 +542,7 @@
 static int
 cpm_enet_close(struct net_device *dev)
 {
- /* Don't know what to do yet.
- */
+ netif_stop_queue(dev);
 
         return 0;
 }
@@ -686,6 +665,7 @@
         cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
         /*memset(cep, 0, sizeof(*cep));*/
         __clear_user(cep,sizeof(*cep));
+ spin_lock_init(&cep->lock);
 
         /* Create an Ethernet device instance.
         */
@@ -857,7 +837,7 @@
                 */
                 pte = find_pte(&init_mm, mem_addr);
                 pte_val(*pte) |= _PAGE_NO_CACHE;
- flush_tlb_page(current->mm->mmap, mem_addr);
+ flush_tlb_page(init_mm.mmap, mem_addr);
 
                 /* Initialize the BD for every fragment in the page.
                 */
@@ -954,6 +934,8 @@
         /* The CPM Ethernet specific entries in the device structure. */
         dev->open = cpm_enet_open;
         dev->hard_start_xmit = cpm_enet_start_xmit;
+ dev->tx_timeout = cpm_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
         dev->stop = cpm_enet_close;
         dev->get_stats = cpm_enet_get_stats;
         dev->set_multicast_list = set_multicast_list;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Apr 15 2000 - 21:00:18 EST