aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc/pn533.c
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-08-17 17:47:54 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-09-24 18:17:23 -0400
commit5d50b364e61e85eb41938d25770db3aab5e07d82 (patch)
tree20c9c21a2cdfc520c11b972dbfda8df8f30204e8 /drivers/nfc/pn533.c
parent90e6274d2ecf3bcb44e3727a395e56b7ef467218 (diff)
NFC: Queue pn533 commands
Instead of returning EBUSY when getting a command while another one is running, we queue them. Upon completion of the pending command, the next one is processed. Besides the fact that it simplifies the pn533 locking scheme, it also comes with the nice side effect of fixing the following warning: [ 82.274297] ===================================== [ 82.274297] [ BUG: bad unlock balance detected! ] [ 82.274298] 3.5.0-rc1+ #1 Not tainted [ 82.274299] ------------------------------------- [ 82.274300] kworker/u:1/16 is trying to release lock (&dev->cmd_lock) at: [ 82.274305] [<ffffffff8144f246>] mutex_unlock+0x9/0xb [ 82.274305] but there are no more locks to release! [ 82.274306] [ 82.274306] other info that might help us debug this: [ 82.274306] 2 locks held by kworker/u:1/16: [ 82.274311] #0: (pn533){.+.+..}, at: [<ffffffff8103a67d>] +process_one_work+0x145/0x2e2 [ 82.274314] #1: ((&dev->cmd_work)){+.+...}, at: [<ffffffff8103a67d>] +process_one_work+0x145/0x2e2 [ 82.274314] [ 82.274314] stack backtrace: [ 82.274315] Pid: 16, comm: kworker/u:1 Not tainted 3.5.0-rc1+ #1 [ 82.274315] Call Trace: [ 82.274317] [<ffffffff8144f246>] ? mutex_unlock+0x9/0xb [ 82.274321] [<ffffffff81059841>] print_unlock_inbalance_bug+0xda/0xe4 [ 82.274323] [<ffffffff8105c74c>] lock_release_non_nested+0xb2/0x232 [ 82.274325] [<ffffffff8105a61e>] ? mark_held_locks+0x6d/0x95 [ 82.274326] [<ffffffff8144f246>] ? mutex_unlock+0x9/0xb [ 82.274328] [<ffffffff81451105>] ? _raw_spin_unlock_irqrestore+0x40/0x5c [ 82.274329] [<ffffffff8144f246>] ? mutex_unlock+0x9/0xb [ 82.274330] [<ffffffff8105ca42>] lock_release+0x176/0x1ac [ 82.274333] [<ffffffff8123de14>] ? pn533_send_complete+0xa8/0xa8 [ 82.274334] [<ffffffff8144f1d6>] __mutex_unlock_slowpath+0xb0/0x117 [ 82.274336] [<ffffffff8144f246>] mutex_unlock+0x9/0xb [ 82.274337] [<ffffffff8123de65>] pn533_wq_cmd_complete+0x51/0x55 [ 82.274338] [<ffffffff8103a6db>] process_one_work+0x1a3/0x2e2 [ 82.274340] [<ffffffff8103a67d>] ? process_one_work+0x145/0x2e2 [ 82.274341] [<ffffffff8103b119>] worker_thread+0xcf/0x153 [ 82.274343] [<ffffffff8103b04a>] ? manage_workers.isra.22+0x16b/0x16b [ 82.274344] [<ffffffff8103b04a>] ? manage_workers.isra.22+0x16b/0x16b [ 82.274346] [<ffffffff8103eb11>] kthread+0x95/0x9d [ 82.274348] [<ffffffff81452ef4>] kernel_thread_helper+0x4/0x10 [ 82.274351] [<ffffffff81046561>] ? finish_task_switch+0x45/0xc3 [ 82.274352] [<ffffffff814514f0>] ? retint_restore_args+0x13/0x13 [ 82.274353] [<ffffffff8103ea7c>] ? __init_kthread_worker+0x55/0x55 [ 82.274354] [<ffffffff81452ef0>] ? gs_change+0x13/0x13 Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc/pn533.c')
-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);