tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: usbd_do_request_flags_pipe diagnostic panic



On 06/06/15 05:39, takahiro hayashi wrote:
Hello,

On nick-nhusb branch kernel panics in usbd_transfer() when the
zero-length request gets stalled.

This happens when the uhidev driver issues usbd_set_idle to my
USB keyboard, one of its uhidevs returns stall for SET_IDLE request.

While usbd_do_request_flags_pipe() processes the xfer for SET_IDLE,
it tries to read endpoint's status and clear stall condition
if the endpoint is stalled.
It reuses the xfer to store GET_STATUS request, but ux_buf of xfer
is not allocated, then KASSERT at line 298 in usbd_transfer() fails.

Should usbd_do_request*() allocate ux_buf even if ux_length is 0?
Should I file PR this prob?

How about this diff?

Nick
Index: dev/usb/usbdi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usbdi.c,v
retrieving revision 1.162.2.26
diff -u -p -r1.162.2.26 usbdi.c
--- dev/usb/usbdi.c	30 Mar 2015 12:09:30 -0000	1.162.2.26
+++ dev/usb/usbdi.c	7 Jun 2015 10:49:55 -0000
@@ -1062,32 +1062,34 @@ usbd_do_request_flags_pipe(struct usbd_d
 		 * any halt condition.
 		 */
 		usb_device_request_t treq;
-		usb_status_t status;
-		uint16_t s;
 		usbd_status nerr;
 
-		treq.bmRequestType = UT_READ_ENDPOINT;
-		treq.bRequest = UR_GET_STATUS;
-		USETW(treq.wValue, 0);
-		USETW(treq.wIndex, 0);
-		USETW(treq.wLength, sizeof(usb_status_t));
-		usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
-					   &treq, &status,sizeof(usb_status_t),
-					   0, 0);
-		nerr = usbd_sync_transfer(xfer);
-		if (nerr)
-			goto bad;
-		s = UGETW(status.wStatus);
-		USBHIST_LOG(usbdebug, "status = 0x%04x", s, 0, 0, 0);
-		if (!(s & UES_HALT))
-			goto bad;
+		void *buf = usbd_alloc_buffer(xfer, sizeof(usb_status_t));
+		if (buf) {
+			usb_status_t status;
+			treq.bmRequestType = UT_READ_ENDPOINT;
+			treq.bRequest = UR_GET_STATUS;
+			USETW(treq.wValue, 0);
+			USETW(treq.wIndex, 0);
+			USETW(treq.wLength, sizeof(usb_status_t));
+			usbd_setup_default_xfer(xfer, dev, 0,
+			    USBD_DEFAULT_TIMEOUT, &treq, &status,
+			    sizeof(usb_status_t), 0, 0);
+			nerr = usbd_sync_transfer(xfer);
+			if (nerr)
+				goto bad;
+			uint16_t s = UGETW(status.wStatus);
+			USBHIST_LOG(usbdebug, "status = 0x%04x", s, 0, 0, 0);
+			if (!(s & UES_HALT))
+				goto bad;
+		}
 		treq.bmRequestType = UT_WRITE_ENDPOINT;
 		treq.bRequest = UR_CLEAR_FEATURE;
 		USETW(treq.wValue, UF_ENDPOINT_HALT);
 		USETW(treq.wIndex, 0);
 		USETW(treq.wLength, 0);
 		usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
-					   &treq, &status, 0, 0, 0);
+		    &treq, NULL, 0, 0, 0);
 		nerr = usbd_sync_transfer(xfer);
 		if (nerr)
 			goto bad;


Home | Main Index | Thread Index | Old Index