diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 85a30fb9177b..0b2f6be7b820 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -541,9 +541,10 @@ static void hci_uart_tty_close(struct tty_struct *tty) cancel_work_sync(&hu->write_work); if (hdev) { - if (test_bit(HCI_UART_REGISTERED, &hu->flags)) + if (test_bit(HCI_UART_REGISTERED, &hu->flags)) { hci_unregister_dev(hdev); - hci_free_dev(hdev); + hci_free_dev(hdev); + } } hu->proto->close(hu); } diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 89ecf0a80aa1..928981d6fb85 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1487,6 +1487,7 @@ void hci_send_monitor_ctrl_event(struct hci_dev *hdev, u16 event, int flag, struct sock *skip_sk); void hci_sock_dev_event(struct hci_dev *hdev, int event); +void hci_release_hdev(struct hci_dev *hdev); #define HCI_MGMT_VAR_LEN BIT(0) #define HCI_MGMT_NO_HDEV BIT(1) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index cbbc34a006d1..ef885021ff02 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3451,8 +3451,7 @@ int hci_register_dev(struct hci_dev *hdev) } EXPORT_SYMBOL(hci_register_dev); -/* Unregister HCI device */ -void hci_unregister_dev(struct hci_dev *hdev) +void hci_release_hdev(struct hci_dev *hdev) { int id; @@ -3462,14 +3461,6 @@ void hci_unregister_dev(struct hci_dev *hdev) id = hdev->id; - write_lock(&hci_dev_list_lock); - list_del(&hdev->list); - write_unlock(&hci_dev_list_lock); - - cancel_work_sync(&hdev->power_on); - - hci_dev_do_close(hdev); - if (!test_bit(HCI_INIT, &hdev->flags) && !hci_dev_test_flag(hdev, HCI_SETUP) && !hci_dev_test_flag(hdev, HCI_CONFIG)) { @@ -3514,10 +3505,22 @@ void hci_unregister_dev(struct hci_dev *hdev) hci_blocked_keys_clear(hdev); hci_dev_unlock(hdev); - hci_dev_put(hdev); - ida_simple_remove(&hci_index_ida, id); } + + +/* Unregister HCI device */ +void hci_unregister_dev(struct hci_dev *hdev) +{ + write_lock(&hci_dev_list_lock); + list_del(&hdev->list); + write_unlock(&hci_dev_list_lock); + + cancel_work_sync(&hdev->power_on); + hci_dev_do_close(hdev); + + hci_dev_put(hdev); +} EXPORT_SYMBOL(hci_unregister_dev); /* Suspend HCI device */ diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 9874844a95a9..3553b141aff4 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -83,6 +83,11 @@ void hci_conn_del_sysfs(struct hci_conn *conn) static void bt_host_release(struct device *dev) { struct hci_dev *hdev = to_hci_dev(dev); + + /* The hdev was registered */ + if (hdev->workqueue) + hci_release_hdev(hdev); + kfree(hdev); module_put(THIS_MODULE); }