diff --git a/sys/mips/rmi/dev/nlge/if_nlge.c b/sys/mips/rmi/dev/nlge/if_nlge.c index 746023020cf..8cb97bf6645 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); }