aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-04-29 12:35:45 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-06-22 19:23:49 -0400
commit44f3b0fbaa9bfa7a88577ee8c446d0a78cb1d73a (patch)
treedff8bc6ec80a81799e66dc8bb6cf285112ee5235 /net
parent0cc59a72c723979cf8973aff4df874a5f7a697c7 (diff)
Bluetooth: Fix multiple LE socket handling
The LE ATT server socket needs to be superseded by any ATT client sockets. Previously this was done by looking at the hcon->out variable (indicating whether the connection is outgoing or incoming) which is a too crude way of determining whether the server socket needs to be picked or not (an outgoing connection doesn't necessarily mean that an ATT client socket has triggered it). This patch extends the ATT server socket lookup function (l2cap_le_conn_ready) to be used for all LE connections (regardless of the hcon->out value) and adds an internal check into the function for the existence of any ATT client sockets (in which case the server socket should be skipped). For this to work reliably all lookups must be done while the l2cap_conn->chan_lock is held, meaning also that the call to l2cap_chan_add needs to be changed to its lockless __l2cap_chan_add counterpart. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_core.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 8ae6a21cf643..9af3a76844f7 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1353,6 +1353,10 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1353 if (!pchan) 1353 if (!pchan)
1354 return; 1354 return;
1355 1355
1356 /* Client ATT sockets should override the server one */
1357 if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))
1358 return;
1359
1356 parent = pchan->sk; 1360 parent = pchan->sk;
1357 1361
1358 lock_sock(parent); 1362 lock_sock(parent);
@@ -1366,7 +1370,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1366 bacpy(&bt_sk(chan->sk)->src, conn->src); 1370 bacpy(&bt_sk(chan->sk)->src, conn->src);
1367 bacpy(&bt_sk(chan->sk)->dst, conn->dst); 1371 bacpy(&bt_sk(chan->sk)->dst, conn->dst);
1368 1372
1369 l2cap_chan_add(conn, chan); 1373 __l2cap_chan_add(conn, chan);
1370 1374
1371clean: 1375clean:
1372 release_sock(parent); 1376 release_sock(parent);
@@ -1379,9 +1383,6 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
1379 1383
1380 BT_DBG("conn %p", conn); 1384 BT_DBG("conn %p", conn);
1381 1385
1382 if (!hcon->out && hcon->type == LE_LINK)
1383 l2cap_le_conn_ready(conn);
1384
1385 /* For outgoing pairing which doesn't necessarily have an 1386 /* For outgoing pairing which doesn't necessarily have an
1386 * associated socket (e.g. mgmt_pair_device). 1387 * associated socket (e.g. mgmt_pair_device).
1387 */ 1388 */
@@ -1390,6 +1391,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
1390 1391
1391 mutex_lock(&conn->chan_lock); 1392 mutex_lock(&conn->chan_lock);
1392 1393
1394 if (hcon->type == LE_LINK)
1395 l2cap_le_conn_ready(conn);
1396
1393 list_for_each_entry(chan, &conn->chan_l, list) { 1397 list_for_each_entry(chan, &conn->chan_l, list) {
1394 1398
1395 l2cap_chan_lock(chan); 1399 l2cap_chan_lock(chan);