diff --git a/subsys/bluetooth/host/Kconfig.gatt b/subsys/bluetooth/host/Kconfig.gatt index 221bc413c4b..3403e8d308b 100644 --- a/subsys/bluetooth/host/Kconfig.gatt +++ b/subsys/bluetooth/host/Kconfig.gatt @@ -52,9 +52,6 @@ config BT_ATT_SENT_CB_AFTER_TX Zephyr fork). It is a temporary solution allowing to control flow of GATT notifications with HID reports for HID use-case. - Enabling this option may require increasing CONFIG_BT_CONN_TX_MAX in - configuration, because ATT would use additional TX contexts. - config BT_EATT bool "Enhanced ATT Bearers support [EXPERIMENTAL]" depends on BT_L2CAP_ECRED diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index d0b6264aaed..f4d1f84c8cd 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -712,10 +712,12 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf, uint16_t frag_len = MIN(conn_mtu(conn), len); /* If ATT sent callback is delayed until data transmission - * is done by BLE controller, the transmitted buffer may - * have an additional reference. The reference is used to - * extend lifetime of the net buffer until the data - * transmission is confirmed by ACK of the remote. + * is done by BLE controller (CONFIG_BT_ATT_SENT_CB_AFTER_TX), + * the `chan_send` function from `att.c` introduces an additional + * reference. The reference is used to extend lifetime of the net + * buffer until the data transmission is confirmed by ACK of the + * remote (the reference is removed when the TX callback passed + * to `bt_l2cap_send_pdu` is called). * * send_buf function can be called multiple times, if buffer * has to be fragmented over HCI. In that case, the callback diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 0879163a8a1..fe5d59b9b58 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -273,6 +273,24 @@ static void l2cap_chan_del(struct bt_l2cap_chan *chan) * `l2cap_chan_destroy()` as it is not called for fixed channels. */ while ((buf = k_fifo_get(&le_chan->tx_queue, K_NO_WAIT))) { + /* If ATT sent callback is delayed until data transmission is done by BLE controller + * (CONFIG_BT_ATT_SENT_CB_AFTER_TX), the `chan_send` function from `att.c` + * introduces an additional reference. The reference is used to extend lifetime of + * the net buffer until the data transmission is confirmed by ACK of the + * remote (the reference is removed when the TX callback passed to + * `bt_l2cap_send_pdu` is called). + * + * The TX callbacks of the buffers removed here are not called, therefore the + * additional reference needs to be removed here. + */ + if (IS_ENABLED(CONFIG_BT_ATT_SENT_CB_AFTER_TX)) { + __ASSERT_NO_MSG(buf->ref <= 2); + + if (buf->ref == 2) { + net_buf_unref(buf); + } + } + net_buf_unref(buf); } @@ -761,9 +779,11 @@ int bt_l2cap_send_pdu(struct bt_l2cap_le_chan *le_chan, struct net_buf *pdu, return -ENOTCONN; } - /* Allow for an additional buffer reference if callback is provided. This can be used to - * extend lifetime of the net buffer until the data transmission is confirmed by ACK of the - * remote. + /* If ATT sent callback is delayed until data transmission is done by BLE controller + * (CONFIG_BT_ATT_SENT_CB_AFTER_TX), the `chan_send` function from `att.c` introduces an + * additional reference. The reference is used to extend lifetime of the net buffer until + * the data transmission is confirmed by ACK of the remote (the reference is removed when + * the TX callback passed to `bt_l2cap_send_pdu` is called). */ if (pdu->ref > 1 + (cb ? 1 : 0)) { /* The host may alter the buf contents when fragmenting. Higher