Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Johan Hedberg says: ==================== pull request: bluetooth 2015-11-05 The following set of Bluetooth patches would be good to get into 4.4-rc1 if possible: - Fix for missing LE CoC parameter validity checks - Fix for potential deadlock in btusb - Fix for issuing unsupported commands during HCI init Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
096273304c
|
@ -1372,6 +1372,8 @@ static void btusb_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->isoc_altsetting != new_alts) {
|
if (data->isoc_altsetting != new_alts) {
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||||
|
|
||||||
|
@ -1384,10 +1386,10 @@ static void btusb_work(struct work_struct *work)
|
||||||
* Clear outstanding fragment when selecting a new
|
* Clear outstanding fragment when selecting a new
|
||||||
* alternate setting.
|
* alternate setting.
|
||||||
*/
|
*/
|
||||||
spin_lock(&data->rxlock);
|
spin_lock_irqsave(&data->rxlock, flags);
|
||||||
kfree_skb(data->sco_skb);
|
kfree_skb(data->sco_skb);
|
||||||
data->sco_skb = NULL;
|
data->sco_skb = NULL;
|
||||||
spin_unlock(&data->rxlock);
|
spin_unlock_irqrestore(&data->rxlock, flags);
|
||||||
|
|
||||||
if (__set_isoc_interface(hdev, new_alts) < 0)
|
if (__set_isoc_interface(hdev, new_alts) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -275,6 +275,8 @@ struct l2cap_conn_rsp {
|
||||||
#define L2CAP_CR_AUTHORIZATION 0x0006
|
#define L2CAP_CR_AUTHORIZATION 0x0006
|
||||||
#define L2CAP_CR_BAD_KEY_SIZE 0x0007
|
#define L2CAP_CR_BAD_KEY_SIZE 0x0007
|
||||||
#define L2CAP_CR_ENCRYPTION 0x0008
|
#define L2CAP_CR_ENCRYPTION 0x0008
|
||||||
|
#define L2CAP_CR_INVALID_SCID 0x0009
|
||||||
|
#define L2CAP_CR_SCID_IN_USE 0x0010
|
||||||
|
|
||||||
/* connect/create channel status */
|
/* connect/create channel status */
|
||||||
#define L2CAP_CS_NO_INFO 0x0000
|
#define L2CAP_CS_NO_INFO 0x0000
|
||||||
|
|
|
@ -508,12 +508,6 @@ static void le_setup(struct hci_request *req)
|
||||||
/* Read LE Supported States */
|
/* Read LE Supported States */
|
||||||
hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
|
hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
|
||||||
|
|
||||||
/* Read LE White List Size */
|
|
||||||
hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
|
|
||||||
|
|
||||||
/* Clear LE White List */
|
|
||||||
hci_req_add(req, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL);
|
|
||||||
|
|
||||||
/* LE-only controllers have LE implicitly enabled */
|
/* LE-only controllers have LE implicitly enabled */
|
||||||
if (!lmp_bredr_capable(hdev))
|
if (!lmp_bredr_capable(hdev))
|
||||||
hci_dev_set_flag(hdev, HCI_LE_ENABLED);
|
hci_dev_set_flag(hdev, HCI_LE_ENABLED);
|
||||||
|
@ -832,6 +826,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
||||||
hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
|
hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hdev->commands[26] & 0x40) {
|
||||||
|
/* Read LE White List Size */
|
||||||
|
hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE,
|
||||||
|
0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdev->commands[26] & 0x80) {
|
||||||
|
/* Clear LE White List */
|
||||||
|
hci_req_add(req, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) {
|
if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) {
|
||||||
/* Read LE Maximum Data Length */
|
/* Read LE Maximum Data Length */
|
||||||
hci_req_add(req, HCI_OP_LE_READ_MAX_DATA_LEN, 0, NULL);
|
hci_req_add(req, HCI_OP_LE_READ_MAX_DATA_LEN, 0, NULL);
|
||||||
|
|
|
@ -239,7 +239,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
|
||||||
else
|
else
|
||||||
dyn_end = L2CAP_CID_DYN_END;
|
dyn_end = L2CAP_CID_DYN_END;
|
||||||
|
|
||||||
for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) {
|
for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
|
||||||
if (!__l2cap_get_chan_by_scid(conn, cid))
|
if (!__l2cap_get_chan_by_scid(conn, cid))
|
||||||
return cid;
|
return cid;
|
||||||
}
|
}
|
||||||
|
@ -5250,7 +5250,9 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
|
||||||
credits = __le16_to_cpu(rsp->credits);
|
credits = __le16_to_cpu(rsp->credits);
|
||||||
result = __le16_to_cpu(rsp->result);
|
result = __le16_to_cpu(rsp->result);
|
||||||
|
|
||||||
if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
|
if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23 ||
|
||||||
|
dcid < L2CAP_CID_DYN_START ||
|
||||||
|
dcid > L2CAP_CID_LE_DYN_END))
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
|
|
||||||
BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
|
BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
|
||||||
|
@ -5270,6 +5272,11 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case L2CAP_CR_SUCCESS:
|
case L2CAP_CR_SUCCESS:
|
||||||
|
if (__l2cap_get_chan_by_dcid(conn, dcid)) {
|
||||||
|
err = -EBADSLT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
chan->ident = 0;
|
chan->ident = 0;
|
||||||
chan->dcid = dcid;
|
chan->dcid = dcid;
|
||||||
chan->omtu = mtu;
|
chan->omtu = mtu;
|
||||||
|
@ -5437,9 +5444,16 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
|
||||||
goto response_unlock;
|
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;
|
||||||
|
chan = NULL;
|
||||||
|
goto response_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if we already have channel with that dcid */
|
/* 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_NO_MEM;
|
result = L2CAP_CR_SCID_IN_USE;
|
||||||
chan = NULL;
|
chan = NULL;
|
||||||
goto response_unlock;
|
goto response_unlock;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue