📄 fec.c.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 + -