]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Bluetooth: hci_sync: hci_cmd_sync_queue_once() return -EEXIST if exists
authorPauli Virtanen <pav@iki.fi>
Wed, 25 Mar 2026 19:07:43 +0000 (21:07 +0200)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 1 Apr 2026 20:44:38 +0000 (16:44 -0400)
hci_cmd_sync_queue_once() needs to indicate whether a queue item was
added, so caller can know if callbacks are called, so it can avoid
leaking resources.

Change the function to return -EEXIST if queue item already exists.

Modify all callsites to handle that.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/hci_sync.c

index 6283a4df78b0055647ebd0b3bc3c700628d3792d..97745710e3ce7062da28d45d4179387c28d0862d 100644 (file)
@@ -780,7 +780,7 @@ int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
                            void *data, hci_cmd_sync_work_destroy_t destroy)
 {
        if (hci_cmd_sync_lookup_entry(hdev, func, data, destroy))
-               return 0;
+               return -EEXIST;
 
        return hci_cmd_sync_queue(hdev, func, data, destroy);
 }
@@ -3262,6 +3262,8 @@ static int update_passive_scan_sync(struct hci_dev *hdev, void *data)
 
 int hci_update_passive_scan(struct hci_dev *hdev)
 {
+       int err;
+
        /* Only queue if it would have any effect */
        if (!test_bit(HCI_UP, &hdev->flags) ||
            test_bit(HCI_INIT, &hdev->flags) ||
@@ -3271,8 +3273,9 @@ int hci_update_passive_scan(struct hci_dev *hdev)
            hci_dev_test_flag(hdev, HCI_UNREGISTER))
                return 0;
 
-       return hci_cmd_sync_queue_once(hdev, update_passive_scan_sync, NULL,
-                                      NULL);
+       err = hci_cmd_sync_queue_once(hdev, update_passive_scan_sync, NULL,
+                                     NULL);
+       return (err == -EEXIST) ? 0 : err;
 }
 
 int hci_write_sc_support_sync(struct hci_dev *hdev, u8 val)
@@ -6965,8 +6968,11 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
 
 int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn)
 {
-       return hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync, conn,
-                                      NULL);
+       int err;
+
+       err = hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync, conn,
+                                     NULL);
+       return (err == -EEXIST) ? 0 : err;
 }
 
 static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
@@ -7002,8 +7008,11 @@ done:
 
 int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn)
 {
-       return hci_cmd_sync_queue_once(hdev, hci_le_create_conn_sync, conn,
-                                      create_le_conn_complete);
+       int err;
+
+       err = hci_cmd_sync_queue_once(hdev, hci_le_create_conn_sync, conn,
+                                     create_le_conn_complete);
+       return (err == -EEXIST) ? 0 : err;
 }
 
 int hci_cancel_connect_sync(struct hci_dev *hdev, struct hci_conn *conn)
@@ -7210,8 +7219,11 @@ done:
 
 int hci_connect_pa_sync(struct hci_dev *hdev, struct hci_conn *conn)
 {
-       return hci_cmd_sync_queue_once(hdev, hci_le_pa_create_sync, conn,
-                                      create_pa_complete);
+       int err;
+
+       err = hci_cmd_sync_queue_once(hdev, hci_le_pa_create_sync, conn,
+                                     create_pa_complete);
+       return (err == -EEXIST) ? 0 : err;
 }
 
 static void create_big_complete(struct hci_dev *hdev, void *data, int err)
@@ -7273,8 +7285,11 @@ static int hci_le_big_create_sync(struct hci_dev *hdev, void *data)
 
 int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn)
 {
-       return hci_cmd_sync_queue_once(hdev, hci_le_big_create_sync, conn,
-                                      create_big_complete);
+       int err;
+
+       err = hci_cmd_sync_queue_once(hdev, hci_le_big_create_sync, conn,
+                                     create_big_complete);
+       return (err == -EEXIST) ? 0 : err;
 }
 
 struct past_data {
@@ -7366,7 +7381,7 @@ int hci_past_sync(struct hci_conn *conn, struct hci_conn *le)
        if (err)
                kfree(data);
 
-       return err;
+       return (err == -EEXIST) ? 0 : err;
 }
 
 static void le_read_features_complete(struct hci_dev *hdev, void *data, int err)
@@ -7453,7 +7468,7 @@ int hci_le_read_remote_features(struct hci_conn *conn)
        else
                err = -EOPNOTSUPP;
 
-       return err;
+       return (err == -EEXIST) ? 0 : err;
 }
 
 static void pkt_type_changed(struct hci_dev *hdev, void *data, int err)
@@ -7479,6 +7494,7 @@ int hci_acl_change_pkt_type(struct hci_conn *conn, u16 pkt_type)
 {
        struct hci_dev *hdev = conn->hdev;
        struct hci_cp_change_conn_ptype *cp;
+       int err;
 
        cp = kmalloc_obj(*cp);
        if (!cp)
@@ -7487,8 +7503,9 @@ int hci_acl_change_pkt_type(struct hci_conn *conn, u16 pkt_type)
        cp->handle = cpu_to_le16(conn->handle);
        cp->pkt_type = cpu_to_le16(pkt_type);
 
-       return hci_cmd_sync_queue_once(hdev, hci_change_conn_ptype_sync, cp,
-                                      pkt_type_changed);
+       err = hci_cmd_sync_queue_once(hdev, hci_change_conn_ptype_sync, cp,
+                                     pkt_type_changed);
+       return (err == -EEXIST) ? 0 : err;
 }
 
 static void le_phy_update_complete(struct hci_dev *hdev, void *data, int err)
@@ -7514,6 +7531,7 @@ int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys)
 {
        struct hci_dev *hdev = conn->hdev;
        struct hci_cp_le_set_phy *cp;
+       int err;
 
        cp = kmalloc_obj(*cp);
        if (!cp)
@@ -7524,6 +7542,7 @@ int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys)
        cp->tx_phys = tx_phys;
        cp->rx_phys = rx_phys;
 
-       return hci_cmd_sync_queue_once(hdev, hci_le_set_phy_sync, cp,
-                                      le_phy_update_complete);
+       err = hci_cmd_sync_queue_once(hdev, hci_le_set_phy_sync, cp,
+                                     le_phy_update_complete);
+       return (err == -EEXIST) ? 0 : err;
 }