--- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -1154,6 +1154,7 @@ EXPORT_SYMBOL(nfc_register_device); void nfc_unregister_device(struct nfc_dev *dev) { int rc; + struct rfkill *rfk = NULL; pr_debug("dev_name=%s\n", dev_name(&dev->dev)); @@ -1163,14 +1164,18 @@ void nfc_unregister_device(struct nfc_dev *dev) "was removed\n", dev_name(&dev->dev)); device_lock(&dev->dev); + dev->shutting_down = true; if (dev->rfkill) { - rfkill_unregister(dev->rfkill); - rfkill_destroy(dev->rfkill); + rfk = dev->rfkill; dev->rfkill = NULL; } - dev->shutting_down = true; device_unlock(&dev->dev); + if (rfk) { + rfkill_unregister(rfk); + rfkill_destroy(rfk); + } + if (dev->ops->check_presence) { timer_delete_sync(&dev->check_pres_timer); cancel_work_sync(&dev->check_pres_work); --- x/net/bluetooth/hci_core.c +++ y/net/bluetooth/hci_core.c @@ -1476,8 +1476,14 @@ static void hci_cmd_timeout(struct work_ if (hdev->reset) hdev->reset(hdev); + rcu_read_lock(); + if (hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE)) { + rcu_read_unlock(); + return; + } atomic_set(&hdev->cmd_cnt, 1); queue_work(hdev->workqueue, &hdev->cmd_work); + rcu_read_unlock(); } /* HCI ncmd timer function */