|
@@ -338,7 +338,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
|
|
|
dev->active_target = target;
|
|
|
dev->rf_mode = NFC_RF_INITIATOR;
|
|
|
|
|
|
- if (dev->ops->check_presence)
|
|
|
+ if (dev->ops->check_presence && !dev->shutting_down)
|
|
|
mod_timer(&dev->check_pres_timer, jiffies +
|
|
|
msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
|
|
|
}
|
|
@@ -429,7 +429,7 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
|
|
|
rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb,
|
|
|
cb_context);
|
|
|
|
|
|
- if (!rc && dev->ops->check_presence)
|
|
|
+ if (!rc && dev->ops->check_presence && !dev->shutting_down)
|
|
|
mod_timer(&dev->check_pres_timer, jiffies +
|
|
|
msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
|
|
|
} else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) {
|
|
@@ -684,11 +684,6 @@ static void nfc_release(struct device *d)
|
|
|
|
|
|
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
|
|
|
|
|
|
- if (dev->ops->check_presence) {
|
|
|
- del_timer_sync(&dev->check_pres_timer);
|
|
|
- cancel_work_sync(&dev->check_pres_work);
|
|
|
- }
|
|
|
-
|
|
|
nfc_genl_data_exit(&dev->genl_data);
|
|
|
kfree(dev->targets);
|
|
|
kfree(dev);
|
|
@@ -706,15 +701,16 @@ static void nfc_check_pres_work(struct work_struct *work)
|
|
|
rc = dev->ops->check_presence(dev, dev->active_target);
|
|
|
if (rc == -EOPNOTSUPP)
|
|
|
goto exit;
|
|
|
- if (!rc) {
|
|
|
- mod_timer(&dev->check_pres_timer, jiffies +
|
|
|
- msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
|
|
|
- } else {
|
|
|
+ if (rc) {
|
|
|
u32 active_target_idx = dev->active_target->idx;
|
|
|
device_unlock(&dev->dev);
|
|
|
nfc_target_lost(dev, active_target_idx);
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
+ if (!dev->shutting_down)
|
|
|
+ mod_timer(&dev->check_pres_timer, jiffies +
|
|
|
+ msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
|
|
|
}
|
|
|
|
|
|
exit:
|
|
@@ -853,26 +849,27 @@ void nfc_unregister_device(struct nfc_dev *dev)
|
|
|
|
|
|
id = dev->idx;
|
|
|
|
|
|
- mutex_lock(&nfc_devlist_mutex);
|
|
|
- nfc_devlist_generation++;
|
|
|
-
|
|
|
- /* lock to avoid unregistering a device while an operation
|
|
|
- is in progress */
|
|
|
- device_lock(&dev->dev);
|
|
|
- device_del(&dev->dev);
|
|
|
- device_unlock(&dev->dev);
|
|
|
+ if (dev->ops->check_presence) {
|
|
|
+ device_lock(&dev->dev);
|
|
|
+ dev->shutting_down = true;
|
|
|
+ device_unlock(&dev->dev);
|
|
|
+ del_timer_sync(&dev->check_pres_timer);
|
|
|
+ cancel_work_sync(&dev->check_pres_work);
|
|
|
+ }
|
|
|
|
|
|
- mutex_unlock(&nfc_devlist_mutex);
|
|
|
+ rc = nfc_genl_device_removed(dev);
|
|
|
+ if (rc)
|
|
|
+ pr_debug("The userspace won't be notified that the device %s "
|
|
|
+ "was removed\n", dev_name(&dev->dev));
|
|
|
|
|
|
nfc_llcp_unregister_device(dev);
|
|
|
|
|
|
- rc = nfc_genl_device_removed(dev);
|
|
|
- if (rc)
|
|
|
- pr_debug("The userspace won't be notified that the device %s was removed\n",
|
|
|
- dev_name(&dev->dev));
|
|
|
+ mutex_lock(&nfc_devlist_mutex);
|
|
|
+ nfc_devlist_generation++;
|
|
|
+ device_del(&dev->dev);
|
|
|
+ mutex_unlock(&nfc_devlist_mutex);
|
|
|
|
|
|
ida_simple_remove(&nfc_index_ida, id);
|
|
|
-
|
|
|
}
|
|
|
EXPORT_SYMBOL(nfc_unregister_device);
|
|
|
|