Ok, _really_ fix the Intel 2100B Centrino deadlock problems this time.
(I hope.) My original instinct to make ndis_return_packet() asynchronous was correct. Making ndis_rxeof() submit packets to the stack asynchronously fixes one recursive spinlock acquisition, but it's also possible for it to happen via the ndis_txeof() path too. So: - In if_ndis.c, revert ndis_rxeof() to its old behavior (and don't bother putting ndis_rxeof_serial() back since we don't need it anymore). - In kern_ndis.c, make ndis_return_packet() submit the call to the MiniportReturnPacket() function to the "ndis swi" thread so that it always happens in another context no matter who calls it.
This commit is contained in:
parent
256588d2c4
commit
b1084a1e96
@ -99,6 +99,7 @@ struct ndisproc {
|
||||
int np_state;
|
||||
};
|
||||
|
||||
static void ndis_return(void *);
|
||||
static int ndis_create_kthreads(void);
|
||||
static void ndis_destroy_kthreads(void);
|
||||
static void ndis_stop_thread(int);
|
||||
@ -724,16 +725,37 @@ ndis_flush_sysctls(arg)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
ndis_return(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct ndis_softc *sc;
|
||||
__stdcall ndis_return_handler returnfunc;
|
||||
ndis_handle adapter;
|
||||
ndis_packet *p;
|
||||
uint8_t irql;
|
||||
|
||||
p = arg;
|
||||
sc = p->np_softc;
|
||||
adapter = sc->ndis_block.nmb_miniportadapterctx;
|
||||
|
||||
if (adapter == NULL)
|
||||
return;
|
||||
|
||||
returnfunc = sc->ndis_chars.nmc_return_packet_func;
|
||||
irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
|
||||
returnfunc(adapter, p);
|
||||
FASTCALL1(hal_lower_irql, irql);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ndis_return_packet(buf, arg)
|
||||
void *buf; /* not used */
|
||||
void *arg;
|
||||
{
|
||||
struct ndis_softc *sc;
|
||||
ndis_handle adapter;
|
||||
ndis_packet *p;
|
||||
__stdcall ndis_return_handler returnfunc;
|
||||
uint8_t irql;
|
||||
|
||||
if (arg == NULL)
|
||||
return;
|
||||
@ -747,14 +769,7 @@ ndis_return_packet(buf, arg)
|
||||
if (p->np_refcnt)
|
||||
return;
|
||||
|
||||
sc = p->np_softc;
|
||||
returnfunc = sc->ndis_chars.nmc_return_packet_func;
|
||||
adapter = sc->ndis_block.nmb_miniportadapterctx;
|
||||
if (adapter != NULL) {
|
||||
irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
|
||||
returnfunc(adapter, p);
|
||||
FASTCALL1(hal_lower_irql, irql);
|
||||
}
|
||||
ndis_sched(ndis_return, p, NDIS_SWI);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -87,8 +87,6 @@ int ndis_suspend (device_t);
|
||||
int ndis_resume (device_t);
|
||||
void ndis_shutdown (device_t);
|
||||
|
||||
static void ndis_input (void *);
|
||||
|
||||
static __stdcall void ndis_txeof (ndis_handle,
|
||||
ndis_packet *, ndis_status);
|
||||
static __stdcall void ndis_rxeof (ndis_handle,
|
||||
@ -773,20 +771,6 @@ ndis_resume(dev)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
ndis_input(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct ifnet *ifp;
|
||||
|
||||
m = arg;
|
||||
ifp = m->m_pkthdr.rcvif;
|
||||
(*ifp->if_input)(ifp, m);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* A frame has been uploaded: pass the resulting mbuf chain up to
|
||||
* the higher level protocols.
|
||||
@ -805,13 +789,7 @@ ndis_input(arg)
|
||||
* 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.
|
||||
*
|
||||
* We have to make sure not to try and return packets to the driver
|
||||
* until after this routine returns. The best way to do that is put the
|
||||
* call to (*ifp->if_input)() on the ndis swi work queue. In theory,
|
||||
* we could also copy the packet. I'm not sure which is faster.
|
||||
*/
|
||||
|
||||
__stdcall static void
|
||||
ndis_rxeof(adapter, packets, pktcnt)
|
||||
ndis_handle adapter;
|
||||
@ -859,6 +837,7 @@ ndis_rxeof(adapter, packets, pktcnt)
|
||||
} else
|
||||
p->np_oob.npo_status = NDIS_STATUS_PENDING;
|
||||
m0->m_pkthdr.rcvif = ifp;
|
||||
ifp->if_ipackets++;
|
||||
|
||||
/* Deal with checksum offload. */
|
||||
|
||||
@ -880,18 +859,13 @@ ndis_rxeof(adapter, packets, pktcnt)
|
||||
}
|
||||
}
|
||||
|
||||
if (ndis_sched(ndis_input, m0, NDIS_SWI)) {
|
||||
p->np_refcnt++;
|
||||
m_freem(m0);
|
||||
ifp->if_ierrors++;
|
||||
p->np_oob.npo_status = NDIS_STATUS_SUCCESS;
|
||||
} else
|
||||
ifp->if_ipackets++;
|
||||
(*ifp->if_input)(ifp, m0);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* A frame was downloaded to the chip. It's safe for us to clean up
|
||||
* the list buffers.
|
||||
|
Loading…
x
Reference in New Issue
Block a user