Date: Mon, 22 Dec 2008 12:15:38 GMT From: Weongyo Jeong <weongyo@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 155115 for review Message-ID: <200812221215.mBMCFcK7051247@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=155115 Change 155115 by weongyo@weongyo_ws on 2008/12/22 12:15:29 record history of timers which are allocated by USB NDIS driver; then try to cancel all of it because some NDIS USB drivers are buggy that it doesn't cancel timers so the ndisulator encounter a page fault after halting or detaching. I don't like this kind of approach to solve the problem but it looks no ways to fix this problem if NDIS drivers have bugs. Affected files ... .. //depot/projects/ndisusb/sys/compat/ndis/subr_ndis.c#5 edit Differences ... ==== //depot/projects/ndisusb/sys/compat/ndis/subr_ndis.c#5 (text+ko) ==== @@ -304,6 +304,15 @@ */ #define NDIS_POOL_EXTRA 16 +struct ktimer_list { + ktimer *kl_timer; + list_entry kl_next; +}; + +static struct list_entry ndis_timerlist; +static kspin_lock ndis_timerlock; +static int ndis_isusbdev; + int ndis_libinit() { @@ -319,6 +328,9 @@ patch++; } + KeInitializeSpinLock(&ndis_timerlock); + InitializeListHead(&ndis_timerlist); + return(0); } @@ -1217,6 +1229,16 @@ ndis_timer_function func; void *ctx; { + ndis_miniport_block *block; + struct ktimer_list *kl; + struct ndis_softc *sc; + uint8_t irql; + + block = (ndis_miniport_block *)handle; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + if (sc->ndis_iftype == PNPBus && ndis_isusbdev == 0) + ndis_isusbdev = 1; + /* Save the driver's funcptr and context */ timer->nmt_timerfunc = func; @@ -1234,7 +1256,38 @@ ndis_findwrap((funcptr)ndis_timercall), timer); timer->nmt_ktimer.k_dpc = &timer->nmt_kdpc; - return; + if (ndis_isusbdev == 1) { + kl = (struct ktimer_list *)malloc(sizeof(*kl), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (kl == NULL) + panic("out of memory"); /* no way to report errors */ + + kl->kl_timer = &timer->nmt_ktimer; + KeAcquireSpinLock(&ndis_timerlock, &irql); + InsertHeadList((&ndis_timerlist), (&kl->kl_next)); + KeReleaseSpinLock(&ndis_timerlock, irql); + } +} + +void +ndis_cancel_timerlist(void) +{ + list_entry *l; + struct ktimer_list *kl; + uint8_t cancelled, irql; + + KeAcquireSpinLock(&ndis_timerlock, &irql); + + while(!IsListEmpty(&ndis_timerlist)) { + l = RemoveHeadList(&ndis_timerlist); + kl = CONTAINING_RECORD(l, struct ktimer_list, kl_next); + KeReleaseSpinLock(&ndis_timerlock, irql); + cancelled = KeCancelTimer(kl->kl_timer); + free(kl, M_DEVBUF); + KeAcquireSpinLock(&ndis_timerlock, &irql); + } + + KeReleaseSpinLock(&ndis_timerlock, irql); } /* @@ -1279,6 +1332,26 @@ ndis_timer *timer; uint8_t *cancelled; { + list_entry *l; + struct ktimer_list *kl; + uint8_t irql; + + if (ndis_isusbdev == 1) { + KeAcquireSpinLock(&ndis_timerlock, &irql); + l = ndis_timerlist.nle_flink; + while(l != &ndis_timerlist) { + kl = CONTAINING_RECORD(l, struct ktimer_list, kl_next); + if (kl->kl_timer == &timer->nt_ktimer) { + RemoveEntryList((&kl->kl_next)); + l = l->nle_flink; + free(kl, M_DEVBUF); + continue; + } + l = l->nle_flink; + } + KeReleaseSpinLock(&ndis_timerlock, irql); + } + *cancelled = KeCancelTimer(&timer->nt_ktimer); return; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812221215.mBMCFcK7051247>