patch v2 revisions: . Limit patch to message changes only. Update dev_err() messages to report status (including success) for each step of USB RX HALT and TX HALT error recovery. If error recovery fails, show the message: stuck RX HALT state requires USB Reset Device to clear or stuck TX HALT state requires USB Reset Device to clear This patch only affects RX and TX HALT error reporting. The capability for mceusb to invoke USB reset device for itself is deferred to a future patch. It's unsafe to perform usb_reset_device() when and where the driver posts the "... requires USB Reset ..." message. Users can fix their mceusb device manually by issuing ioctl(fd, USBDEVFS_RESET, 0) to the mceusb device, as in: $ sudo ./usbreset /dev/bus/usb/001/010 --- As seen on very rare occasions with mceusb device 2304:0225 [59388.696941] mceusb 1-1.1.2:1.0: Error: urb status = -32 (RX HALT) [59388.698838] mceusb 1-1.1.2:1.0: rx clear halt error -32 the device can get into RX or TX HALT state where usb_clear_halt() also fails and also returns -EPIPE (HALT/STALL). After which, all further mceusb device control and data I/O fails with HALT/STALL. Cause and problem replication conditions are still unknown. Further troubleshooting revealed that usb_reset_device() successfully restores mceusb device operation. Of note is "modprobe -r mceusb" with "modprobe mceusb" usb_reset_endpoint(), and usb_reset_configuration(), were all unsuccessful. Signed-off-by: A Sun <as1033x@xxxxxxxxxxx> --- drivers/media/rc/mceusb.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index efffb1795..fffd826c6 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -765,7 +765,7 @@ static void mceusb_defer_kevent(struct mceusb_dev *ir, int kevent) { set_bit(kevent, &ir->kevent_flags); if (!schedule_work(&ir->kevent)) - dev_err(ir->dev, "kevent %d may have been dropped", kevent); + dev_dbg(ir->dev, "kevent %d already scheduled", kevent); else dev_dbg(ir->dev, "kevent %d scheduled", kevent); } @@ -1404,19 +1404,27 @@ static void mceusb_deferred_kevent(struct work_struct *work) container_of(work, struct mceusb_dev, kevent); int status; + dev_err(ir->dev, "kevent handler called (flags 0x%lx)", + ir->kevent_flags); + if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) { usb_unlink_urb(ir->urb_in); status = usb_clear_halt(ir->usbdev, ir->pipe_in); + dev_err(ir->dev, "rx clear halt status = %d", status); if (status < 0) { - dev_err(ir->dev, "rx clear halt error %d", - status); + /* + * Unable to clear RX halt/stall. + * Will need to call usb_reset_device(). + */ + dev_err(ir->dev, + "stuck RX HALT state requires USB Reset Device to clear"); } clear_bit(EVENT_RX_HALT, &ir->kevent_flags); if (status == 0) { status = usb_submit_urb(ir->urb_in, GFP_KERNEL); if (status < 0) { dev_err(ir->dev, - "rx unhalt submit urb error %d", + "rx unhalt submit urb error = %d", status); } } @@ -1424,8 +1432,15 @@ static void mceusb_deferred_kevent(struct work_struct *work) if (test_bit(EVENT_TX_HALT, &ir->kevent_flags)) { status = usb_clear_halt(ir->usbdev, ir->pipe_out); - if (status < 0) - dev_err(ir->dev, "tx clear halt error %d", status); + dev_err(ir->dev, "tx clear halt status = %d", status); + if (status < 0) { + /* + * Unable to clear TX halt/stall. + * Will need to call usb_reset_device(). + */ + dev_err(ir->dev, + "stuck TX HALT state requires USB Reset Device to clear"); + } clear_bit(EVENT_TX_HALT, &ir->kevent_flags); } } -- 2.11.0