diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index f5221b018808..f8e3e87cf1a3 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -598,8 +598,11 @@ static int send_packet(struct imon_context *ictx) int retval = 0; struct usb_ctrlrequest *control_req = NULL; + BUG_ON(mutex_get_owner(&ictx->lock) != (unsigned long) current); + /* Check if we need to use control or interrupt urb */ if (!ictx->tx_control) { + printk(KERN_INFO "int %px %d\n", ictx, ictx->tx_endpoint->bEndpointAddress); pipe = usb_sndintpipe(ictx->usbdev_intf0, ictx->tx_endpoint->bEndpointAddress); interval = ictx->tx_endpoint->bInterval; @@ -623,6 +626,7 @@ static int send_packet(struct imon_context *ictx) control_req->wIndex = cpu_to_le16(0x0001); control_req->wLength = cpu_to_le16(0x0008); + printk(KERN_INFO "control %px\n", ictx); /* control pipe is endpoint 0x00 */ pipe = usb_sndctrlpipe(ictx->usbdev_intf0, 0); @@ -645,12 +649,15 @@ static int send_packet(struct imon_context *ictx) smp_rmb(); /* ensure later readers know we're not busy */ pr_err_ratelimited("error submitting urb(%d)\n", retval); } else { - /* Wait for transmission to complete (or abort) */ - retval = wait_for_completion_interruptible( - &ictx->tx.finished); - if (retval) { + /* Wait for transmission to complete (or abort or timeout) */ + retval = wait_for_completion_interruptible_timeout(&ictx->tx.finished, 10 * HZ); + if (retval <= 0) { usb_kill_urb(ictx->tx_urb); pr_err_ratelimited("task interrupted\n"); + if (retval < 0) + ictx->tx.status = retval; + else + ictx->tx.status = -ETIMEDOUT; } ictx->tx.busy = false; @@ -1125,6 +1132,11 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_proto) unsigned char ir_proto_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; + if (mutex_get_owner(&ictx->lock) != (unsigned long) current) { + unlock = true; + mutex_lock(&ictx->lock); + } + if (*rc_proto && !(*rc_proto & rc->allowed_protocols)) dev_warn(dev, "Looks like you're trying to use an IR protocol this device does not support\n"); @@ -1148,8 +1160,6 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_proto) memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); - unlock = mutex_trylock(&ictx->lock); - retval = send_packet(ictx); if (retval) goto out; @@ -1744,14 +1754,17 @@ static void usb_rx_callback_intf0(struct urb *urb) ictx = (struct imon_context *)urb->context; if (!ictx) return; + printk(KERN_INFO "%s %px\n", __func__, ictx); /* * if we get a callback before we're done configuring the hardware, we * can't yet process the data, as there's nowhere to send it, but we * still need to submit a new rx URB to avoid wedging the hardware */ - if (!ictx->dev_present_intf0) + if (!ictx->dev_present_intf0) { + printk(KERN_INFO "%s %px %d\n", __func__, ictx, urb->status); goto out; + } switch (urb->status) { case -ENOENT: /* usbcore unlink successful! */ @@ -1764,6 +1777,15 @@ static void usb_rx_callback_intf0(struct urb *urb) imon_incoming_packet(ictx, urb, intfnum); break; + case -ECONNRESET: + case -EILSEQ: + case -EPROTO: + case -EPIPE: + dev_warn(ictx->dev, "imon %s: status(%d)\n", + __func__, urb->status); + usb_unlink_urb(urb); + return; + default: dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", __func__, urb->status); @@ -1785,14 +1807,17 @@ static void usb_rx_callback_intf1(struct urb *urb) ictx = (struct imon_context *)urb->context; if (!ictx) return; + printk(KERN_INFO "%s %px\n", __func__, ictx); /* * if we get a callback before we're done configuring the hardware, we * can't yet process the data, as there's nowhere to send it, but we * still need to submit a new rx URB to avoid wedging the hardware */ - if (!ictx->dev_present_intf1) + if (!ictx->dev_present_intf1) { + printk(KERN_INFO "%s %px %d\n", __func__, ictx, urb->status); goto out; + } switch (urb->status) { case -ENOENT: /* usbcore unlink successful! */ @@ -1805,6 +1830,15 @@ static void usb_rx_callback_intf1(struct urb *urb) imon_incoming_packet(ictx, urb, intfnum); break; + case -ECONNRESET: + case -EILSEQ: + case -EPROTO: + case -EPIPE: + dev_warn(ictx->dev, "imon %s: status(%d)\n", + __func__, urb->status); + usb_unlink_urb(urb); + return; + default: dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", __func__, urb->status);