aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-04-10 13:43:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-12 15:10:43 -0400
commit4849f85ee36db94033a7c8b32689458d6f435e80 (patch)
treed05ee7aa15f1f48980a8904f80650974bc8a96f2 /drivers/nfc
parentffc29315e5b665d3e7e17d6156ac82f85a6d0205 (diff)
NFC: Convert pn533 from tasklet to workqueues
There is no need for soft IRQ contexts, and workqueues are more flexible. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/pn533.c86
1 files changed, 48 insertions, 38 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index cb6204f78300..f2ee06f059f9 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -266,9 +266,10 @@ struct pn533 {
266 int in_maxlen; 266 int in_maxlen;
267 struct pn533_frame *in_frame; 267 struct pn533_frame *in_frame;
268 268
269 struct tasklet_struct tasklet; 269 struct workqueue_struct *wq;
270 struct pn533_frame *tklt_in_frame; 270 struct work_struct cmd_work;
271 int tklt_in_error; 271 struct pn533_frame *wq_in_frame;
272 int wq_in_error;
272 273
273 pn533_cmd_complete_t cmd_complete; 274 pn533_cmd_complete_t cmd_complete;
274 void *cmd_complete_arg; 275 void *cmd_complete_arg;
@@ -383,15 +384,21 @@ static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd)
383 return (PN533_FRAME_CMD(frame) == PN533_CMD_RESPONSE(cmd)); 384 return (PN533_FRAME_CMD(frame) == PN533_CMD_RESPONSE(cmd));
384} 385}
385 386
386static void pn533_tasklet_cmd_complete(unsigned long arg) 387
388static void pn533_wq_cmd_complete(struct work_struct *work)
387{ 389{
388 struct pn533 *dev = (struct pn533 *) arg; 390 struct pn533 *dev = container_of(work, struct pn533, cmd_work);
389 struct pn533_frame *in_frame = dev->tklt_in_frame; 391 struct pn533_frame *in_frame;
390 int rc; 392 int rc;
391 393
392 if (dev->tklt_in_error) 394 if (dev == NULL)
395 return;
396
397 in_frame = dev->wq_in_frame;
398
399 if (dev->wq_in_error)
393 rc = dev->cmd_complete(dev, dev->cmd_complete_arg, NULL, 400 rc = dev->cmd_complete(dev, dev->cmd_complete_arg, NULL,
394 dev->tklt_in_error); 401 dev->wq_in_error);
395 else 402 else
396 rc = dev->cmd_complete(dev, dev->cmd_complete_arg, 403 rc = dev->cmd_complete(dev, dev->cmd_complete_arg,
397 PN533_FRAME_CMD_PARAMS_PTR(in_frame), 404 PN533_FRAME_CMD_PARAMS_PTR(in_frame),
@@ -406,7 +413,7 @@ static void pn533_recv_response(struct urb *urb)
406 struct pn533 *dev = urb->context; 413 struct pn533 *dev = urb->context;
407 struct pn533_frame *in_frame; 414 struct pn533_frame *in_frame;
408 415
409 dev->tklt_in_frame = NULL; 416 dev->wq_in_frame = NULL;
410 417
411 switch (urb->status) { 418 switch (urb->status) {
412 case 0: 419 case 0:
@@ -417,36 +424,36 @@ static void pn533_recv_response(struct urb *urb)
417 case -ESHUTDOWN: 424 case -ESHUTDOWN:
418 nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with" 425 nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
419 " status: %d", urb->status); 426 " status: %d", urb->status);
420 dev->tklt_in_error = urb->status; 427 dev->wq_in_error = urb->status;
421 goto sched_tasklet; 428 goto sched_wq;
422 default: 429 default:
423 nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:" 430 nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
424 " %d", urb->status); 431 " %d", urb->status);
425 dev->tklt_in_error = urb->status; 432 dev->wq_in_error = urb->status;
426 goto sched_tasklet; 433 goto sched_wq;
427 } 434 }
428 435
429 in_frame = dev->in_urb->transfer_buffer; 436 in_frame = dev->in_urb->transfer_buffer;
430 437
431 if (!pn533_rx_frame_is_valid(in_frame)) { 438 if (!pn533_rx_frame_is_valid(in_frame)) {
432 nfc_dev_err(&dev->interface->dev, "Received an invalid frame"); 439 nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
433 dev->tklt_in_error = -EIO; 440 dev->wq_in_error = -EIO;
434 goto sched_tasklet; 441 goto sched_wq;
435 } 442 }
436 443
437 if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) { 444 if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) {
438 nfc_dev_err(&dev->interface->dev, "The received frame is not " 445 nfc_dev_err(&dev->interface->dev, "The received frame is not "
439 "response to the last command"); 446 "response to the last command");
440 dev->tklt_in_error = -EIO; 447 dev->wq_in_error = -EIO;
441 goto sched_tasklet; 448 goto sched_wq;
442 } 449 }
443 450
444 nfc_dev_dbg(&dev->interface->dev, "Received a valid frame"); 451 nfc_dev_dbg(&dev->interface->dev, "Received a valid frame");
445 dev->tklt_in_error = 0; 452 dev->wq_in_error = 0;
446 dev->tklt_in_frame = in_frame; 453 dev->wq_in_frame = in_frame;
447 454
448sched_tasklet: 455sched_wq:
449 tasklet_schedule(&dev->tasklet); 456 queue_work(dev->wq, &dev->cmd_work);
450} 457}
451 458
452static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags) 459static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags)
@@ -471,21 +478,21 @@ static void pn533_recv_ack(struct urb *urb)
471 case -ESHUTDOWN: 478 case -ESHUTDOWN:
472 nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with" 479 nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
473 " status: %d", urb->status); 480 " status: %d", urb->status);
474 dev->tklt_in_error = urb->status; 481 dev->wq_in_error = urb->status;
475 goto sched_tasklet; 482 goto sched_wq;
476 default: 483 default:
477 nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:" 484 nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
478 " %d", urb->status); 485 " %d", urb->status);
479 dev->tklt_in_error = urb->status; 486 dev->wq_in_error = urb->status;
480 goto sched_tasklet; 487 goto sched_wq;
481 } 488 }
482 489
483 in_frame = dev->in_urb->transfer_buffer; 490 in_frame = dev->in_urb->transfer_buffer;
484 491
485 if (!pn533_rx_frame_is_ack(in_frame)) { 492 if (!pn533_rx_frame_is_ack(in_frame)) {
486 nfc_dev_err(&dev->interface->dev, "Received an invalid ack"); 493 nfc_dev_err(&dev->interface->dev, "Received an invalid ack");
487 dev->tklt_in_error = -EIO; 494 dev->wq_in_error = -EIO;
488 goto sched_tasklet; 495 goto sched_wq;
489 } 496 }
490 497
491 nfc_dev_dbg(&dev->interface->dev, "Received a valid ack"); 498 nfc_dev_dbg(&dev->interface->dev, "Received a valid ack");
@@ -494,15 +501,15 @@ static void pn533_recv_ack(struct urb *urb)
494 if (rc) { 501 if (rc) {
495 nfc_dev_err(&dev->interface->dev, "usb_submit_urb failed with" 502 nfc_dev_err(&dev->interface->dev, "usb_submit_urb failed with"
496 " result %d", rc); 503 " result %d", rc);
497 dev->tklt_in_error = rc; 504 dev->wq_in_error = rc;
498 goto sched_tasklet; 505 goto sched_wq;
499 } 506 }
500 507
501 return; 508 return;
502 509
503sched_tasklet: 510sched_wq:
504 dev->tklt_in_frame = NULL; 511 dev->wq_in_frame = NULL;
505 tasklet_schedule(&dev->tasklet); 512 queue_work(dev->wq, &dev->cmd_work);
506} 513}
507 514
508static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags) 515static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags)
@@ -1668,7 +1675,10 @@ static int pn533_probe(struct usb_interface *interface,
1668 NULL, 0, 1675 NULL, 0,
1669 pn533_send_complete, dev); 1676 pn533_send_complete, dev);
1670 1677
1671 tasklet_init(&dev->tasklet, pn533_tasklet_cmd_complete, (ulong)dev); 1678 INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete);
1679 dev->wq = create_singlethread_workqueue("pn533");
1680 if (dev->wq == NULL)
1681 goto error;
1672 1682
1673 usb_set_intfdata(interface, dev); 1683 usb_set_intfdata(interface, dev);
1674 1684
@@ -1678,7 +1688,7 @@ static int pn533_probe(struct usb_interface *interface,
1678 rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, 1688 rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
1679 dev->in_maxlen); 1689 dev->in_maxlen);
1680 if (rc) 1690 if (rc)
1681 goto kill_tasklet; 1691 goto destroy_wq;
1682 1692
1683 fw_ver = (struct pn533_fw_version *) 1693 fw_ver = (struct pn533_fw_version *)
1684 PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame); 1694 PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame);
@@ -1694,7 +1704,7 @@ static int pn533_probe(struct usb_interface *interface,
1694 PN533_CMD_DATAEXCH_HEAD_LEN, 1704 PN533_CMD_DATAEXCH_HEAD_LEN,
1695 PN533_FRAME_TAIL_SIZE); 1705 PN533_FRAME_TAIL_SIZE);
1696 if (!dev->nfc_dev) 1706 if (!dev->nfc_dev)
1697 goto kill_tasklet; 1707 goto destroy_wq;
1698 1708
1699 nfc_set_parent_dev(dev->nfc_dev, &interface->dev); 1709 nfc_set_parent_dev(dev->nfc_dev, &interface->dev);
1700 nfc_set_drvdata(dev->nfc_dev, dev); 1710 nfc_set_drvdata(dev->nfc_dev, dev);
@@ -1720,8 +1730,8 @@ static int pn533_probe(struct usb_interface *interface,
1720 1730
1721free_nfc_dev: 1731free_nfc_dev:
1722 nfc_free_device(dev->nfc_dev); 1732 nfc_free_device(dev->nfc_dev);
1723kill_tasklet: 1733destroy_wq:
1724 tasklet_kill(&dev->tasklet); 1734 destroy_workqueue(dev->wq);
1725error: 1735error:
1726 kfree(dev->in_frame); 1736 kfree(dev->in_frame);
1727 usb_free_urb(dev->in_urb); 1737 usb_free_urb(dev->in_urb);
@@ -1744,7 +1754,7 @@ static void pn533_disconnect(struct usb_interface *interface)
1744 usb_kill_urb(dev->in_urb); 1754 usb_kill_urb(dev->in_urb);
1745 usb_kill_urb(dev->out_urb); 1755 usb_kill_urb(dev->out_urb);
1746 1756
1747 tasklet_kill(&dev->tasklet); 1757 destroy_workqueue(dev->wq);
1748 1758
1749 kfree(dev->in_frame); 1759 kfree(dev->in_frame);
1750 usb_free_urb(dev->in_urb); 1760 usb_free_urb(dev->in_urb);