Correct the definition of the ndis_miniport_interrupt structure:
the ni_dpccountlock member is an ndis_kspin_lock, not an ndis_spin_lock (the latter is too big). Run if_ndis.c:ndis_tick() via taskqueue_schedule(). Also run ndis_start() via taskqueue in certain circumstances. Using these tweaks, I can now get the Broadcom BCM5701 NDIS driver to load and run. Unfortunately, the version I have seems to suffer from the same bug as the SMC 83820 driver, which is that it creates a spinlock during its DriverEntry() routine. I'm still debating the right way to deal with this.
This commit is contained in:
parent
b1f53e3dd8
commit
de79d89d37
@ -808,7 +808,7 @@ typedef struct ndis_request ndis_request;
|
||||
*/
|
||||
struct ndis_miniport_interrupt {
|
||||
void *ni_introbj;
|
||||
ndis_spin_lock ni_dpccountlock;
|
||||
ndis_kspin_lock ni_dpccountlock;
|
||||
void *ni_rsvd;
|
||||
void *ni_isrfunc;
|
||||
void *ni_dpcfunc;
|
||||
@ -1157,6 +1157,14 @@ struct ndis_timer_entry {
|
||||
|
||||
TAILQ_HEAD(nte_head, ndis_timer_entry);
|
||||
|
||||
struct ndis_fh {
|
||||
void *nf_vp;
|
||||
void *nf_map;
|
||||
uint32_t nf_maplen;
|
||||
};
|
||||
|
||||
typedef struct ndis_fh ndis_fh;
|
||||
|
||||
/*
|
||||
* The miniport block is basically the internal NDIS handle. We need
|
||||
* to define this because, unfortunately, it is not entirely opaque
|
||||
|
@ -108,7 +108,9 @@ static __stdcall void ndis_linksts_done (ndis_handle);
|
||||
static void ndis_intr (void *);
|
||||
static void ndis_intrtask (void *, int);
|
||||
static void ndis_tick (void *);
|
||||
static void ndis_ticktask (void *, int);
|
||||
static void ndis_start (struct ifnet *);
|
||||
static void ndis_starttask (void *, int);
|
||||
static int ndis_ioctl (struct ifnet *, u_long, caddr_t);
|
||||
static void ndis_init (void *);
|
||||
static void ndis_stop (struct ndis_softc *);
|
||||
@ -332,6 +334,8 @@ ndis_attach(dev)
|
||||
mtx_init(&sc->ndis_intrmtx, device_get_nameunit(dev), "ndisisrlock",
|
||||
MTX_DEF | MTX_RECURSE);
|
||||
TASK_INIT(&sc->ndis_intrtask, 0, ndis_intrtask, sc);
|
||||
TASK_INIT(&sc->ndis_ticktask, 0, ndis_ticktask, sc);
|
||||
TASK_INIT(&sc->ndis_starttask, 0, ndis_starttask, sc);
|
||||
|
||||
/*
|
||||
* Allocate the parent bus DMA tag appropriate for PCI.
|
||||
@ -772,8 +776,7 @@ ndis_txeof(adapter, packet, status)
|
||||
|
||||
m_freem(m);
|
||||
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
ndis_start(ifp);
|
||||
taskqueue_enqueue(taskqueue_swi, &sc->ndis_starttask);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -814,8 +817,7 @@ ndis_linksts_done(adapter)
|
||||
device_printf(sc->ndis_dev, "link up\n");
|
||||
if (sc->ndis_80211)
|
||||
ndis_getstate_80211(sc);
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
ndis_start(ifp);
|
||||
taskqueue_enqueue(taskqueue_swi, &sc->ndis_starttask);
|
||||
break;
|
||||
case NDIS_STATUS_MEDIA_DISCONNECT:
|
||||
device_printf(sc->ndis_dev, "link down\n");
|
||||
@ -885,6 +887,16 @@ ndis_intr(arg)
|
||||
static void
|
||||
ndis_tick(xsc)
|
||||
void *xsc;
|
||||
{
|
||||
struct ndis_softc *sc;
|
||||
sc = xsc;
|
||||
taskqueue_enqueue(taskqueue_swi, &sc->ndis_ticktask);
|
||||
}
|
||||
|
||||
static void
|
||||
ndis_ticktask(xsc, pending)
|
||||
void *xsc;
|
||||
int pending;
|
||||
{
|
||||
struct ndis_softc *sc;
|
||||
__stdcall ndis_checkforhang_handler hangfunc;
|
||||
@ -946,6 +958,19 @@ ndis_map_sclist(arg, segs, nseg, mapsize, error)
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ndis_starttask(arg, pending)
|
||||
void *arg;
|
||||
int pending;
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
|
||||
ifp = arg;
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
ndis_start(ifp);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Main transmit routine. To make NDIS drivers happy, we need to
|
||||
* transform mbuf chains into NDIS packets and feed them to the
|
||||
@ -1120,12 +1145,12 @@ ndis_init(xsc)
|
||||
* the default checkforhang timeout is approximately 2
|
||||
* seconds.
|
||||
*/
|
||||
|
||||
if (sc->ndis_block.nmb_checkforhangsecs == 0)
|
||||
sc->ndis_block.nmb_checkforhangsecs = 2;
|
||||
|
||||
if (sc->ndis_chars.nmc_checkhang_func != NULL)
|
||||
sc->ndis_stat_ch = timeout(ndis_tick, sc,
|
||||
hz * sc->ndis_block.nmb_checkforhangsecs);
|
||||
sc->ndis_stat_ch = timeout(ndis_tick, sc,
|
||||
hz * sc->ndis_block.nmb_checkforhangsecs);
|
||||
|
||||
/*NDIS_UNLOCK(sc);*/
|
||||
|
||||
@ -1486,8 +1511,8 @@ ndis_watchdog(ifp)
|
||||
|
||||
ndis_reset(sc);
|
||||
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
ndis_start(ifp);
|
||||
taskqueue_enqueue(taskqueue_swi, &sc->ndis_starttask);
|
||||
|
||||
NDIS_UNLOCK(sc);
|
||||
|
||||
return;
|
||||
|
@ -93,6 +93,8 @@ struct ndis_softc {
|
||||
struct mtx ndis_mtx;
|
||||
struct mtx ndis_intrmtx;
|
||||
struct task ndis_intrtask;
|
||||
struct task ndis_ticktask;
|
||||
struct task ndis_starttask;
|
||||
device_t ndis_dev;
|
||||
int ndis_unit;
|
||||
ndis_miniport_block ndis_block;
|
||||
|
Loading…
x
Reference in New Issue
Block a user