aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/l2cap.h10
-rw-r--r--net/bluetooth/l2cap_core.c86
2 files changed, 96 insertions, 0 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7b4cc5b98535..fb94cf13c777 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -584,6 +584,13 @@ struct l2cap_conn {
584 struct list_head chan_l; 584 struct list_head chan_l;
585 struct mutex chan_lock; 585 struct mutex chan_lock;
586 struct kref ref; 586 struct kref ref;
587 struct list_head users;
588};
589
590struct l2cap_user {
591 struct list_head list;
592 int (*probe) (struct l2cap_conn *conn, struct l2cap_user *user);
593 void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user);
587}; 594};
588 595
589#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 596#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
@@ -817,4 +824,7 @@ void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
817void l2cap_conn_get(struct l2cap_conn *conn); 824void l2cap_conn_get(struct l2cap_conn *conn);
818void l2cap_conn_put(struct l2cap_conn *conn); 825void l2cap_conn_put(struct l2cap_conn *conn);
819 826
827int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user);
828void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user);
829
820#endif /* __L2CAP_H */ 830#endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index be9ad89339cd..eae1d9f90b68 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1446,6 +1446,89 @@ static void l2cap_info_timeout(struct work_struct *work)
1446 l2cap_conn_start(conn); 1446 l2cap_conn_start(conn);
1447} 1447}
1448 1448
1449/*
1450 * l2cap_user
1451 * External modules can register l2cap_user objects on l2cap_conn. The ->probe
1452 * callback is called during registration. The ->remove callback is called
1453 * during unregistration.
1454 * An l2cap_user object can either be explicitly unregistered or when the
1455 * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
1456 * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
1457 * External modules must own a reference to the l2cap_conn object if they intend
1458 * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
1459 * any time if they don't.
1460 */
1461
1462int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
1463{
1464 struct hci_dev *hdev = conn->hcon->hdev;
1465 int ret;
1466
1467 /* We need to check whether l2cap_conn is registered. If it is not, we
1468 * must not register the l2cap_user. l2cap_conn_del() is unregisters
1469 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
1470 * relies on the parent hci_conn object to be locked. This itself relies
1471 * on the hci_dev object to be locked. So we must lock the hci device
1472 * here, too. */
1473
1474 hci_dev_lock(hdev);
1475
1476 if (user->list.next || user->list.prev) {
1477 ret = -EINVAL;
1478 goto out_unlock;
1479 }
1480
1481 /* conn->hchan is NULL after l2cap_conn_del() was called */
1482 if (!conn->hchan) {
1483 ret = -ENODEV;
1484 goto out_unlock;
1485 }
1486
1487 ret = user->probe(conn, user);
1488 if (ret)
1489 goto out_unlock;
1490
1491 list_add(&user->list, &conn->users);
1492 ret = 0;
1493
1494out_unlock:
1495 hci_dev_unlock(hdev);
1496 return ret;
1497}
1498EXPORT_SYMBOL(l2cap_register_user);
1499
1500void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
1501{
1502 struct hci_dev *hdev = conn->hcon->hdev;
1503
1504 hci_dev_lock(hdev);
1505
1506 if (!user->list.next || !user->list.prev)
1507 goto out_unlock;
1508
1509 list_del(&user->list);
1510 user->list.next = NULL;
1511 user->list.prev = NULL;
1512 user->remove(conn, user);
1513
1514out_unlock:
1515 hci_dev_unlock(hdev);
1516}
1517EXPORT_SYMBOL(l2cap_unregister_user);
1518
1519static void l2cap_unregister_all_users(struct l2cap_conn *conn)
1520{
1521 struct l2cap_user *user;
1522
1523 while (!list_empty(&conn->users)) {
1524 user = list_first_entry(&conn->users, struct l2cap_user, list);
1525 list_del(&user->list);
1526 user->list.next = NULL;
1527 user->list.prev = NULL;
1528 user->remove(conn, user);
1529 }
1530}
1531
1449static void l2cap_conn_del(struct hci_conn *hcon, int err) 1532static void l2cap_conn_del(struct hci_conn *hcon, int err)
1450{ 1533{
1451 struct l2cap_conn *conn = hcon->l2cap_data; 1534 struct l2cap_conn *conn = hcon->l2cap_data;
@@ -1458,6 +1541,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
1458 1541
1459 kfree_skb(conn->rx_skb); 1542 kfree_skb(conn->rx_skb);
1460 1543
1544 l2cap_unregister_all_users(conn);
1545
1461 mutex_lock(&conn->chan_lock); 1546 mutex_lock(&conn->chan_lock);
1462 1547
1463 /* Kill channels */ 1548 /* Kill channels */
@@ -1550,6 +1635,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
1550 mutex_init(&conn->chan_lock); 1635 mutex_init(&conn->chan_lock);
1551 1636
1552 INIT_LIST_HEAD(&conn->chan_l); 1637 INIT_LIST_HEAD(&conn->chan_l);
1638 INIT_LIST_HEAD(&conn->users);
1553 1639
1554 if (hcon->type == LE_LINK) 1640 if (hcon->type == LE_LINK)
1555 INIT_DELAYED_WORK(&conn->security_timer, security_timeout); 1641 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);