[PATCH] arch/ppc/8xx_io/enet.c, version 3

Joakim Tjernlund joakim.tjernlund at lumentis.se
Tue Feb 11 01:35:34 EST 2003


> Hi there,
>
> has someone actually ported Jocke's patch to 8xx FEC !?
>
> Any benchmarks?
>
> Thanks,
>
> Steven

Actually I had a copy at work so here it goes. Not tested(not even compiled)

 Jocke

--- arch/ppc/8xx_io/fec.c	Fri Nov  1 14:44:05 2002
+++ arch/ppc/8xx_io/new_fec.c	Sun Feb  9 14:24:45 2003
@@ -83,26 +83,34 @@
 } phy_info_t;
 #endif	/* CONFIG_USE_MDIO */

+/* Define COPY_SMALL_FRAMES if you want to save buffer memory for small packets
+ * at a small performance hit. Note performance testing needed */
+/* #define COPY_SMALL_FRAMES 1  */
+
+#ifdef COPY_SMALL_FRAMES
+  #define RX_COPYBREAK (256-16) /* dev_alloc_skb() adds 16 bytes for internal use */
+#endif
+
+
 /* 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.
  * We don't need to allocate pages for the transmitter.  We just use
  * the skbuffer directly.
  */
+
 #ifdef CONFIG_ENET_BIG_BUFFERS
-#define FEC_ENET_RX_PAGES	16
-#define FEC_ENET_RX_FRSIZE	2048
-#define FEC_ENET_RX_FRPPG	(PAGE_SIZE / FEC_ENET_RX_FRSIZE)
-#define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
-#define TX_RING_SIZE		16	/* Must be power of two */
-#define TX_RING_MOD_MASK	15	/*   for this to work */
+  #define RX_RING_SIZE		32
+  #define TX_RING_SIZE		16	/* Must be power of two for this to work */
 #else
-#define FEC_ENET_RX_PAGES	4
-#define FEC_ENET_RX_FRSIZE	2048
-#define FEC_ENET_RX_FRPPG	(PAGE_SIZE / FEC_ENET_RX_FRSIZE)
-#define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
-#define TX_RING_SIZE		8	/* Must be power of two */
-#define TX_RING_MOD_MASK	7	/*   for this to work */
+  #define RX_RING_SIZE		8
+  #define TX_RING_SIZE		8	/* Must be power of two for this to work */
+#endif
+#define TX_RING_MOD_MASK	(TX_RING_SIZE-1)
+
+#define CPM_ENET_RX_FRSIZE	1552 /* must be a multiple of cache line */
+#if CPM_ENET_RX_FRSIZE % L1_CACHE_LINE_SIZE != 0
+    #error CPM_ENET_RX_FRSIZE must be a multiple of L1 cache size
 #endif

 /* Interrupt events/masks.
@@ -573,7 +581,7 @@

 	/* Check for errors. */
 	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
-			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+			   BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_CL)) {
 		fep->stats.rx_errors++;
 		if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
 		/* Frame too long or too short. */
@@ -585,41 +593,53 @@
 			fep->stats.rx_crc_errors++;
 		if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
 			fep->stats.rx_crc_errors++;
-	}
-
-	/* Report late collisions as a frame error.
-	 * On this error, the BD is closed, but we don't know what we
-	 * have in the buffer.  So, just drop this frame on the floor.
-	 */
-	if (bdp->cbd_sc & BD_ENET_RX_CL) {
-		fep->stats.rx_errors++;
-		fep->stats.rx_frame_errors++;
-		goto rx_processing_done;
-	}
-
-	/* Process the incoming frame.
-	 */
-	fep->stats.rx_packets++;
-	pkt_len = bdp->cbd_datlen;
-	fep->stats.rx_bytes += pkt_len;
-	data = fep->rx_vaddr[bdp - fep->rx_bd_base];
-
-	/* This does 16 byte alignment, exactly what we need.
-	 * The packet length includes FCS, but we don't want to
-	 * include that when passing upstream as it messes up
-	 * bridging applications.
-	 */
-	skb = dev_alloc_skb(pkt_len-4);
-
-	if (skb == NULL) {
-		printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-		fep->stats.rx_dropped++;
+		if (bdp->cbd_sc & BD_ENET_RX_CL)	/* Late collision */
+			fep->stats.rx_frame_errors++;	/* Report as a frame error. */
 	} else {
-		skb->dev = dev;
-		skb_put(skb,pkt_len-4);	/* Make room */
-		eth_copy_and_sum(skb, data, pkt_len-4, 0);
-		skb->protocol=eth_type_trans(skb,dev);
-		netif_rx(skb);
+
+		/* Process the incoming frame.
+		 */
+		fep->stats.rx_packets++;
+		pkt_len = bdp->cbd_datlen;
+		fep->stats.rx_bytes += pkt_len;
+		pkt_len -= 4; /* The packet length includes FCS, but we don't want to
+			       * include that when passing upstream as it messes up
+			       * bridging applications. Is this still true ???? */
+#ifdef COPY_SMALL_FRAMES
+		/* Allocate the next buffer now so we are sure to have one when needed
+		 * This does 16 byte alignment, exactly what we need(L1_CACHE aligned). */
+		if(pkt_len < RX_COPYBREAK)
+			skb_tmp = __dev_alloc_skb(pkt_len, GFP_ATOMIC | GFP_DMA);
+		else
+#endif
+			skb_tmp = __dev_alloc_skb(CPM_ENET_RX_FRSIZE, GFP_ATOMIC | GFP_DMA);
+
+		if (skb_tmp == NULL) {
+			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+			fep->stats.rx_dropped++;
+
+		} else {
+			skb = fep->rx_vaddr[bdp - fep->rx_bd_base];
+#ifdef COPY_SMALL_FRAMES
+			if(pkt_len < RX_COPYBREAK) {
+				typeof(skb) skb_swap = skb;
+				memcpy(skb_put(skb_tmp, pkt_len), skb->data, pkt_len);
+				/* swap the skb and skb_tmp */
+				skb = skb_tmp;
+				skb_tmp = skb_swap;
+			}
+			else
+#endif
+			{
+				skb_put(skb, pkt_len);  /* Make room */
+				bdp->cbd_bufaddr = __pa(skb_tmp->data);
+				fep->rx_vaddr[bdp - fep->rx_bd_base] = skb_tmp;
+			}
+			dma_cache_inv((unsigned long) skb_tmp->data, CPM_ENET_RX_FRSIZE);
+			skb->dev = dev;
+			skb->protocol=eth_type_trans(skb, dev);
+			netif_rx(skb);
+		}
 	}
   rx_processing_done:

@@ -1662,7 +1682,7 @@

 			dmi = dev->mc_list;

-			for (i=0; i<dev->mc_count; i++) {
+			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {

 				/* Only support group multicast for now.
 				*/
@@ -1698,8 +1718,7 @@
 	struct net_device *dev;
 	struct fec_enet_private *fep;
 	int i, j, k;
-	unsigned char	*eap, *iap, *ba;
-	unsigned long	mem_addr;
+	unsigned char	*eap, *iap;
 	volatile	cbd_t	*bdp;
 	cbd_t		*cbd_base;
 	volatile	immap_t	*immap;
@@ -1783,24 +1802,15 @@
 	*/
 	bdp = fep->rx_bd_base;
 	k = 0;
-	for (i=0; i<FEC_ENET_RX_PAGES; i++) {
-
-		/* Allocate a page.
-		*/
-		ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
-			bdp->cbd_sc = BD_ENET_RX_EMPTY;
-			bdp->cbd_bufaddr = mem_addr;
-			fep->rx_vaddr[k++] = ba;
-			mem_addr += FEC_ENET_RX_FRSIZE;
-			ba += FEC_ENET_RX_FRSIZE;
-			bdp++;
-		}
+	/* Initialize the BDs. */
+	for (j=0; j < RX_RING_SIZE; j++) {
+		struct	sk_buff * skb = __dev_alloc_skb(CPM_ENET_RX_FRSIZE, GFP_ATOMIC | GFP_DMA);
+		dma_cache_inv((unsigned long) skb->data, CPM_ENET_RX_FRSIZE);
+		bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+		bdp->cbd_bufaddr = __pa(skb->data);
+		fep->rx_vaddr[k++] = skb;
+		bdp++;
 	}
-
 	/* Set the last buffer to wrap.
 	*/
 	bdp--;


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/





More information about the Linuxppc-embedded mailing list