aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/nfc/pn533.c102
1 files changed, 85 insertions, 17 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index d606f52fec84..7ceea111439b 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -356,6 +356,7 @@ struct pn533 {
356 356
357 struct workqueue_struct *wq; 357 struct workqueue_struct *wq;
358 struct work_struct cmd_work; 358 struct work_struct cmd_work;
359 struct work_struct cmd_complete_work;
359 struct work_struct poll_work; 360 struct work_struct poll_work;
360 struct work_struct mi_work; 361 struct work_struct mi_work;
361 struct work_struct tg_work; 362 struct work_struct tg_work;
@@ -383,6 +384,19 @@ struct pn533 {
383 u8 tgt_mode; 384 u8 tgt_mode;
384 385
385 u32 device_type; 386 u32 device_type;
387
388 struct list_head cmd_queue;
389 u8 cmd_pending;
390};
391
392struct pn533_cmd {
393 struct list_head queue;
394 struct pn533_frame *out_frame;
395 struct pn533_frame *in_frame;
396 int in_frame_len;
397 pn533_cmd_complete_t cmd_complete;
398 void *arg;
399 gfp_t flags;
386}; 400};
387 401
388struct pn533_frame { 402struct pn533_frame {
@@ -487,7 +501,7 @@ static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd)
487 501
488static void pn533_wq_cmd_complete(struct work_struct *work) 502static void pn533_wq_cmd_complete(struct work_struct *work)
489{ 503{
490 struct pn533 *dev = container_of(work, struct pn533, cmd_work); 504 struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work);
491 struct pn533_frame *in_frame; 505 struct pn533_frame *in_frame;
492 int rc; 506 int rc;
493 507
@@ -502,7 +516,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work)
502 PN533_FRAME_CMD_PARAMS_LEN(in_frame)); 516 PN533_FRAME_CMD_PARAMS_LEN(in_frame));
503 517
504 if (rc != -EINPROGRESS) 518 if (rc != -EINPROGRESS)
505 mutex_unlock(&dev->cmd_lock); 519 queue_work(dev->wq, &dev->cmd_work);
506} 520}
507 521
508static void pn533_recv_response(struct urb *urb) 522static void pn533_recv_response(struct urb *urb)
@@ -550,7 +564,7 @@ static void pn533_recv_response(struct urb *urb)
550 dev->wq_in_frame = in_frame; 564 dev->wq_in_frame = in_frame;
551 565
552sched_wq: 566sched_wq:
553 queue_work(dev->wq, &dev->cmd_work); 567 queue_work(dev->wq, &dev->cmd_complete_work);
554} 568}
555 569
556static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags) 570static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags)
@@ -606,7 +620,7 @@ static void pn533_recv_ack(struct urb *urb)
606 620
607sched_wq: 621sched_wq:
608 dev->wq_in_frame = NULL; 622 dev->wq_in_frame = NULL;
609 queue_work(dev->wq, &dev->cmd_work); 623 queue_work(dev->wq, &dev->cmd_complete_work);
610} 624}
611 625
612static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags) 626static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags)
@@ -669,6 +683,31 @@ error:
669 return rc; 683 return rc;
670} 684}
671 685
686static void pn533_wq_cmd(struct work_struct *work)
687{
688 struct pn533 *dev = container_of(work, struct pn533, cmd_work);
689 struct pn533_cmd *cmd;
690
691 mutex_lock(&dev->cmd_lock);
692
693 if (list_empty(&dev->cmd_queue)) {
694 dev->cmd_pending = 0;
695 mutex_unlock(&dev->cmd_lock);
696 return;
697 }
698
699 cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue);
700
701 mutex_unlock(&dev->cmd_lock);
702
703 __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame,
704 cmd->in_frame_len, cmd->cmd_complete,
705 cmd->arg, cmd->flags);
706
707 list_del(&cmd->queue);
708 kfree(cmd);
709}
710
672static int pn533_send_cmd_frame_async(struct pn533 *dev, 711static int pn533_send_cmd_frame_async(struct pn533 *dev,
673 struct pn533_frame *out_frame, 712 struct pn533_frame *out_frame,
674 struct pn533_frame *in_frame, 713 struct pn533_frame *in_frame,
@@ -676,22 +715,44 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
676 pn533_cmd_complete_t cmd_complete, 715 pn533_cmd_complete_t cmd_complete,
677 void *arg, gfp_t flags) 716 void *arg, gfp_t flags)
678{ 717{
718 struct pn533_cmd *cmd;
679 int rc; 719 int rc;
680 720
681 nfc_dev_dbg(&dev->interface->dev, "%s", __func__); 721 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
682 722
683 if (!mutex_trylock(&dev->cmd_lock)) 723 mutex_lock(&dev->cmd_lock);
684 return -EBUSY;
685 724
686 rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, 725 if (!dev->cmd_pending) {
687 in_frame_len, cmd_complete, arg, flags); 726 rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame,
688 if (rc) 727 in_frame_len, cmd_complete,
689 goto error; 728 arg, flags);
729 if (!rc)
730 dev->cmd_pending = 1;
731
732 mutex_unlock(&dev->cmd_lock);
733
734 return rc;
735 }
736
737 nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__);
738
739 cmd = kzalloc(sizeof(struct pn533_cmd), flags);
740 if (!cmd)
741 return -ENOMEM;
742
743 INIT_LIST_HEAD(&cmd->queue);
744 cmd->out_frame = out_frame;
745 cmd->in_frame = in_frame;
746 cmd->in_frame_len = in_frame_len;
747 cmd->cmd_complete = cmd_complete;
748 cmd->arg = arg;
749 cmd->flags = flags;
750
751 list_add_tail(&cmd->queue, &dev->cmd_queue);
690 752
691 return 0;
692error:
693 mutex_unlock(&dev->cmd_lock); 753 mutex_unlock(&dev->cmd_lock);
694 return rc; 754
755 return 0;
695} 756}
696 757
697struct pn533_sync_cmd_response { 758struct pn533_sync_cmd_response {
@@ -1305,8 +1366,6 @@ static void pn533_listen_mode_timer(unsigned long data)
1305 1366
1306 dev->cancel_listen = 1; 1367 dev->cancel_listen = 1;
1307 1368
1308 mutex_unlock(&dev->cmd_lock);
1309
1310 pn533_poll_next_mod(dev); 1369 pn533_poll_next_mod(dev);
1311 1370
1312 queue_work(dev->wq, &dev->poll_work); 1371 queue_work(dev->wq, &dev->poll_work);
@@ -2131,7 +2190,7 @@ error_cmd:
2131 2190
2132 kfree(arg); 2191 kfree(arg);
2133 2192
2134 mutex_unlock(&dev->cmd_lock); 2193 queue_work(dev->wq, &dev->cmd_work);
2135} 2194}
2136 2195
2137static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, 2196static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
@@ -2330,7 +2389,8 @@ static int pn533_probe(struct usb_interface *interface,
2330 NULL, 0, 2389 NULL, 0,
2331 pn533_send_complete, dev); 2390 pn533_send_complete, dev);
2332 2391
2333 INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete); 2392 INIT_WORK(&dev->cmd_work, pn533_wq_cmd);
2393 INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete);
2334 INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); 2394 INIT_WORK(&dev->mi_work, pn533_wq_mi_recv);
2335 INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); 2395 INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
2336 INIT_WORK(&dev->poll_work, pn533_wq_poll); 2396 INIT_WORK(&dev->poll_work, pn533_wq_poll);
@@ -2346,6 +2406,8 @@ static int pn533_probe(struct usb_interface *interface,
2346 2406
2347 skb_queue_head_init(&dev->resp_q); 2407 skb_queue_head_init(&dev->resp_q);
2348 2408
2409 INIT_LIST_HEAD(&dev->cmd_queue);
2410
2349 usb_set_intfdata(interface, dev); 2411 usb_set_intfdata(interface, dev);
2350 2412
2351 pn533_tx_frame_init(dev->out_frame, PN533_CMD_GET_FIRMWARE_VERSION); 2413 pn533_tx_frame_init(dev->out_frame, PN533_CMD_GET_FIRMWARE_VERSION);
@@ -2417,6 +2479,7 @@ error:
2417static void pn533_disconnect(struct usb_interface *interface) 2479static void pn533_disconnect(struct usb_interface *interface)
2418{ 2480{
2419 struct pn533 *dev; 2481 struct pn533 *dev;
2482 struct pn533_cmd *cmd, *n;
2420 2483
2421 dev = usb_get_intfdata(interface); 2484 dev = usb_get_intfdata(interface);
2422 usb_set_intfdata(interface, NULL); 2485 usb_set_intfdata(interface, NULL);
@@ -2433,6 +2496,11 @@ static void pn533_disconnect(struct usb_interface *interface)
2433 2496
2434 del_timer(&dev->listen_timer); 2497 del_timer(&dev->listen_timer);
2435 2498
2499 list_for_each_entry_safe(cmd, n, &dev->cmd_queue, queue) {
2500 list_del(&cmd->queue);
2501 kfree(cmd);
2502 }
2503
2436 kfree(dev->in_frame); 2504 kfree(dev->in_frame);
2437 usb_free_urb(dev->in_urb); 2505 usb_free_urb(dev->in_urb);
2438 kfree(dev->out_frame); 2506 kfree(dev->out_frame);