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 dcc0dc6e2624..2a37d3eb3c55 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1027,7 +1027,7 @@ static inline void hci_conn_drop(struct hci_conn *conn) /* ----- HCI Devices ----- */ static inline void hci_dev_put(struct hci_dev *d) { - BT_DBG("%s orig refcnt %d", d->name, + printk("%#llx orig refcnt %d. put\n", d, kref_read(&d->dev.kobj.kref)); put_device(&d->dev); @@ -1035,9 +1035,9 @@ static inline void hci_dev_put(struct hci_dev *d) static inline struct hci_dev *hci_dev_hold(struct hci_dev *d) { - BT_DBG("%s orig refcnt %d", d->name, + printk("%#llx orig refcnt %d. get\n", d, kref_read(&d->dev.kobj.kref)); - + get_device(&d->dev); return d; } @@ -1162,6 +1162,7 @@ void hci_init_sysfs(struct hci_dev *hdev); void hci_conn_init_sysfs(struct hci_conn *conn); void hci_conn_add_sysfs(struct hci_conn *conn); void hci_conn_del_sysfs(struct hci_conn *conn); +void hci_release_hdev(struct hci_dev *hdev); #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev)) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index cbbc34a006d1..fb5251182909 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3338,6 +3338,7 @@ struct hci_dev *hci_alloc_dev(void) } EXPORT_SYMBOL(hci_alloc_dev); +extern void show_stack(struct task_struct *task, unsigned long *sp); /* Free HCI device */ void hci_free_dev(struct hci_dev *hdev) { @@ -3451,38 +3452,9 @@ 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; - - BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); - - hci_dev_set_flag(hdev, HCI_UNREGISTER); - - 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)) { - hci_dev_lock(hdev); - mgmt_index_removed(hdev); - hci_dev_unlock(hdev); - } - - /* mgmt_index_removed should take care of emptying the - * pending list */ - BUG_ON(!list_empty(&hdev->mgmt_pending)); - - hci_sock_dev_event(hdev, HCI_DEV_UNREG); + int id = hdev->id; if (hdev->rfkill) { rfkill_unregister(hdev->rfkill); @@ -3514,9 +3486,40 @@ 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); + printk("haley release %#llx\n", hdev); +} + +/* Unregister HCI device */ +void hci_unregister_dev(struct hci_dev *hdev) +{ + BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); + + hci_dev_set_flag(hdev, HCI_UNREGISTER); + + 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)) { + hci_dev_lock(hdev); + mgmt_index_removed(hdev); + hci_dev_unlock(hdev); + } + + /* mgmt_index_removed should take care of emptying the + * pending list */ + BUG_ON(!list_empty(&hdev->mgmt_pending)); + + hci_sock_dev_event(hdev, HCI_DEV_UNREG); + + hci_dev_put(hdev); } EXPORT_SYMBOL(hci_unregister_dev); diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 9874844a95a9..2420c929f43e --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -83,6 +83,10 @@ 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); + + if (hdev->workqueue) + hci_release_hdev(hdev); + kfree(hdev); module_put(THIS_MODULE); }