diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-04-10 13:43:17 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-12 15:10:43 -0400 |
commit | 4849f85ee36db94033a7c8b32689458d6f435e80 (patch) | |
tree | d05ee7aa15f1f48980a8904f80650974bc8a96f2 /drivers/nfc | |
parent | ffc29315e5b665d3e7e17d6156ac82f85a6d0205 (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.c | 86 |
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 | ||
386 | static void pn533_tasklet_cmd_complete(unsigned long arg) | 387 | |
388 | static 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 | ||
448 | sched_tasklet: | 455 | sched_wq: |
449 | tasklet_schedule(&dev->tasklet); | 456 | queue_work(dev->wq, &dev->cmd_work); |
450 | } | 457 | } |
451 | 458 | ||
452 | static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags) | 459 | static 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 | ||
503 | sched_tasklet: | 510 | sched_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 | ||
508 | static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags) | 515 | static 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 | ||
1721 | free_nfc_dev: | 1731 | free_nfc_dev: |
1722 | nfc_free_device(dev->nfc_dev); | 1732 | nfc_free_device(dev->nfc_dev); |
1723 | kill_tasklet: | 1733 | destroy_wq: |
1724 | tasklet_kill(&dev->tasklet); | 1734 | destroy_workqueue(dev->wq); |
1725 | error: | 1735 | error: |
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); |