When connecting to remote device that uses RPA, first we start scan, to find current address of this device. Inside hci_connect_le_scan hci_conn_add is called. If we find device with matching RPA, and start connecting, hci_conn that was returned from this call is reused, and destroyed at end of connection by calling hci_conn_del. If we don't find device with matching RPA, and scan timeouts, or is canceled, we also have to call hci_conn_del, which is not happening right now. That is leaving module refcount in bad state. This patch adds hci_conn_del_from_disc_work method, that is same as hci_conn_del, except that it doesn't cancel disc_work (because it's called from it, and that would cause stalled worker). It also adds call to this new method from hci_connect_le_scan_remove. Signed-off-by: Jakub Pawlowski <jpawlowski@xxxxxxxxxx> --- net/bluetooth/hci_conn.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2ebcaaa..d8a995a 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -35,6 +35,8 @@ #include "smp.h" #include "a2mp.h" +static int hci_conn_del_from_disc_work(struct hci_conn *conn); + struct sco_param { u16 pkt_type; u16 max_latency; @@ -104,7 +106,10 @@ static void hci_connect_le_scan_remove(struct hci_conn *conn) { hci_connect_le_scan_cleanup(conn); - hci_conn_hash_del(conn->hdev, conn); + /* hci_connect_le_scan_remove is only called from disc_work. Make sure + * we don't try to cancel synchronously this work when deleting conn. + */ + hci_conn_del_from_disc_work(conn); } static void hci_acl_create_connection(struct hci_conn *conn) @@ -550,13 +555,11 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, return conn; } -int hci_conn_del(struct hci_conn *conn) +static int hci_conn_del_from_disc_work(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle); - - cancel_delayed_work_sync(&conn->disc_work); cancel_delayed_work_sync(&conn->auto_accept_work); cancel_delayed_work_sync(&conn->idle_work); @@ -607,6 +610,16 @@ int hci_conn_del(struct hci_conn *conn) return 0; } +int hci_conn_del(struct hci_conn *conn) +{ + struct hci_dev *hdev = conn->hdev; + + BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle); + + cancel_delayed_work_sync(&conn->disc_work); + return hci_conn_del_from_disc_work(conn); +} + struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) { int use_src = bacmp(src, BDADDR_ANY); -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html