svn commit: r215939 - head/sys/mips/rmi/dev/nlge

Jayachandran C. jchandra at FreeBSD.org
Sat Nov 27 13:35:19 UTC 2010


Author: jchandra
Date: Sat Nov 27 13:35:19 2010
New Revision: 215939
URL: http://svn.freebsd.org/changeset/base/215939

Log:
  Use if_transmit method instead of if_start, this avoids the interface queue lock.
  Use the hardware IP checksum verification on receive.
  
  Submitted by:	Sriram Gorti (srgorti at netlogicmicro dot com)

Modified:
  head/sys/mips/rmi/dev/nlge/if_nlge.c
  head/sys/mips/rmi/dev/nlge/if_nlge.h

Modified: head/sys/mips/rmi/dev/nlge/if_nlge.c
==============================================================================
--- head/sys/mips/rmi/dev/nlge/if_nlge.c	Sat Nov 27 12:26:40 2010	(r215938)
+++ head/sys/mips/rmi/dev/nlge/if_nlge.c	Sat Nov 27 13:35:19 2010	(r215939)
@@ -137,7 +137,7 @@ static int	nlge_suspend(device_t);
 static int	nlge_resume(device_t);
 static void	nlge_init(void *);
 static int	nlge_ioctl(struct ifnet *, u_long, caddr_t);
-static void	nlge_start(struct ifnet *);
+static int	nlge_tx(struct ifnet *ifp, struct mbuf *m);
 static void 	nlge_rx(struct nlge_softc *sc, vm_paddr_t paddr, int len);
 
 static int	nlge_mii_write(struct device *, int, int, int);
@@ -199,7 +199,8 @@ static void	nlge_set_port_attribs(struct
     struct xlr_gmac_port *);
 static void	nlge_mac_set_rx_mode(struct nlge_softc *sc);
 static void 	nlge_sgmii_init(struct nlge_softc *sc);
-static void	nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc);
+static int 	nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc,
+    struct mbuf *m);
 
 static int	prepare_fmn_message(struct nlge_softc *sc,
     struct msgrng_msg *msg, uint32_t *n_entries, struct mbuf *m_head,
@@ -209,9 +210,6 @@ static void 	release_tx_desc(vm_paddr_t 
 static int	send_fmn_msg_tx(struct nlge_softc *, struct msgrng_msg *,
     uint32_t n_entries);
 
-static void
-nl_tx_q_wakeup(void *addr);
-
 //#define DEBUG
 #ifdef DEBUG
 static int	mac_debug = 1;
@@ -309,6 +307,8 @@ static uma_zone_t nl_tx_desc_zone;
 static int flow_classification = 0;
 TUNABLE_INT("hw.nlge.flow_classification", &flow_classification);
 
+#define	NLGE_HW_CHKSUM		1
+
 static __inline void
 atomic_incr_long(unsigned long *addr)
 {
@@ -431,10 +431,6 @@ nlna_attach(device_t dev)
 		    XLR_CACHELINE_SIZE, 0);
 	}
 
-	/* Other per NA s/w initialization */
-	callout_init(&sc->tx_thr, CALLOUT_MPSAFE);
-	callout_reset(&sc->tx_thr, hz, nl_tx_q_wakeup, sc);
-
 	/* Enable NA interrupts */
 	nlna_setup_intr(sc);
 
@@ -697,8 +693,6 @@ nlge_msgring_handler(int bucket, int siz
 			NLGE_LOCK(sc);
 			if (ifp->if_drv_flags & IFF_DRV_OACTIVE){
 				ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-				callout_reset(&na_sc->tx_thr, hz,
-				    nl_tx_q_wakeup, na_sc);
 			}
 			NLGE_UNLOCK(sc);
 		} else {
@@ -717,97 +711,76 @@ nlge_msgring_handler(int bucket, int siz
 
 }
 
-static void
-nlge_start(struct ifnet *ifp)
+static int
+nlge_tx(struct ifnet *ifp, struct mbuf *m)
 {
-	struct nlge_softc	*sc;
-
-	sc = ifp->if_softc;
-	//NLGE_LOCK(sc);
-	nlge_start_locked(ifp, sc);
-	//NLGE_UNLOCK(sc);
+	return (nlge_start_locked(ifp, ifp->if_softc, m));
 }
 
-static void
-nl_tx_q_wakeup(void *addr)
-{
-	struct nlna_softc *na_sc;
-	struct nlge_softc *sc;
-	int i;
-
-	na_sc = (struct nlna_softc *) addr;
-	for (i = 0; i < XLR_MAX_MACS; i++) { 
-		sc = na_sc->child_sc[i];
-		if (sc == NULL)
-			continue;
-		nlge_start_locked(sc->nlge_if, sc);
-	}
-	callout_reset(&na_sc->tx_thr, 5 * hz, nl_tx_q_wakeup, na_sc);
-}
-
-static void
-nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc)
+static int
+nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc, struct mbuf *m)
 {
 	struct msgrng_msg 	msg;
-	struct mbuf  		*m;
 	struct nlge_tx_desc 	*tx_desc;
 	uint64_t		fr_stid;
 	uint32_t		cpu;	
 	uint32_t		n_entries;
 	uint32_t		tid;
-	int 			ret;
+	int 			error, ret;
+
+	if (m == NULL)
+		return (0);
+
+	tx_desc = NULL;
+	error = 0;
+	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) ||
+	    ifp->if_drv_flags & IFF_DRV_OACTIVE) {
+	    	error = ENXIO;
+		goto fail;	// note: mbuf will get free'd
+	}
 
 	cpu = xlr_core_id();	
 	tid = xlr_thr_id();
 	/* H/w threads [0, 2] --> bucket 6 and [1, 3] --> bucket 7 */
 	fr_stid = cpu * 8 + 6 + (tid % 2); 
 
-	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-		return;
-	}
-
-	do {
-		/*
-		 * First, remove some freeback messages before transmitting
-		 * any new packets. However, cap the number of messages
-		 * drained to permit this thread to continue with its
-		 * transmission.
-		 *
-		 * Mask for buckets {6, 7} is 0xc0
-		 */
-		xlr_msgring_handler(0xc0, 4);
+	/*
+	 * First, remove some freeback messages before transmitting
+	 * any new packets. However, cap the number of messages
+	 * drained to permit this thread to continue with its
+	 * transmission.
+	 *
+	 * Mask for buckets {6, 7} is 0xc0
+	 */
+	xlr_msgring_handler(0xc0, 4);
 
-		/* Grab a packet off the queue. */
-		IF_DEQUEUE(&ifp->if_snd, m);
-		if (m == NULL) {
-			return;
-		}
-		
-		tx_desc = NULL;
-		ret = prepare_fmn_message(sc, &msg, &n_entries, m, fr_stid, &tx_desc);
-		if (ret) {
-			goto fail;
-		}
-		ret = send_fmn_msg_tx(sc, &msg, n_entries);
-		if (ret != 0) {
-			goto fail;
-		}
-	} while(1);
+	ret = prepare_fmn_message(sc, &msg, &n_entries, m, fr_stid, &tx_desc);
+	if (ret) {
+		error = (ret == 2) ? ENOBUFS : ENOTSUP;
+		goto fail;
+	}
+	ret = send_fmn_msg_tx(sc, &msg, n_entries);
+	if (ret != 0) {
+		error = EBUSY;
+		goto fail;
+	}
 
-	return;
+	return (0);
 
 fail:
 	if (tx_desc != NULL) {
 		uma_zfree(nl_tx_desc_zone, tx_desc);
 	}
 	if (m != NULL) {
-		NLGE_LOCK(sc);
-		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-		NLGE_UNLOCK(sc);
-		IF_PREPEND(&ifp->if_snd, m);
+		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+			NLGE_LOCK(sc);
+			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+			NLGE_UNLOCK(sc);
+		}
+		m_freem(m);
 		atomic_incr_long(&ifp->if_iqdrops);
 	}
-	return;
+	return (error);
 }
 
 static void
@@ -833,8 +806,24 @@ nlge_rx(struct nlge_softc *sc, vm_paddr_
 
 	ifp = sc->nlge_if;
 
+#ifdef NLGE_HW_CHKSUM
+	m->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
+	if (m->m_data[10] & 0x2) {
+		m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
+		if (m->m_data[10] & 0x1) {
+			m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID |
+			    CSUM_PSEUDO_HDR);
+			m->m_pkthdr.csum_data = htons(0xffff);
+		}
+	}
+	m->m_data += NLGE_PREPAD_LEN;
+	len -= NLGE_PREPAD_LEN;
+#else
+	m->m_pkthdr.csum_flags = 0;
+#endif
+
 	/* align the data */
-	m->m_data += BYTE_OFFSET;
+	m->m_data += BYTE_OFFSET ;
 	m->m_pkthdr.len = m->m_len = len;
 	m->m_pkthdr.rcvif = ifp;
 
@@ -1294,8 +1283,10 @@ nlna_config_parser(struct nlna_softc *sc
 	 */
 	NLGE_WRITE(sc->base, R_L2TYPE_0, 0x01);
 
+#ifndef NLGE_HW_CHKSUM
 	if (!flow_classification)
 		return;
+#endif
 
 	/* Use 7bit CRChash for flow classification with 127 as CRC polynomial*/
 	NLGE_WRITE(sc->base, R_PARSERCONFIGREG, ((0x7f << 8) | (1 << 1)));
@@ -1307,13 +1298,17 @@ nlna_config_parser(struct nlna_softc *sc
 	    (0x0800 << 0));
 	NLGE_WRITE(sc->base, R_L3CTABLE + 1,
 	    (9 << 25) | (1 << 21) | (12 << 14) | (4 << 10) | (16 << 4) | 4);
+#ifdef NLGE_HW_CHKSUM
+	device_printf(sc->nlna_dev, "Enabled h/w support to compute TCP/IP"
+	    " checksum\n");
+#endif
 
 	/* Configure to extract SRC port and Dest port for TCP and UDP pkts */
 	NLGE_WRITE(sc->base, R_L4CTABLE, 6);
-	NLGE_WRITE(sc->base, R_L4CTABLE+2, 17);
+	NLGE_WRITE(sc->base, R_L4CTABLE + 2, 17);
 	val = ((0 << 21) | (2 << 17) | (2 << 11) | (2 << 7));
-	NLGE_WRITE(sc->base, R_L4CTABLE+1, val);
-	NLGE_WRITE(sc->base, R_L4CTABLE+3, val);
+	NLGE_WRITE(sc->base, R_L4CTABLE + 1, val);
+	NLGE_WRITE(sc->base, R_L4CTABLE + 3, val);
 }
 
 static void
@@ -1756,8 +1751,11 @@ nlge_hw_init(struct nlge_softc *sc)
 
 	/* each packet buffer is 1536 bytes */
 	NLGE_WRITE(base, R_DESC_PACK_CTRL,
-		  (1 << O_DESC_PACK_CTRL__MaxEntry) |
-		  (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize));
+	    (1 << O_DESC_PACK_CTRL__MaxEntry) |
+#ifdef NLGE_HW_CHKSUM
+	    (1 << O_DESC_PACK_CTRL__PrePadEnable) |
+#endif
+	    (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize));
 	NLGE_WRITE(base, R_STATCTRL, ((1 << O_STATCTRL__Sten) |
 	    (1 << O_STATCTRL__ClrCnt)));
 	NLGE_WRITE(base, R_L2ALLOCCTRL, 0xffffffff);
@@ -1879,7 +1877,6 @@ nlge_if_init(struct nlge_softc *sc)
 	ifp->if_capabilities = 0;
 	ifp->if_capenable = ifp->if_capabilities;
 	ifp->if_ioctl = nlge_ioctl;
-	ifp->if_start = nlge_start;
 	ifp->if_init = nlge_init;
 	ifp->if_hwassist = 0;
 	ifp->if_snd.ifq_drv_maxlen = RGE_TX_Q_SIZE;
@@ -1895,6 +1892,9 @@ nlge_if_init(struct nlge_softc *sc)
 
 	ether_ifattach(ifp, sc->dev_addr);
 
+	/* override if_transmit : per ifnet(9), do it after if_attach */
+	ifp->if_transmit = nlge_tx;
+
 fail:
 	return (error);
 }

Modified: head/sys/mips/rmi/dev/nlge/if_nlge.h
==============================================================================
--- head/sys/mips/rmi/dev/nlge/if_nlge.h	Sat Nov 27 12:26:40 2010	(r215938)
+++ head/sys/mips/rmi/dev/nlge/if_nlge.h	Sat Nov 27 13:35:19 2010	(r215939)
@@ -985,8 +985,10 @@
 
 #define MAC_B2B_IPG                     88
 
+#define	NLGE_PREPAD_LEN			32
+
 /* frame sizes need to be cacheline aligned */
-#define MAX_FRAME_SIZE                  1536
+#define MAX_FRAME_SIZE                  (1536 + NLGE_PREPAD_LEN)
 #define MAX_FRAME_SIZE_JUMBO            9216
 #define RGE_TX_THRESHOLD_BYTES		ETHER_MAX_LEN
 
@@ -1019,7 +1021,6 @@
 
 #define PHY_STATUS_RETRIES 		25000
 
-
 /* Structs representing hardware data structures */
 struct size_1_desc {
 	uint64_t	entry0;
@@ -1110,7 +1111,6 @@ struct nlna_softc {
 	int		mac_type;
 	xlr_reg_t	*base;
 
-	struct callout 	tx_thr;
 	struct fr_desc *frin_spill;
 	struct fr_desc *frout_spill;
 	union rx_tx_desc *class_0_spill;


More information about the svn-src-head mailing list