diff options
author | Eric Lapuyade <eric.lapuyade@intel.com> | 2012-05-07 06:31:15 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-05-15 17:28:00 -0400 |
commit | d4ccb132801aeeb2cfd18c4b4b7fa0043ab37f80 (patch) | |
tree | 7f3372d3925e5cb69cb5db5867accee4d17ff9b8 /net/nfc | |
parent | addfabf98daad7b469ad788a622dbeab6aaaa330 (diff) |
NFC: Specify usage for targets found and target lost events
It is now specified that nfc_target_found() and nfc_target_lost() core
functions must not be called from an atomic context. This allow us to
serialize calls and protect the targets table using the nfc device lock
instead of a spinlock.
Signed-off-by: Eric Lapuyade <eric.lapuyade@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/core.c | 35 | ||||
-rw-r--r-- | net/nfc/netlink.c | 4 |
2 files changed, 28 insertions, 11 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c index 7df28ad4727f..9f6ce011d35d 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -501,6 +501,9 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb); | |||
501 | * The device driver must call this function when one or many nfc targets | 501 | * The device driver must call this function when one or many nfc targets |
502 | * are found. After calling this function, the device driver must stop | 502 | * are found. After calling this function, the device driver must stop |
503 | * polling for targets. | 503 | * polling for targets. |
504 | * IMPORTANT: this function must not be called from an atomic context. | ||
505 | * In addition, it must also not be called from a context that would prevent | ||
506 | * the NFC Core to call other nfc ops entry point concurrently. | ||
504 | */ | 507 | */ |
505 | int nfc_targets_found(struct nfc_dev *dev, | 508 | int nfc_targets_found(struct nfc_dev *dev, |
506 | struct nfc_target *targets, int n_targets) | 509 | struct nfc_target *targets, int n_targets) |
@@ -514,7 +517,7 @@ int nfc_targets_found(struct nfc_dev *dev, | |||
514 | for (i = 0; i < n_targets; i++) | 517 | for (i = 0; i < n_targets; i++) |
515 | targets[i].idx = dev->target_next_idx++; | 518 | targets[i].idx = dev->target_next_idx++; |
516 | 519 | ||
517 | spin_lock_bh(&dev->targets_lock); | 520 | device_lock(&dev->dev); |
518 | 521 | ||
519 | dev->targets_generation++; | 522 | dev->targets_generation++; |
520 | 523 | ||
@@ -524,12 +527,12 @@ int nfc_targets_found(struct nfc_dev *dev, | |||
524 | 527 | ||
525 | if (!dev->targets) { | 528 | if (!dev->targets) { |
526 | dev->n_targets = 0; | 529 | dev->n_targets = 0; |
527 | spin_unlock_bh(&dev->targets_lock); | 530 | device_unlock(&dev->dev); |
528 | return -ENOMEM; | 531 | return -ENOMEM; |
529 | } | 532 | } |
530 | 533 | ||
531 | dev->n_targets = n_targets; | 534 | dev->n_targets = n_targets; |
532 | spin_unlock_bh(&dev->targets_lock); | 535 | device_unlock(&dev->dev); |
533 | 536 | ||
534 | nfc_genl_targets_found(dev); | 537 | nfc_genl_targets_found(dev); |
535 | 538 | ||
@@ -537,6 +540,18 @@ int nfc_targets_found(struct nfc_dev *dev, | |||
537 | } | 540 | } |
538 | EXPORT_SYMBOL(nfc_targets_found); | 541 | EXPORT_SYMBOL(nfc_targets_found); |
539 | 542 | ||
543 | /** | ||
544 | * nfc_target_lost - inform that an activated target went out of field | ||
545 | * | ||
546 | * @dev: The nfc device that had the activated target in field | ||
547 | * @target_idx: the nfc index of the target | ||
548 | * | ||
549 | * The device driver must call this function when the activated target | ||
550 | * goes out of the field. | ||
551 | * IMPORTANT: this function must not be called from an atomic context. | ||
552 | * In addition, it must also not be called from a context that would prevent | ||
553 | * the NFC Core to call other nfc ops entry point concurrently. | ||
554 | */ | ||
540 | int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) | 555 | int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) |
541 | { | 556 | { |
542 | struct nfc_target *tg; | 557 | struct nfc_target *tg; |
@@ -544,7 +559,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) | |||
544 | 559 | ||
545 | pr_debug("dev_name %s n_target %d\n", dev_name(&dev->dev), target_idx); | 560 | pr_debug("dev_name %s n_target %d\n", dev_name(&dev->dev), target_idx); |
546 | 561 | ||
547 | spin_lock_bh(&dev->targets_lock); | 562 | device_lock(&dev->dev); |
548 | 563 | ||
549 | for (i = 0; i < dev->n_targets; i++) { | 564 | for (i = 0; i < dev->n_targets; i++) { |
550 | tg = &dev->targets[i]; | 565 | tg = &dev->targets[i]; |
@@ -553,7 +568,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) | |||
553 | } | 568 | } |
554 | 569 | ||
555 | if (i == dev->n_targets) { | 570 | if (i == dev->n_targets) { |
556 | spin_unlock_bh(&dev->targets_lock); | 571 | device_unlock(&dev->dev); |
557 | return -EINVAL; | 572 | return -EINVAL; |
558 | } | 573 | } |
559 | 574 | ||
@@ -569,7 +584,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) | |||
569 | dev->targets = NULL; | 584 | dev->targets = NULL; |
570 | } | 585 | } |
571 | 586 | ||
572 | spin_unlock_bh(&dev->targets_lock); | 587 | device_unlock(&dev->dev); |
573 | 588 | ||
574 | nfc_genl_target_lost(dev, target_idx); | 589 | nfc_genl_target_lost(dev, target_idx); |
575 | 590 | ||
@@ -607,8 +622,10 @@ static void nfc_check_pres_work(struct work_struct *work) | |||
607 | mod_timer(&dev->check_pres_timer, jiffies + | 622 | mod_timer(&dev->check_pres_timer, jiffies + |
608 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | 623 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
609 | } else { | 624 | } else { |
610 | nfc_target_lost(dev, dev->active_target->idx); | 625 | u32 active_target_idx = dev->active_target->idx; |
611 | dev->active_target = NULL; | 626 | device_unlock(&dev->dev); |
627 | nfc_target_lost(dev, active_target_idx); | ||
628 | return; | ||
612 | } | 629 | } |
613 | } | 630 | } |
614 | 631 | ||
@@ -681,9 +698,9 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
681 | dev->tx_headroom = tx_headroom; | 698 | dev->tx_headroom = tx_headroom; |
682 | dev->tx_tailroom = tx_tailroom; | 699 | dev->tx_tailroom = tx_tailroom; |
683 | 700 | ||
684 | spin_lock_init(&dev->targets_lock); | ||
685 | nfc_genl_data_init(&dev->genl_data); | 701 | nfc_genl_data_init(&dev->genl_data); |
686 | 702 | ||
703 | |||
687 | /* first generation must not be 0 */ | 704 | /* first generation must not be 0 */ |
688 | dev->targets_generation = 1; | 705 | dev->targets_generation = 1; |
689 | 706 | ||
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index f1829f6ae9c5..77dae74832d3 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -128,7 +128,7 @@ static int nfc_genl_dump_targets(struct sk_buff *skb, | |||
128 | cb->args[1] = (long) dev; | 128 | cb->args[1] = (long) dev; |
129 | } | 129 | } |
130 | 130 | ||
131 | spin_lock_bh(&dev->targets_lock); | 131 | device_lock(&dev->dev); |
132 | 132 | ||
133 | cb->seq = dev->targets_generation; | 133 | cb->seq = dev->targets_generation; |
134 | 134 | ||
@@ -141,7 +141,7 @@ static int nfc_genl_dump_targets(struct sk_buff *skb, | |||
141 | i++; | 141 | i++; |
142 | } | 142 | } |
143 | 143 | ||
144 | spin_unlock_bh(&dev->targets_lock); | 144 | device_unlock(&dev->dev); |
145 | 145 | ||
146 | cb->args[0] = i; | 146 | cb->args[0] = i; |
147 | 147 | ||