inet: move inet->recverr_rfc4884 to inet->inet_flags
[platform/kernel/linux-rpi.git] / net / bluetooth / hci_event.c
index 31ca320..559b608 100644 (file)
@@ -1639,7 +1639,7 @@ static u8 hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, void *data,
 
                hci_dev_set_flag(hdev, HCI_LE_ADV);
 
-               if (adv)
+               if (adv && !adv->periodic)
                        adv->enabled = true;
 
                conn = hci_lookup_le_connect(hdev);
@@ -1747,7 +1747,7 @@ static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
 {
        struct discovery_state *d = &hdev->discovery;
 
-       if (len > HCI_MAX_AD_LENGTH)
+       if (len > max_adv_len(hdev))
                return;
 
        bacpy(&d->last_adv_addr, bdaddr);
@@ -3173,19 +3173,15 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
         * As the connection handle is set here for the first time, it indicates
         * whether the connection is already set up.
         */
-       if (conn->handle != HCI_CONN_HANDLE_UNSET) {
+       if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
                bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
                goto unlock;
        }
 
        if (!status) {
-               conn->handle = __le16_to_cpu(ev->handle);
-               if (conn->handle > HCI_CONN_HANDLE_MAX) {
-                       bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
-                                  conn->handle, HCI_CONN_HANDLE_MAX);
-                       status = HCI_ERROR_INVALID_PARAMETERS;
+               status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
+               if (status)
                        goto done;
-               }
 
                if (conn->type == ACL_LINK) {
                        conn->state = BT_CONFIG;
@@ -3803,6 +3799,22 @@ static u8 hci_cc_le_read_buffer_size_v2(struct hci_dev *hdev, void *data,
        return rp->status;
 }
 
+static void hci_unbound_cis_failed(struct hci_dev *hdev, u8 cig, u8 status)
+{
+       struct hci_conn *conn, *tmp;
+
+       lockdep_assert_held(&hdev->lock);
+
+       list_for_each_entry_safe(conn, tmp, &hdev->conn_hash.list, list) {
+               if (conn->type != ISO_LINK || !bacmp(&conn->dst, BDADDR_ANY) ||
+                   conn->state == BT_OPEN || conn->iso_qos.ucast.cig != cig)
+                       continue;
+
+               if (HCI_CONN_HANDLE_UNSET(conn->handle))
+                       hci_conn_failed(conn, status);
+       }
+}
+
 static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
                                   struct sk_buff *skb)
 {
@@ -3810,6 +3822,7 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
        struct hci_cp_le_set_cig_params *cp;
        struct hci_conn *conn;
        u8 status = rp->status;
+       bool pending = false;
        int i;
 
        bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
@@ -3823,12 +3836,15 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
 
        hci_dev_lock(hdev);
 
+       /* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E page 2554
+        *
+        * If the Status return parameter is non-zero, then the state of the CIG
+        * and its CIS configurations shall not be changed by the command. If
+        * the CIG did not already exist, it shall not be created.
+        */
        if (status) {
-               while ((conn = hci_conn_hash_lookup_cig(hdev, rp->cig_id))) {
-                       conn->state = BT_CLOSED;
-                       hci_connect_cfm(conn, status);
-                       hci_conn_del(conn);
-               }
+               /* Keep current configuration, fail only the unbound CIS */
+               hci_unbound_cis_failed(hdev, rp->cig_id, status);
                goto unlock;
        }
 
@@ -3848,17 +3864,17 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
                if (conn->state != BT_BOUND && conn->state != BT_CONNECT)
                        continue;
 
-               conn->handle = __le16_to_cpu(rp->handle[i]);
-
-               bt_dev_dbg(hdev, "%p handle 0x%4.4x parent %p", conn,
-                          conn->handle, conn->parent);
+               if (hci_conn_set_handle(conn, __le16_to_cpu(rp->handle[i])))
+                       continue;
 
-               /* Create CIS if LE is already connected */
-               if (conn->parent && conn->parent->state == BT_CONNECTED)
-                       hci_le_create_cis(conn);
+               if (conn->state == BT_CONNECT)
+                       pending = true;
        }
 
 unlock:
+       if (pending)
+               hci_le_create_cis_pending(hdev);
+
        hci_dev_unlock(hdev);
 
        return rp->status;
@@ -3938,24 +3954,47 @@ static u8 hci_cc_le_set_per_adv_enable(struct hci_dev *hdev, void *data,
                                       struct sk_buff *skb)
 {
        struct hci_ev_status *rp = data;
-       __u8 *sent;
+       struct hci_cp_le_set_per_adv_enable *cp;
+       struct adv_info *adv = NULL, *n;
+       u8 per_adv_cnt = 0;
 
        bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
        if (rp->status)
                return rp->status;
 
-       sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_PER_ADV_ENABLE);
-       if (!sent)
+       cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_PER_ADV_ENABLE);
+       if (!cp)
                return rp->status;
 
        hci_dev_lock(hdev);
 
-       if (*sent)
+       adv = hci_find_adv_instance(hdev, cp->handle);
+
+       if (cp->enable) {
                hci_dev_set_flag(hdev, HCI_LE_PER_ADV);
-       else
+
+               if (adv)
+                       adv->enabled = true;
+       } else {
+               /* If just one instance was disabled check if there are
+                * any other instance enabled before clearing HCI_LE_PER_ADV.
+                * The current periodic adv instance will be marked as
+                * disabled once extended advertising is also disabled.
+                */
+               list_for_each_entry_safe(adv, n, &hdev->adv_instances,
+                                        list) {
+                       if (adv->periodic && adv->enabled)
+                               per_adv_cnt++;
+               }
+
+               if (per_adv_cnt > 1)
+                       goto unlock;
+
                hci_dev_clear_flag(hdev, HCI_LE_PER_ADV);
+       }
 
+unlock:
        hci_dev_unlock(hdev);
 
        return rp->status;
@@ -4224,6 +4263,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
 static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
 {
        struct hci_cp_le_create_cis *cp;
+       bool pending = false;
        int i;
 
        bt_dev_dbg(hdev, "status 0x%2.2x", status);
@@ -4246,12 +4286,18 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
 
                conn = hci_conn_hash_lookup_handle(hdev, handle);
                if (conn) {
+                       if (test_and_clear_bit(HCI_CONN_CREATE_CIS,
+                                              &conn->flags))
+                               pending = true;
                        conn->state = BT_CLOSED;
                        hci_connect_cfm(conn, status);
                        hci_conn_del(conn);
                }
        }
 
+       if (pending)
+               hci_le_create_cis_pending(hdev);
+
        hci_dev_unlock(hdev);
 }
 
@@ -4999,18 +5045,15 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
         * As the connection handle is set here for the first time, it indicates
         * whether the connection is already set up.
         */
-       if (conn->handle != HCI_CONN_HANDLE_UNSET) {
+       if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
                bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete event for existing connection");
                goto unlock;
        }
 
        switch (status) {
        case 0x00:
-               conn->handle = __le16_to_cpu(ev->handle);
-               if (conn->handle > HCI_CONN_HANDLE_MAX) {
-                       bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
-                                  conn->handle, HCI_CONN_HANDLE_MAX);
-                       status = HCI_ERROR_INVALID_PARAMETERS;
+               status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
+               if (status) {
                        conn->state = BT_CLOSED;
                        break;
                }
@@ -5863,7 +5906,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
         * As the connection handle is set here for the first time, it indicates
         * whether the connection is already set up.
         */
-       if (conn->handle != HCI_CONN_HANDLE_UNSET) {
+       if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
                bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
                goto unlock;
        }
@@ -6216,8 +6259,9 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
                return;
        }
 
-       if (!ext_adv && len > HCI_MAX_AD_LENGTH) {
-               bt_dev_err_ratelimited(hdev, "legacy adv larger than 31 bytes");
+       if (len > max_adv_len(hdev)) {
+               bt_dev_err_ratelimited(hdev,
+                                      "adv larger than maximum supported");
                return;
        }
 
@@ -6282,7 +6326,8 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
         */
        conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, bdaddr_resolved,
                                     type);
-       if (!ext_adv && conn && type == LE_ADV_IND && len <= HCI_MAX_AD_LENGTH) {
+       if (!ext_adv && conn && type == LE_ADV_IND &&
+           len <= max_adv_len(hdev)) {
                /* Store report for later inclusion by
                 * mgmt_device_connected
                 */
@@ -6423,7 +6468,7 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data,
                                        info->length + 1))
                        break;
 
-               if (info->length <= HCI_MAX_AD_LENGTH) {
+               if (info->length <= max_adv_len(hdev)) {
                        rssi = info->data[info->length];
                        process_adv_report(hdev, info->type, &info->bdaddr,
                                           info->bdaddr_type, NULL, 0, rssi,
@@ -6790,6 +6835,7 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
        struct hci_evt_le_cis_established *ev = data;
        struct hci_conn *conn;
        struct bt_iso_qos *qos;
+       bool pending = false;
        u16 handle = __le16_to_cpu(ev->handle);
 
        bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@@ -6813,6 +6859,8 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
 
        qos = &conn->iso_qos;
 
+       pending = test_and_clear_bit(HCI_CONN_CREATE_CIS, &conn->flags);
+
        /* Convert ISO Interval (1.25 ms slots) to SDU Interval (us) */
        qos->ucast.in.interval = le16_to_cpu(ev->interval) * 1250;
        qos->ucast.out.interval = qos->ucast.in.interval;
@@ -6854,10 +6902,14 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
                goto unlock;
        }
 
+       conn->state = BT_CLOSED;
        hci_connect_cfm(conn, ev->status);
        hci_conn_del(conn);
 
 unlock:
+       if (pending)
+               hci_le_create_cis_pending(hdev);
+
        hci_dev_unlock(hdev);
 }
 
@@ -6936,6 +6988,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
 {
        struct hci_evt_le_create_big_complete *ev = data;
        struct hci_conn *conn;
+       __u8 i = 0;
 
        BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
@@ -6944,33 +6997,46 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
                return;
 
        hci_dev_lock(hdev);
+       rcu_read_lock();
 
-       conn = hci_conn_hash_lookup_big(hdev, ev->handle);
-       if (!conn)
-               goto unlock;
+       /* Connect all BISes that are bound to the BIG */
+       list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
+               if (bacmp(&conn->dst, BDADDR_ANY) ||
+                   conn->type != ISO_LINK ||
+                   conn->iso_qos.bcast.big != ev->handle)
+                       continue;
 
-       if (conn->type != ISO_LINK) {
-               bt_dev_err(hdev,
-                          "Invalid connection link type handle 0x%2.2x",
-                          ev->handle);
-               goto unlock;
-       }
+               if (hci_conn_set_handle(conn,
+                                       __le16_to_cpu(ev->bis_handle[i++])))
+                       continue;
 
-       if (ev->num_bis)
-               conn->handle = __le16_to_cpu(ev->bis_handle[0]);
+               if (!ev->status) {
+                       conn->state = BT_CONNECTED;
+                       set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
+                       rcu_read_unlock();
+                       hci_debugfs_create_conn(conn);
+                       hci_conn_add_sysfs(conn);
+                       hci_iso_setup_path(conn);
+                       rcu_read_lock();
+                       continue;
+               }
 
-       if (!ev->status) {
-               conn->state = BT_CONNECTED;
-               hci_debugfs_create_conn(conn);
-               hci_conn_add_sysfs(conn);
-               hci_iso_setup_path(conn);
-               goto unlock;
+               hci_connect_cfm(conn, ev->status);
+               rcu_read_unlock();
+               hci_conn_del(conn);
+               rcu_read_lock();
        }
 
-       hci_connect_cfm(conn, ev->status);
-       hci_conn_del(conn);
+       if (!ev->status && !i)
+               /* If no BISes have been connected for the BIG,
+                * terminate. This is in case all bound connections
+                * have been closed before the BIG creation
+                * has completed.
+                */
+               hci_le_terminate_big_sync(hdev, ev->handle,
+                                         HCI_ERROR_LOCAL_HOST_TERM);
 
-unlock:
+       rcu_read_unlock();
        hci_dev_unlock(hdev);
 }
 
@@ -6987,9 +7053,6 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
                                flex_array_size(ev, bis, ev->num_bis)))
                return;
 
-       if (ev->status)
-               return;
-
        hci_dev_lock(hdev);
 
        for (i = 0; i < ev->num_bis; i++) {
@@ -7013,9 +7076,25 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
                bis->iso_qos.bcast.in.latency = le16_to_cpu(ev->interval) * 125 / 100;
                bis->iso_qos.bcast.in.sdu = le16_to_cpu(ev->max_pdu);
 
-               hci_iso_setup_path(bis);
+               if (!ev->status) {
+                       set_bit(HCI_CONN_BIG_SYNC, &bis->flags);
+                       hci_iso_setup_path(bis);
+               }
        }
 
+       /* In case BIG sync failed, notify each failed connection to
+        * the user after all hci connections have been added
+        */
+       if (ev->status)
+               for (i = 0; i < ev->num_bis; i++) {
+                       u16 handle = le16_to_cpu(ev->bis[i]);
+
+                       bis = hci_conn_hash_lookup_handle(hdev, handle);
+
+                       set_bit(HCI_CONN_BIG_SYNC_FAILED, &bis->flags);
+                       hci_connect_cfm(bis, ev->status);
+               }
+
        hci_dev_unlock(hdev);
 }