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:
wpaul 2004-01-08 10:44:37 +00:00
parent b1f53e3dd8
commit de79d89d37
3 changed files with 45 additions and 10 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;