All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mceusb: RX -EPIPE lockup fault and more
@ 2017-03-25 16:59 A Sun
  2017-03-26 10:27 ` Sean Young
  0 siblings, 1 reply; 14+ messages in thread
From: A Sun @ 2017-03-25 16:59 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, as1033x

commit https://github.com/asunxx/linux/commit/e557c1d737462961f2aadfbfb0836ffa3c778518
Author: A Sun <as1033x@comcast.net>
Date:   Sat Mar 25 02:42:03 2017 -0400

[PATCH] mceusb RX -EPIPE fault and more

Patch for mceusb driver tested with

[    8.627769] mceusb 1-1.2:1.0: Registered Pinnacle Systems PCTV Remote USB with mce emulator interface version 1
[    8.627797] mceusb 1-1.2:1.0: 2 tx ports (0x1 cabled) and 2 rx sensors (0x1 active)

running on

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 4.4.50-v7+ #970 SMP Mon Feb 20 19:18:29 GMT 2017 armv7l GNU/Linux
pi@raspberrypi:~ $

This patch is bug fix and debug messages fix (used for troubleshooting) for

Bug:

RX -EPIPE failure with infinite loop and flooding of
Mar 20 22:24:56 raspberrypi kernel: [ 2851.966506] mceusb 1-1.2:1.0: Error: urb status = -32
log message at 8000 messages per second.
Bug trigger appears to be normal, but heavy, IR receiver use.
Driver and Linux host become unusable after error.
Also seen at https://sourceforge.net/p/lirc/mailman/message/34886165/

Fix:

Message reports RX usb halt (stall) condition requiring usb_clear_halt() call in non-interrupt context to recover.
Add driver workqueue call to perform this recovery based on method in use for the usbnet device driver.

Bug:

Intermittent RX truncation and loss of IR received data. Results in receive data stream synchronization errors where driver attempts to incorrectly parse IR data as command responses.

Mar 22 12:01:40 raspberrypi kernel: [ 3969.139898] mceusb 1-1.2:1.0: processed IR data
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151315] mceusb 1-1.2:1.0: rx data: 00 90 (length=2)
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151321] mceusb 1-1.2:1.0: Unknown command 0x00 0x90
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151336] mceusb 1-1.2:1.0: rx data: 98 0a 8d 0a 8e 0a 8e 0a 8e 0a 8e 0a 9a 0a 8e 0a 0b 3a 8e 00 80 41 59 00 00 (length=25)
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151341] mceusb 1-1.2:1.0: Raw IR data, 24 pulse/space samples
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151348] mceusb 1-1.2:1.0: Storing space with duration 500000

Bug trigger appears to be normal, but heavy, IR receiver use.

Fix:

Cause may be receiver with ep_in bulk endpoint incorrectly bound to usb_fill_int_urb() urb for interrupt endpoint.
In mceusb_dev_probe(), test ep_in endpoint for int versus bulk and use usb_fill_bulk_urb() as appropriate.

Bug:

Memory leak on disconnect for rc = rc_allocate_device().

Fix:

Add call rc_free_device() to mceusb_dev_disconnect()

Bug:

mceusb_dev_printdata() prints incorrect window of bytes (0 to len) that are of interest and will be processed next.

Fix:

Add size of received data argument to mceusb_dev_printdata().
Revise buffer print window (offset to offset+len).
Remove static USB_BUFLEN = 32, which is variable depending on device
(my receiver buffer size is 64 for Pinnacle IR transceiver).
Revise bound test to prevent reporting data beyond end of read or end of buffer.

Bug:

Debug messages; some misleading.

Fix:

Drop "\n" use from dev_dbg().
References to "receive request" should read "send request".
Various syntax and other corrections.

Signed-off-by: A Sun <as1033x@comcast.net>

diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 238d8ea..48e942e 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -36,18 +36,18 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 #include <linux/usb.h>
 #include <linux/usb/input.h>
 #include <linux/pm_wakeup.h>
 #include <media/rc-core.h>
 
-#define DRIVER_VERSION	"1.92"
+#define DRIVER_VERSION	"1.93"
 #define DRIVER_AUTHOR	"Jarod Wilson <jarod@redhat.com>"
 #define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
 			"device driver"
 #define DRIVER_NAME	"mceusb"
 
-#define USB_BUFLEN		32 /* USB reception buffer length */
 #define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */
 #define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */
 
@@ -417,6 +417,7 @@ struct mceusb_dev {
 	/* usb */
 	struct usb_device *usbdev;
 	struct urb *urb_in;
+	unsigned int pipe_in;
 	struct usb_endpoint_descriptor *usb_ep_out;
 
 	/* buffers and dma */
@@ -454,6 +455,12 @@ struct mceusb_dev {
 	u8 num_rxports;		/* number of receive sensors */
 	u8 txports_cabled;	/* bitmask of transmitters with cable */
 	u8 rxports_active;	/* bitmask of active receive sensors */
+
+	/* kevent support */
+	struct work_struct kevent;
+	unsigned long kevent_flags;
+#		define EVENT_TX_HALT	0
+#		define EVENT_RX_HALT	1
 };
 
 /* MCE Device Command Strings, generally a port and command pair */
@@ -527,7 +534,7 @@ static int mceusb_cmd_datasize(u8 cmd, u8 subcmd)
 }
 
 static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
-				 int offset, int len, bool out)
+				 int buf_len, int offset, int len, bool out)
 {
 #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
 	char *inout;
@@ -544,7 +551,8 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
 		return;
 
 	dev_dbg(dev, "%cx data: %*ph (length=%d)",
-		(out ? 't' : 'r'), min(len, USB_BUFLEN), buf, len);
+		(out ? 't' : 'r'),
+		min(len, buf_len - offset), buf + offset, len);
 
 	inout = out ? "Request" : "Got";
 
@@ -701,7 +709,8 @@ static void mce_async_callback(struct urb *urb)
 	case 0:
 		len = urb->actual_length;
 
-		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
+		mceusb_dev_printdata(ir, urb->transfer_buffer, len,
+				     0, len, true);
 		break;
 
 	case -ECONNRESET:
@@ -721,7 +730,7 @@ static void mce_async_callback(struct urb *urb)
 	usb_free_urb(urb);
 }
 
-/* request incoming or send outgoing usb packet - used to initialize remote */
+/* request outgoing (send) usb packet - used to initialize remote */
 static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
 								int size)
 {
@@ -732,7 +741,7 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
 
 	async_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (unlikely(!async_urb)) {
-		dev_err(dev, "Error, couldn't allocate urb!\n");
+		dev_err(dev, "Error, couldn't allocate urb!");
 		return;
 	}
 
@@ -758,17 +767,17 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
 	}
 	memcpy(async_buf, data, size);
 
-	dev_dbg(dev, "receive request called (size=%#x)", size);
+	dev_dbg(dev, "send request called (size=%#x)", size);
 
 	async_urb->transfer_buffer_length = size;
 	async_urb->dev = ir->usbdev;
 
 	res = usb_submit_urb(async_urb, GFP_ATOMIC);
 	if (res) {
-		dev_err(dev, "receive request FAILED! (res=%d)", res);
+		dev_err(dev, "send request FAILED! (res=%d)", res);
 		return;
 	}
-	dev_dbg(dev, "receive request complete (res=%d)", res);
+	dev_dbg(dev, "send request complete (res=%d)", res);
 }
 
 static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
@@ -974,7 +983,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 		switch (ir->parser_state) {
 		case SUBCMD:
 			ir->rem = mceusb_cmd_datasize(ir->cmd, ir->buf_in[i]);
-			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
+			mceusb_dev_printdata(ir, ir->buf_in, buf_len, i - 1,
 					     ir->rem + 2, false);
 			mceusb_handle_command(ir, i);
 			ir->parser_state = CMD_DATA;
@@ -986,7 +995,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
 					 * US_TO_NS(MCE_TIME_UNIT);
 
-			dev_dbg(ir->dev, "Storing %s with duration %d",
+			dev_dbg(ir->dev, "Storing %s with duration %u",
 				rawir.pulse ? "pulse" : "space",
 				rawir.duration);
 
@@ -1007,7 +1016,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 				continue;
 			}
 			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
-			mceusb_dev_printdata(ir, ir->buf_in,
+			mceusb_dev_printdata(ir, ir->buf_in, buf_len,
 					     i, ir->rem + 1, false);
 			if (ir->rem)
 				ir->parser_state = PARSE_IRDATA;
@@ -1025,6 +1034,23 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 	}
 }
 
+/*
+ * Workqueue task dispatcher
+ * for work that can't be done in interrupt handlers
+ * (mceusb_dev_recv() and mce_async_callback()) nor tasklets.
+ * Invokes mceusb_deferred_kevent() for recovering from
+ * error events specified by the kevent bit field.
+ */
+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);
+	} else {
+		dev_dbg(ir->dev, "kevent %d scheduled", kevent);
+	}
+}
+
 static void mceusb_dev_recv(struct urb *urb)
 {
 	struct mceusb_dev *ir;
@@ -1052,6 +1078,11 @@ static void mceusb_dev_recv(struct urb *urb)
 		return;
 
 	case -EPIPE:
+		dev_err(ir->dev, "Error: urb status = %d (RX HALT)",
+			urb->status);
+		mceusb_defer_kevent(ir, EVENT_RX_HALT);
+		return;
+
 	default:
 		dev_err(ir->dev, "Error: urb status = %d", urb->status);
 		break;
@@ -1170,6 +1201,37 @@ static void mceusb_flash_led(struct mceusb_dev *ir)
 	mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
 }
 
+/*
+ * Workqueue function
+ * for resetting or recovering device after occurrence of error events
+ * specified in ir->kevent bit field.
+ * Function runs (via schedule_work()) in non-interrupt context, for
+ * calls here (such as usb_clear_halt()) requiring non-interrupt context.
+ */
+static void mceusb_deferred_kevent(struct work_struct *work)
+{
+	struct mceusb_dev *ir =
+		container_of(work, struct mceusb_dev, kevent);
+	int status;
+
+	if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) {
+		usb_unlink_urb(ir->urb_in);
+		status = usb_clear_halt(ir->usbdev, ir->pipe_in);
+		if (status < 0) {
+			dev_err(ir->dev, "rx clear halt error %d",
+				status);
+			return;
+		}
+		clear_bit(EVENT_RX_HALT, &ir->kevent_flags);
+		status = usb_submit_urb(ir->urb_in, GFP_ATOMIC);
+		if (status < 0) {
+			dev_err(ir->dev, "rx unhalt submit urb error %d",
+				status);
+			return;
+		}
+	}
+}
+
 static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
 {
 	struct usb_device *udev = ir->usbdev;
@@ -1336,17 +1398,25 @@ static int mceusb_dev_probe(struct usb_interface *intf,
 	if (!ir->rc)
 		goto rc_dev_fail;
 
+	ir->pipe_in = pipe;
+	INIT_WORK(&ir->kevent, mceusb_deferred_kevent);
+
 	/* wire up inbound data handler */
-	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
+	if (usb_endpoint_xfer_int(ep_in)) {
+		usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
 				mceusb_dev_recv, ir, ep_in->bInterval);
+	} else {
+		usb_fill_bulk_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
+				mceusb_dev_recv, ir);
+	}
 	ir->urb_in->transfer_dma = ir->dma_in;
 	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* flush buffers on the device */
-	dev_dbg(&intf->dev, "Flushing receive buffers\n");
+	dev_dbg(&intf->dev, "Flushing receive buffers");
 	res = usb_submit_urb(ir->urb_in, GFP_KERNEL);
 	if (res)
-		dev_err(&intf->dev, "failed to flush buffers: %d\n", res);
+		dev_err(&intf->dev, "failed to flush buffers: %d", res);
 
 	/* figure out which firmware/emulator version this hardware has */
 	mceusb_get_emulator_version(ir);
@@ -1405,7 +1475,9 @@ static void mceusb_dev_disconnect(struct usb_interface *intf)
 		return;
 
 	ir->usbdev = NULL;
+	cancel_work_sync(&ir->kevent);
 	rc_unregister_device(ir->rc);
+	rc_free_device(ir->rc);
 	usb_kill_urb(ir->urb_in);
 	usb_free_urb(ir->urb_in);
 	usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] mceusb: RX -EPIPE lockup fault and more
  2017-03-25 16:59 [PATCH] mceusb: RX -EPIPE lockup fault and more A Sun
@ 2017-03-26 10:27 ` Sean Young
  2017-03-26 16:36   ` [PATCH 0/3] [media] " A Sun
                     ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Sean Young @ 2017-03-26 10:27 UTC (permalink / raw)
  To: A Sun; +Cc: linux-media, Mauro Carvalho Chehab

On Sat, Mar 25, 2017 at 12:59:09PM -0400, A Sun wrote:
> commit https://github.com/asunxx/linux/commit/e557c1d737462961f2aadfbfb0836ffa3c778518
> Author: A Sun <as1033x@comcast.net>
> Date:   Sat Mar 25 02:42:03 2017 -0400
> 
> [PATCH] mceusb RX -EPIPE fault and more
> 
> Patch for mceusb driver tested with
> 
> [    8.627769] mceusb 1-1.2:1.0: Registered Pinnacle Systems PCTV Remote USB with mce emulator interface version 1
> [    8.627797] mceusb 1-1.2:1.0: 2 tx ports (0x1 cabled) and 2 rx sensors (0x1 active)
> 
> running on
> 
> pi@raspberrypi:~ $ uname -a
> Linux raspberrypi 4.4.50-v7+ #970 SMP Mon Feb 20 19:18:29 GMT 2017 armv7l GNU/Linux
> pi@raspberrypi:~ $
> 
> This patch is bug fix and debug messages fix (used for troubleshooting) for

Patches should be against media_tree. Also, one change per commit; please
split this into multiple commits.

> 
> Bug:
> 
> RX -EPIPE failure with infinite loop and flooding of
> Mar 20 22:24:56 raspberrypi kernel: [ 2851.966506] mceusb 1-1.2:1.0: Error: urb status = -32
> log message at 8000 messages per second.
> Bug trigger appears to be normal, but heavy, IR receiver use.
> Driver and Linux host become unusable after error.
> Also seen at https://sourceforge.net/p/lirc/mailman/message/34886165/
> 
> Fix:
> 
> Message reports RX usb halt (stall) condition requiring usb_clear_halt() call in non-interrupt context to recover.
> Add driver workqueue call to perform this recovery based on method in use for the usbnet device driver.
> 
> Bug:
> 
> Intermittent RX truncation and loss of IR received data. Results in receive data stream synchronization errors where driver attempts to incorrectly parse IR data as command responses.
> 
> Mar 22 12:01:40 raspberrypi kernel: [ 3969.139898] mceusb 1-1.2:1.0: processed IR data
> Mar 22 12:01:40 raspberrypi kernel: [ 3969.151315] mceusb 1-1.2:1.0: rx data: 00 90 (length=2)
> Mar 22 12:01:40 raspberrypi kernel: [ 3969.151321] mceusb 1-1.2:1.0: Unknown command 0x00 0x90
> Mar 22 12:01:40 raspberrypi kernel: [ 3969.151336] mceusb 1-1.2:1.0: rx data: 98 0a 8d 0a 8e 0a 8e 0a 8e 0a 8e 0a 9a 0a 8e 0a 0b 3a 8e 00 80 41 59 00 00 (length=25)
> Mar 22 12:01:40 raspberrypi kernel: [ 3969.151341] mceusb 1-1.2:1.0: Raw IR data, 24 pulse/space samples
> Mar 22 12:01:40 raspberrypi kernel: [ 3969.151348] mceusb 1-1.2:1.0: Storing space with duration 500000
> 
> Bug trigger appears to be normal, but heavy, IR receiver use.
> 
> Fix:
> 
> Cause may be receiver with ep_in bulk endpoint incorrectly bound to usb_fill_int_urb() urb for interrupt endpoint.
> In mceusb_dev_probe(), test ep_in endpoint for int versus bulk and use usb_fill_bulk_urb() as appropriate.
> 
> Bug:
> 
> Memory leak on disconnect for rc = rc_allocate_device().
> 
> Fix:
> 
> Add call rc_free_device() to mceusb_dev_disconnect()

rc_unregister_device() will call rc_free_device() for you.

> Bug:
> 
> mceusb_dev_printdata() prints incorrect window of bytes (0 to len) that are of interest and will be processed next.
> 
> Fix:
> 
> Add size of received data argument to mceusb_dev_printdata().
> Revise buffer print window (offset to offset+len).
> Remove static USB_BUFLEN = 32, which is variable depending on device
> (my receiver buffer size is 64 for Pinnacle IR transceiver).
> Revise bound test to prevent reporting data beyond end of read or end of buffer.
> 
> Bug:
> 
> Debug messages; some misleading.
> 
> Fix:
> 
> Drop "\n" use from dev_dbg().
> References to "receive request" should read "send request".
> Various syntax and other corrections.
> 
> Signed-off-by: A Sun <as1033x@comcast.net>
> 
> diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
> index 238d8ea..48e942e 100644
> --- a/drivers/media/rc/mceusb.c
> +++ b/drivers/media/rc/mceusb.c
> @@ -36,18 +36,18 @@
>  #include <linux/device.h>
>  #include <linux/module.h>
>  #include <linux/slab.h>
> +#include <linux/workqueue.h>
>  #include <linux/usb.h>
>  #include <linux/usb/input.h>
>  #include <linux/pm_wakeup.h>
>  #include <media/rc-core.h>
>  
> -#define DRIVER_VERSION	"1.92"
> +#define DRIVER_VERSION	"1.93"
>  #define DRIVER_AUTHOR	"Jarod Wilson <jarod@redhat.com>"
>  #define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
>  			"device driver"
>  #define DRIVER_NAME	"mceusb"
>  
> -#define USB_BUFLEN		32 /* USB reception buffer length */
>  #define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */
>  #define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */
>  
> @@ -417,6 +417,7 @@ struct mceusb_dev {
>  	/* usb */
>  	struct usb_device *usbdev;
>  	struct urb *urb_in;
> +	unsigned int pipe_in;
>  	struct usb_endpoint_descriptor *usb_ep_out;
>  
>  	/* buffers and dma */
> @@ -454,6 +455,12 @@ struct mceusb_dev {
>  	u8 num_rxports;		/* number of receive sensors */
>  	u8 txports_cabled;	/* bitmask of transmitters with cable */
>  	u8 rxports_active;	/* bitmask of active receive sensors */
> +
> +	/* kevent support */
> +	struct work_struct kevent;
> +	unsigned long kevent_flags;
> +#		define EVENT_TX_HALT	0
> +#		define EVENT_RX_HALT	1
>  };
>  
>  /* MCE Device Command Strings, generally a port and command pair */
> @@ -527,7 +534,7 @@ static int mceusb_cmd_datasize(u8 cmd, u8 subcmd)
>  }
>  
>  static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
> -				 int offset, int len, bool out)
> +				 int buf_len, int offset, int len, bool out)
>  {
>  #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
>  	char *inout;
> @@ -544,7 +551,8 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
>  		return;
>  
>  	dev_dbg(dev, "%cx data: %*ph (length=%d)",
> -		(out ? 't' : 'r'), min(len, USB_BUFLEN), buf, len);
> +		(out ? 't' : 'r'),
> +		min(len, buf_len - offset), buf + offset, len);
>  
>  	inout = out ? "Request" : "Got";
>  
> @@ -701,7 +709,8 @@ static void mce_async_callback(struct urb *urb)
>  	case 0:
>  		len = urb->actual_length;
>  
> -		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
> +		mceusb_dev_printdata(ir, urb->transfer_buffer, len,
> +				     0, len, true);
>  		break;
>  
>  	case -ECONNRESET:
> @@ -721,7 +730,7 @@ static void mce_async_callback(struct urb *urb)
>  	usb_free_urb(urb);
>  }
>  
> -/* request incoming or send outgoing usb packet - used to initialize remote */
> +/* request outgoing (send) usb packet - used to initialize remote */
>  static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
>  								int size)
>  {
> @@ -732,7 +741,7 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
>  
>  	async_urb = usb_alloc_urb(0, GFP_KERNEL);
>  	if (unlikely(!async_urb)) {
> -		dev_err(dev, "Error, couldn't allocate urb!\n");
> +		dev_err(dev, "Error, couldn't allocate urb!");
>  		return;
>  	}
>  
> @@ -758,17 +767,17 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
>  	}
>  	memcpy(async_buf, data, size);
>  
> -	dev_dbg(dev, "receive request called (size=%#x)", size);
> +	dev_dbg(dev, "send request called (size=%#x)", size);
>  
>  	async_urb->transfer_buffer_length = size;
>  	async_urb->dev = ir->usbdev;
>  
>  	res = usb_submit_urb(async_urb, GFP_ATOMIC);
>  	if (res) {
> -		dev_err(dev, "receive request FAILED! (res=%d)", res);
> +		dev_err(dev, "send request FAILED! (res=%d)", res);
>  		return;
>  	}
> -	dev_dbg(dev, "receive request complete (res=%d)", res);
> +	dev_dbg(dev, "send request complete (res=%d)", res);
>  }
>  
>  static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
> @@ -974,7 +983,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
>  		switch (ir->parser_state) {
>  		case SUBCMD:
>  			ir->rem = mceusb_cmd_datasize(ir->cmd, ir->buf_in[i]);
> -			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
> +			mceusb_dev_printdata(ir, ir->buf_in, buf_len, i - 1,
>  					     ir->rem + 2, false);
>  			mceusb_handle_command(ir, i);
>  			ir->parser_state = CMD_DATA;
> @@ -986,7 +995,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
>  			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
>  					 * US_TO_NS(MCE_TIME_UNIT);
>  
> -			dev_dbg(ir->dev, "Storing %s with duration %d",
> +			dev_dbg(ir->dev, "Storing %s with duration %u",
>  				rawir.pulse ? "pulse" : "space",
>  				rawir.duration);
>  
> @@ -1007,7 +1016,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
>  				continue;
>  			}
>  			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
> -			mceusb_dev_printdata(ir, ir->buf_in,
> +			mceusb_dev_printdata(ir, ir->buf_in, buf_len,
>  					     i, ir->rem + 1, false);
>  			if (ir->rem)
>  				ir->parser_state = PARSE_IRDATA;
> @@ -1025,6 +1034,23 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
>  	}
>  }
>  
> +/*
> + * Workqueue task dispatcher
> + * for work that can't be done in interrupt handlers
> + * (mceusb_dev_recv() and mce_async_callback()) nor tasklets.
> + * Invokes mceusb_deferred_kevent() for recovering from
> + * error events specified by the kevent bit field.
> + */
> +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);
> +	} else {
> +		dev_dbg(ir->dev, "kevent %d scheduled", kevent);
> +	}
> +}
> +
>  static void mceusb_dev_recv(struct urb *urb)
>  {
>  	struct mceusb_dev *ir;
> @@ -1052,6 +1078,11 @@ static void mceusb_dev_recv(struct urb *urb)
>  		return;
>  
>  	case -EPIPE:
> +		dev_err(ir->dev, "Error: urb status = %d (RX HALT)",
> +			urb->status);
> +		mceusb_defer_kevent(ir, EVENT_RX_HALT);
> +		return;
> +
>  	default:
>  		dev_err(ir->dev, "Error: urb status = %d", urb->status);
>  		break;
> @@ -1170,6 +1201,37 @@ static void mceusb_flash_led(struct mceusb_dev *ir)
>  	mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
>  }
>  
> +/*
> + * Workqueue function
> + * for resetting or recovering device after occurrence of error events
> + * specified in ir->kevent bit field.
> + * Function runs (via schedule_work()) in non-interrupt context, for
> + * calls here (such as usb_clear_halt()) requiring non-interrupt context.
> + */
> +static void mceusb_deferred_kevent(struct work_struct *work)
> +{
> +	struct mceusb_dev *ir =
> +		container_of(work, struct mceusb_dev, kevent);
> +	int status;
> +
> +	if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) {
> +		usb_unlink_urb(ir->urb_in);
> +		status = usb_clear_halt(ir->usbdev, ir->pipe_in);
> +		if (status < 0) {
> +			dev_err(ir->dev, "rx clear halt error %d",
> +				status);
> +			return;
> +		}
> +		clear_bit(EVENT_RX_HALT, &ir->kevent_flags);
> +		status = usb_submit_urb(ir->urb_in, GFP_ATOMIC);

This can be GFP_KERNEL.

> +		if (status < 0) {
> +			dev_err(ir->dev, "rx unhalt submit urb error %d",
> +				status);
> +			return;
> +		}
> +	}
> +}
> +
>  static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
>  {
>  	struct usb_device *udev = ir->usbdev;
> @@ -1336,17 +1398,25 @@ static int mceusb_dev_probe(struct usb_interface *intf,
>  	if (!ir->rc)
>  		goto rc_dev_fail;
>  
> +	ir->pipe_in = pipe;
> +	INIT_WORK(&ir->kevent, mceusb_deferred_kevent);
> +
>  	/* wire up inbound data handler */
> -	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
> +	if (usb_endpoint_xfer_int(ep_in)) {
> +		usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
>  				mceusb_dev_recv, ir, ep_in->bInterval);
> +	} else {
> +		usb_fill_bulk_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
> +				mceusb_dev_recv, ir);
> +	}
>  	ir->urb_in->transfer_dma = ir->dma_in;
>  	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
>  
>  	/* flush buffers on the device */
> -	dev_dbg(&intf->dev, "Flushing receive buffers\n");
> +	dev_dbg(&intf->dev, "Flushing receive buffers");
>  	res = usb_submit_urb(ir->urb_in, GFP_KERNEL);
>  	if (res)
> -		dev_err(&intf->dev, "failed to flush buffers: %d\n", res);
> +		dev_err(&intf->dev, "failed to flush buffers: %d", res);
>  
>  	/* figure out which firmware/emulator version this hardware has */
>  	mceusb_get_emulator_version(ir);
> @@ -1405,7 +1475,9 @@ static void mceusb_dev_disconnect(struct usb_interface *intf)
>  		return;
>  
>  	ir->usbdev = NULL;
> +	cancel_work_sync(&ir->kevent);
>  	rc_unregister_device(ir->rc);
> +	rc_free_device(ir->rc);

That change is wrong and will cause a double free.

>  	usb_kill_urb(ir->urb_in);
>  	usb_free_urb(ir->urb_in);
>  	usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);

Would you be able to split this into multiple commits please?

Thanks,
Sean

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/3] [media] mceusb: RX -EPIPE lockup fault and more
  2017-03-26 10:27 ` Sean Young
@ 2017-03-26 16:36   ` A Sun
  2017-03-26 18:28   ` [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix A Sun
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: A Sun @ 2017-03-26 16:36 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, Mauro Carvalho Chehab

On 3/26/2017 6:27 AM, Sean Young wrote:
...

>> +		status = usb_submit_urb(ir->urb_in, GFP_ATOMIC);
> 
> This can be GFP_KERNEL.
> 
...

>> +	rc_free_device(ir->rc);
> 
> That change is wrong and will cause a double free.
> 
>>  	usb_kill_urb(ir->urb_in);
>>  	usb_free_urb(ir->urb_in);
>>  	usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
> 
> Would you be able to split this into multiple commits please?
> 
> Thanks,
> Sean
> 

Hi Sean,

Thank you for the quick reply, review, corrections, and suggestions. Please bear with me since this is my first contribution for Linux. The patch production submission/review process is entirely new to me at this time.

I'll perform the corrections in the forthcoming replies containing the split patches:
    [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
    [PATCH 2/3] [media] mceusb: sporadic RX truncation corruption fix
    [PATCH 3/3] [media] mceusb: fix inaccurate debug buffer dumps and misleading debug messages

Thanks again. ..A Sun

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-26 10:27 ` Sean Young
  2017-03-26 16:36   ` [PATCH 0/3] [media] " A Sun
@ 2017-03-26 18:28   ` A Sun
  2017-03-26 20:31     ` Sean Young
  2017-03-26 18:33   ` [PATCH 2/3] [media] mceusb: sporadic RX truncation corruption fix A Sun
  2017-03-26 19:04   ` [PATCH 3/3] [media] mceusb: fix inaccurate debug buffer dumps,and misleading debug messages A Sun
  3 siblings, 1 reply; 14+ messages in thread
From: A Sun @ 2017-03-26 18:28 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, Mauro Carvalho Chehab

commit https://github.com/asunxx/linux/commit/17fe3b51f4ad5202a876ea4c92b5d99d4e166823
Author: A Sun <as1033x@comcast.net>
Date:   Sun, 26 Mar 2017 13:24:18 -0400 

Bug:

RX -EPIPE failure with infinite loop and flooding of
Mar 20 22:24:56 raspberrypi kernel: [ 2851.966506] mceusb 1-1.2:1.0: Error: urb status = -32
log message at 8000 messages per second.
Bug trigger appears to be normal, but heavy, IR receiver use.
Driver and Linux host become unusable after error.
Also seen at https://sourceforge.net/p/lirc/mailman/message/34886165/

Fix:

Message reports RX usb halt (stall) condition requiring usb_clear_halt() call in non-interrupt context to recover.
Add driver workqueue call to perform this recovery based on method in use for the usbnet device driver.

Tested with:

Linux raspberrypi 4.4.50-v7+ #970 SMP Mon Feb 20 19:18:29 GMT 2017 armv7l GNU/Linux
mceusb 1-1.2:1.0: Registered Pinnacle Systems PCTV Remote USB with mce emulator interface version 1
mceusb 1-1.2:1.0: 2 tx ports (0x1 cabled) and 2 rx sensors (0x1 active)

Signed-off-by: A Sun <as1033x@comcast.net>
---
 drivers/media/rc/mceusb.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 238d8ea..7b6f9e5 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -36,12 +36,13 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 #include <linux/usb.h>
 #include <linux/usb/input.h>
 #include <linux/pm_wakeup.h>
 #include <media/rc-core.h>
 
-#define DRIVER_VERSION	"1.92"
+#define DRIVER_VERSION	"1.93"
 #define DRIVER_AUTHOR	"Jarod Wilson <jarod@redhat.com>"
 #define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
 			"device driver"
@@ -417,6 +418,7 @@ struct mceusb_dev {
 	/* usb */
 	struct usb_device *usbdev;
 	struct urb *urb_in;
+	unsigned int pipe_in;
 	struct usb_endpoint_descriptor *usb_ep_out;
 
 	/* buffers and dma */
@@ -454,6 +456,12 @@ struct mceusb_dev {
 	u8 num_rxports;		/* number of receive sensors */
 	u8 txports_cabled;	/* bitmask of transmitters with cable */
 	u8 rxports_active;	/* bitmask of active receive sensors */
+
+	/* kevent support */
+	struct work_struct kevent;
+	unsigned long kevent_flags;
+#		define EVENT_TX_HALT	0
+#		define EVENT_RX_HALT	1
 };
 
 /* MCE Device Command Strings, generally a port and command pair */
@@ -1025,6 +1033,23 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 	}
 }
 
+/*
+ * Workqueue task dispatcher
+ * for work that can't be done in interrupt handlers
+ * (mceusb_dev_recv() and mce_async_callback()) nor tasklets.
+ * Invokes mceusb_deferred_kevent() for recovering from
+ * error events specified by the kevent bit field.
+ */
+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);
+	} else {
+		dev_dbg(ir->dev, "kevent %d scheduled", kevent);
+	}
+}
+
 static void mceusb_dev_recv(struct urb *urb)
 {
 	struct mceusb_dev *ir;
@@ -1052,6 +1077,11 @@ static void mceusb_dev_recv(struct urb *urb)
 		return;
 
 	case -EPIPE:
+		dev_err(ir->dev, "Error: urb status = %d (RX HALT)",
+			urb->status);
+		mceusb_defer_kevent(ir, EVENT_RX_HALT);
+		return;
+
 	default:
 		dev_err(ir->dev, "Error: urb status = %d", urb->status);
 		break;
@@ -1170,6 +1200,37 @@ static void mceusb_flash_led(struct mceusb_dev *ir)
 	mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
 }
 
+/*
+ * Workqueue function
+ * for resetting or recovering device after occurrence of error events
+ * specified in ir->kevent bit field.
+ * Function runs (via schedule_work()) in non-interrupt context, for
+ * calls here (such as usb_clear_halt()) requiring non-interrupt context.
+ */
+static void mceusb_deferred_kevent(struct work_struct *work)
+{
+	struct mceusb_dev *ir =
+		container_of(work, struct mceusb_dev, kevent);
+	int status;
+
+	if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) {
+		usb_unlink_urb(ir->urb_in);
+		status = usb_clear_halt(ir->usbdev, ir->pipe_in);
+		if (status < 0) {
+			dev_err(ir->dev, "rx clear halt error %d",
+				status);
+			return;
+		}
+		clear_bit(EVENT_RX_HALT, &ir->kevent_flags);
+		status = usb_submit_urb(ir->urb_in, GFP_KERNEL);
+		if (status < 0) {
+			dev_err(ir->dev, "rx unhalt submit urb error %d",
+				status);
+			return;
+		}
+	}
+}
+
 static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
 {
 	struct usb_device *udev = ir->usbdev;
@@ -1336,6 +1397,9 @@ static int mceusb_dev_probe(struct usb_interface *intf,
 	if (!ir->rc)
 		goto rc_dev_fail;
 
+	ir->pipe_in = pipe;
+	INIT_WORK(&ir->kevent, mceusb_deferred_kevent);
+
 	/* wire up inbound data handler */
 	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
 				mceusb_dev_recv, ir, ep_in->bInterval);
@@ -1405,6 +1469,7 @@ static void mceusb_dev_disconnect(struct usb_interface *intf)
 		return;
 
 	ir->usbdev = NULL;
+	cancel_work_sync(&ir->kevent);
 	rc_unregister_device(ir->rc);
 	usb_kill_urb(ir->urb_in);
 	usb_free_urb(ir->urb_in);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] [media] mceusb: sporadic RX truncation corruption fix
  2017-03-26 10:27 ` Sean Young
  2017-03-26 16:36   ` [PATCH 0/3] [media] " A Sun
  2017-03-26 18:28   ` [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix A Sun
@ 2017-03-26 18:33   ` A Sun
  2017-03-26 19:04   ` [PATCH 3/3] [media] mceusb: fix inaccurate debug buffer dumps,and misleading debug messages A Sun
  3 siblings, 0 replies; 14+ messages in thread
From: A Sun @ 2017-03-26 18:33 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, Mauro Carvalho Chehab

commit https://github.com/asunxx/linux/commit/d71c609e99cabc0a92a4d0b225486cbc09bbd8bd
Author: A Sun <as1033x@comcast.net>
Date:   Sun, 26 Mar 2017 14:11:49 -0400

Bug:

Intermittent RX truncation and loss of IR received data.
This resulted in receive stream synchronization errors where driver attempted to incorrectly parse IR data (eg 0x90 below) as command response.

Mar 22 12:01:40 raspberrypi kernel: [ 3969.139898] mceusb 1-1.2:1.0: processed IR data
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151315] mceusb 1-1.2:1.0: rx data: 00 90 (length=2)
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151321] mceusb 1-1.2:1.0: Unknown command 0x00 0x90
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151336] mceusb 1-1.2:1.0: rx data: 98 0a 8d 0a 8e 0a 8e 0a 8e 0a 8e 0a 9a 0a 8e 0a 0b 3a 8e 00 80 41 59 00 00 (length=25)
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151341] mceusb 1-1.2:1.0: Raw IR data, 24 pulse/space samples
Mar 22 12:01:40 raspberrypi kernel: [ 3969.151348] mceusb 1-1.2:1.0: Storing space with duration 500000

Bug trigger appears to be normal, but heavy, IR receiver use.

Fix:

Cause may be receiver with ep_in bulk endpoint incorrectly bound to usb_fill_int_urb() urb for interrupt endpoint.
This may also have been the root cause for "RX -EPIPE (urb status = -32)" lockups.
In mceusb_dev_probe(), test ep_in endpoint for int versus bulk and use usb_fill_bulk_urb() as appropriate.

Tested with:
Linux raspberrypi 4.4.50-v7+ #970 SMP Mon Feb 20 19:18:29 GMT 2017 armv7l GNU/Linux
mceusb 1-1.2:1.0: Registered Pinnacle Systems PCTV Remote USB with mce emulator interface version 1
mceusb 1-1.2:1.0: 2 tx ports (0x1 cabled) and 2 rx sensors (0x1 active)

Signed-off-by: A Sun <as1033x@comcast.net>
---
 drivers/media/rc/mceusb.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 7b6f9e5..720df6f 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1401,8 +1401,13 @@ static int mceusb_dev_probe(struct usb_interface *intf,
 	INIT_WORK(&ir->kevent, mceusb_deferred_kevent);
 
 	/* wire up inbound data handler */
-	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
+	if (usb_endpoint_xfer_int(ep_in)) {
+		usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
 				mceusb_dev_recv, ir, ep_in->bInterval);
+	} else {
+		usb_fill_bulk_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
+				mceusb_dev_recv, ir);
+	}
 	ir->urb_in->transfer_dma = ir->dma_in;
 	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] [media] mceusb: fix inaccurate debug buffer dumps,and misleading debug messages
  2017-03-26 10:27 ` Sean Young
                     ` (2 preceding siblings ...)
  2017-03-26 18:33   ` [PATCH 2/3] [media] mceusb: sporadic RX truncation corruption fix A Sun
@ 2017-03-26 19:04   ` A Sun
  3 siblings, 0 replies; 14+ messages in thread
From: A Sun @ 2017-03-26 19:04 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, Mauro Carvalho Chehab

commit https://github.com/asunxx/linux/commit/14cae79824739ae03caa3b1c4f66cbdf73654bde
Author: A Sun <as1033x@comcast.net>
Date:   Sun, 26 Mar 2017 14:55:31 -0400

Bug:

Some dev_dbg messages are misleading.
Some dev_dbg messages have inconsistent formatting.
mceusb_dev_printdata() prints incorrect range of bytes (0 to len) in buffer which the driver will actually process next.

Fix:

Add size of received data argument to mceusb_dev_printdata().
Revise buffer print range to (offset to offset+len).
Remove static USB_BUFLEN = 32, which is variable depending on device
(buffer size is 64 for Pinnacle IR transceiver).
Revise bound test to prevent reporting data beyond end of read or end of buffer.
Drop "\n" use from dev_dbg().
References to "receive request" should read "send request".

Tested with:

Linux raspberrypi 4.4.50-v7+ #970 SMP Mon Feb 20 19:18:29 GMT 2017 armv7l GNU/Linux
mceusb 1-1.2:1.0: Registered Pinnacle Systems PCTV Remote USB with mce emulator interface version 1
mceusb 1-1.2:1.0: 2 tx ports (0x1 cabled) and 2 rx sensors (0x1 active)

Signed-off-by: A Sun <as1033x@comcast.net>
---
 drivers/media/rc/mceusb.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 720df6f..a9a9a85 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -48,7 +48,6 @@
 			"device driver"
 #define DRIVER_NAME	"mceusb"
 
-#define USB_BUFLEN		32 /* USB reception buffer length */
 #define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */
 #define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */
 
@@ -535,7 +534,7 @@ static int mceusb_cmd_datasize(u8 cmd, u8 subcmd)
 }
 
 static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
-				 int offset, int len, bool out)
+				 int buf_len, int offset, int len, bool out)
 {
 #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
 	char *inout;
@@ -552,7 +551,8 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
 		return;
 
 	dev_dbg(dev, "%cx data: %*ph (length=%d)",
-		(out ? 't' : 'r'), min(len, USB_BUFLEN), buf, len);
+		(out ? 't' : 'r'),
+		min(len, buf_len - offset), buf + offset, len);
 
 	inout = out ? "Request" : "Got";
 
@@ -709,7 +709,8 @@ static void mce_async_callback(struct urb *urb)
 	case 0:
 		len = urb->actual_length;
 
-		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
+		mceusb_dev_printdata(ir, urb->transfer_buffer, len,
+				     0, len, true);
 		break;
 
 	case -ECONNRESET:
@@ -729,7 +730,7 @@ static void mce_async_callback(struct urb *urb)
 	usb_free_urb(urb);
 }
 
-/* request incoming or send outgoing usb packet - used to initialize remote */
+/* request outgoing (send) usb packet - used to initialize remote */
 static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
 								int size)
 {
@@ -740,7 +741,7 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
 
 	async_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (unlikely(!async_urb)) {
-		dev_err(dev, "Error, couldn't allocate urb!\n");
+		dev_err(dev, "Error, couldn't allocate urb!");
 		return;
 	}
 
@@ -766,17 +767,17 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
 	}
 	memcpy(async_buf, data, size);
 
-	dev_dbg(dev, "receive request called (size=%#x)", size);
+	dev_dbg(dev, "send request called (size=%#x)", size);
 
 	async_urb->transfer_buffer_length = size;
 	async_urb->dev = ir->usbdev;
 
 	res = usb_submit_urb(async_urb, GFP_ATOMIC);
 	if (res) {
-		dev_err(dev, "receive request FAILED! (res=%d)", res);
+		dev_err(dev, "send request FAILED! (res=%d)", res);
 		return;
 	}
-	dev_dbg(dev, "receive request complete (res=%d)", res);
+	dev_dbg(dev, "send request complete (res=%d)", res);
 }
 
 static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
@@ -982,7 +983,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 		switch (ir->parser_state) {
 		case SUBCMD:
 			ir->rem = mceusb_cmd_datasize(ir->cmd, ir->buf_in[i]);
-			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
+			mceusb_dev_printdata(ir, ir->buf_in, buf_len, i - 1,
 					     ir->rem + 2, false);
 			mceusb_handle_command(ir, i);
 			ir->parser_state = CMD_DATA;
@@ -994,7 +995,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
 					 * US_TO_NS(MCE_TIME_UNIT);
 
-			dev_dbg(ir->dev, "Storing %s with duration %d",
+			dev_dbg(ir->dev, "Storing %s with duration %u",
 				rawir.pulse ? "pulse" : "space",
 				rawir.duration);
 
@@ -1015,7 +1016,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 				continue;
 			}
 			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
-			mceusb_dev_printdata(ir, ir->buf_in,
+			mceusb_dev_printdata(ir, ir->buf_in, buf_len,
 					     i, ir->rem + 1, false);
 			if (ir->rem)
 				ir->parser_state = PARSE_IRDATA;
@@ -1412,10 +1413,10 @@ static int mceusb_dev_probe(struct usb_interface *intf,
 	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* flush buffers on the device */
-	dev_dbg(&intf->dev, "Flushing receive buffers\n");
+	dev_dbg(&intf->dev, "Flushing receive buffers");
 	res = usb_submit_urb(ir->urb_in, GFP_KERNEL);
 	if (res)
-		dev_err(&intf->dev, "failed to flush buffers: %d\n", res);
+		dev_err(&intf->dev, "failed to flush buffers: %d", res);
 
 	/* figure out which firmware/emulator version this hardware has */
 	mceusb_get_emulator_version(ir);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-26 18:28   ` [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix A Sun
@ 2017-03-26 20:31     ` Sean Young
  2017-03-27  8:18       ` A Sun
  0 siblings, 1 reply; 14+ messages in thread
From: Sean Young @ 2017-03-26 20:31 UTC (permalink / raw)
  To: A Sun; +Cc: linux-media, Mauro Carvalho Chehab

On Sun, Mar 26, 2017 at 02:28:08PM -0400, A Sun wrote:
> commit https://github.com/asunxx/linux/commit/17fe3b51f4ad5202a876ea4c92b5d99d4e166823
> Author: A Sun <as1033x@comcast.net>
> Date:   Sun, 26 Mar 2017 13:24:18 -0400 

Please don't include this.

> 
> Bug:
> 
> RX -EPIPE failure with infinite loop and flooding of
> Mar 20 22:24:56 raspberrypi kernel: [ 2851.966506] mceusb 1-1.2:1.0: Error: urb status = -32
> log message at 8000 messages per second.
> Bug trigger appears to be normal, but heavy, IR receiver use.
> Driver and Linux host become unusable after error.
> Also seen at https://sourceforge.net/p/lirc/mailman/message/34886165/
> 
> Fix:
> 
> Message reports RX usb halt (stall) condition requiring usb_clear_halt() call in non-interrupt context to recover.
> Add driver workqueue call to perform this recovery based on method in use for the usbnet device driver.
> 
> Tested with:
> 
> Linux raspberrypi 4.4.50-v7+ #970 SMP Mon Feb 20 19:18:29 GMT 2017 armv7l GNU/Linux
> mceusb 1-1.2:1.0: Registered Pinnacle Systems PCTV Remote USB with mce emulator interface version 1
> mceusb 1-1.2:1.0: 2 tx ports (0x1 cabled) and 2 rx sensors (0x1 active)

It would be nice to have this tested against a mainline kernel. I thought
that was entirely possible on raspberry pis nowadays.
> 
> Signed-off-by: A Sun <as1033x@comcast.net>
> ---
>  drivers/media/rc/mceusb.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 66 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
> index 238d8ea..7b6f9e5 100644
> --- a/drivers/media/rc/mceusb.c
> +++ b/drivers/media/rc/mceusb.c
> @@ -36,12 +36,13 @@
>  #include <linux/device.h>
>  #include <linux/module.h>
>  #include <linux/slab.h>
> +#include <linux/workqueue.h>
>  #include <linux/usb.h>
>  #include <linux/usb/input.h>
>  #include <linux/pm_wakeup.h>
>  #include <media/rc-core.h>
>  
> -#define DRIVER_VERSION	"1.92"
> +#define DRIVER_VERSION	"1.93"
>  #define DRIVER_AUTHOR	"Jarod Wilson <jarod@redhat.com>"
>  #define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
>  			"device driver"
> @@ -417,6 +418,7 @@ struct mceusb_dev {
>  	/* usb */
>  	struct usb_device *usbdev;
>  	struct urb *urb_in;
> +	unsigned int pipe_in;
>  	struct usb_endpoint_descriptor *usb_ep_out;
>  
>  	/* buffers and dma */
> @@ -454,6 +456,12 @@ struct mceusb_dev {
>  	u8 num_rxports;		/* number of receive sensors */
>  	u8 txports_cabled;	/* bitmask of transmitters with cable */
>  	u8 rxports_active;	/* bitmask of active receive sensors */
> +
> +	/* kevent support */
> +	struct work_struct kevent;

kevent is not a descriptive name. How about something like clear_halt?

> +	unsigned long kevent_flags;
> +#		define EVENT_TX_HALT	0
> +#		define EVENT_RX_HALT	1

EVENT_TX_HALT is never used, so kevent_flags is only ever set to 1. The
entire field can be dropped.

>  };
>  
>  /* MCE Device Command Strings, generally a port and command pair */
> @@ -1025,6 +1033,23 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
>  	}
>  }
>  
> +/*
> + * Workqueue task dispatcher
> + * for work that can't be done in interrupt handlers
> + * (mceusb_dev_recv() and mce_async_callback()) nor tasklets.
> + * Invokes mceusb_deferred_kevent() for recovering from
> + * error events specified by the kevent bit field.
> + */
> +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);
> +	} else {
> +		dev_dbg(ir->dev, "kevent %d scheduled", kevent);
> +	}
> +}

Again name is not very descriptive.

> +
>  static void mceusb_dev_recv(struct urb *urb)
>  {
>  	struct mceusb_dev *ir;
> @@ -1052,6 +1077,11 @@ static void mceusb_dev_recv(struct urb *urb)
>  		return;
>  
>  	case -EPIPE:
> +		dev_err(ir->dev, "Error: urb status = %d (RX HALT)",
> +			urb->status);
> +		mceusb_defer_kevent(ir, EVENT_RX_HALT);

Here you could simply call schedule_work(). Note that EPIPE might also
be returned for device disconnect for some host controllers.

> +		return;
> +
>  	default:
>  		dev_err(ir->dev, "Error: urb status = %d", urb->status);
>  		break;
> @@ -1170,6 +1200,37 @@ static void mceusb_flash_led(struct mceusb_dev *ir)
>  	mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
>  }
>  
> +/*
> + * Workqueue function
> + * for resetting or recovering device after occurrence of error events
> + * specified in ir->kevent bit field.
> + * Function runs (via schedule_work()) in non-interrupt context, for
> + * calls here (such as usb_clear_halt()) requiring non-interrupt context.
> + */
> +static void mceusb_deferred_kevent(struct work_struct *work)
> +{
> +	struct mceusb_dev *ir =
> +		container_of(work, struct mceusb_dev, kevent);
> +	int status;
> +
> +	if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) {

If condition can go.

> +		usb_unlink_urb(ir->urb_in);
> +		status = usb_clear_halt(ir->usbdev, ir->pipe_in);
> +		if (status < 0) {
> +			dev_err(ir->dev, "rx clear halt error %d",
> +				status);
> +			return;
> +		}
> +		clear_bit(EVENT_RX_HALT, &ir->kevent_flags);
> +		status = usb_submit_urb(ir->urb_in, GFP_KERNEL);
> +		if (status < 0) {
> +			dev_err(ir->dev, "rx unhalt submit urb error %d",
> +				status);
> +			return;
> +		}
> +	}
> +}
> +
>  static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
>  {
>  	struct usb_device *udev = ir->usbdev;
> @@ -1336,6 +1397,9 @@ static int mceusb_dev_probe(struct usb_interface *intf,
>  	if (!ir->rc)
>  		goto rc_dev_fail;
>  
> +	ir->pipe_in = pipe;
> +	INIT_WORK(&ir->kevent, mceusb_deferred_kevent);
> +
>  	/* wire up inbound data handler */
>  	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp,
>  				mceusb_dev_recv, ir, ep_in->bInterval);
> @@ -1405,6 +1469,7 @@ static void mceusb_dev_disconnect(struct usb_interface *intf)
>  		return;
>  
>  	ir->usbdev = NULL;
> +	cancel_work_sync(&ir->kevent);
>  	rc_unregister_device(ir->rc);
>  	usb_kill_urb(ir->urb_in);
>  	usb_free_urb(ir->urb_in);
> -- 
> 2.1.4
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-26 20:31     ` Sean Young
@ 2017-03-27  8:18       ` A Sun
  2017-03-28 20:25         ` Sean Young
  0 siblings, 1 reply; 14+ messages in thread
From: A Sun @ 2017-03-27  8:18 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, Mauro Carvalho Chehab

On 3/26/2017 4:31 PM, Sean Young wrote:
> On Sun, Mar 26, 2017 at 02:28:08PM -0400, A Sun wrote:
>> commit https://github.com/asunxx/linux/commit/17fe3b51f4ad5202a876ea4c92b5d99d4e166823
>> Author: A Sun <as1033x@comcast.net>
>> Date:   Sun, 26 Mar 2017 13:24:18 -0400 
> 
> Please don't include this.
> 
>>
...
>> mceusb 1-1.2:1.0: 2 tx ports (0x1 cabled) and 2 rx sensors (0x1 active)
> 
> It would be nice to have this tested against a mainline kernel. I thought
> that was entirely possible on raspberry pis nowadays.
...
>> +	/* kevent support */
>> +	struct work_struct kevent;
> 
> kevent is not a descriptive name. How about something like clear_halt?
> 
>> +	unsigned long kevent_flags;
>> +#		define EVENT_TX_HALT	0
>> +#		define EVENT_RX_HALT	1
> 
> EVENT_TX_HALT is never used, so kevent_flags is only ever set to 1. The
> entire field can be dropped.
> 
...
>> +	if (!schedule_work(&ir->kevent)) {
>> +		dev_err(ir->dev, "kevent %d may have been dropped", kevent);
>> +	} else {
>> +		dev_dbg(ir->dev, "kevent %d scheduled", kevent);
>> +	}
>> +}
> 
> Again name is not very descriptive.
> 
...
>> +		dev_err(ir->dev, "Error: urb status = %d (RX HALT)",
>> +			urb->status);
>> +		mceusb_defer_kevent(ir, EVENT_RX_HALT);
> 
> Here you could simply call schedule_work(). Note that EPIPE might also
> be returned for device disconnect for some host controllers.
> 
>> +		return;
...
>> +	int status;
>> +
>> +	if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) {
> 
> If condition can go.
> 
>> +		usb_unlink_urb(ir->urb_in);
>> +		status = usb_clear_halt(ir->usbdev, ir->pipe_in);

Hi Sean,

Thanks again for looking at this. This patch is based on similar error and recovery, with the USB ethernet driver usbnet (usbnet.c, usbnet.h).

In usbnet, they call "kevent" (kernel device event?) any kind of hardware state change or event in interrupt context that requires invoking non-interrupt code to handle. I'm not sure what else I should name it. Possible kevent-s are not limited to situations needing usb_clear_halt(). From usbnet:
 69 #               define EVENT_TX_HALT    0
 70 #               define EVENT_RX_HALT    1
 71 #               define EVENT_RX_MEMORY  2
 72 #               define EVENT_STS_SPLIT  3
 73 #               define EVENT_LINK_RESET 4
 74 #               define EVENT_RX_PAUSED  5
 75 #               define EVENT_DEV_ASLEEP 6
 76 #               define EVENT_DEV_OPEN   7
 77 #               define EVENT_DEVICE_REPORT_IDLE 8
 78 #               define EVENT_NO_RUNTIME_PM      9
 79 #               define EVENT_RX_KILL    10
 80 #               define EVENT_LINK_CHANGE        11
 81 #               define EVENT_SET_RX_MODE        12
So far, the first two are appearing applicable for mceusb.

The unused EVENT_TX_HALT and the apparently extra _kevent functions and kevent_flags are necessary for a later:
    [PATCH] [media] mceusb: TX -EPIPE lockup fix
...not yet written, transmit side equivalent bug. I respectfully recommend keeping these hooks in place.

For now, I think the transmit side EPIPE bug fix is less critical, since the TX bug avoids hanging the host/kernel, but would still cause lockup of the device.

In case of RX EPIPE on disconnect, the fix is still safe. Recovery attempt should fail (in usb_clear_halt() or usb_submit_urb()) and abort without further retry, and the recovery handler itself gets shutdown in mceusb_dev_disconnect().

Please let me know how to proceed. Thanks. ..A Sun

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-27  8:18       ` A Sun
@ 2017-03-28 20:25         ` Sean Young
  2017-03-29  1:40           ` A Sun
  0 siblings, 1 reply; 14+ messages in thread
From: Sean Young @ 2017-03-28 20:25 UTC (permalink / raw)
  To: A Sun; +Cc: linux-media, Mauro Carvalho Chehab

On Mon, Mar 27, 2017 at 04:18:33AM -0400, A Sun wrote:
> On 3/26/2017 4:31 PM, Sean Young wrote:
> > On Sun, Mar 26, 2017 at 02:28:08PM -0400, A Sun wrote:
> >> commit https://github.com/asunxx/linux/commit/17fe3b51f4ad5202a876ea4c92b5d99d4e166823
> >> Author: A Sun <as1033x@comcast.net>
> >> Date:   Sun, 26 Mar 2017 13:24:18 -0400 
> > 
> > Please don't include this.
> > 
> >>
> ...
> >> mceusb 1-1.2:1.0: 2 tx ports (0x1 cabled) and 2 rx sensors (0x1 active)
> > 
> > It would be nice to have this tested against a mainline kernel. I thought
> > that was entirely possible on raspberry pis nowadays.
> ...
> >> +	/* kevent support */
> >> +	struct work_struct kevent;
> > 
> > kevent is not a descriptive name. How about something like clear_halt?
> > 
> >> +	unsigned long kevent_flags;
> >> +#		define EVENT_TX_HALT	0
> >> +#		define EVENT_RX_HALT	1
> > 
> > EVENT_TX_HALT is never used, so kevent_flags is only ever set to 1. The
> > entire field can be dropped.
> > 
> ...
> >> +	if (!schedule_work(&ir->kevent)) {
> >> +		dev_err(ir->dev, "kevent %d may have been dropped", kevent);
> >> +	} else {
> >> +		dev_dbg(ir->dev, "kevent %d scheduled", kevent);
> >> +	}
> >> +}
> > 
> > Again name is not very descriptive.
> > 
> ...
> >> +		dev_err(ir->dev, "Error: urb status = %d (RX HALT)",
> >> +			urb->status);
> >> +		mceusb_defer_kevent(ir, EVENT_RX_HALT);
> > 
> > Here you could simply call schedule_work(). Note that EPIPE might also
> > be returned for device disconnect for some host controllers.
> > 
> >> +		return;
> ...
> >> +	int status;
> >> +
> >> +	if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) {
> > 
> > If condition can go.
> > 
> >> +		usb_unlink_urb(ir->urb_in);
> >> +		status = usb_clear_halt(ir->usbdev, ir->pipe_in);
> 
> Hi Sean,
> 
> Thanks again for looking at this. This patch is based on similar error and recovery, with the USB ethernet driver usbnet (usbnet.c, usbnet.h).
> 
> In usbnet, they call "kevent" (kernel device event?) any kind of hardware state change or event in interrupt context that requires invoking non-interrupt code to handle. I'm not sure what else I should name it. Possible kevent-s are not limited to situations needing usb_clear_halt(). From usbnet:
>  69 #               define EVENT_TX_HALT    0
>  70 #               define EVENT_RX_HALT    1
>  71 #               define EVENT_RX_MEMORY  2
>  72 #               define EVENT_STS_SPLIT  3
>  73 #               define EVENT_LINK_RESET 4
>  74 #               define EVENT_RX_PAUSED  5
>  75 #               define EVENT_DEV_ASLEEP 6
>  76 #               define EVENT_DEV_OPEN   7
>  77 #               define EVENT_DEVICE_REPORT_IDLE 8
>  78 #               define EVENT_NO_RUNTIME_PM      9
>  79 #               define EVENT_RX_KILL    10
>  80 #               define EVENT_LINK_CHANGE        11
>  81 #               define EVENT_SET_RX_MODE        12
> So far, the first two are appearing applicable for mceusb.

So far, only EVENT_RX_HALT is relevant for mceusb. It is likely that, this
will the be only one we will ever need in which case all this kevent kind
of business is completely unnecessary for a simple usb driver, rather
than usb networking driver infrastructure.
 
> The unused EVENT_TX_HALT and the apparently extra _kevent functions and kevent_flags are necessary for a later:
>     [PATCH] [media] mceusb: TX -EPIPE lockup fix
> ...not yet written, transmit side equivalent bug. I respectfully recommend keeping these hooks in place.

Have you observed this happening?

Speaking of which, how do you reproduce the original -EPIPE issue? I've
tried to reproduce on my raspberry pi 3 with a very similar mceusb
device, but I haven't had any luck.

What's the lsusb -vv for this device?

> For now, I think the transmit side EPIPE bug fix is less critical, since the TX bug avoids hanging the host/kernel, but would still cause lockup of the device.
> 
> In case of RX EPIPE on disconnect, the fix is still safe. Recovery attempt should fail (in usb_clear_halt() or usb_submit_urb()) and abort without further retry, and the recovery handler itself gets shutdown in mceusb_dev_disconnect().


Thanks
Sean

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-28 20:25         ` Sean Young
@ 2017-03-29  1:40           ` A Sun
  2017-03-29 21:06             ` Sean Young
  0 siblings, 1 reply; 14+ messages in thread
From: A Sun @ 2017-03-29  1:40 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, Mauro Carvalho Chehab

On 3/28/2017 4:25 PM, Sean Young wrote:
<snip>
>  
>> The unused EVENT_TX_HALT and the apparently extra _kevent functions and kevent_flags are necessary for a later:
>>     [PATCH] [media] mceusb: TX -EPIPE lockup fix
>> ...not yet written, transmit side equivalent bug. I respectfully recommend keeping these hooks in place.
> 
> Have you observed this happening?
> 

Not yet for my Infrared Transceiver device only. USB halt/stall errors apparently are not USB device specific, and can occur with both TX and RX according to the Linux Urb errors documentation. Calling usb_clear_halt() is required for both cases to recover and restore operation of the stalled endpoint.

The TX -EPIPE error is already separated out by code in the mceusb driver, but with no error recovery handling.
In mce_async_callback()
        case -EPIPE:
        default:
                dev_err(ir->dev, "Error: request urb status = %d", urb->status);
                break;
        }

I believe I can trigger the condition by stress test flooding or otherwise misusing the device's TX end-point in the driver (like the RX case), but I haven't put much work into that yet.

> Speaking of which, how do you reproduce the original -EPIPE issue? I've
> tried to reproduce on my raspberry pi 3 with a very similar mceusb
> device, but I haven't had any luck.
> 

Reproduction of the RX -EPIPE is "hard" to get. I haven't found a consistent way to reproduce, other than inconsistently by:
   Bug trigger appears to be normal, but heavy, IR receiver use.
In particular, punch up a bunch of buttons at random on a remote control (I used a Sony TV remote) and include some long button presses in the process. Do for say about 1 minute at the time. The bug won't trigger for idle or occasional IR receiver activity.
Some mceusb devices may be more susceptible to the problem than others.

> What's the lsusb -vv for this device?

Here it is, on my raspberry pi 3:

...
Bus 001 Device 006: ID 2304:0225 Pinnacle Systems, Inc. Remote Kit Infrared Transceiver
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x2304 Pinnacle Systems, Inc.
  idProduct          0x0225 Remote Kit Infrared Transceiver
  bcdDevice            0.01
  iManufacturer           1 Pinnacle Systems
  iProduct                2 PCTV Remote USB
  iSerial                 5 7FFFFFFFFFFFFFFF
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          3 StandardConfiguration
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              4 StandardInterface
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              10
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              10
Device Status:     0x0000
  (Bus Powered)
...

The most recent bug replication I got was while testing the fix methodology for [patch 1/3]. The fault, when it occurs, is between IR data blocks during receive.

...
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489177] mceusb 1-1.2:1.0: rx data: 90 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f (length=17)
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489184] mceusb 1-1.2:1.0: Raw IR data, 16 pulse/space samples
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489189] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489195] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489199] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489203] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489207] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489211] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489216] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489220] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489224] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489228] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489232] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489236] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489240] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489246] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489250] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489254] mceusb 1-1.2:1.0: Storing space with duration 6350000
Mar 22 12:16:35 raspberrypi kernel: [ 4863.489257] mceusb 1-1.2:1.0: processed IR data
Mar 22 12:16:35 raspberrypi kernel: [ 4863.589429] mceusb 1-1.2:1.0: Error: urb status = -32 (RX HALT)
Mar 22 12:16:35 raspberrypi kernel: [ 4863.589452] mceusb 1-1.2:1.0: kevent 1 scheduled
Mar 22 12:16:35 raspberrypi kernel: [ 4863.590203] mceusb 1-1.2:1.0: unhalt usb_submit_urb, status 0
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614325] mceusb 1-1.2:1.0: rx data: 90 0b 98 0c 8c 0c 8c 0c 98 0c 98 0c 98 0c 8c 0c 8c (length=17)
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614338] mceusb 1-1.2:1.0: Raw IR data, 16 pulse/space samples
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614346] mceusb 1-1.2:1.0: Storing space with duration 550000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614355] mceusb 1-1.2:1.0: Storing pulse with duration 1200000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614363] mceusb 1-1.2:1.0: Storing space with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614370] mceusb 1-1.2:1.0: Storing pulse with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614377] mceusb 1-1.2:1.0: Storing space with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614384] mceusb 1-1.2:1.0: Storing pulse with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614391] mceusb 1-1.2:1.0: Storing space with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614399] mceusb 1-1.2:1.0: Storing pulse with duration 1200000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614405] mceusb 1-1.2:1.0: Storing space with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614414] mceusb 1-1.2:1.0: Storing pulse with duration 1200000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614421] mceusb 1-1.2:1.0: Storing space with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614428] mceusb 1-1.2:1.0: Storing pulse with duration 1200000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614435] mceusb 1-1.2:1.0: Storing space with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614443] mceusb 1-1.2:1.0: Storing pulse with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614450] mceusb 1-1.2:1.0: Storing space with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614458] mceusb 1-1.2:1.0: Storing pulse with duration 600000
Mar 22 12:16:36 raspberrypi kernel: [ 4864.614463] mceusb 1-1.2:1.0: processed IR data
Mar 22 12:16:36 raspberrypi kernel: [ 4864.648331] mceusb 1-1.2:1.0: rx data: 90 0b 8d 0b 8d 7f 7f 7f 72 b0 0c 98 0c 8c 0c 98 0c (length=17)
...

Thanks, ..A Sun

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-29  1:40           ` A Sun
@ 2017-03-29 21:06             ` Sean Young
  2017-03-29 22:04               ` A Sun
  0 siblings, 1 reply; 14+ messages in thread
From: Sean Young @ 2017-03-29 21:06 UTC (permalink / raw)
  To: A Sun; +Cc: linux-media, Mauro Carvalho Chehab

On Tue, Mar 28, 2017 at 09:40:05PM -0400, A Sun wrote:
> On 3/28/2017 4:25 PM, Sean Young wrote:
> <snip>
> >  
> >> The unused EVENT_TX_HALT and the apparently extra _kevent functions and kevent_flags are necessary for a later:
> >>     [PATCH] [media] mceusb: TX -EPIPE lockup fix
> >> ...not yet written, transmit side equivalent bug. I respectfully recommend keeping these hooks in place.
> > 
> > Have you observed this happening?
> > 
> 
> Not yet for my Infrared Transceiver device only. USB halt/stall errors apparently are not USB device specific, and can occur with both TX and RX according to the Linux Urb errors documentation. Calling usb_clear_halt() is required for both cases to recover and restore operation of the stalled endpoint.

Yes, I did not realise this, but you're right, they can happen in both
cases.

> The TX -EPIPE error is already separated out by code in the mceusb driver, but with no error recovery handling.
> In mce_async_callback()
>         case -EPIPE:
>         default:
>                 dev_err(ir->dev, "Error: request urb status = %d", urb->status);
>                 break;
>         }
> 
> I believe I can trigger the condition by stress test flooding or otherwise misusing the device's TX end-point in the driver (like the RX case), but I haven't put much work into that yet.

The problem in the rx case is that in the EPIPE error case, the urb simply
resubmitted from the urb callback. In the tx case this does not happen
so I wouldn't expect a flood. Also after initialisation, no commands are
sent to the mceusb device except for IR transmit or tx carrier.

> > Speaking of which, how do you reproduce the original -EPIPE issue? I've
> > tried to reproduce on my raspberry pi 3 with a very similar mceusb
> > device, but I haven't had any luck.
> > 
> 
> Reproduction of the RX -EPIPE is "hard" to get. I haven't found a consistent way to reproduce, other than inconsistently by:
>    Bug trigger appears to be normal, but heavy, IR receiver use.
> In particular, punch up a bunch of buttons at random on a remote control (I used a Sony TV remote) and include some long button presses in the process. Do for say about 1 minute at the time. The bug won't trigger for idle or occasional IR receiver activity.
> Some mceusb devices may be more susceptible to the problem than others.
> 
> > What's the lsusb -vv for this device?
> 
> Here it is, on my raspberry pi 3:
> 
> ...
> Bus 001 Device 006: ID 2304:0225 Pinnacle Systems, Inc. Remote Kit Infrared Transceiver
> Device Descriptor:
>   bLength                18
>   bDescriptorType         1
>   bcdUSB               2.00
>   bDeviceClass            0 (Defined at Interface level)
>   bDeviceSubClass         0
>   bDeviceProtocol         0
>   bMaxPacketSize0         8
>   idVendor           0x2304 Pinnacle Systems, Inc.
>   idProduct          0x0225 Remote Kit Infrared Transceiver
>   bcdDevice            0.01
>   iManufacturer           1 Pinnacle Systems
>   iProduct                2 PCTV Remote USB
>   iSerial                 5 7FFFFFFFFFFFFFFF
>   bNumConfigurations      1
>   Configuration Descriptor:
>     bLength                 9
>     bDescriptorType         2
>     wTotalLength           32
>     bNumInterfaces          1
>     bConfigurationValue     1
>     iConfiguration          3 StandardConfiguration
>     bmAttributes         0xa0
>       (Bus Powered)
>       Remote Wakeup
>     MaxPower              100mA
>     Interface Descriptor:
>       bLength                 9
>       bDescriptorType         4
>       bInterfaceNumber        0
>       bAlternateSetting       0
>       bNumEndpoints           2
>       bInterfaceClass       255 Vendor Specific Class
>       bInterfaceSubClass      0
>       bInterfaceProtocol      0
>       iInterface              4 StandardInterface
>       Endpoint Descriptor:
>         bLength                 7
>         bDescriptorType         5
>         bEndpointAddress     0x81  EP 1 IN
>         bmAttributes            2
>           Transfer Type            Bulk
>           Synch Type               None
>           Usage Type               Data
>         wMaxPacketSize     0x0040  1x 64 bytes
>         bInterval              10
>       Endpoint Descriptor:
>         bLength                 7
>         bDescriptorType         5
>         bEndpointAddress     0x02  EP 2 OUT
>         bmAttributes            2
>           Transfer Type            Bulk
>           Synch Type               None
>           Usage Type               Data
>         wMaxPacketSize     0x0040  1x 64 bytes
>         bInterval              10
> Device Status:     0x0000
>   (Bus Powered)
> ...
> 
> The most recent bug replication I got was while testing the fix methodology for [patch 1/3]. The fault, when it occurs, is between IR data blocks during receive.
> 
> ...
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489177] mceusb 1-1.2:1.0: rx data: 90 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f (length=17)
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489184] mceusb 1-1.2:1.0: Raw IR data, 16 pulse/space samples
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489189] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489195] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489199] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489203] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489207] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489211] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489216] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489220] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489224] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489228] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489232] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489236] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489240] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489246] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489250] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489254] mceusb 1-1.2:1.0: Storing space with duration 6350000
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.489257] mceusb 1-1.2:1.0: processed IR data
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.589429] mceusb 1-1.2:1.0: Error: urb status = -32 (RX HALT)
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.589452] mceusb 1-1.2:1.0: kevent 1 scheduled
> Mar 22 12:16:35 raspberrypi kernel: [ 4863.590203] mceusb 1-1.2:1.0: unhalt usb_submit_urb, status 0
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614325] mceusb 1-1.2:1.0: rx data: 90 0b 98 0c 8c 0c 8c 0c 98 0c 98 0c 98 0c 8c 0c 8c (length=17)
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614338] mceusb 1-1.2:1.0: Raw IR data, 16 pulse/space samples
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614346] mceusb 1-1.2:1.0: Storing space with duration 550000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614355] mceusb 1-1.2:1.0: Storing pulse with duration 1200000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614363] mceusb 1-1.2:1.0: Storing space with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614370] mceusb 1-1.2:1.0: Storing pulse with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614377] mceusb 1-1.2:1.0: Storing space with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614384] mceusb 1-1.2:1.0: Storing pulse with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614391] mceusb 1-1.2:1.0: Storing space with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614399] mceusb 1-1.2:1.0: Storing pulse with duration 1200000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614405] mceusb 1-1.2:1.0: Storing space with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614414] mceusb 1-1.2:1.0: Storing pulse with duration 1200000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614421] mceusb 1-1.2:1.0: Storing space with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614428] mceusb 1-1.2:1.0: Storing pulse with duration 1200000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614435] mceusb 1-1.2:1.0: Storing space with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614443] mceusb 1-1.2:1.0: Storing pulse with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614450] mceusb 1-1.2:1.0: Storing space with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614458] mceusb 1-1.2:1.0: Storing pulse with duration 600000
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.614463] mceusb 1-1.2:1.0: processed IR data
> Mar 22 12:16:36 raspberrypi kernel: [ 4864.648331] mceusb 1-1.2:1.0: rx data: 90 0b 8d 0b 8d 7f 7f 7f 72 b0 0c 98 0c 8c 0c 98 0c (length=17)
> ...

Anyway, you're right and this patch looks ok. It would be nice to have the
tx case handled too though.

Thanks
Sean

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-29 21:06             ` Sean Young
@ 2017-03-29 22:04               ` A Sun
  2017-03-30  7:12                 ` Sean Young
  0 siblings, 1 reply; 14+ messages in thread
From: A Sun @ 2017-03-29 22:04 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, Mauro Carvalho Chehab

On 3/29/2017 5:06 PM, Sean Young wrote:
<snip>
> 
> Anyway, you're right and this patch looks ok. It would be nice to have the
> tx case handled too though.
> 
> Thanks
> Sean
> 

Thanks; I'm looking at handling the tx case. If I can figure out the details, I'll post a new patch proposal separate, and likely dependent, on this one.

My main obstacle at the moment, is I'm looking for a way to get mceusb device to respond with a USB TX error halt/stall (rather than the typical ACK and NAK) on a TX endpoint, in order to test halt/stall error detection and recovery for TX. ..A Sun

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-29 22:04               ` A Sun
@ 2017-03-30  7:12                 ` Sean Young
  2017-03-30 16:35                   ` A Sun
  0 siblings, 1 reply; 14+ messages in thread
From: Sean Young @ 2017-03-30  7:12 UTC (permalink / raw)
  To: A Sun; +Cc: linux-media, Mauro Carvalho Chehab

On Wed, Mar 29, 2017 at 06:04:58PM -0400, A Sun wrote:
> On 3/29/2017 5:06 PM, Sean Young wrote:
> <snip>
> > 
> > Anyway, you're right and this patch looks ok. It would be nice to have the
> > tx case handled too though.
> > 
> > Thanks
> > Sean
> > 
> 
> Thanks; I'm looking at handling the tx case. If I can figure out the details, I'll post a new patch proposal separate, and likely dependent, on this one.
> 
> My main obstacle at the moment, is I'm looking for a way to get mceusb device to respond with a USB TX error halt/stall (rather than the typical ACK and NAK) on a TX endpoint, in order to test halt/stall error detection and recovery for TX. ..A Sun

If you send IR, the drivers send a usb packet. However, the kernel will
sleep for however long the IR is in ir_lirc_transmit_ir, so your other option
is to set the transmit carrier repeatedly instead. You'd have to set the
carrier to a different value every time.


{
	int fd, carrier;

	fd = open("/dev/lirc0", O_RDWR);
	carrier = 38000;
	for (;;) {
		ioctl(fd, LIRC_SET_SEND_CARRIER, &carrier);
		if (++carrier >= 40000)
			carrier = 38000;
	}
}


Sean

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
  2017-03-30  7:12                 ` Sean Young
@ 2017-03-30 16:35                   ` A Sun
  0 siblings, 0 replies; 14+ messages in thread
From: A Sun @ 2017-03-30 16:35 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, Mauro Carvalho Chehab

On 3/30/2017 3:12 AM, Sean Young wrote:
> On Wed, Mar 29, 2017 at 06:04:58PM -0400, A Sun wrote:
>> On 3/29/2017 5:06 PM, Sean Young wrote:
>> <snip>
>>>
>>> Anyway, you're right and this patch looks ok. It would be nice to have the
>>> tx case handled too though.
>>>
>>> Thanks
>>> Sean
>>>
>>
>> Thanks; I'm looking at handling the tx case. If I can figure out the details, I'll post a new patch proposal separate, and likely dependent, on this one.
>>
>> My main obstacle at the moment, is I'm looking for a way to get mceusb device to respond with a USB TX error halt/stall (rather than the typical ACK and NAK) on a TX endpoint, in order to test halt/stall error detection and recovery for TX. ..A Sun
> 
> If you send IR, the drivers send a usb packet. However, the kernel will
> sleep for however long the IR is in ir_lirc_transmit_ir, so your other option
> is to set the transmit carrier repeatedly instead. You'd have to set the
> carrier to a different value every time.
> 
> 
> {
> 	int fd, carrier;
> 
> 	fd = open("/dev/lirc0", O_RDWR);
> 	carrier = 38000;
> 	for (;;) {
> 		ioctl(fd, LIRC_SET_SEND_CARRIER, &carrier);
> 		if (++carrier >= 40000)
> 			carrier = 38000;
> 	}
> }
> 
> 
> Sean
> 

Thanks, this is good to know, for testing where multiple TX I/Os are pending prior to fault. 

I found a way to set up the TX -EPIPE fault administratively:

	retval = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
		USB_REQ_SET_FEATURE, USB_RECIP_ENDPOINT,
		USB_ENDPOINT_HALT, usb_pipeendpoint(ir->pipe_out),
		NULL, 0, USB_CTRL_SET_TIMEOUT);
	dev_dbg(ir->dev, "set halt retval, %d", retval);
	
and have replications now for TX error and lock -out. Error occurs for every TX. No message flooding otherwise, as we expect. The RX side remains working.

...
[  249.986174] mceusb 1-1.2:1.0: requesting 38000 HZ carrier
[  249.986210] mceusb 1-1.2:1.0: send request called (size=0x4)
[  249.986256] mceusb 1-1.2:1.0: send request complete (res=0)
[  249.986403] mceusb 1-1.2:1.0: Error: request urb status = -32 (TX HALT)
[  249.999885] mceusb 1-1.2:1.0: send request called (size=0x3)
[  249.999929] mceusb 1-1.2:1.0: send request complete (res=0)
[  250.000013] mceusb 1-1.2:1.0: Error: request urb status = -32 (TX HALT)
[  250.019830] mceusb 1-1.2:1.0: send request called (size=0x21)
[  250.019868] mceusb 1-1.2:1.0: send request complete (res=0)
[  250.020007] mceusb 1-1.2:1.0: Error: request urb status = -32 (TX HALT)
...

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2017-03-30 16:35 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-25 16:59 [PATCH] mceusb: RX -EPIPE lockup fault and more A Sun
2017-03-26 10:27 ` Sean Young
2017-03-26 16:36   ` [PATCH 0/3] [media] " A Sun
2017-03-26 18:28   ` [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix A Sun
2017-03-26 20:31     ` Sean Young
2017-03-27  8:18       ` A Sun
2017-03-28 20:25         ` Sean Young
2017-03-29  1:40           ` A Sun
2017-03-29 21:06             ` Sean Young
2017-03-29 22:04               ` A Sun
2017-03-30  7:12                 ` Sean Young
2017-03-30 16:35                   ` A Sun
2017-03-26 18:33   ` [PATCH 2/3] [media] mceusb: sporadic RX truncation corruption fix A Sun
2017-03-26 19:04   ` [PATCH 3/3] [media] mceusb: fix inaccurate debug buffer dumps,and misleading debug messages A Sun

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.