Attempt to handle the status field in the ndis_packet oob area correctly.
For received packets, an status of NDIS_STATUS_RESOURCES means we need to copy the packet data and return the ndis_packet to the driver immediatel. NDIS_STATUS_SUCCESS means we get to hold onto the packet, but we have to set the status to NDIS_STATUS_PENDING so the driver knows we're going to hang onto it for a while. For transmit packets, NDIS_STATUS_PENDING means the driver will asynchronously return the packet to us via the ndis_txeof() routine, and NDIS_STATUS_SUCCESS means the driver sent the frame, and NDIS (i.e. the OS) retains ownership of the packet and can free it right away.
This commit is contained in:
parent
ebda8238cd
commit
57cde0f9a7
@ -352,10 +352,9 @@ ndis_return_packet(buf, arg)
|
||||
sc = p->np_softc;
|
||||
returnfunc = sc->ndis_chars.nmc_return_packet_func;
|
||||
adapter = sc->ndis_block.nmb_miniportadapterctx;
|
||||
if (returnfunc == NULL)
|
||||
ndis_free_packet(p);
|
||||
else
|
||||
if (returnfunc != NULL)
|
||||
returnfunc(adapter, p);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -654,12 +653,37 @@ ndis_send_packets(arg, packets, cnt)
|
||||
struct ndis_softc *sc;
|
||||
ndis_handle adapter;
|
||||
__stdcall ndis_sendmulti_handler sendfunc;
|
||||
int i, idx;
|
||||
struct ifnet *ifp;
|
||||
struct mbuf *m;
|
||||
ndis_packet *p;
|
||||
|
||||
sc = arg;
|
||||
adapter = sc->ndis_block.nmb_miniportadapterctx;
|
||||
sendfunc = sc->ndis_chars.nmc_sendmulti_func;
|
||||
sendfunc(adapter, packets, cnt);
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
p = packets[i];
|
||||
if (p->np_oob.npo_status == NDIS_STATUS_PENDING)
|
||||
continue;
|
||||
idx = p->np_txidx;
|
||||
m = p->np_m0;
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
if (sc->ndis_sc)
|
||||
bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
|
||||
sc->ndis_txarray[idx] = NULL;
|
||||
sc->ndis_txpending++;
|
||||
m_freem(m);
|
||||
ndis_free_packet(p);
|
||||
if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
|
||||
ifp->if_opackets++;
|
||||
else
|
||||
ifp->if_oerrors++;
|
||||
ifp->if_timer = 0;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -633,6 +633,21 @@ ndis_detach(dev)
|
||||
/*
|
||||
* A frame has been uploaded: pass the resulting mbuf chain up to
|
||||
* the higher level protocols.
|
||||
*
|
||||
* When handling received NDIS packets, the 'status' field in the
|
||||
* out-of-band portion of the ndis_packet has special meaning. In the
|
||||
* most common case, the underlying NDIS driver will set this field
|
||||
* to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
|
||||
* take posession of it. We then change the status field to
|
||||
* NDIS_STATUS_PENDING to tell the driver that we now own the packet,
|
||||
* and that we will return it at some point in the future via the
|
||||
* return packet handler.
|
||||
*
|
||||
* If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
|
||||
* this means the driver is running out of packet/buffer resources and
|
||||
* wants to maintain ownership of the packet. In this case, we have to
|
||||
* copy the packet data into local storage and let the driver keep the
|
||||
* packet.
|
||||
*/
|
||||
__stdcall static void
|
||||
ndis_rxeof(adapter, packets, pktcnt)
|
||||
@ -644,7 +659,7 @@ ndis_rxeof(adapter, packets, pktcnt)
|
||||
ndis_miniport_block *block;
|
||||
ndis_packet *p;
|
||||
struct ifnet *ifp;
|
||||
struct mbuf *m0;
|
||||
struct mbuf *m0, *m;
|
||||
int i;
|
||||
|
||||
block = (ndis_miniport_block *)adapter;
|
||||
@ -657,8 +672,18 @@ ndis_rxeof(adapter, packets, pktcnt)
|
||||
p->np_softc = sc;
|
||||
if (ndis_ptom(&m0, p)) {
|
||||
printf ("ndis%d: ptom failed\n", sc->ndis_unit);
|
||||
ndis_return_packet(sc, p);
|
||||
if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
|
||||
ndis_return_packet(sc, p);
|
||||
} else {
|
||||
if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
|
||||
m = m_dup(m0, M_DONTWAIT);
|
||||
m_freem(m0);
|
||||
if (m == NULL)
|
||||
ifp->if_ierrors++;
|
||||
else
|
||||
m0 = m;
|
||||
} else
|
||||
p->np_oob.npo_status = NDIS_STATUS_PENDING;
|
||||
m0->m_pkthdr.rcvif = ifp;
|
||||
ifp->if_ipackets++;
|
||||
(*ifp->if_input)(ifp, m0);
|
||||
|
Loading…
Reference in New Issue
Block a user