--- x/net/bluetooth/l2cap_core.c +++ y/net/bluetooth/l2cap_core.c @@ -624,10 +624,7 @@ void __l2cap_chan_add(struct l2cap_conn l2cap_chan_hold(chan); - /* Only keep a reference for fixed channels if they requested it */ - if (chan->chan_type != L2CAP_CHAN_FIXED || - test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) - hci_conn_hold(conn->hcon); + hci_conn_hold(conn->hcon); list_add(&chan->list, &conn->chan_l); } @@ -659,13 +656,7 @@ void l2cap_chan_del(struct l2cap_chan *c chan->conn = NULL; - /* Reference was only held for non-fixed channels or - * fixed channels that explicitly requested it using the - * FLAG_HOLD_HCI_CONN flag. - */ - if (chan->chan_type != L2CAP_CHAN_FIXED || - test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) - hci_conn_drop(conn->hcon); + hci_conn_drop(conn->hcon); if (mgr && mgr->bredr_chan == chan) mgr->bredr_chan = NULL; @@ -1890,6 +1881,7 @@ static void l2cap_conn_del(struct hci_co { struct l2cap_conn *conn = hcon->l2cap_data; struct l2cap_chan *chan, *l; + LIST_HEAD(head); if (!conn) return; @@ -1931,13 +1923,12 @@ static void l2cap_conn_del(struct hci_co mutex_unlock(&conn->chan_lock); + cancel_delayed_work_sync(&conn->info_timer); + list_add(&conn->hchan->list, &head); hci_chan_del(conn->hchan); - if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) - cancel_delayed_work_sync(&conn->info_timer); - - hcon->l2cap_data = NULL; conn->hchan = NULL; + hcon->l2cap_data = NULL; l2cap_conn_put(conn); } @@ -7893,6 +7884,7 @@ static struct l2cap_conn *l2cap_conn_add INIT_DELAYED_WORK(&conn->id_addr_timer, l2cap_conn_update_id_addr); conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; + list_del(&hchan->list); return conn; } --- x/include/net/bluetooth/hci_core.h +++ y/include/net/bluetooth/hci_core.h @@ -1545,9 +1545,7 @@ static inline void hci_conn_drop(struct break; } - cancel_delayed_work(&conn->disc_work); - queue_delayed_work(conn->hdev->workqueue, - &conn->disc_work, timeo); + queue_delayed_work(system_unbound_wq, &conn->disc_work, timeo); } } --- x/net/bluetooth/hci_conn.c +++ y/net/bluetooth/hci_conn.c @@ -613,6 +613,7 @@ static void hci_conn_timeout(struct work struct hci_conn *conn = container_of(work, struct hci_conn, disc_work.work); int refcnt = atomic_read(&conn->refcnt); + struct hci_dev *hdev = conn->hdev; BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); @@ -629,6 +630,7 @@ static void hci_conn_timeout(struct work return; hci_abort_conn(conn, hci_proto_disconn_ind(conn)); + hci_dev_put(hdev); } /* Enter sniff mode */ @@ -1027,6 +1029,7 @@ struct hci_conn *hci_conn_add(struct hci atomic_set(&conn->refcnt, 0); hci_dev_hold(hdev); + hci_dev_hold(hdev); hci_conn_hash_add(hdev, conn);