Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetoot...
authorDavid S. Miller <davem@davemloft.net>
Sat, 20 Oct 2018 19:33:48 +0000 (12:33 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 20 Oct 2018 19:33:48 +0000 (12:33 -0700)
Johan Hedberg says:

====================
pull request: bluetooth-next 2018-10-20

Here's one more bluetooth-next pull request for the 4.20 kernel.

 - Added new USB ID for QCA_ROME controller
 - Added debug trace support from QCA wcn3990 controllers
 - Updated L2CAP to conform to latest Errata Service Release
 - Fix binding to non-removable BCM43430 devices

Please let me know if there are any issues pulling. Thanks.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/bluetooth/btsdio.c
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_qca.c
include/net/bluetooth/l2cap.h
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c

index 20142bc77554c0f3400da0506a6158e94722f54b..282d1af1d3bae7aa4b8c770764626836a0d6a6a2 100644 (file)
@@ -293,13 +293,17 @@ static int btsdio_probe(struct sdio_func *func,
                tuple = tuple->next;
        }
 
-       /* BCM43341 devices soldered onto the PCB (non-removable) use an
-        * uart connection for bluetooth, ignore the BT SDIO interface.
+       /* Broadcom devices soldered onto the PCB (non-removable) use an
+        * UART connection for Bluetooth, ignore the BT SDIO interface.
         */
        if (func->vendor == SDIO_VENDOR_ID_BROADCOM &&
-           func->device == SDIO_DEVICE_ID_BROADCOM_43341 &&
-           !mmc_card_is_removable(func->card->host))
-               return -ENODEV;
+           !mmc_card_is_removable(func->card->host)) {
+               switch (func->device) {
+               case SDIO_DEVICE_ID_BROADCOM_43341:
+               case SDIO_DEVICE_ID_BROADCOM_43430:
+                       return -ENODEV;
+               }
+       }
 
        data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
index 61cde1a7ec1be7fe25d3e1bc8a0f4366f1d309dd..7439a7eb50acbed5fb81cc6bd62ee9707a13d796 100644 (file)
@@ -264,6 +264,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
 
        /* QCA ROME chipset */
+       { USB_DEVICE(0x0cf3, 0x535b), .driver_info = BTUSB_QCA_ROME },
        { USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
        { USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME },
        { USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME },
index 9f1392fc71054dadce37298aa648bcf1ae7b6ed3..f036c8f98ea3376317e0256a83cec44a3a4d0cc2 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/serdev.h>
+#include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -63,6 +64,9 @@
 /* susclk rate */
 #define SUSCLK_RATE_32KHZ      32768
 
+/* Controller debug log header */
+#define QCA_DEBUG_HANDLE       0x2EDC
+
 /* HCI_IBS transmit side sleep protocol states */
 enum tx_ibs_states {
        HCI_IBS_TX_ASLEEP,
@@ -849,6 +853,19 @@ static int qca_ibs_wake_ack(struct hci_dev *hdev, struct sk_buff *skb)
        return 0;
 }
 
+static int qca_recv_acl_data(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       /* We receive debug logs from chip as an ACL packets.
+        * Instead of sending the data to ACL to decode the
+        * received data, we are pushing them to the above layers
+        * as a diagnostic packet.
+        */
+       if (get_unaligned_le16(skb->data) == QCA_DEBUG_HANDLE)
+               return hci_recv_diag(hdev, skb);
+
+       return hci_recv_frame(hdev, skb);
+}
+
 #define QCA_IBS_SLEEP_IND_EVENT \
        .type = HCI_IBS_SLEEP_IND, \
        .hlen = 0, \
@@ -871,7 +888,7 @@ static int qca_ibs_wake_ack(struct hci_dev *hdev, struct sk_buff *skb)
        .maxlen = HCI_MAX_IBS_SIZE
 
 static const struct h4_recv_pkt qca_recv_pkts[] = {
-       { H4_RECV_ACL,             .recv = hci_recv_frame    },
+       { H4_RECV_ACL,             .recv = qca_recv_acl_data },
        { H4_RECV_SCO,             .recv = hci_recv_frame    },
        { H4_RECV_EVENT,           .recv = hci_recv_frame    },
        { QCA_IBS_WAKE_IND_EVENT,  .recv = qca_ibs_wake_ind  },
index 3555440e14fc910c6355468cb0468e9e8f8796ce..093aedebdf0ca03f1f270fa77a523d8309229c84 100644 (file)
@@ -277,12 +277,19 @@ struct l2cap_conn_rsp {
 #define L2CAP_CR_SEC_BLOCK     0x0003
 #define L2CAP_CR_NO_MEM                0x0004
 #define L2CAP_CR_BAD_AMP       0x0005
-#define L2CAP_CR_AUTHENTICATION        0x0005
-#define L2CAP_CR_AUTHORIZATION 0x0006
-#define L2CAP_CR_BAD_KEY_SIZE  0x0007
-#define L2CAP_CR_ENCRYPTION    0x0008
-#define L2CAP_CR_INVALID_SCID  0x0009
-#define L2CAP_CR_SCID_IN_USE   0x000A
+#define L2CAP_CR_INVALID_SCID  0x0006
+#define L2CAP_CR_SCID_IN_USE   0x0007
+
+/* credit based connect results */
+#define L2CAP_CR_LE_SUCCESS            0x0000
+#define L2CAP_CR_LE_BAD_PSM            0x0002
+#define L2CAP_CR_LE_NO_MEM             0x0004
+#define L2CAP_CR_LE_AUTHENTICATION     0x0005
+#define L2CAP_CR_LE_AUTHORIZATION      0x0006
+#define L2CAP_CR_LE_BAD_KEY_SIZE       0x0007
+#define L2CAP_CR_LE_ENCRYPTION         0x0008
+#define L2CAP_CR_LE_INVALID_SCID       0x0009
+#define L2CAP_CR_LE_SCID_IN_USE                0X000A
 
 /* connect/create channel status */
 #define L2CAP_CS_NO_INFO       0x0000
index f47f8fad757ac97db775ad05fb3db3ce6285d336..ef9928d7b4fb5abd497e01a45261aa5dab8ac1e0 100644 (file)
@@ -4937,31 +4937,27 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
        hci_debugfs_create_conn(conn);
        hci_conn_add_sysfs(conn);
 
-       if (!status) {
-               /* The remote features procedure is defined for master
-                * role only. So only in case of an initiated connection
-                * request the remote features.
-                *
-                * If the local controller supports slave-initiated features
-                * exchange, then requesting the remote features in slave
-                * role is possible. Otherwise just transition into the
-                * connected state without requesting the remote features.
-                */
-               if (conn->out ||
-                   (hdev->le_features[0] & HCI_LE_SLAVE_FEATURES)) {
-                       struct hci_cp_le_read_remote_features cp;
+       /* The remote features procedure is defined for master
+        * role only. So only in case of an initiated connection
+        * request the remote features.
+        *
+        * If the local controller supports slave-initiated features
+        * exchange, then requesting the remote features in slave
+        * role is possible. Otherwise just transition into the
+        * connected state without requesting the remote features.
+        */
+       if (conn->out ||
+           (hdev->le_features[0] & HCI_LE_SLAVE_FEATURES)) {
+               struct hci_cp_le_read_remote_features cp;
 
-                       cp.handle = __cpu_to_le16(conn->handle);
+               cp.handle = __cpu_to_le16(conn->handle);
 
-                       hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES,
-                                    sizeof(cp), &cp);
+               hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES,
+                            sizeof(cp), &cp);
 
-                       hci_conn_hold(conn);
-               } else {
-                       conn->state = BT_CONNECTED;
-                       hci_connect_cfm(conn, status);
-               }
+               hci_conn_hold(conn);
        } else {
+               conn->state = BT_CONNECTED;
                hci_connect_cfm(conn, status);
        }
 
index 514899f7f0d4bfa12b8dcc7424a0379b9a87891c..2146e0f3b6f868dc032fbbd741af55a7956a23bc 100644 (file)
@@ -680,9 +680,9 @@ static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
        u16 result;
 
        if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
-               result = L2CAP_CR_AUTHORIZATION;
+               result = L2CAP_CR_LE_AUTHORIZATION;
        else
-               result = L2CAP_CR_BAD_PSM;
+               result = L2CAP_CR_LE_BAD_PSM;
 
        l2cap_state_change(chan, BT_DISCONN);
 
@@ -3670,7 +3670,7 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
        rsp.mtu     = cpu_to_le16(chan->imtu);
        rsp.mps     = cpu_to_le16(chan->mps);
        rsp.credits = cpu_to_le16(chan->rx_credits);
-       rsp.result  = cpu_to_le16(L2CAP_CR_SUCCESS);
+       rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
 
        l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
                       &rsp);
@@ -3816,9 +3816,17 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 
        result = L2CAP_CR_NO_MEM;
 
+       /* Check for valid dynamic CID range (as per Erratum 3253) */
+       if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
+               result = L2CAP_CR_INVALID_SCID;
+               goto response;
+       }
+
        /* Check if we already have channel with that dcid */
-       if (__l2cap_get_chan_by_dcid(conn, scid))
+       if (__l2cap_get_chan_by_dcid(conn, scid)) {
+               result = L2CAP_CR_SCID_IN_USE;
                goto response;
+       }
 
        chan = pchan->ops->new_connection(pchan);
        if (!chan)
@@ -5280,7 +5288,7 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
        credits = __le16_to_cpu(rsp->credits);
        result  = __le16_to_cpu(rsp->result);
 
-       if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23 ||
+       if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
                                           dcid < L2CAP_CID_DYN_START ||
                                           dcid > L2CAP_CID_LE_DYN_END))
                return -EPROTO;
@@ -5301,7 +5309,7 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
        l2cap_chan_lock(chan);
 
        switch (result) {
-       case L2CAP_CR_SUCCESS:
+       case L2CAP_CR_LE_SUCCESS:
                if (__l2cap_get_chan_by_dcid(conn, dcid)) {
                        err = -EBADSLT;
                        break;
@@ -5315,8 +5323,8 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
                l2cap_chan_ready(chan);
                break;
 
-       case L2CAP_CR_AUTHENTICATION:
-       case L2CAP_CR_ENCRYPTION:
+       case L2CAP_CR_LE_AUTHENTICATION:
+       case L2CAP_CR_LE_ENCRYPTION:
                /* If we already have MITM protection we can't do
                 * anything.
                 */
@@ -5459,7 +5467,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
        pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
                                         &conn->hcon->dst, LE_LINK);
        if (!pchan) {
-               result = L2CAP_CR_BAD_PSM;
+               result = L2CAP_CR_LE_BAD_PSM;
                chan = NULL;
                goto response;
        }
@@ -5469,28 +5477,28 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 
        if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
                                     SMP_ALLOW_STK)) {
-               result = L2CAP_CR_AUTHENTICATION;
+               result = L2CAP_CR_LE_AUTHENTICATION;
                chan = NULL;
                goto response_unlock;
        }
 
        /* Check for valid dynamic CID range */
        if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
-               result = L2CAP_CR_INVALID_SCID;
+               result = L2CAP_CR_LE_INVALID_SCID;
                chan = NULL;
                goto response_unlock;
        }
 
        /* Check if we already have channel with that dcid */
        if (__l2cap_get_chan_by_dcid(conn, scid)) {
-               result = L2CAP_CR_SCID_IN_USE;
+               result = L2CAP_CR_LE_SCID_IN_USE;
                chan = NULL;
                goto response_unlock;
        }
 
        chan = pchan->ops->new_connection(pchan);
        if (!chan) {
-               result = L2CAP_CR_NO_MEM;
+               result = L2CAP_CR_LE_NO_MEM;
                goto response_unlock;
        }
 
@@ -5526,7 +5534,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
                chan->ops->defer(chan);
        } else {
                l2cap_chan_ready(chan);
-               result = L2CAP_CR_SUCCESS;
+               result = L2CAP_CR_LE_SUCCESS;
        }
 
 response_unlock: