Bring overhauled nfe(4) into tree.

o s/printf/device_printf/g
o Nuke OpenBSDism.
o Nuke NetBSD/OpenBSD specific DMA sync operations.(we don't have a way
   to sync a single descriptor within a DMA map.)
o Remove recursive mutex.
o bus_dma(9) clean up.
o 40bit DMA address support.
o Add protection for Rx map load failure.
o Fix a long standing bug for watchdog timeout. [1]
o Add additional protections, missing Tx completion interrupt, losing
   start Tx command, for watchdog timeout.
o Switch to taskqueue(9) API to handle interrupts.
o Use our own timer for watchdog instead of if_watchdog/if_timer
   interface.
o Advertise VLAN header length/capability correctly to upper layer.
o Remove excessive kernel stack consumption in nfe_encap().
o Handle highly fragmented mbuf chains correctly.
o Enable etherenet address reprogramming with ifconfig(8).
o Add ALTQ/TSO, MSI/MSIX support.
o Increased Rx ring to 256 descriptors from 128.
o Align Tx/Rx descriptor ring on sizeof(struct nfe_desc64) boundary.
o Remove alignment restrictions on Tx/Rx buffers.
o Rewritten jumbo frame support code.
o Add support for hardware assistend VLAN tag insertion/stripping.
o Add support for Tx/Rx flow control based on patches from Peer Chen. [2]
o Add a routine that detects whether ethernet address swap routines is
   required. [3]
o Add a workaround that take MAC/PHY out of power down mode.
o Add suspend/resume support.
o style(9) and code clean up.

Special thanks to Shigeaki Tagashira, the original porter of nfe(4),
who submitted lots of patches, performed uncountable number of
regression tests and maintained nfe(4) for a long time. Without his
enthusiastic help and support I could never have completed this
overhauling task.

The only weak point of nfe(4) compared to nve(4) is instability of
manual half-duplex media selection on certain hardwares(auto sensing
media type should work for all cases, though). This was a long
standing bug of nfe(4) and I still have no idea why it doesn't work
on some hardwares.

Obtained from:	OpenBSD [1]
Submitted by:	Peer Chen < pchen at nvidia dot com > [2], [3]
Reviewed by:	Shigeaki Tagashira < shigeaki AT se DOT hiroshima-u DOT ac DOT jp >
Tested by:	Shigeaki Tagashira, current
Discussed with:	current
Silence from:	obrien
This commit is contained in:
Pyun YongHyeon 2007-06-12 02:16:02 +00:00
parent 927a1b4120
commit aab5582f0a
3 changed files with 2143 additions and 949 deletions

File diff suppressed because it is too large Load Diff

View File

@ -18,26 +18,47 @@
* $FreeBSD$ * $FreeBSD$
*/ */
#define NFE_PCI_BA 0x10 #define NFE_RX_RING_COUNT 256
#define NFE_JUMBO_RX_RING_COUNT NFE_RX_RING_COUNT
#define NFE_RX_RING_COUNT 128
#define NFE_TX_RING_COUNT 256 #define NFE_TX_RING_COUNT 256
#define NFE_PROC_DEFAULT ((NFE_RX_RING_COUNT * 3) / 4)
#define NFE_PROC_MIN 50
#define NFE_PROC_MAX (NFE_RX_RING_COUNT - 1)
#define NFE_INC(x, y) (x) = ((x) + 1) % y
/* RX/TX MAC addr + type + VLAN + align + slack */ /* RX/TX MAC addr + type + VLAN + align + slack */
#define NFE_RX_HEADERS 64 #define NFE_RX_HEADERS 64
/* Maximum MTU size. */ /* Maximum MTU size. */
#define NV_PKTLIMIT_1 ETH_DATA_LEN /* Hard limit not known. */ #define NV_PKTLIMIT_1 ETH_DATA_LEN /* Hard limit not known. */
#define NV_PKTLIMIT_2 9100 /* Actual limit according to NVidia:9202 */ #define NV_PKTLIMIT_2 9100 /* Actual limit according to NVidia:9202 */
#define NFE_JBYTES (ETHER_MAX_LEN_JUMBO + ETHER_ALIGN)
#define NFE_JPOOL_COUNT (NFE_RX_RING_COUNT + NFE_RX_HEADERS)
#define NFE_MAX_SCATTER (NFE_TX_RING_COUNT - 2) #define NFE_JUMBO_FRAMELEN NV_PKTLIMIT_2
#define NFE_JUMBO_MTU \
(NFE_JUMBO_FRAMELEN - NFE_RX_HEADERS)
#define NFE_MIN_FRAMELEN (ETHER_MIN_LEN - ETHER_CRC_LEN)
#define NFE_JSLOTS ((NFE_JUMBO_RX_RING_COUNT * 3) / 2)
#define NFE_JRAWLEN (NFE_JUMBO_FRAMELEN + ETHER_ALIGN)
#define NFE_JLEN \
(NFE_JRAWLEN + (sizeof(uint64_t) - (NFE_JRAWLEN % sizeof(uint64_t))))
#define NFE_JPAGESZ PAGE_SIZE
#define NFE_RESID \
(NFE_JPAGESZ - (NFE_JLEN * NFE_JSLOTS) % NFE_JPAGESZ)
#define NFE_JMEM ((NFE_JLEN * NFE_JSLOTS) + NFE_RESID)
#define NFE_MAX_SCATTER 32
#define NFE_IRQ_STATUS 0x000 #define NFE_IRQ_STATUS 0x000
#define NFE_IRQ_MASK 0x004 #define NFE_IRQ_MASK 0x004
#define NFE_SETUP_R6 0x008 #define NFE_SETUP_R6 0x008
#define NFE_IMTIMER 0x00c #define NFE_IMTIMER 0x00c
#define NFE_MSI_MAP0 0x020
#define NFE_MSI_MAP1 0x024
#define NFE_MSI_IRQ_MASK 0x030
#define NFE_MAC_RESET 0x03c
#define NFE_MISC1 0x080 #define NFE_MISC1 0x080
#define NFE_TX_CTL 0x084 #define NFE_TX_CTL 0x084
#define NFE_TX_STATUS 0x088 #define NFE_TX_STATUS 0x088
@ -66,6 +87,7 @@
#define NFE_RXTX_CTL 0x144 #define NFE_RXTX_CTL 0x144
#define NFE_TX_RING_ADDR_HI 0x148 #define NFE_TX_RING_ADDR_HI 0x148
#define NFE_RX_RING_ADDR_HI 0x14c #define NFE_RX_RING_ADDR_HI 0x14c
#define NFE_TX_PAUSE_FRAME 0x170
#define NFE_PHY_STATUS 0x180 #define NFE_PHY_STATUS 0x180
#define NFE_SETUP_R4 0x184 #define NFE_SETUP_R4 0x184
#define NFE_STATUS 0x188 #define NFE_STATUS 0x188
@ -78,6 +100,14 @@
#define NFE_PWR_CAP 0x268 #define NFE_PWR_CAP 0x268
#define NFE_PWR_STATE 0x26c #define NFE_PWR_STATE 0x26c
#define NFE_VTAG_CTL 0x300 #define NFE_VTAG_CTL 0x300
#define NFE_MSIX_MAP0 0x3e0
#define NFE_MSIX_MAP1 0x3e4
#define NFE_MSIX_IRQ_STATUS 0x3f0
#define NFE_PWR2_CTL 0x600
#define NFE_MAC_RESET_MAGIC 0x00f3
#define NFE_MAC_ADDR_INORDER 0x8000
#define NFE_PHY_ERROR 0x00001 #define NFE_PHY_ERROR 0x00001
#define NFE_PHY_WRITE 0x00400 #define NFE_PHY_WRITE 0x00400
@ -86,7 +116,9 @@
#define NFE_STATUS_MAGIC 0x140000 #define NFE_STATUS_MAGIC 0x140000
#define NFE_R1_MAGIC 0x16070f #define NFE_R1_MAGIC_1000 0x14050f
#define NFE_R1_MAGIC_10_100 0x16070f
#define NFE_R1_MAGIC_DEFAULT 0x15050f
#define NFE_R2_MAGIC 0x16 #define NFE_R2_MAGIC 0x16
#define NFE_R4_MAGIC 0x08 #define NFE_R4_MAGIC 0x08
#define NFE_R6_MAGIC 0x03 #define NFE_R6_MAGIC 0x03
@ -118,9 +150,11 @@
#define NFE_RXTX_RXCSUM 0x0400 #define NFE_RXTX_RXCSUM 0x0400
#define NFE_RXTX_V2MAGIC 0x2100 #define NFE_RXTX_V2MAGIC 0x2100
#define NFE_RXTX_V3MAGIC 0x2200 #define NFE_RXTX_V3MAGIC 0x2200
#define NFE_RXFILTER_MAGIC 0x007f0008 #define NFE_RXFILTER_MAGIC 0x007f0000
#define NFE_U2M (1 << 5) #define NFE_PFF_RX_PAUSE (1 << 3)
#define NFE_PROMISC (1 << 7) #define NFE_PFF_LOOPBACK (1 << 4)
#define NFE_PFF_U2M (1 << 5)
#define NFE_PFF_PROMISC (1 << 7)
#define NFE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) #define NFE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP)
/* default interrupt moderation timer of 128us */ /* default interrupt moderation timer of 128us */
@ -131,6 +165,9 @@
#define NFE_PWR_VALID (1 << 8) #define NFE_PWR_VALID (1 << 8)
#define NFE_PWR_WAKEUP (1 << 15) #define NFE_PWR_WAKEUP (1 << 15)
#define NFE_PWR2_WAKEUP_MASK 0x0f11
#define NFE_PWR2_REVA3 (1 << 0)
#define NFE_MEDIA_SET 0x10000 #define NFE_MEDIA_SET 0x10000
#define NFE_MEDIA_1000T 0x00032 #define NFE_MEDIA_1000T 0x00032
#define NFE_MEDIA_100TX 0x00064 #define NFE_MEDIA_100TX 0x00064
@ -141,13 +178,32 @@
#define NFE_PHY_HDX (1 << 8) #define NFE_PHY_HDX (1 << 8)
#define NFE_MISC1_MAGIC 0x003b0f3c #define NFE_MISC1_MAGIC 0x003b0f3c
#define NFE_MISC1_TX_PAUSE (1 << 0)
#define NFE_MISC1_HDX (1 << 1) #define NFE_MISC1_HDX (1 << 1)
#define NFE_TX_PAUSE_FRAME_DISABLE 0x1ff0080
#define NFE_TX_PAUSE_FRAME_ENABLE 0x0c00030
#define NFE_SEED_MASK 0x0003ff00 #define NFE_SEED_MASK 0x0003ff00
#define NFE_SEED_10T 0x00007f00 #define NFE_SEED_10T 0x00007f00
#define NFE_SEED_100TX 0x00002d00 #define NFE_SEED_100TX 0x00002d00
#define NFE_SEED_1000T 0x00007400 #define NFE_SEED_1000T 0x00007400
#define NFE_MSI_MESSAGES 8
#define NFE_MSI_VECTOR_0_ENABLED 0x01
/*
* It seems that nForce supports only the lower 40 bits of a DMA address.
*/
#if (BUS_SPACE_MAXADDR < 0xFFFFFFFFFF)
#define NFE_DMA_MAXADDR BUS_SPACE_MAXADDR
#else
#define NFE_DMA_MAXADDR 0xFFFFFFFFFF
#endif
#define NFE_ADDR_LO(x) ((u_int64_t) (x) & 0xffffffff)
#define NFE_ADDR_HI(x) ((u_int64_t) (x) >> 32)
/* Rx/Tx descriptor */ /* Rx/Tx descriptor */
struct nfe_desc32 { struct nfe_desc32 {
uint32_t physaddr; uint32_t physaddr;
@ -179,9 +235,6 @@ struct nfe_desc64 {
#define NFE_RX_VALID_V2 (1 << 13) #define NFE_RX_VALID_V2 (1 << 13)
#define NFE_TX_ERROR_V2 0x5c04 #define NFE_TX_ERROR_V2 0x5c04
#define NFE_TX_LASTFRAG_V2 (1 << 13) #define NFE_TX_LASTFRAG_V2 (1 << 13)
#define NFE_RX_IP_CSUMOK_V2 0x1000
#define NFE_RX_UDP_CSUMOK_V2 0x1400
#define NFE_RX_TCP_CSUMOK_V2 0x1800
#define NFE_RX_ERROR1_V2 (1<<2) #define NFE_RX_ERROR1_V2 (1<<2)
#define NFE_RX_ERROR2_V2 (1<<3) #define NFE_RX_ERROR2_V2 (1<<3)
#define NFE_RX_ERROR3_V2 (1<<4) #define NFE_RX_ERROR3_V2 (1<<4)
@ -191,19 +244,28 @@ struct nfe_desc64 {
#define NFE_V2_TXERR "\020" \ #define NFE_V2_TXERR "\020" \
"\14FORCEDINT\13LASTPACKET\12UNDERFLOW\10LOSTCARRIER\09DEFERRED\02RETRY" "\14FORCEDINT\13LASTPACKET\12UNDERFLOW\10LOSTCARRIER\09DEFERRED\02RETRY"
#define NFE_RING_ALIGN (sizeof(struct nfe_desc64))
/* flags common to V1/V2 descriptors */ /* flags common to V1/V2 descriptors */
#define NFE_RX_CSUMOK 0x1c00 #define NFE_RX_UDP_CSUMOK (1 << 10)
#define NFE_RX_TCP_CSUMOK (1 << 11)
#define NFE_RX_IP_CSUMOK (1 << 12)
#define NFE_RX_ERROR (1 << 14) #define NFE_RX_ERROR (1 << 14)
#define NFE_RX_READY (1 << 15) #define NFE_RX_READY (1 << 15)
#define NFE_TX_TCP_CSUM (1 << 10) #define NFE_RX_LEN_MASK 0x3fff
#define NFE_TX_TCP_UDP_CSUM (1 << 10)
#define NFE_TX_IP_CSUM (1 << 11) #define NFE_TX_IP_CSUM (1 << 11)
#define NFE_TX_TSO (1 << 12)
#define NFE_TX_TSO_SHIFT 14
#define NFE_TX_VALID (1 << 15) #define NFE_TX_VALID (1 << 15)
#define NFE_READ(sc, reg) \ #define NFE_READ(sc, reg) \
bus_space_read_4((sc)->nfe_memt, (sc)->nfe_memh, (reg)) bus_read_4((sc)->nfe_res[0], (reg))
#define NFE_WRITE(sc, reg, val) \ #define NFE_WRITE(sc, reg, val) \
bus_space_write_4((sc)->nfe_memt, (sc)->nfe_memh, (reg), (val)) bus_write_4((sc)->nfe_res[0], (reg), (val))
#define NFE_TIMEOUT 1000
#ifndef PCI_VENDOR_NVIDIA #ifndef PCI_VENDOR_NVIDIA
#define PCI_VENDOR_NVIDIA 0x10DE #define PCI_VENDOR_NVIDIA 0x10DE
@ -232,6 +294,10 @@ struct nfe_desc64 {
#define PCI_PRODUCT_NVIDIA_MCP65_LAN2 0x0451 #define PCI_PRODUCT_NVIDIA_MCP65_LAN2 0x0451
#define PCI_PRODUCT_NVIDIA_MCP65_LAN3 0x0452 #define PCI_PRODUCT_NVIDIA_MCP65_LAN3 0x0452
#define PCI_PRODUCT_NVIDIA_MCP65_LAN4 0x0453 #define PCI_PRODUCT_NVIDIA_MCP65_LAN4 0x0453
#define PCI_PRODUCT_NVIDIA_MCP67_LAN1 0x054c
#define PCI_PRODUCT_NVIDIA_MCP67_LAN2 0x054d
#define PCI_PRODUCT_NVIDIA_MCP67_LAN3 0x054e
#define PCI_PRODUCT_NVIDIA_MCP67_LAN4 0x054f
#define PCI_PRODUCT_NVIDIA_NFORCE3_LAN2 PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1 #define PCI_PRODUCT_NVIDIA_NFORCE3_LAN2 PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1
#define PCI_PRODUCT_NVIDIA_NFORCE3_LAN3 PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2 #define PCI_PRODUCT_NVIDIA_NFORCE3_LAN3 PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2

View File

@ -18,110 +18,120 @@
* $FreeBSD$ * $FreeBSD$
*/ */
#define NFE_IFQ_MAXLEN 64
struct nfe_tx_data { struct nfe_tx_data {
bus_dmamap_t tx_data_map; bus_dmamap_t tx_data_map;
bus_dmamap_t active;
int nsegs;
struct mbuf *m; struct mbuf *m;
}; };
struct nfe_tx_ring { struct nfe_tx_ring {
bus_dma_tag_t tx_desc_tag;
bus_dmamap_t tx_desc_map; bus_dmamap_t tx_desc_map;
bus_dma_segment_t tx_desc_segs;
bus_addr_t physaddr; bus_addr_t physaddr;
struct nfe_desc32 *desc32; struct nfe_desc32 *desc32;
struct nfe_desc64 *desc64; struct nfe_desc64 *desc64;
bus_dma_tag_t tx_data_tag;
struct nfe_tx_data data[NFE_TX_RING_COUNT]; struct nfe_tx_data data[NFE_TX_RING_COUNT];
int queued; int queued;
int cur; int cur;
int next; int next;
bus_addr_t tx_desc_addr;
bus_addr_t tx_data_addr;
bus_dma_tag_t tx_desc_tag;
bus_dma_tag_t tx_data_tag;
}; };
struct nfe_jbuf { struct nfe_jpool_entry {
caddr_t buf; int slot;
bus_addr_t physaddr; SLIST_ENTRY(nfe_jpool_entry) jpool_entries;
SLIST_ENTRY(nfe_jbuf) jnext;
}; };
struct nfe_rx_data { struct nfe_rx_data {
bus_dmamap_t rx_data_map; bus_dmamap_t rx_data_map;
bus_dma_tag_t rx_data_tag; bus_addr_t paddr;
bus_addr_t rx_data_addr;
bus_dma_segment_t rx_data_segs;
struct mbuf *m; struct mbuf *m;
}; };
struct nfe_rx_ring { struct nfe_rx_ring {
bus_dma_tag_t rx_desc_tag;
bus_dmamap_t rx_desc_map; bus_dmamap_t rx_desc_map;
bus_dma_segment_t rx_desc_segs;
bus_dma_tag_t rx_desc_tag;
bus_addr_t rx_desc_addr;
#ifndef JMBUF
bus_dmamap_t rx_jumbo_map;
bus_dma_segment_t rx_jumbo_segs;
bus_dma_tag_t rx_jumbo_tag;
bus_addr_t rx_jumbo_addr;
caddr_t jpool;
struct nfe_jbuf jbuf[NFE_JPOOL_COUNT];
SLIST_HEAD(, nfe_jbuf) jfreelist;
#endif
bus_addr_t physaddr; bus_addr_t physaddr;
struct nfe_desc32 *desc32; struct nfe_desc32 *desc32;
struct nfe_desc64 *desc64; struct nfe_desc64 *desc64;
bus_dma_tag_t rx_data_tag;
bus_dmamap_t rx_spare_map;
struct nfe_rx_data data[NFE_RX_RING_COUNT]; struct nfe_rx_data data[NFE_RX_RING_COUNT];
int bufsz;
int cur; int cur;
int next; int next;
}; };
struct nfe_jrx_ring {
bus_dma_tag_t jrx_desc_tag;
bus_dmamap_t jrx_desc_map;
bus_dma_tag_t jrx_jumbo_tag;
bus_dmamap_t jrx_jumbo_map;
void *jpool;
caddr_t jslots[NFE_JSLOTS];
bus_addr_t jphysaddr;
struct nfe_desc32 *jdesc32;
struct nfe_desc64 *jdesc64;
bus_dma_tag_t jrx_data_tag;
bus_dmamap_t jrx_spare_map;
struct nfe_rx_data jdata[NFE_JUMBO_RX_RING_COUNT];
int jcur;
int jnext;
};
struct nfe_softc { struct nfe_softc {
struct ifnet *nfe_ifp; struct ifnet *nfe_ifp;
device_t nfe_dev; device_t nfe_dev;
uint16_t nfe_devid;
uint16_t nfe_revid;
device_t nfe_miibus; device_t nfe_miibus;
struct mtx nfe_mtx; struct mtx nfe_mtx;
bus_space_handle_t nfe_memh; struct resource *nfe_res[1];
bus_space_tag_t nfe_memt; struct resource *nfe_msix_res;
struct resource *nfe_res; struct resource *nfe_msix_pba_res;
struct resource *nfe_irq; struct resource *nfe_irq[NFE_MSI_MESSAGES];
void *nfe_intrhand; void *nfe_intrhand[NFE_MSI_MESSAGES];
struct mii_data nfe_mii;
u_int8_t nfe_unit;
struct callout nfe_stat_ch; struct callout nfe_stat_ch;
int nfe_watchdog_timer;
struct arpcom nfe_arpcom;
bus_dma_tag_t nfe_parent_tag; bus_dma_tag_t nfe_parent_tag;
/* struct timeout nfe_tick_ch; */
void *nfe_powerhook;
int nfe_if_flags; int nfe_if_flags;
u_int nfe_flags; uint32_t nfe_flags;
#define NFE_JUMBO_SUP 0x01 #define NFE_JUMBO_SUP 0x0001
#define NFE_40BIT_ADDR 0x02 #define NFE_40BIT_ADDR 0x0002
#define NFE_HW_CSUM 0x04 #define NFE_HW_CSUM 0x0004
#define NFE_HW_VLAN 0x08 #define NFE_HW_VLAN 0x0008
u_int32_t rxtxctl; #define NFE_PWR_MGMT 0x0010
u_int32_t nfe_mtu; #define NFE_CORRECT_MACADDR 0x0020
u_int8_t mii_phyaddr; #define NFE_TX_FLOW_CTRL 0x0040
u_char eaddr[ETHER_ADDR_LEN]; uint32_t rxtxctl;
struct task nfe_txtask; uint8_t mii_phyaddr;
uint8_t eaddr[ETHER_ADDR_LEN];
struct taskqueue *nfe_tq;
struct task nfe_int_task;
struct task nfe_tx_task;
struct task nfe_link_task;
int nfe_link; int nfe_link;
int nfe_suspended;
int nfe_framesize;
int nfe_process_limit;
int nfe_force_tx;
uint32_t nfe_irq_status;
uint32_t nfe_irq_mask;
uint32_t nfe_intrs;
uint32_t nfe_nointrs;
uint32_t nfe_msi;
uint32_t nfe_msix;
struct nfe_tx_ring txq; struct nfe_tx_ring txq;
struct nfe_rx_ring rxq; struct nfe_rx_ring rxq;
struct nfe_jrx_ring jrxq;
#ifdef DEVICE_POLLING SLIST_HEAD(__nfe_jfreehead, nfe_jpool_entry) nfe_jfree_listhead;
int rxcycles; SLIST_HEAD(__nfe_jinusehead, nfe_jpool_entry) nfe_jinuse_listhead;
#endif struct mtx nfe_jlist_mtx;
}; };
struct nfe_type { struct nfe_type {
u_int16_t vid_id; uint16_t vid_id;
u_int16_t dev_id; uint16_t dev_id;
char *name; char *name;
}; };