From: A Sun <as1033x@comcast.net>
To: Sean Young <sean@mess.org>
Cc: linux-media@vger.kernel.org,
Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Subject: [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix
Date: Sun, 26 Mar 2017 14:28:08 -0400 [thread overview]
Message-ID: <58D80838.8050809@comcast.net> (raw)
In-Reply-To: <20170326102748.GA1672@gofer.mess.org>
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
next prev parent reply other threads:[~2017-03-26 18:30 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` A Sun [this message]
2017-03-26 20:31 ` [PATCH 1/3] [media] mceusb: RX -EPIPE (urb status = -32) lockup failure fix 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=58D80838.8050809@comcast.net \
--to=as1033x@comcast.net \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@osg.samsung.com \
--cc=sean@mess.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).