aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@collabora.com>2016-06-16 14:25:21 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2016-07-06 04:02:07 -0400
commitb74584c1a6d68110d135a6ce0336aab0055f4341 (patch)
tree86cd2ef99b4e43c242ca0b84c4ed0efce68fed1c
parente3e0258839a01f793a8a0c0885e8ad387681cdc6 (diff)
NFC: port100: Fix the command cancellation process
The USB out_urb used to send commands to the device can be submitted through the standard command processing queue coming from the Digital Protocol layer but it can also be submitted from port100_abort_cmd(). To not submit the URB while already active, a mutex is now used to protect it and a cmd_cancel flag is used to not send command while canceling the previous one. Signed-off-by: Thierry Escande <thierry.escande@collabora.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/nfc/port100.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c
index 14a3cc2d0fd6..909e3df2c16a 100644
--- a/drivers/nfc/port100.c
+++ b/drivers/nfc/port100.c
@@ -456,6 +456,12 @@ struct port100 {
456 struct urb *out_urb; 456 struct urb *out_urb;
457 struct urb *in_urb; 457 struct urb *in_urb;
458 458
459 /* This mutex protects the out_urb and avoids to submit a new command
460 * through port100_send_frame_async() while the previous one is being
461 * canceled through port100_abort_cmd().
462 */
463 struct mutex out_urb_lock;
464
459 struct work_struct cmd_complete_work; 465 struct work_struct cmd_complete_work;
460 466
461 u8 cmd_type; 467 u8 cmd_type;
@@ -464,6 +470,8 @@ struct port100 {
464 * for any queuing/locking mechanism at driver level. 470 * for any queuing/locking mechanism at driver level.
465 */ 471 */
466 struct port100_cmd *cmd; 472 struct port100_cmd *cmd;
473
474 bool cmd_cancel;
467}; 475};
468 476
469struct port100_cmd { 477struct port100_cmd {
@@ -718,10 +726,22 @@ static int port100_send_ack(struct port100 *dev)
718{ 726{
719 int rc; 727 int rc;
720 728
729 mutex_lock(&dev->out_urb_lock);
730
731 usb_kill_urb(dev->out_urb);
732
721 dev->out_urb->transfer_buffer = ack_frame; 733 dev->out_urb->transfer_buffer = ack_frame;
722 dev->out_urb->transfer_buffer_length = sizeof(ack_frame); 734 dev->out_urb->transfer_buffer_length = sizeof(ack_frame);
723 rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); 735 rc = usb_submit_urb(dev->out_urb, GFP_KERNEL);
724 736
737 /* Set the cmd_cancel flag only if the URB has been successfully
738 * submitted. It will be reset by the out URB completion callback
739 * port100_send_complete().
740 */
741 dev->cmd_cancel = !rc;
742
743 mutex_unlock(&dev->out_urb_lock);
744
725 return rc; 745 return rc;
726} 746}
727 747
@@ -730,6 +750,16 @@ static int port100_send_frame_async(struct port100 *dev, struct sk_buff *out,
730{ 750{
731 int rc; 751 int rc;
732 752
753 mutex_lock(&dev->out_urb_lock);
754
755 /* A command cancel frame as been sent through dev->out_urb. Don't try
756 * to submit a new one.
757 */
758 if (dev->cmd_cancel) {
759 rc = -EAGAIN;
760 goto exit;
761 }
762
733 dev->out_urb->transfer_buffer = out->data; 763 dev->out_urb->transfer_buffer = out->data;
734 dev->out_urb->transfer_buffer_length = out->len; 764 dev->out_urb->transfer_buffer_length = out->len;
735 765
@@ -741,16 +771,15 @@ static int port100_send_frame_async(struct port100 *dev, struct sk_buff *out,
741 771
742 rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); 772 rc = usb_submit_urb(dev->out_urb, GFP_KERNEL);
743 if (rc) 773 if (rc)
744 return rc; 774 goto exit;
745 775
746 rc = port100_submit_urb_for_ack(dev, GFP_KERNEL); 776 rc = port100_submit_urb_for_ack(dev, GFP_KERNEL);
747 if (rc) 777 if (rc)
748 goto error; 778 usb_unlink_urb(dev->out_urb);
749 779
750 return 0; 780exit:
781 mutex_unlock(&dev->out_urb_lock);
751 782
752error:
753 usb_unlink_urb(dev->out_urb);
754 return rc; 783 return rc;
755} 784}
756 785
@@ -892,6 +921,8 @@ static void port100_send_complete(struct urb *urb)
892{ 921{
893 struct port100 *dev = urb->context; 922 struct port100 *dev = urb->context;
894 923
924 dev->cmd_cancel = false;
925
895 switch (urb->status) { 926 switch (urb->status) {
896 case 0: 927 case 0:
897 break; /* success */ 928 break; /* success */
@@ -1455,6 +1486,7 @@ static int port100_probe(struct usb_interface *interface,
1455 if (!dev) 1486 if (!dev)
1456 return -ENOMEM; 1487 return -ENOMEM;
1457 1488
1489 mutex_init(&dev->out_urb_lock);
1458 dev->udev = usb_get_dev(interface_to_usbdev(interface)); 1490 dev->udev = usb_get_dev(interface_to_usbdev(interface));
1459 dev->interface = interface; 1491 dev->interface = interface;
1460 usb_set_intfdata(interface, dev); 1492 usb_set_intfdata(interface, dev);