summaryrefslogtreecommitdiffstats
path: root/sys/dev/if_ndis/if_ndis.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2003-12-26 07:01:05 +0000
committerwpaul <wpaul@FreeBSD.org>2003-12-26 07:01:05 +0000
commit57cde0f9a725c266d83624b53174fd6d15564985 (patch)
tree369c2b936158e3011feb06fb0c987635f7c72b48 /sys/dev/if_ndis/if_ndis.c
parentebda8238cd6c308fee05639feb3a0614f972e7db (diff)
downloadFreeBSD-src-57cde0f9a725c266d83624b53174fd6d15564985.zip
FreeBSD-src-57cde0f9a725c266d83624b53174fd6d15564985.tar.gz
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.
Diffstat (limited to 'sys/dev/if_ndis/if_ndis.c')
-rw-r--r--sys/dev/if_ndis/if_ndis.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index 6ee63b1..e9e756d 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -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);
OpenPOWER on IntegriCloud