Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Apr 2008 17:02:18 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 140309 for review
Message-ID:  <200804201702.m3KH2IFa060081@repoman.freebsd.org>

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

Change 140309 by hselasky@hselasky_laptop001 on 2008/04/20 17:02:09

	
	Minor software change in USB LPT driver:
	
	If the device is multifunctional, it can be a problem to use a
	software interval of 1 second on a control endpoint, hence it
	will block all other control requests for that long on the
	same USB device. Use a watchdog instead to do polling.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/ulpt.c#44 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/ulpt.c#44 (text+ko) ====

@@ -87,6 +87,7 @@
 struct ulpt_softc {
 	struct usb_cdev sc_cdev;
 	struct mtx sc_mtx;
+	struct usb_callout sc_watchdog;
 
 	device_t sc_dev;
 	struct usbd_xfer *sc_xfer[ULPT_N_TRANSFER];
@@ -114,6 +115,7 @@
 static usbd_callback_t ulpt_read_clear_stall_callback;
 static usbd_callback_t ulpt_status_callback;
 static usbd_callback_t ulpt_reset_callback;
+static void ulpt_watchdog(void *arg);
 
 static void
 ulpt_write_callback(struct usbd_xfer *xfer)
@@ -254,9 +256,9 @@
 		else if (new_status & LPS_NERR)
 			log(LOG_NOTICE, "%s: output error\n",
 			    device_get_nameunit(sc->sc_dev));
+		break;
 
 	case USBD_ST_SETUP:
-tr_setup:
 		req.bmRequestType = UT_READ_CLASS_INTERFACE;
 		req.bRequest = UR_GET_PORT_STATUS;
 		USETW(req.wValue, 0);
@@ -270,16 +272,16 @@
 		xfer->frlengths[1] = 1;
 		xfer->nframes = 2;
 		usbd_start_hardware(xfer);
+		break;
 
-		return;
-
 	default:			/* Error */
 		DPRINTF(0, "error=%s\n", usbd_errstr(xfer->error));
 		if (xfer->error != USBD_ERR_CANCELLED) {
-			goto tr_setup;
+			/* wait for next watchdog timeout */
 		}
-		return;
+		break;
 	}
+	return;
 }
 
 static void
@@ -359,7 +361,6 @@
 		.mh.bufsize = sizeof(usb_device_request_t) + 1,
 		.mh.callback = &ulpt_status_callback,
 		.mh.timeout = 1000,	/* 1 second */
-		.mh.interval = 1000,	/* 1 second */
 	},
 
 	[3] = {
@@ -525,6 +526,9 @@
 
 	mtx_init(&(sc->sc_mtx), "ulpt lock", NULL, MTX_DEF | MTX_RECURSE);
 
+	usb_callout_init_mtx(&(sc->sc_watchdog),
+	    &(sc->sc_mtx), CALLOUT_RETURNUNLOCKED);
+
 	/* search through all the descriptors looking for bidir mode */
 
 	while (iface_alt_index < 32) {
@@ -637,8 +641,8 @@
 	/* start reading of status */
 
 	mtx_lock(&(sc->sc_mtx));
-	usbd_transfer_start(sc->sc_xfer[2]);
-	mtx_unlock(&(sc->sc_mtx));
+
+	ulpt_watchdog(sc);		/* will unlock mutex */
 
 	return (0);
 
@@ -656,8 +660,14 @@
 
 	usb_cdev_detach(&(sc->sc_cdev));
 
+	mtx_lock(&(sc->sc_mtx));
+	usb_callout_stop(&(sc->sc_watchdog));
+	mtx_unlock(&(sc->sc_mtx));
+
 	usbd_transfer_unsetup(sc->sc_xfer, ULPT_N_TRANSFER);
 
+	usb_callout_drain(&(sc->sc_watchdog));
+
 	mtx_destroy(&(sc->sc_mtx));
 
 	return (0);
@@ -710,6 +720,22 @@
 
 #endif
 
+static void
+ulpt_watchdog(void *arg)
+{
+	struct ulpt_softc *sc = arg;
+
+	mtx_assert(&(sc->sc_mtx), MA_OWNED);
+
+	usbd_transfer_start(sc->sc_xfer[2]);
+
+	usb_callout_reset(&(sc->sc_watchdog),
+	    hz, &ulpt_watchdog, sc);
+
+	mtx_unlock(&(sc->sc_mtx));
+	return;
+}
+
 static devclass_t ulpt_devclass;
 
 static device_method_t ulpt_methods[] = {



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