summaryrefslogtreecommitdiffstats
path: root/sys/mips
diff options
context:
space:
mode:
authorjchandra <jchandra@FreeBSD.org>2010-09-08 17:11:49 +0000
committerjchandra <jchandra@FreeBSD.org>2010-09-08 17:11:49 +0000
commit9396bcb9a7e83fa93f39a37dda5edd421a430e08 (patch)
treecbfba65ecd9eda7d826c294e73c0ceaeca64b3bc /sys/mips
parentc7fe35c363a80c261bef345a04c964e4d80e672a (diff)
downloadFreeBSD-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')
-rw-r--r--sys/mips/rmi/dev/nlge/if_nlge.c95
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);
}
OpenPOWER on IntegriCloud