⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fec.c.patch1

📁 实现一个网卡到内存空间的零拷贝程序
💻 PATCH1
字号:
--- fec.c.orig	Wed May 23 10:00:28 2001+++ fec.c	Wed May 23 12:47:49 2001@@ -23,14 +23,21 @@  * Make use of MII for PHY control configurable.  * Some fixes.  * Copyright (c) 2000 Wolfgang Denk, DENX Software Engineering.+ *+ * Experimental support for scatter/gather.+ * Joris van Rantwijk, May 2001.  */  /* List of PHYs we wish to support. */-#undef	CONFIG_FEC_LXT970-#define	CONFIG_FEC_LXT971+#define	CONFIG_FEC_LXT970+#undef	CONFIG_FEC_LXT971 #undef	CONFIG_FEC_QS6612 +#if defined(CONFIG_FEC_SUPPORT_SG) && !defined(CONFIG_ENET_BIG_BUFFERS)+#error "Must use big buffers for scatter/gather support on MPC8xx FEC"+#endif+ #include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h>@@ -163,6 +170,7 @@ 	scc_t	*sccp; 	struct	net_device_stats stats; 	uint	tx_full;+	uint	tx_ring_len; 	spinlock_t lock;  #ifdef	CONFIG_USE_MDIO@@ -381,11 +389,50 @@ 	fep->stats.tx_bytes += skb->len; 	fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; +#ifdef CONFIG_FEC_SUPPORT_SG+	if (skb_shinfo(skb)->nr_frags > 0) {+		/* Put additional fragments in seperate buffers */++		skb_frag_t *frag = skb_shinfo(skb)->frags;+		volatile cbd_t *fbdp = bdp;+		int i;++		/* Note: skb->len is total length including all fragments */+		bdp->cbd_datlen -= skb->data_len;+		flush_dcache_range((unsigned long)skb->data,+		                   (unsigned long)skb->data + skb->len - skb->data_len);++		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++, frag++) {+			unsigned long faddr = (unsigned long) page_address(frag->page) + frag->page_offset;+			unsigned long flen = frag->size;++			/* Get next BD, wrap around end */+			if (fbdp->cbd_sc & BD_ENET_TX_WRAP)+				fbdp = fep->tx_bd_base;+			else+				fbdp++;+#ifndef final_version+			if (fbdp->cbd_sc & BD_ENET_TX_READY)+				printk(KERN_CRIT "fec: rhaaa: tx BD ring full\n");+#endif+			/* Clear all of the status flags. */+			fbdp->cbd_sc &= ~BD_ENET_TX_STATS;++			/* Set buffer length and buffer pointer. */+			fbdp->cbd_bufaddr = __pa(faddr);+			fbdp->cbd_datlen = flen;++			/* Push the data cache. */+			flush_dcache_range(faddr, faddr + flen);+		}+	} else /* WATCH OUT FOR THIS ELSE */+#endif 	/* Push the data cache so the CPM does not get stale memory 	 * data. 	 */ 	flush_dcache_range((unsigned long)skb->data, 			   (unsigned long)skb->data + skb->len);+/* END IF FRAGMENTS */  	spin_lock_irq(&fep->lock); @@ -393,6 +440,19 @@ 	 * its the last BD of the frame, and to put the CRC on the end. 	 */ +#ifdef CONFIG_FEC_SUPPORT_SG+	if (skb_shinfo(skb)->nr_frags > 0) {+		int i;+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {+			bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR);+			if (bdp->cbd_sc & BD_ENET_TX_WRAP)+				bdp = fep->tx_bd_base;+			else+				bdp++;+			fep->tx_ring_len++;+		}+	}+#endif 	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR 			| BD_ENET_TX_LAST | BD_ENET_TX_TC); @@ -408,8 +468,16 @@ 	} else { 		bdp++; 	}+	fep->tx_ring_len++;  	if (bdp->cbd_sc & BD_ENET_TX_READY)+		fep->tx_full = 1;++#ifdef CONFIG_FEC_SUPPORT_SG+	if (fep->tx_ring_len + MAX_SKB_FRAGS >= TX_RING_SIZE)+#else+	if (fep->tx_ring_len >= TX_RING_SIZE)+#endif 		netif_stop_queue(dev);  	fep->cur_tx = (cbd_t *)bdp;@@ -541,53 +609,55 @@ 	while ((bdp->cbd_sc&BD_ENET_TX_READY) == 0) { 		if (bdp == fep->cur_tx && fep->tx_full == 0) break; -		skb = fep->tx_skbuff[fep->skb_dirty];-		/* Check for errors. */-		if (bdp->cbd_sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |-				   BD_ENET_TX_RL | BD_ENET_TX_UN |-				   BD_ENET_TX_CSL)) {-			fep->stats.tx_errors++;-			if (bdp->cbd_sc & BD_ENET_TX_HB)  /* No heartbeat */-				fep->stats.tx_heartbeat_errors++;-			if (bdp->cbd_sc & BD_ENET_TX_LC)  /* Late collision */-				fep->stats.tx_window_errors++;-			if (bdp->cbd_sc & BD_ENET_TX_RL)  /* Retrans limit */-				fep->stats.tx_aborted_errors++;-			if (bdp->cbd_sc & BD_ENET_TX_UN)  /* Underrun */-				fep->stats.tx_fifo_errors++;-			if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */-				fep->stats.tx_carrier_errors++;-		} else {+		if (bdp->cbd_sc & BD_ENET_TX_LAST) {+			/* Was last buffer of frame: check for errors+			   and deal with skb. */++			skb = fep->tx_skbuff[fep->skb_dirty];+			/* Check for errors. */+			if (bdp->cbd_sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |+					   BD_ENET_TX_RL | BD_ENET_TX_UN |+					   BD_ENET_TX_CSL)) {+				fep->stats.tx_errors++;+				if (bdp->cbd_sc & BD_ENET_TX_HB)  /* No heartbeat */+					fep->stats.tx_heartbeat_errors++;+				if (bdp->cbd_sc & BD_ENET_TX_LC)  /* Late collision */+					fep->stats.tx_window_errors++;+				if (bdp->cbd_sc & BD_ENET_TX_RL)  /* Retrans limit */+					fep->stats.tx_aborted_errors++;+				if (bdp->cbd_sc & BD_ENET_TX_UN)  /* Underrun */+					fep->stats.tx_fifo_errors++;+				if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */+					fep->stats.tx_carrier_errors++;+			} else { #ifdef CONFIG_FEC_PACKETHOOK-			/* Packet hook ... */-			if (fep->ph_txhandler &&-			    ((struct ethhdr *)skb->data)->h_proto-			    == fep->ph_proto) {-				fep->ph_txhandler((__u8*)skb->data, skb->len,-						  regval, fep->ph_priv);-			}+				/* Packet hook ... */+				if (fep->ph_txhandler &&+				    ((struct ethhdr *)skb->data)->h_proto+				    == fep->ph_proto) {+					fep->ph_txhandler((__u8*)skb->data, skb->len,+							  regval, fep->ph_priv);+				} #endif-			fep->stats.tx_packets++;-		}+				fep->stats.tx_packets++;+			} -#ifndef final_version-		if (bdp->cbd_sc & BD_ENET_TX_READY)-			printk("HEY! Enet xmit interrupt and TX_READY.\n");-#endif-		/* Deferred means some collisions occurred during transmit,-		 * but we eventually sent the packet OK.-		 */-		if (bdp->cbd_sc & BD_ENET_TX_DEF)-			fep->stats.collisions++;+			/* Deferred means some collisions occurred during transmit,+			 * but we eventually sent the packet OK.+			 */+			if (bdp->cbd_sc & BD_ENET_TX_DEF)+				fep->stats.collisions++; -		/* Free the sk buffer associated with this last transmit.-		 */+			/* Free the sk buffer associated with this last transmit.+			 */ #if 0 printk("TXI: %x %x %x\n", bdp, skb, fep->skb_dirty); #endif-		dev_kfree_skb_irq (skb/*, FREE_WRITE*/);-		fep->tx_skbuff[fep->skb_dirty] = NULL;-		fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;+			dev_kfree_skb_irq (skb/*, FREE_WRITE*/);+			fep->tx_skbuff[fep->skb_dirty] = NULL;+			fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;++		}  		/* Update pointer to next buffer descriptor to be transmitted. 		 */@@ -595,21 +665,26 @@ 			bdp = fep->tx_bd_base; 		else 			bdp++;+		fep->tx_ring_len--; -		/* Since we have freed up a buffer, the ring is no longer-		 * full.-		 */-		if (fep->tx_full) {-			fep->tx_full = 0;-			if (netif_queue_stopped(dev))-				netif_wake_queue(dev);-		} #ifdef CONFIG_FEC_PACKETHOOK 		/* Re-read register. Not exactly guaranteed to be correct, 		   but... */ 		if (fep->ph_regaddr) regval = *fep->ph_regaddr; #endif 	}++	/* Wake queue if there is enough room in the tx ring */+#ifdef CONFIG_FEC_SUPPORT_SG+	if (fep->tx_full && fep->tx_ring_len + MAX_SKB_FRAGS < TX_RING_SIZE) {+#else+	if (fep->tx_full && fep->tx_ring_len < TX_RING_SIZE) {+#endif+		fep->tx_full = 0;+		if (netif_queue_stopped(dev))+			netif_wake_queue(dev);+	}+ 	fep->dirty_tx = (cbd_t *)bdp; 	spin_unlock(&fep->lock); }@@ -1852,8 +1927,10 @@  	/* Enable interrupts we wish to service. 	*/+/* Joris: don't ask for TXB and RXB, we won't use them anyway. 	fecp->fec_imask = ( FEC_ENET_TXF | FEC_ENET_TXB |-			    FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII );+			    FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII ); */+	fecp->fec_imask = ( FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII );  	/* And last, enable the transmit and receive processing. 	*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -