aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/hci
diff options
context:
space:
mode:
authorEric Lapuyade <eric.lapuyade@linux.intel.com>2012-11-26 18:06:27 +0100
committerSamuel Ortiz <sameo@linux.intel.com>2013-01-10 00:51:48 +0100
commitf0c9103813b3045bd5b43220b6a78c9908a45d24 (patch)
tree78422096c0728f84a43c057bcf6ffa185bd13190 /net/nfc/hci
parentNFC: nfcwilink: Use devm_kzalloc (diff)
downloadlinux-dev-f0c9103813b3045bd5b43220b6a78c9908a45d24.tar.xz
linux-dev-f0c9103813b3045bd5b43220b6a78c9908a45d24.zip
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>
Diffstat (limited to 'net/nfc/hci')
-rw-r--r--net/nfc/hci/core.c31
-rw-r--r--net/nfc/hci/hcp.c7
2 files changed, 31 insertions, 7 deletions
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 7bea574d5934..b4b84268653d 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -57,6 +57,8 @@ static void nfc_hci_msg_tx_work(struct work_struct *work)
int r = 0;
mutex_lock(&hdev->msg_tx_mutex);
+ if (hdev->shutting_down)
+ goto exit;
if (hdev->cmd_pending_msg) {
if (timer_pending(&hdev->cmd_timer) == 0) {
@@ -868,6 +870,28 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev)
{
struct hci_msg *msg, *n;
+ mutex_lock(&hdev->msg_tx_mutex);
+
+ if (hdev->cmd_pending_msg) {
+ if (hdev->cmd_pending_msg->cb)
+ hdev->cmd_pending_msg->cb(
+ hdev->cmd_pending_msg->cb_context,
+ NULL, -ESHUTDOWN);
+ kfree(hdev->cmd_pending_msg);
+ hdev->cmd_pending_msg = NULL;
+ }
+
+ hdev->shutting_down = true;
+
+ mutex_unlock(&hdev->msg_tx_mutex);
+
+ del_timer_sync(&hdev->cmd_timer);
+ cancel_work_sync(&hdev->msg_tx_work);
+
+ cancel_work_sync(&hdev->msg_rx_work);
+
+ nfc_unregister_device(hdev->ndev);
+
skb_queue_purge(&hdev->rx_hcp_frags);
skb_queue_purge(&hdev->msg_rx_queue);
@@ -876,13 +900,6 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev)
skb_queue_purge(&msg->msg_frags);
kfree(msg);
}
-
- del_timer_sync(&hdev->cmd_timer);
-
- nfc_unregister_device(hdev->ndev);
-
- cancel_work_sync(&hdev->msg_tx_work);
- cancel_work_sync(&hdev->msg_rx_work);
}
EXPORT_SYMBOL(nfc_hci_unregister_device);
diff --git a/net/nfc/hci/hcp.c b/net/nfc/hci/hcp.c
index bc308a7ca609..b6b4109f2343 100644
--- a/net/nfc/hci/hcp.c
+++ b/net/nfc/hci/hcp.c
@@ -105,6 +105,13 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe,
}
mutex_lock(&hdev->msg_tx_mutex);
+
+ if (hdev->shutting_down) {
+ err = -ESHUTDOWN;
+ mutex_unlock(&hdev->msg_tx_mutex);
+ goto out_skb_err;
+ }
+
list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue);
mutex_unlock(&hdev->msg_tx_mutex);