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

Jayachandran C. jchandra at FreeBSD.org
Wed Sep 8 17:11:49 UTC 2010


Author: jchandra
Date: Wed Sep  8 17:11:49 2010
New Revision: 212324
URL: http://svn.freebsd.org/changeset/base/212324

Log:
  nlge (alternate XLR GMAC driver) updates:
  
  - Updates for the message ring clean up in r212321.
  - Instead of dropping Tx packet on credit fail, retry send until it
    succeeds.
  - Fix freeing mbufs in case of P2P descriptors:
    We cannot free the mbuf when the P2P descriptor freeback is received. The
    mbuf may be still in use by the GMAC, since the P2P freeback indicates that
    it read the P2D descriptors in the P2P message.
    Now we free just the P2P descriptor when the P2P freeback message is
    received.  Another freeback P2D message has been added to the end of
    the packet descriptors, the mbuf will be freed only when we received
    this.
  
  The P2P descriptor issue was reported by srgorti at netlogicmicro dot com.

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

Modified: head/sys/mips/rmi/dev/nlge/if_nlge.c
==============================================================================
--- head/sys/mips/rmi/dev/nlge/if_nlge.c	Wed Sep  8 16:59:22 2010	(r212323)
+++ head/sys/mips/rmi/dev/nlge/if_nlge.c	Wed Sep  8 17:11:49 2010	(r212324)
@@ -207,7 +207,7 @@ static int	prepare_fmn_message(struct nl
     uint64_t fr_stid, struct nlge_tx_desc **tx_desc);
 
 static void	release_mbuf(uint64_t phy_addr);
-static void 	release_tx_desc(struct msgrng_msg *msg);
+static void 	release_tx_desc(vm_paddr_t phy_addr);
 static int	send_fmn_msg_tx(struct nlge_softc *, struct msgrng_msg *,
     uint32_t n_entries);
 
@@ -637,7 +637,7 @@ nlge_msgring_handler(int bucket, int siz
 	struct nlna_softc *na_sc;
 	struct nlge_softc *sc;
 	struct ifnet   *ifp;
-	uint64_t	phys_addr;
+	vm_paddr_t	phys_addr;
 	unsigned long	addr;
 	uint32_t	length;
 	int		ctrl;
@@ -655,14 +655,15 @@ nlge_msgring_handler(int bucket, int siz
 	tx_error = 0;
 	length = (msg->msg0 >> 40) & 0x3fff;
 	na_sc = (struct nlna_softc *)data;
-	phys_addr = (uint64_t) (msg->msg0 & 0xffffffffe0ULL);
 	if (length == 0) {
 		ctrl = CTRL_REG_FREE;
+		phys_addr = msg->msg0 & 0xffffffffffULL;
 		port = (msg->msg0 >> 54) & 0x0f;
 		is_p2p = (msg->msg0 >> 62) & 0x1;
 		tx_error = (msg->msg0 >> 58) & 0xf;
 	} else {
 		ctrl = CTRL_SNGL;
+		phys_addr = msg->msg0 & 0xffffffffe0ULL;
 		length = length - BYTE_OFFSET - MAC_CRC_LEN;
 		port = msg->msg0 & 0x0f;
 	}
@@ -676,11 +677,12 @@ nlge_msgring_handler(int bucket, int siz
 	}
 
 	if (ctrl == CTRL_REG_FREE || ctrl == CTRL_JUMBO_FREE) {
-		if (is_p2p)
-			release_tx_desc(msg);
-		else {
-			release_mbuf(msg->msg0 & 0xffffffffffULL);
+		if (is_p2p) {
+			release_tx_desc(phys_addr);
+		} else {
+			release_mbuf(phys_addr);
 		}
+
 		ifp = sc->nlge_if;
 		if (ifp->if_drv_flags & IFF_DRV_OACTIVE){
 			ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -742,7 +744,7 @@ nlge_start_locked(struct ifnet *ifp, str
 			goto fail;
 		}
 		sent = send_fmn_msg_tx(sc, &msg, n_entries);
-		if (!sent) {
+		if (sent != 0) {
 			goto fail;
 		}
 	} while(1);
@@ -1011,28 +1013,27 @@ static __inline__ int
 nlna_send_free_desc(struct nlna_softc *sc, vm_paddr_t addr)
 {
 	struct msgrng_msg msg;
-	int	stid;
-	int	code;
-	int 	i;
+	uint32_t msgrng_flags;
+	int i = 0, stid, code, ret;
 
 	stid = sc->rfrbucket;
 	memset(&msg, 0, sizeof(msg));
 	msg.msg0 = (uint64_t) addr & 0xffffffffe0ULL;
 
 	code = (sc->na_type == XLR_XGMAC) ? MSGRNG_CODE_XGMAC : MSGRNG_CODE_MAC;
-	for (i = 0; i < MAX_MSG_SND_ATTEMPTS; i++) {
-		if (message_send(1, code, stid, &msg) == 0)
-			return (0);
-	}
-	printf("Error: failed to send free desc to station %d\n", stid);
-	return (1);
+	do {
+		msgrng_flags = msgrng_access_enable();
+		ret = message_send_retry(1, code, stid, &msg);
+		msgrng_restore(msgrng_flags);
+		KASSERT(i++ < 100000, ("Too many credit fails\n"));
+	} while (ret != 0);
+	return (0);
 }
 
 static void
 nlna_submit_rx_free_desc(struct nlna_softc *sc, uint32_t n_desc)
 {
 	void           *ptr;
-	unsigned long	msgrng_flags;
 	int		i;
 	int		ret;
 
@@ -1050,10 +1051,8 @@ nlna_submit_rx_free_desc(struct nlna_sof
 		}
 
 		/* Send the free Rx desc to the MAC */
-		msgrng_access_enable(msgrng_flags);
 		ret = nlna_send_free_desc(sc, vtophys(ptr));
-		msgrng_access_disable(msgrng_flags);
-		if (ret)  /* no point trying other descriptors after
+		if (ret != 0)  /* no point trying other descriptors after
 		             a failure. */
 			break;
 	}
@@ -1907,9 +1906,10 @@ prepare_fmn_message(struct nlge_softc *s
 
 		while (len) {
 			if (msg_sz == (FMN_SZ - 1)) {
-				p2p = uma_zalloc(nl_tx_desc_zone, M_WAITOK);
-				if (p2p == NULL)
+				p2p = uma_zalloc(nl_tx_desc_zone, M_NOWAIT);
+				if (p2p == NULL) {
 					return 2;
+				}
 				/*
 				 * As we currently use xlr_paddr_lw on a 32-bit
 				 * OS, both the pointers are laid out in one
@@ -1922,7 +1922,7 @@ prepare_fmn_message(struct nlge_softc *s
 				    ((vm_offset_t) mbuf_chain);
 				cur_p2d = &p2p->frag[0];
 				is_p2p = 1;
-			} else if (msg_sz == (FMN_SZ - 1 + XLR_MAX_TX_FRAGS)) {
+			} else if (msg_sz == (FMN_SZ - 2 + XLR_MAX_TX_FRAGS)) {
 				uma_zfree(nl_tx_desc_zone, p2p);
 				return 1;
 			}
@@ -1940,26 +1940,24 @@ prepare_fmn_message(struct nlge_softc *s
 		}
 	}
 
-	if (msg_sz > 0) {
-		cur_p2d[-1] |= (1ULL << 63); /* set eop in most-recent p2d */
-	} else {
+	if (msg_sz ==  0) {
 		printf("Zero-length mbuf chain ??\n");
 		*n_entries = msg_sz ;
 		return 0;
 	}
 
+	cur_p2d[-1] |= (1ULL << 63); /* set eop in most-recent p2d */
+	*cur_p2d = (1ULL << 63) | ((uint64_t)fb_stn_id << 54) |
+	     (vm_offset_t) mbuf_chain;
 	*tx_desc = p2p;
 
 	if (is_p2p) {
 		paddr = vtophys(p2p);
-		fmn_msg->msg3 = (1ULL << 63) | (1ULL << 62) |
-		    ((uint64_t)fb_stn_id << 54) |
+		p2p_sz++;
+		fmn_msg->msg3 = (1ULL << 62) | ((uint64_t)fb_stn_id << 54) |
 		    ((uint64_t)(p2p_sz * 8) << 40) | paddr;
 		*n_entries = FMN_SZ;
 	} else {
-		/* zero-len p2d */
-		*cur_p2d = (1ULL << 63) | ((uint64_t)fb_stn_id << 54) |
-		     (vm_offset_t) mbuf_chain;
 		*n_entries = msg_sz + 1;
 	}
 
@@ -1970,15 +1968,17 @@ static int
 send_fmn_msg_tx(struct nlge_softc *sc, struct msgrng_msg *msg,
     uint32_t n_entries)
 {
-	unsigned long mflags;
-	int ret;
+	uint32_t msgrng_flags;
+	int i = 0, ret;
 
-	mflags = 0;
-	msgrng_access_enable(mflags);
-	ret = message_send_retry(n_entries, MSGRNG_CODE_MAC, sc->tx_bucket_id,
-	    msg);
-	msgrng_access_disable(mflags);
-	return (!ret);
+	do {
+		msgrng_flags = msgrng_access_enable();
+		ret = message_send_retry(n_entries, MSGRNG_CODE_MAC,
+		    sc->tx_bucket_id, msg);
+		msgrng_restore(msgrng_flags);
+		KASSERT(i++ < 100000, ("Too many credit fails\n"));
+	} while (ret != 0);
+	return (0);
 }
 
 static void
@@ -1991,25 +1991,20 @@ release_mbuf(uint64_t phy_addr)
 }
 
 static void
-release_tx_desc(struct msgrng_msg *msg)
+release_tx_desc(vm_paddr_t paddr)
 {
-	vm_paddr_t	paddr;
-	uint64_t	temp;
 	struct nlge_tx_desc *tx_desc;
-	struct mbuf	*m;
 	uint32_t 	sr;
+	uint32_t	val1, val2;
 
-	paddr = msg->msg0 & 0xffffffffffULL;
 	paddr += (XLR_MAX_TX_FRAGS * sizeof(uint64_t));
 	sr = xlr_enable_kx();
-	temp = xlr_paddr_lw(paddr);
-	tx_desc = (struct nlge_tx_desc*)((intptr_t) temp);
+	val1 = xlr_paddr_lw(paddr);
 	paddr += sizeof(void *);
-	temp = xlr_paddr_lw(paddr);
+	val2 = xlr_paddr_lw(paddr);
 	mips_wr_status(sr);
-	m = (struct mbuf *)((intptr_t) temp);
-	m_freem(m);
 
+	tx_desc = (struct nlge_tx_desc*)(intptr_t) val1;
 	uma_zfree(nl_tx_desc_zone, tx_desc);
 }
 


More information about the svn-src-head mailing list