diff options
author | jchandra <jchandra@FreeBSD.org> | 2010-09-08 17:11:49 +0000 |
---|---|---|
committer | jchandra <jchandra@FreeBSD.org> | 2010-09-08 17:11:49 +0000 |
commit | 9396bcb9a7e83fa93f39a37dda5edd421a430e08 (patch) | |
tree | cbfba65ecd9eda7d826c294e73c0ceaeca64b3bc /sys/mips/rmi | |
parent | c7fe35c363a80c261bef345a04c964e4d80e672a (diff) | |
download | FreeBSD-src-9396bcb9a7e83fa93f39a37dda5edd421a430e08.zip FreeBSD-src-9396bcb9a7e83fa93f39a37dda5edd421a430e08.tar.gz |
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.
Diffstat (limited to 'sys/mips/rmi')
-rw-r--r-- | sys/mips/rmi/dev/nlge/if_nlge.c | 95 |
1 files changed, 45 insertions, 50 deletions
diff --git a/sys/mips/rmi/dev/nlge/if_nlge.c b/sys/mips/rmi/dev/nlge/if_nlge.c index 7460230..8cb97bf 100644 --- a/sys/mips/rmi/dev/nlge/if_nlge.c +++ b/sys/mips/rmi/dev/nlge/if_nlge.c @@ -207,7 +207,7 @@ static int prepare_fmn_message(struct nlge_softc *sc, 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 size, int code, int stid, 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 size, int code, int stid, 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 size, int code, int stid, } 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, struct nlge_softc *sc) 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_softc *sc, uint32_t n_desc) } /* 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 *sc, struct msgrng_msg *fmn_msg, 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 *sc, struct msgrng_msg *fmn_msg, ((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 *sc, struct msgrng_msg *fmn_msg, } } - 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); } |