Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: l2cap: add l2cap_user sub-modules

Several sub-modules like HIDP, rfcomm, ... need to track l2cap
connections. The l2cap_conn->hcon->dev object is used as parent for sysfs
devices so the sub-modules need to be notified when the hci_conn object is
removed from sysfs.

As submodules normally use the l2cap layer, the l2cap_user objects are
registered there instead of on the underlying hci_conn object. This avoids
any direct dependency on the HCI layer and lets the l2cap core handle any
specifics.

This patch introduces l2cap_user objects which contain a "probe" and
"remove" callback. You can register them on any l2cap_conn object and if
it is active, the "probe" callback will get called. Otherwise, an error is
returned.

The l2cap_conn object will call your "remove" callback directly before it
is removed from user-space. This allows you to remove your submodules
_before_ the parent l2cap_conn and hci_conn object is removed.

At any time you can asynchronously unregister your l2cap_user object if
your submodule vanishes before the l2cap_conn object does.

There is no way around l2cap_user. If we want wire-protocols in the
kernel, we always want the hci_conn object as parent in the sysfs tree. We
cannot use a channel here since we might need multiple channels for a
single protocol.
But the problem is, we _must_ get notified when an l2cap_conn object is
removed. We cannot use reference-counting for object-removal! This is not
how it works. If a hardware is removed, we should immediately remove the
object from sysfs. Any other behavior would be inconsistent with the rest
of the system. Also note that device_del() might sleep, but it doesn't
wait for user-space or block very long. It only _unlinks_ the object from
sysfs and the whole device-tree. Everything else is handled by ref-counts!
This is exactly what the other sub-modules must do: unlink their devices
when the "remove" l2cap_user callback is called. They should not do any
cleanup or synchronous shutdowns.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

authored by

David Herrmann and committed by
Gustavo Padovan
2c8e1411 9c903e37

+96
+10
include/net/bluetooth/l2cap.h
··· 584 584 struct list_head chan_l; 585 585 struct mutex chan_lock; 586 586 struct kref ref; 587 + struct list_head users; 588 + }; 589 + 590 + struct 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 596 #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 ··· 823 816 824 817 void l2cap_conn_get(struct l2cap_conn *conn); 825 818 void l2cap_conn_put(struct l2cap_conn *conn); 819 + 820 + int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); 821 + void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user); 826 822 827 823 #endif /* __L2CAP_H */
+86
net/bluetooth/l2cap_core.c
··· 1446 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 + 1462 + int 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 + 1494 + out_unlock: 1495 + hci_dev_unlock(hdev); 1496 + return ret; 1497 + } 1498 + EXPORT_SYMBOL(l2cap_register_user); 1499 + 1500 + void 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 + 1514 + out_unlock: 1515 + hci_dev_unlock(hdev); 1516 + } 1517 + EXPORT_SYMBOL(l2cap_unregister_user); 1518 + 1519 + static 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 + 1449 1532 static void l2cap_conn_del(struct hci_conn *hcon, int err) 1450 1533 { 1451 1534 struct l2cap_conn *conn = hcon->l2cap_data; ··· 1540 1457 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); 1541 1458 1542 1459 kfree_skb(conn->rx_skb); 1460 + 1461 + l2cap_unregister_all_users(conn); 1543 1462 1544 1463 mutex_lock(&conn->chan_lock); 1545 1464 ··· 1635 1550 mutex_init(&conn->chan_lock); 1636 1551 1637 1552 INIT_LIST_HEAD(&conn->chan_l); 1553 + INIT_LIST_HEAD(&conn->users); 1638 1554 1639 1555 if (hcon->type == LE_LINK) 1640 1556 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);