Commit f0c9103813b3045bd5b43220b6a78c9908a45d24
Committed by
Samuel Ortiz
1 parent
5f4d6214ef
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
NFC: Fixed nfc core and hci unregistration and cleanup
When an adapter is removed, it will unregister itself from hci and/or nfc core. In order to do that safely, work tasks must first be canceled and prevented to be scheduled again, before the hci or nfc device can be destroyed. Signed-off-by: Eric Lapuyade <eric.lapuyade@intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Showing 5 changed files with 57 additions and 32 deletions Side-by-side Diff
include/net/nfc/hci.h
include/net/nfc/nfc.h
net/nfc/core.c
... | ... | @@ -338,7 +338,7 @@ |
338 | 338 | dev->active_target = target; |
339 | 339 | dev->rf_mode = NFC_RF_INITIATOR; |
340 | 340 | |
341 | - if (dev->ops->check_presence) | |
341 | + if (dev->ops->check_presence && !dev->shutting_down) | |
342 | 342 | mod_timer(&dev->check_pres_timer, jiffies + |
343 | 343 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
344 | 344 | } |
... | ... | @@ -429,7 +429,7 @@ |
429 | 429 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, |
430 | 430 | cb_context); |
431 | 431 | |
432 | - if (!rc && dev->ops->check_presence) | |
432 | + if (!rc && dev->ops->check_presence && !dev->shutting_down) | |
433 | 433 | mod_timer(&dev->check_pres_timer, jiffies + |
434 | 434 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
435 | 435 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { |
... | ... | @@ -684,11 +684,6 @@ |
684 | 684 | |
685 | 685 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); |
686 | 686 | |
687 | - if (dev->ops->check_presence) { | |
688 | - del_timer_sync(&dev->check_pres_timer); | |
689 | - cancel_work_sync(&dev->check_pres_work); | |
690 | - } | |
691 | - | |
692 | 687 | nfc_genl_data_exit(&dev->genl_data); |
693 | 688 | kfree(dev->targets); |
694 | 689 | kfree(dev); |
695 | 690 | |
... | ... | @@ -706,15 +701,16 @@ |
706 | 701 | rc = dev->ops->check_presence(dev, dev->active_target); |
707 | 702 | if (rc == -EOPNOTSUPP) |
708 | 703 | goto exit; |
709 | - if (!rc) { | |
710 | - mod_timer(&dev->check_pres_timer, jiffies + | |
711 | - msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | |
712 | - } else { | |
704 | + if (rc) { | |
713 | 705 | u32 active_target_idx = dev->active_target->idx; |
714 | 706 | device_unlock(&dev->dev); |
715 | 707 | nfc_target_lost(dev, active_target_idx); |
716 | 708 | return; |
717 | 709 | } |
710 | + | |
711 | + if (!dev->shutting_down) | |
712 | + mod_timer(&dev->check_pres_timer, jiffies + | |
713 | + msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | |
718 | 714 | } |
719 | 715 | |
720 | 716 | exit: |
721 | 717 | |
722 | 718 | |
723 | 719 | |
724 | 720 | |
... | ... | @@ -853,26 +849,27 @@ |
853 | 849 | |
854 | 850 | id = dev->idx; |
855 | 851 | |
852 | + if (dev->ops->check_presence) { | |
853 | + device_lock(&dev->dev); | |
854 | + dev->shutting_down = true; | |
855 | + device_unlock(&dev->dev); | |
856 | + del_timer_sync(&dev->check_pres_timer); | |
857 | + cancel_work_sync(&dev->check_pres_work); | |
858 | + } | |
859 | + | |
860 | + rc = nfc_genl_device_removed(dev); | |
861 | + if (rc) | |
862 | + pr_debug("The userspace won't be notified that the device %s " | |
863 | + "was removed\n", dev_name(&dev->dev)); | |
864 | + | |
865 | + nfc_llcp_unregister_device(dev); | |
866 | + | |
856 | 867 | mutex_lock(&nfc_devlist_mutex); |
857 | 868 | nfc_devlist_generation++; |
858 | - | |
859 | - /* lock to avoid unregistering a device while an operation | |
860 | - is in progress */ | |
861 | - device_lock(&dev->dev); | |
862 | 869 | device_del(&dev->dev); |
863 | - device_unlock(&dev->dev); | |
864 | - | |
865 | 870 | mutex_unlock(&nfc_devlist_mutex); |
866 | 871 | |
867 | - nfc_llcp_unregister_device(dev); | |
868 | - | |
869 | - rc = nfc_genl_device_removed(dev); | |
870 | - if (rc) | |
871 | - pr_debug("The userspace won't be notified that the device %s was removed\n", | |
872 | - dev_name(&dev->dev)); | |
873 | - | |
874 | 872 | ida_simple_remove(&nfc_index_ida, id); |
875 | - | |
876 | 873 | } |
877 | 874 | EXPORT_SYMBOL(nfc_unregister_device); |
878 | 875 |
net/nfc/hci/core.c
... | ... | @@ -57,6 +57,8 @@ |
57 | 57 | int r = 0; |
58 | 58 | |
59 | 59 | mutex_lock(&hdev->msg_tx_mutex); |
60 | + if (hdev->shutting_down) | |
61 | + goto exit; | |
60 | 62 | |
61 | 63 | if (hdev->cmd_pending_msg) { |
62 | 64 | if (timer_pending(&hdev->cmd_timer) == 0) { |
... | ... | @@ -868,6 +870,28 @@ |
868 | 870 | { |
869 | 871 | struct hci_msg *msg, *n; |
870 | 872 | |
873 | + mutex_lock(&hdev->msg_tx_mutex); | |
874 | + | |
875 | + if (hdev->cmd_pending_msg) { | |
876 | + if (hdev->cmd_pending_msg->cb) | |
877 | + hdev->cmd_pending_msg->cb( | |
878 | + hdev->cmd_pending_msg->cb_context, | |
879 | + NULL, -ESHUTDOWN); | |
880 | + kfree(hdev->cmd_pending_msg); | |
881 | + hdev->cmd_pending_msg = NULL; | |
882 | + } | |
883 | + | |
884 | + hdev->shutting_down = true; | |
885 | + | |
886 | + mutex_unlock(&hdev->msg_tx_mutex); | |
887 | + | |
888 | + del_timer_sync(&hdev->cmd_timer); | |
889 | + cancel_work_sync(&hdev->msg_tx_work); | |
890 | + | |
891 | + cancel_work_sync(&hdev->msg_rx_work); | |
892 | + | |
893 | + nfc_unregister_device(hdev->ndev); | |
894 | + | |
871 | 895 | skb_queue_purge(&hdev->rx_hcp_frags); |
872 | 896 | skb_queue_purge(&hdev->msg_rx_queue); |
873 | 897 | |
... | ... | @@ -876,13 +900,6 @@ |
876 | 900 | skb_queue_purge(&msg->msg_frags); |
877 | 901 | kfree(msg); |
878 | 902 | } |
879 | - | |
880 | - del_timer_sync(&hdev->cmd_timer); | |
881 | - | |
882 | - nfc_unregister_device(hdev->ndev); | |
883 | - | |
884 | - cancel_work_sync(&hdev->msg_tx_work); | |
885 | - cancel_work_sync(&hdev->msg_rx_work); | |
886 | 903 | } |
887 | 904 | EXPORT_SYMBOL(nfc_hci_unregister_device); |
888 | 905 |
net/nfc/hci/hcp.c
... | ... | @@ -105,6 +105,13 @@ |
105 | 105 | } |
106 | 106 | |
107 | 107 | mutex_lock(&hdev->msg_tx_mutex); |
108 | + | |
109 | + if (hdev->shutting_down) { | |
110 | + err = -ESHUTDOWN; | |
111 | + mutex_unlock(&hdev->msg_tx_mutex); | |
112 | + goto out_skb_err; | |
113 | + } | |
114 | + | |
108 | 115 | list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue); |
109 | 116 | mutex_unlock(&hdev->msg_tx_mutex); |
110 | 117 |