mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-04 04:04:19 +00:00
Bluetooth: L2CAP: Fix div-by-zero in l2cap_le_flowctl_init()
l2cap_le_flowctl_init() can cause both div-by-zero and an integer
overflow since hdev->le_mtu may not fall in the valid range.
Move MTU from hci_dev to hci_conn to validate MTU and stop the connection
process earlier if MTU is invalid.
Also, add a missing validation in read_buffer_size() and make it return
an error value if the validation fails.
Now hci_conn_add() returns ERR_PTR() as it can fail due to the both a
kzalloc failure and invalid MTU value.
divide error: 0000 [#1] PREEMPT SMP KASAN NOPTI
CPU: 0 PID: 67 Comm: kworker/u5:0 Tainted: G W 6.9.0-rc5+ #20
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Workqueue: hci0 hci_rx_work
RIP: 0010:l2cap_le_flowctl_init+0x19e/0x3f0 net/bluetooth/l2cap_core.c:547
Code: e8 17 17 0c 00 66 41 89 9f 84 00 00 00 bf 01 00 00 00 41 b8 02 00 00 00 4c
89 fe 4c 89 e2 89 d9 e8 27 17 0c 00 44 89 f0 31 d2 <66> f7 f3 89 c3 ff c3 4d 8d
b7 88 00 00 00 4c 89 f0 48 c1 e8 03 42
RSP: 0018:ffff88810bc0f858 EFLAGS: 00010246
RAX: 00000000000002a0 RBX: 0000000000000000 RCX: dffffc0000000000
RDX: 0000000000000000 RSI: ffff88810bc0f7c0 RDI: ffffc90002dcb66f
RBP: ffff88810bc0f880 R08: aa69db2dda70ff01 R09: 0000ffaaaaaaaaaa
R10: 0084000000ffaaaa R11: 0000000000000000 R12: ffff88810d65a084
R13: dffffc0000000000 R14: 00000000000002a0 R15: ffff88810d65a000
FS: 0000000000000000(0000) GS:ffff88811ac00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000020000100 CR3: 0000000103268003 CR4: 0000000000770ef0
PKRU: 55555554
Call Trace:
<TASK>
l2cap_le_connect_req net/bluetooth/l2cap_core.c:4902 [inline]
l2cap_le_sig_cmd net/bluetooth/l2cap_core.c:5420 [inline]
l2cap_le_sig_channel net/bluetooth/l2cap_core.c:5486 [inline]
l2cap_recv_frame+0xe59d/0x11710 net/bluetooth/l2cap_core.c:6809
l2cap_recv_acldata+0x544/0x10a0 net/bluetooth/l2cap_core.c:7506
hci_acldata_packet net/bluetooth/hci_core.c:3939 [inline]
hci_rx_work+0x5e5/0xb20 net/bluetooth/hci_core.c:4176
process_one_work kernel/workqueue.c:3254 [inline]
process_scheduled_works+0x90f/0x1530 kernel/workqueue.c:3335
worker_thread+0x926/0xe70 kernel/workqueue.c:3416
kthread+0x2e3/0x380 kernel/kthread.c:388
ret_from_fork+0x5c/0x90 arch/x86/kernel/process.c:147
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
Fixes: 6ed58ec520
("Bluetooth: Use LE buffers for LE traffic")
Suggested-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Signed-off-by: Sungwoo Kim <iam@sung-woo.kim>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
a189f0ee66
commit
a5b862c6a2
@ -1665,6 +1665,15 @@ struct hci_cp_le_set_event_mask {
|
|||||||
__u8 mask[8];
|
__u8 mask[8];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E
|
||||||
|
* 7.8.2 LE Read Buffer Size command
|
||||||
|
* MAX_LE_MTU is 0xffff.
|
||||||
|
* 0 is also valid. It means that no dedicated LE Buffer exists.
|
||||||
|
* It should use the HCI_Read_Buffer_Size command and mtu is shared
|
||||||
|
* between BR/EDR and LE.
|
||||||
|
*/
|
||||||
|
#define HCI_MIN_LE_MTU 0x001b
|
||||||
|
|
||||||
#define HCI_OP_LE_READ_BUFFER_SIZE 0x2002
|
#define HCI_OP_LE_READ_BUFFER_SIZE 0x2002
|
||||||
struct hci_rp_le_read_buffer_size {
|
struct hci_rp_le_read_buffer_size {
|
||||||
__u8 status;
|
__u8 status;
|
||||||
|
@ -706,6 +706,7 @@ struct hci_conn {
|
|||||||
__u16 handle;
|
__u16 handle;
|
||||||
__u16 sync_handle;
|
__u16 sync_handle;
|
||||||
__u16 state;
|
__u16 state;
|
||||||
|
__u16 mtu;
|
||||||
__u8 mode;
|
__u8 mode;
|
||||||
__u8 type;
|
__u8 type;
|
||||||
__u8 role;
|
__u8 role;
|
||||||
|
@ -904,11 +904,37 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
{
|
{
|
||||||
struct hci_conn *conn;
|
struct hci_conn *conn;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case ACL_LINK:
|
||||||
|
if (!hdev->acl_mtu)
|
||||||
|
return ERR_PTR(-ECONNREFUSED);
|
||||||
|
break;
|
||||||
|
case ISO_LINK:
|
||||||
|
if (hdev->iso_mtu)
|
||||||
|
/* Dedicated ISO Buffer exists */
|
||||||
|
break;
|
||||||
|
fallthrough;
|
||||||
|
case LE_LINK:
|
||||||
|
if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
|
||||||
|
return ERR_PTR(-ECONNREFUSED);
|
||||||
|
if (!hdev->le_mtu && hdev->acl_mtu < HCI_MIN_LE_MTU)
|
||||||
|
return ERR_PTR(-ECONNREFUSED);
|
||||||
|
break;
|
||||||
|
case SCO_LINK:
|
||||||
|
case ESCO_LINK:
|
||||||
|
if (!hdev->sco_pkts)
|
||||||
|
/* Controller does not support SCO or eSCO over HCI */
|
||||||
|
return ERR_PTR(-ECONNREFUSED);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ERR_PTR(-ECONNREFUSED);
|
||||||
|
}
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle);
|
bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle);
|
||||||
|
|
||||||
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
||||||
if (!conn)
|
if (!conn)
|
||||||
return NULL;
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
bacpy(&conn->dst, dst);
|
bacpy(&conn->dst, dst);
|
||||||
bacpy(&conn->src, &hdev->bdaddr);
|
bacpy(&conn->src, &hdev->bdaddr);
|
||||||
@ -939,10 +965,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case ACL_LINK:
|
case ACL_LINK:
|
||||||
conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
|
conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
|
||||||
|
conn->mtu = hdev->acl_mtu;
|
||||||
break;
|
break;
|
||||||
case LE_LINK:
|
case LE_LINK:
|
||||||
/* conn->src should reflect the local identity address */
|
/* conn->src should reflect the local identity address */
|
||||||
hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
|
hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
|
||||||
|
conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
|
||||||
break;
|
break;
|
||||||
case ISO_LINK:
|
case ISO_LINK:
|
||||||
/* conn->src should reflect the local identity address */
|
/* conn->src should reflect the local identity address */
|
||||||
@ -954,6 +982,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
else if (conn->role == HCI_ROLE_MASTER)
|
else if (conn->role == HCI_ROLE_MASTER)
|
||||||
conn->cleanup = cis_cleanup;
|
conn->cleanup = cis_cleanup;
|
||||||
|
|
||||||
|
conn->mtu = hdev->iso_mtu ? hdev->iso_mtu :
|
||||||
|
hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
|
||||||
break;
|
break;
|
||||||
case SCO_LINK:
|
case SCO_LINK:
|
||||||
if (lmp_esco_capable(hdev))
|
if (lmp_esco_capable(hdev))
|
||||||
@ -961,9 +991,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
(hdev->esco_type & EDR_ESCO_MASK);
|
(hdev->esco_type & EDR_ESCO_MASK);
|
||||||
else
|
else
|
||||||
conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
|
conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
|
||||||
|
|
||||||
|
conn->mtu = hdev->sco_mtu;
|
||||||
break;
|
break;
|
||||||
case ESCO_LINK:
|
case ESCO_LINK:
|
||||||
conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
|
conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
|
||||||
|
conn->mtu = hdev->sco_mtu;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,7 +1039,7 @@ struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
|
|||||||
|
|
||||||
handle = hci_conn_hash_alloc_unset(hdev);
|
handle = hci_conn_hash_alloc_unset(hdev);
|
||||||
if (unlikely(handle < 0))
|
if (unlikely(handle < 0))
|
||||||
return NULL;
|
return ERR_PTR(-ECONNREFUSED);
|
||||||
|
|
||||||
return hci_conn_add(hdev, type, dst, role, handle);
|
return hci_conn_add(hdev, type, dst, role, handle);
|
||||||
}
|
}
|
||||||
@ -1312,8 +1345,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
bacpy(&conn->dst, dst);
|
bacpy(&conn->dst, dst);
|
||||||
} else {
|
} else {
|
||||||
conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
|
conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
|
||||||
if (!conn)
|
if (IS_ERR(conn))
|
||||||
return ERR_PTR(-ENOMEM);
|
return conn;
|
||||||
hci_conn_hold(conn);
|
hci_conn_hold(conn);
|
||||||
conn->pending_sec_level = sec_level;
|
conn->pending_sec_level = sec_level;
|
||||||
}
|
}
|
||||||
@ -1489,8 +1522,8 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
return ERR_PTR(-EADDRINUSE);
|
return ERR_PTR(-EADDRINUSE);
|
||||||
|
|
||||||
conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
|
conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
|
||||||
if (!conn)
|
if (IS_ERR(conn))
|
||||||
return ERR_PTR(-ENOMEM);
|
return conn;
|
||||||
|
|
||||||
conn->state = BT_CONNECT;
|
conn->state = BT_CONNECT;
|
||||||
|
|
||||||
@ -1533,8 +1566,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
BT_DBG("requesting refresh of dst_addr");
|
BT_DBG("requesting refresh of dst_addr");
|
||||||
|
|
||||||
conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
|
conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
|
||||||
if (!conn)
|
if (IS_ERR(conn))
|
||||||
return ERR_PTR(-ENOMEM);
|
return conn;
|
||||||
|
|
||||||
if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) {
|
if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) {
|
||||||
hci_conn_del(conn);
|
hci_conn_del(conn);
|
||||||
@ -1581,8 +1614,8 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
|
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
|
||||||
if (!acl) {
|
if (!acl) {
|
||||||
acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
|
acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
|
||||||
if (!acl)
|
if (IS_ERR(acl))
|
||||||
return ERR_PTR(-ENOMEM);
|
return acl;
|
||||||
}
|
}
|
||||||
|
|
||||||
hci_conn_hold(acl);
|
hci_conn_hold(acl);
|
||||||
@ -1650,9 +1683,9 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
|
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
|
||||||
if (!sco) {
|
if (!sco) {
|
||||||
sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
|
sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
|
||||||
if (!sco) {
|
if (IS_ERR(sco)) {
|
||||||
hci_conn_drop(acl);
|
hci_conn_drop(acl);
|
||||||
return ERR_PTR(-ENOMEM);
|
return sco;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1841,8 +1874,8 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
qos->ucast.cis);
|
qos->ucast.cis);
|
||||||
if (!cis) {
|
if (!cis) {
|
||||||
cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
|
cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
|
||||||
if (!cis)
|
if (IS_ERR(cis))
|
||||||
return ERR_PTR(-ENOMEM);
|
return cis;
|
||||||
cis->cleanup = cis_cleanup;
|
cis->cleanup = cis_cleanup;
|
||||||
cis->dst_type = dst_type;
|
cis->dst_type = dst_type;
|
||||||
cis->iso_qos.ucast.cig = BT_ISO_QOS_CIG_UNSET;
|
cis->iso_qos.ucast.cig = BT_ISO_QOS_CIG_UNSET;
|
||||||
@ -1977,14 +2010,8 @@ static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn,
|
|||||||
struct bt_iso_io_qos *qos, __u8 phy)
|
struct bt_iso_io_qos *qos, __u8 phy)
|
||||||
{
|
{
|
||||||
/* Only set MTU if PHY is enabled */
|
/* Only set MTU if PHY is enabled */
|
||||||
if (!qos->sdu && qos->phy) {
|
if (!qos->sdu && qos->phy)
|
||||||
if (hdev->iso_mtu > 0)
|
qos->sdu = conn->mtu;
|
||||||
qos->sdu = hdev->iso_mtu;
|
|
||||||
else if (hdev->le_mtu > 0)
|
|
||||||
qos->sdu = hdev->le_mtu;
|
|
||||||
else
|
|
||||||
qos->sdu = hdev->acl_mtu;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use the same PHY as ACL if set to any */
|
/* Use the same PHY as ACL if set to any */
|
||||||
if (qos->phy == BT_ISO_PHY_ANY)
|
if (qos->phy == BT_ISO_PHY_ANY)
|
||||||
@ -2065,8 +2092,8 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
return ERR_PTR(-EBUSY);
|
return ERR_PTR(-EBUSY);
|
||||||
|
|
||||||
conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE);
|
conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE);
|
||||||
if (!conn)
|
if (IS_ERR(conn))
|
||||||
return ERR_PTR(-ENOMEM);
|
return conn;
|
||||||
|
|
||||||
conn->iso_qos = *qos;
|
conn->iso_qos = *qos;
|
||||||
conn->state = BT_LISTEN;
|
conn->state = BT_LISTEN;
|
||||||
|
@ -954,6 +954,9 @@ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data,
|
|||||||
BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
|
BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
|
||||||
hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
|
hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
|
||||||
|
|
||||||
|
if (!hdev->acl_mtu || !hdev->acl_pkts)
|
||||||
|
return HCI_ERROR_INVALID_PARAMETERS;
|
||||||
|
|
||||||
return rp->status;
|
return rp->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1263,6 +1266,9 @@ static u8 hci_cc_le_read_buffer_size(struct hci_dev *hdev, void *data,
|
|||||||
|
|
||||||
BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
|
BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
|
||||||
|
|
||||||
|
if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
|
||||||
|
return HCI_ERROR_INVALID_PARAMETERS;
|
||||||
|
|
||||||
return rp->status;
|
return rp->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2341,8 +2347,8 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
|
|||||||
if (!conn) {
|
if (!conn) {
|
||||||
conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
|
conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
|
||||||
HCI_ROLE_MASTER);
|
HCI_ROLE_MASTER);
|
||||||
if (!conn)
|
if (IS_ERR(conn))
|
||||||
bt_dev_err(hdev, "no memory for new connection");
|
bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3153,8 +3159,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
|
|||||||
BDADDR_BREDR)) {
|
BDADDR_BREDR)) {
|
||||||
conn = hci_conn_add_unset(hdev, ev->link_type,
|
conn = hci_conn_add_unset(hdev, ev->link_type,
|
||||||
&ev->bdaddr, HCI_ROLE_SLAVE);
|
&ev->bdaddr, HCI_ROLE_SLAVE);
|
||||||
if (!conn) {
|
if (IS_ERR(conn)) {
|
||||||
bt_dev_err(hdev, "no memory for new conn");
|
bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -3342,8 +3348,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
|
|||||||
if (!conn) {
|
if (!conn) {
|
||||||
conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
|
conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
|
||||||
HCI_ROLE_SLAVE);
|
HCI_ROLE_SLAVE);
|
||||||
if (!conn) {
|
if (IS_ERR(conn)) {
|
||||||
bt_dev_err(hdev, "no memory for new connection");
|
bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3820,6 +3826,9 @@ static u8 hci_cc_le_read_buffer_size_v2(struct hci_dev *hdev, void *data,
|
|||||||
BT_DBG("%s acl mtu %d:%d iso mtu %d:%d", hdev->name, hdev->acl_mtu,
|
BT_DBG("%s acl mtu %d:%d iso mtu %d:%d", hdev->name, hdev->acl_mtu,
|
||||||
hdev->acl_pkts, hdev->iso_mtu, hdev->iso_pkts);
|
hdev->acl_pkts, hdev->iso_mtu, hdev->iso_pkts);
|
||||||
|
|
||||||
|
if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
|
||||||
|
return HCI_ERROR_INVALID_PARAMETERS;
|
||||||
|
|
||||||
return rp->status;
|
return rp->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5768,8 +5777,8 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
|
conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
|
||||||
if (!conn) {
|
if (IS_ERR(conn)) {
|
||||||
bt_dev_err(hdev, "no memory for new connection");
|
bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6497,7 +6506,7 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
|
|||||||
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
|
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
|
||||||
HCI_ROLE_SLAVE);
|
HCI_ROLE_SLAVE);
|
||||||
|
|
||||||
if (!pa_sync)
|
if (IS_ERR(pa_sync))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
pa_sync->sync_handle = le16_to_cpu(ev->handle);
|
pa_sync->sync_handle = le16_to_cpu(ev->handle);
|
||||||
@ -6921,7 +6930,7 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data,
|
|||||||
if (!cis) {
|
if (!cis) {
|
||||||
cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE,
|
cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE,
|
||||||
cis_handle);
|
cis_handle);
|
||||||
if (!cis) {
|
if (IS_ERR(cis)) {
|
||||||
hci_le_reject_cis(hdev, ev->cis_handle);
|
hci_le_reject_cis(hdev, ev->cis_handle);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
@ -7030,7 +7039,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||||||
if (!bis) {
|
if (!bis) {
|
||||||
bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
|
bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
|
||||||
HCI_ROLE_SLAVE, handle);
|
HCI_ROLE_SLAVE, handle);
|
||||||
if (!bis)
|
if (IS_ERR(bis))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1258,7 +1258,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
mtu = iso_pi(sk)->conn->hcon->hdev->iso_mtu;
|
mtu = iso_pi(sk)->conn->hcon->mtu;
|
||||||
|
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
|
|
||||||
|
@ -6264,7 +6264,7 @@ static int l2cap_finish_move(struct l2cap_chan *chan)
|
|||||||
BT_DBG("chan %p", chan);
|
BT_DBG("chan %p", chan);
|
||||||
|
|
||||||
chan->rx_state = L2CAP_RX_STATE_RECV;
|
chan->rx_state = L2CAP_RX_STATE_RECV;
|
||||||
chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
|
chan->conn->mtu = chan->conn->hcon->mtu;
|
||||||
|
|
||||||
return l2cap_resegment(chan);
|
return l2cap_resegment(chan);
|
||||||
}
|
}
|
||||||
@ -6331,7 +6331,7 @@ static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
|
|||||||
*/
|
*/
|
||||||
chan->next_tx_seq = control->reqseq;
|
chan->next_tx_seq = control->reqseq;
|
||||||
chan->unacked_frames = 0;
|
chan->unacked_frames = 0;
|
||||||
chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
|
chan->conn->mtu = chan->conn->hcon->mtu;
|
||||||
|
|
||||||
err = l2cap_resegment(chan);
|
err = l2cap_resegment(chan);
|
||||||
|
|
||||||
@ -6889,18 +6889,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
|
|||||||
|
|
||||||
BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
|
BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
|
||||||
|
|
||||||
switch (hcon->type) {
|
conn->mtu = hcon->mtu;
|
||||||
case LE_LINK:
|
|
||||||
if (hcon->hdev->le_mtu) {
|
|
||||||
conn->mtu = hcon->hdev->le_mtu;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fallthrough;
|
|
||||||
default:
|
|
||||||
conn->mtu = hcon->hdev->acl_mtu;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->feat_mask = 0;
|
conn->feat_mask = 0;
|
||||||
|
|
||||||
conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
|
conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
|
||||||
|
@ -126,7 +126,6 @@ static void sco_sock_clear_timer(struct sock *sk)
|
|||||||
/* ---- SCO connections ---- */
|
/* ---- SCO connections ---- */
|
||||||
static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
|
static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = hcon->hdev;
|
|
||||||
struct sco_conn *conn = hcon->sco_data;
|
struct sco_conn *conn = hcon->sco_data;
|
||||||
|
|
||||||
if (conn) {
|
if (conn) {
|
||||||
@ -144,9 +143,10 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
|
|||||||
|
|
||||||
hcon->sco_data = conn;
|
hcon->sco_data = conn;
|
||||||
conn->hcon = hcon;
|
conn->hcon = hcon;
|
||||||
|
conn->mtu = hcon->mtu;
|
||||||
|
|
||||||
if (hdev->sco_mtu > 0)
|
if (hcon->mtu > 0)
|
||||||
conn->mtu = hdev->sco_mtu;
|
conn->mtu = hcon->mtu;
|
||||||
else
|
else
|
||||||
conn->mtu = 60;
|
conn->mtu = 60;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user