patch-2.4.27 linux-2.4.27/arch/ppc/cpm2_io/fcc_enet.c

Next file: linux-2.4.27/arch/ppc/kernel/head_44x.S
Previous file: linux-2.4.27/arch/ppc/config.in
Back to the patch index
Back to the overall index

diff -urN linux-2.4.26/arch/ppc/cpm2_io/fcc_enet.c linux-2.4.27/arch/ppc/cpm2_io/fcc_enet.c
@@ -305,6 +305,8 @@
 	ushort	skb_cur;
 	ushort	skb_dirty;
 
+	atomic_t n_pkts;        /* Number of packets in tx ring */
+
 	/* CPM dual port RAM relative addresses.
 	*/
 	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
@@ -396,13 +398,15 @@
 	bdp->cbd_datlen = skb->len;
 	bdp->cbd_bufaddr = __pa(skb->data);
 
+	spin_lock_irq(&cep->lock);
+
 	/* Save skb pointer. */
 	cep->tx_skbuff[cep->skb_cur] = skb;
 
 	cep->stats.tx_bytes += skb->len;
 	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
 
-	spin_lock_irq(&cep->lock);
+	atomic_inc(&cep->n_pkts);
 
 	/* 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.
@@ -421,9 +425,12 @@
 	else
 		bdp++;
 
-	if (bdp->cbd_sc & BD_ENET_TX_READY) {
-		netif_stop_queue(dev);
+	/* If the tx_ring is full, stop the queue */
+	if (atomic_read(&cep->n_pkts) >= (TX_RING_SIZE-1)) {
+	  if (!netif_queue_stopped(dev)) {
+	  	netif_stop_queue(dev);
 		cep->tx_full = 1;
+	  }
 	}
 
 	cep->cur_tx = (cbd_t *)bdp;
@@ -542,6 +549,8 @@
 		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
 		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
 
+		atomic_dec(&cep->n_pkts);
+
 		/* Update pointer to next buffer descriptor to be transmitted. */
 		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
 			bdp = cep->tx_bd_base;
@@ -1782,6 +1791,7 @@
 	while (cp->cp_cpcr & CPM_CR_FLG);
 
 	cep->skb_cur = cep->skb_dirty = 0;
+	atomic_set(&cep->n_pkts, 0);
 }
 
 /* Let 'er rip.

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)