mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +00:00
When ndis_attach() runs, it has to very briefly initialize the card
in order to query the underlying Windows driver for the station address and some other properties. There is a slim chance that the card may receive a packet and indicate it up to us before ndis_attach() can call ndis_halt_nic(). This is bad, because both the softc structure and the ifnet structure aren't fully initialized yet: many pointers are still NULL, so if we make it into ndis_rxeof(), we will panic. To fix this, we need to do the following: - Move the calls to IoAllocateWorkItem() to before the call to ndis_init_nic(). - Move the initialization of the RX DPC and status callback function pointers to before ndis_init_nic() as well. - Modify ndis_rxeof() to check if the IFF_DRV_RUNNING flag is set. If it isn't, we return any supplied NDIS_PACKETs to the NIC without processing them. This fixes a crash than can occur when activating a wireless NIC in close proximity to a very busy wireless network, reported by Ryan Beasley (ryan%^$!ATgoddamnbastard-****!!!DOTorg. MFC after: 3 days
This commit is contained in:
parent
41b0acb1ac
commit
55ad415824
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=155311
@ -552,6 +552,21 @@ ndis_attach(dev)
|
||||
sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
|
||||
sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
|
||||
|
||||
/* Override the status handler so we can detect link changes. */
|
||||
sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
|
||||
sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
|
||||
|
||||
/* Set up work item handlers. */
|
||||
sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
|
||||
sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
|
||||
sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
|
||||
sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
|
||||
KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
|
||||
|
||||
/* make sure drv flags are all cleared before initing the NIC. */
|
||||
|
||||
ifp->if_drv_flags = 0;
|
||||
|
||||
/* Call driver's init routine. */
|
||||
if (ndis_init_nic(sc)) {
|
||||
device_printf (dev, "init handler failed\n");
|
||||
@ -902,18 +917,6 @@ ndis_attach(dev)
|
||||
ether_ifattach(ifp, eaddr);
|
||||
}
|
||||
|
||||
/* Override the status handler so we can detect link changes. */
|
||||
sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
|
||||
sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
|
||||
|
||||
/* Set up work item handlers. */
|
||||
sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
|
||||
sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
|
||||
sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
|
||||
sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
|
||||
KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
|
||||
|
||||
|
||||
fail:
|
||||
if (error)
|
||||
ndis_detach(dev);
|
||||
@ -1317,6 +1320,23 @@ ndis_rxeof(adapter, packets, pktcnt)
|
||||
sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
|
||||
ifp = sc->ifp;
|
||||
|
||||
/*
|
||||
* There's a slim chance the driver may indicate some packets
|
||||
* before we're completely ready to handle them. If we detect this,
|
||||
* we need to return them to the miniport and ignore them.
|
||||
*/
|
||||
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
for (i = 0; i < pktcnt; i++) {
|
||||
p = packets[i];
|
||||
if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
|
||||
p->np_refcnt++;
|
||||
ndis_return_packet(p, block);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < pktcnt; i++) {
|
||||
p = packets[i];
|
||||
/* Stash the softc here so ptom can use it. */
|
||||
@ -1324,7 +1344,7 @@ ndis_rxeof(adapter, packets, pktcnt)
|
||||
if (ndis_ptom(&m0, p)) {
|
||||
device_printf (sc->ndis_dev, "ptom failed\n");
|
||||
if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
|
||||
ndis_return_packet(sc, p);
|
||||
ndis_return_packet(p, block);
|
||||
} else {
|
||||
#ifdef notdef
|
||||
if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
|
||||
@ -1380,7 +1400,7 @@ ndis_rxeof(adapter, packets, pktcnt)
|
||||
}
|
||||
|
||||
KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
|
||||
_IF_ENQUEUE(&sc->ndis_rxqueue, m);
|
||||
_IF_ENQUEUE(&sc->ndis_rxqueue, m0);
|
||||
KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
|
||||
IoQueueWorkItem(sc->ndis_inputitem,
|
||||
(io_workitem_func)ndis_inputtask_wrap,
|
||||
|
Loading…
Reference in New Issue
Block a user