From owner-p4-projects@FreeBSD.ORG Mon Dec 22 12:15:39 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 13A87106568D; Mon, 22 Dec 2008 12:15:39 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B53621065680 for ; Mon, 22 Dec 2008 12:15:38 +0000 (UTC) (envelope-from weongyo@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id A427B8FC12 for ; Mon, 22 Dec 2008 12:15:38 +0000 (UTC) (envelope-from weongyo@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id mBMCFcZ3051249 for ; Mon, 22 Dec 2008 12:15:38 GMT (envelope-from weongyo@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id mBMCFcK7051247 for perforce@freebsd.org; Mon, 22 Dec 2008 12:15:38 GMT (envelope-from weongyo@FreeBSD.org) Date: Mon, 22 Dec 2008 12:15:38 GMT Message-Id: <200812221215.mBMCFcK7051247@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to weongyo@FreeBSD.org using -f From: Weongyo Jeong To: Perforce Change Reviews Cc: Subject: PERFORCE change 155115 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Dec 2008 12:15:39 -0000 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; }