Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Jul 2008 05:06:57 GMT
From:      Weongyo Jeong <weongyo@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 145590 for review
Message-ID:  <200807220506.m6M56vWV060595@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=145590

Change 145590 by weongyo@weongyo_ws on 2008/07/22 05:06:36

	fix a case that it's caused by NDIS driver's bug(?) that when NDIS
	framework try to query/set a information using ndis_(set|get)_info
	functions, some drivers return NDIS_STATUS_PENDING value in spite of
	it already called the callback.

Affected files ...

.. //depot/projects/ndisusb/sys/compat/ndis/kern_ndis.c#3 edit
.. //depot/projects/ndisusb/sys/dev/if_ndis/if_ndis.c#4 edit

Differences ...

==== //depot/projects/ndisusb/sys/compat/ndis/kern_ndis.c#3 (text+ko) ====

@@ -884,8 +884,10 @@
 	if (sc->ndis_block->nmb_pendingreq != NULL) {
 		KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
 		panic("ndis_set_info() called while other request pending");
-	} else
+	} else {
 		sc->ndis_block->nmb_pendingreq = (ndis_request *)sc;
+		sc->ndis_block->nmb_setstat = -1;
+	}
 
 	setfunc = sc->ndis_chars->nmc_setinfo_func;
 	adapter = sc->ndis_block->nmb_miniportadapterctx;
@@ -901,6 +903,9 @@
 	    &byteswritten, &bytesneeded);
 
 	sc->ndis_block->nmb_pendingreq = NULL;
+	/* please see a description of ndis_get_info() why we check this.  */
+	if (rval == NDIS_STATUS_PENDING && sc->ndis_block->nmb_setstat != -1)
+		rval = sc->ndis_block->nmb_setstat;
 
 	KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
 
@@ -1306,8 +1311,11 @@
 	if (sc->ndis_block->nmb_pendingreq != NULL) {
 		KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
 		panic("ndis_get_info() called while other request pending");
-	} else
+	} else {
 		sc->ndis_block->nmb_pendingreq = (ndis_request *)sc;
+		/* NB: `nmb_getstat' type is uint32_t.  */
+		sc->ndis_block->nmb_getstat = -1;
+	}
 
 	queryfunc = sc->ndis_chars->nmc_queryinfo_func;
 	adapter = sc->ndis_block->nmb_miniportadapterctx;
@@ -1323,6 +1331,18 @@
 	    &byteswritten, &bytesneeded);
 
 	sc->ndis_block->nmb_pendingreq = NULL;
+	/*
+	 * NB: some NDIS USB drivers (AFAIK Netgear WG111v2) looks that they
+	 * return NDIS_STATUS_PENDING value even if they already called the
+	 * callback function in their routine, ndis_getdone_func().  So we
+	 * need to check the value whether it's set or not before waiting for
+	 * 5 seconds.  If we doesn't, we would always be blocked for 5 seconds
+	 * because the `nmb_getevent' event wouldn't be happened that the event
+	 * is already fired before we try to set it using
+	 * KeWaitForSingleObject().
+	 */
+	if (rval == NDIS_STATUS_PENDING && sc->ndis_block->nmb_getstat != -1)
+		rval = sc->ndis_block->nmb_getstat;
 
 	KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
 

==== //depot/projects/ndisusb/sys/dev/if_ndis/if_ndis.c#4 (text+ko) ====




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807220506.m6M56vWV060595>