diff options
author | wpaul <wpaul@FreeBSD.org> | 2003-12-14 21:31:32 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2003-12-14 21:31:32 +0000 |
commit | 953349a8b8ddfbf5397e22c1bb8a24b53c4e2790 (patch) | |
tree | 51a3bccb96f6842e2ec3221ffb7482f6c5c8d952 | |
parent | a2e08c3ed417496ce19a6b839cc5f4ce96f123ad (diff) | |
download | FreeBSD-src-953349a8b8ddfbf5397e22c1bb8a24b53c4e2790.zip FreeBSD-src-953349a8b8ddfbf5397e22c1bb8a24b53c4e2790.tar.gz |
Rework mbuf<->ndis_packet/ndis_packet<->mbuf translation a little to
make it more robust. This should fix problems with crashes under
heavy traffic loads that have been reported. Also add a 'query done'
callback handler to satisfy the e100bex.sys sample Intel driver.
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 65 | ||||
-rw-r--r-- | sys/compat/ndis/ndis_var.h | 9 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 41 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndisvar.h | 1 |
4 files changed, 65 insertions, 51 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index 3aca08f..5214a1f 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -76,6 +76,7 @@ __stdcall static void ndis_status_func(ndis_handle, ndis_status, void *, uint32_t); __stdcall static void ndis_statusdone_func(ndis_handle); __stdcall static void ndis_setdone_func(ndis_handle, ndis_status); +__stdcall static void ndis_getdone_func(ndis_handle, ndis_status); __stdcall static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t); /* @@ -122,6 +123,15 @@ ndis_setdone_func(adapter, status) } __stdcall static void +ndis_getdone_func(adapter, status) + ndis_handle adapter; + ndis_status status; +{ + printf ("Query done... %x\n", status); + return; +} + +__stdcall static void ndis_resetdone_func(adapter, status, addressingreset) ndis_handle adapter; ndis_status status; @@ -309,11 +319,24 @@ ndis_return_packet(packet, arg) { struct ndis_softc *sc; ndis_handle adapter; + ndis_packet *p; __stdcall ndis_return_handler returnfunc; + uint32_t t; if (arg == NULL || packet == NULL) return; + p = packet; + + /* Decrement refcount. */ + p->np_private.npp_count--; + + /* Release packet when refcount hits zero, otherwise return. */ + if (p->np_private.npp_count) + return; + t = *(uint32_t *)&p->u.np_clrsvd.np_miniport_rsvd[0]; +if (t == 0) +printf ("returning %p %x\n", p, t); sc = arg; returnfunc = sc->ndis_chars.nmc_return_packet_func; adapter = sc->ndis_block.nmb_miniportadapterctx; @@ -439,6 +462,7 @@ ndis_ptom(m0, p) priv = &p->np_private; buf = priv->npp_head; + priv->npp_count = 0; for (buf = priv->npp_head; buf != NULL; buf = buf->nb_next) { if (buf == priv->npp_head) @@ -450,25 +474,15 @@ ndis_ptom(m0, p) *m0 = NULL; return(ENOBUFS); } - - /* - * Note: there's some hackery going on here. We want - * to mate the mbufs to the buffers in the NDIS packet, - * but we don't mark the mbufs with the M_EXT flag to - * indicate external storage. This is because we don't - * want anything special done to free the buffers. - * Depending on the circumstances, the caller may want - * the entire packet to be released, buffers and all, - * by calling ndis_return_packet(), or ndis_free_packet(). - * We leave it up to the caller to do the MEXTADD() to - * set up the free mechanism in the first mbuf of the - * chain. - */ if (buf->nb_bytecount > buf->nb_size) m->m_len = buf->nb_size; else m->m_len = buf->nb_bytecount; m->m_data = buf->nb_mappedsystemva; + MEXTADD(m, m->m_data, m->m_len, ndis_return_packet, + p->np_rsvd[0], 0, EXT_NDIS); + m->m_ext.ext_buf = (void *)p; /* XXX */ + priv->npp_count++; totlen += m->m_len; if (m->m_flags & MT_HEADER) *m0 = m; @@ -524,7 +538,6 @@ ndis_mtop(m0, p) for (m = m0; m != NULL; m = m->m_next) { if (m->m_len == NULL) continue; - buf = malloc(sizeof(ndis_buffer), M_DEVBUF, M_NOWAIT|M_ZERO); if (buf == NULL) { ndis_free_packet(*p); @@ -651,20 +664,11 @@ ndis_init_dma(arg) if (sc->ndis_tmaps == NULL) return(ENOMEM); - sc->ndis_mbufs = malloc(sizeof(struct mbuf) * sc->ndis_maxpkts, - M_DEVBUF, M_NOWAIT|M_ZERO); - - if (sc->ndis_mbufs == NULL) { - free(sc->ndis_tmaps, M_DEVBUF); - return(ENOMEM); - } - for (i = 0; i < sc->ndis_maxpkts; i++) { error = bus_dmamap_create(sc->ndis_ttag, 0, &sc->ndis_tmaps[i]); if (error) { free(sc->ndis_tmaps, M_DEVBUF); - free(sc->ndis_mbufs, M_DEVBUF); return(ENODEV); } } @@ -677,18 +681,24 @@ ndis_destroy_dma(arg) void *arg; { struct ndis_softc *sc; + struct mbuf *m; + ndis_packet *p = NULL; int i; sc = arg; for (i = 0; i < sc->ndis_maxpkts; i++) { - if (sc->ndis_mbufs[i] != NULL) - m_freem(sc->ndis_mbufs[i]); + if (sc->ndis_txarray[i] != NULL) { + p = sc->ndis_txarray[i]; + m = (struct mbuf *)p->np_rsvd[1]; + if (m != NULL) + m_freem(m); + ndis_free_packet(sc->ndis_txarray[i]); + } bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]); } free(sc->ndis_tmaps, M_DEVBUF); - free(sc->ndis_mbufs, M_DEVBUF); bus_dma_tag_destroy(sc->ndis_ttag); @@ -1041,6 +1051,7 @@ ndis_load_driver(img, arg) block->nmb_signature = (void *)0xcafebabe; block->nmb_setdone_func = ndis_setdone_func; + block->nmb_querydone_func = ndis_getdone_func; block->nmb_status_func = ndis_status_func; block->nmb_statusdone_func = ndis_statusdone_func; block->nmb_resetdone_func = ndis_resetdone_func; diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h index 78bcfd2..df6d3ce 100644 --- a/sys/compat/ndis/ndis_var.h +++ b/sys/compat/ndis/ndis_var.h @@ -814,14 +814,16 @@ typedef struct ndis_packet_oob ndis_packet_oob; struct ndis_packet { ndis_packet_private np_private; union { + /* For connectionless miniports. */ struct { uint8_t np_miniport_rsvd[2 * sizeof(void *)]; uint8_t np_wrapper_rsvd[2 * sizeof(void *)]; - } np_rsvd; + } np_clrsvd; + /* For de-serialized miniports */ struct { uint8_t np_miniport_rsvdex[3 * sizeof(void *)]; uint8_t np_wrapper_rsvdex[sizeof(void *)]; - } np_rsvdrx; + } np_dsrsvd; struct { uint8_t np_mac_rsvd[4 * sizeof(void *)]; } np_macrsvd; @@ -840,6 +842,9 @@ struct ndis_packet { typedef struct ndis_packet ndis_packet; +/* mbuf ext type for NDIS */ +#define EXT_NDIS 0x999 + struct ndis_filterdbs { union { void *nf_ethdb; diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index 7a6b56a..c96d918 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -354,11 +354,6 @@ ndis_attach(dev) } sc->ndis_txpending = sc->ndis_maxpkts; - sc->ndis_mbufs = malloc(sizeof(struct mbuf) * sc->ndis_maxpkts, - M_DEVBUF, M_NOWAIT); - - if (sc->ndis_mbufs == NULL) - goto fail; sc->ndis_oidcnt = 0; /* Get supported oid list. */ @@ -489,13 +484,12 @@ ndis_rxeof(adapter, packets, pktcnt) for (i = 0; i < pktcnt; i++) { p = packets[i]; + /* Stash the softc here so ptom can use it. */ + p->np_rsvd[0] = (uint32_t *)sc; if (ndis_ptom(&m0, p)) { printf ("ndis%d: ptom failed\n", sc->ndis_unit); ndis_return_packet(sc, p); } else { - MEXTADD(m0, m0->m_data, m0->m_pkthdr.len, - ndis_return_packet, sc, 0, EXT_NET_DRV); - m0->m_ext.ext_buf = (void *)p; /* XXX */ m0->m_pkthdr.rcvif = ifp; ifp->if_ipackets++; (*ifp->if_input)(ifp, m0); @@ -520,23 +514,24 @@ ndis_txeof(adapter, packet, status) ndis_miniport_block *block; struct ifnet *ifp; int idx; + struct mbuf *m; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)block->nmb_ifp; ifp = block->nmb_ifp; - if (packet->np_rsvd[1] != NULL) { - idx = (int)packet->np_rsvd[1]; - ifp->if_opackets++; - if (sc->ndis_mbufs[idx] != NULL) { - m_freem(sc->ndis_mbufs[idx]); - sc->ndis_mbufs[idx] = NULL; - } - if (sc->ndis_sc) - bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]); - } + if (packet->np_rsvd[1] == NULL) + panic("NDIS driver corrupted reserved packet fields"); + + m = (struct mbuf *)packet->np_rsvd[1]; + idx = (int)packet->np_rsvd[0]; + ifp->if_opackets++; + m_freem(m); + if (sc->ndis_sc) + bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]); ndis_free_packet(packet); + sc->ndis_txarray[idx] = NULL; sc->ndis_txpending++; ifp->if_timer = 0; @@ -667,6 +662,7 @@ ndis_start(ifp) NDIS_LOCK(sc); sc->ndis_txarray[sc->ndis_txidx] = NULL; + if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { NDIS_UNLOCK(sc); IF_PREPEND(&ifp->if_snd, m); @@ -678,9 +674,9 @@ ndis_start(ifp) * so we can free it later. */ - sc->ndis_mbufs[sc->ndis_txidx] = m; - (sc->ndis_txarray[sc->ndis_txidx])->np_rsvd[1] = + (sc->ndis_txarray[sc->ndis_txidx])->np_rsvd[0] = (uint32_t *)sc->ndis_txidx; + (sc->ndis_txarray[sc->ndis_txidx])->np_rsvd[1] = (uint32_t *)m; /* * Do scatter/gather processing, if driver requested it. @@ -781,6 +777,9 @@ ndis_init(xsc) if (error) printf ("set filter failed: %d\n", error); + sc->ndis_txidx = 0; + sc->ndis_txpending = sc->ndis_maxpkts; + ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -955,7 +954,7 @@ ndis_shutdown(dev) struct ndis_softc *sc; sc = device_get_softc(dev); -/* ndis_shutdown_nic(sc); */ + ndis_shutdown_nic(sc); return; } diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h index 7a76217..bc3b902 100644 --- a/sys/dev/if_ndis/if_ndisvar.h +++ b/sys/dev/if_ndis/if_ndisvar.h @@ -111,7 +111,6 @@ struct ndis_softc { bus_dma_tag_t ndis_ttag; bus_dmamap_t *ndis_mmaps; bus_dmamap_t *ndis_tmaps; - struct mbuf **ndis_mbufs; int ndis_mmapcnt; }; |