diff --git a/doc/releases/migration-guide-3.6.rst b/doc/releases/migration-guide-3.6.rst index 38e819d840d..8dc1b1f1ff2 100644 --- a/doc/releases/migration-guide-3.6.rst +++ b/doc/releases/migration-guide-3.6.rst @@ -241,6 +241,10 @@ Bluetooth Any pointer to a UUID must be prefixed with `const`, otherwise there will be a compilation warning. For example change ``struct bt_uuid *uuid = BT_UUID_DECLARE_16(xx)`` to ``const struct bt_uuid *uuid = BT_UUID_DECLARE_16(xx)``. (:github:`66136`) +* The :c:func:`bt_l2cap_chan_send` API no longer allocates buffers from the same pool as its `buf` + parameter when segmenting SDUs into PDUs. In order to reproduce the previous behavior, the + application should register the `alloc_seg` channel callback and allocate from the same pool as + `buf`. * Mesh diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index 3386c38bdb3..f688595f604 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -587,9 +587,10 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan); * If the application is reserving the bytes it should use the * BT_L2CAP_BUF_SIZE() helper to correctly size the buffers for the for the * outgoing buffer pool. - * When segmenting an L2CAP SDU into L2CAP PDUs the stack will first attempt - * to allocate buffers from the original buffer pool of the L2CAP SDU before - * using the stacks own buffer pool. + * When segmenting an L2CAP SDU into L2CAP PDUs the stack will first attempt to + * allocate buffers from the channel's `alloc_seg` callback and will fallback + * on the stack's global buffer pool (sized + * @kconfig{CONFIG_BT_L2CAP_TX_BUF_COUNT}). * * @note Buffer ownership is transferred to the stack in case of success, in * case of an error the caller retains the ownership of the buffer. diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 44a013f14b9..e511d44d12b 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -1818,25 +1818,24 @@ static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident, static inline struct net_buf *l2cap_alloc_seg(struct net_buf *buf, struct bt_l2cap_le_chan *ch) { - struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id); - struct net_buf *seg; + struct net_buf *seg = NULL; - /* Use the dedicated segment callback if registered */ + /* Use the user-defined allocator */ if (ch->chan.ops->alloc_seg) { seg = ch->chan.ops->alloc_seg(&ch->chan); __ASSERT_NO_MSG(seg); - } else { - /* Try to use original pool if possible */ - seg = net_buf_alloc(pool, K_NO_WAIT); + } + + /* Fallback to using global connection tx pool */ + if (!seg) { + seg = bt_l2cap_create_pdu_timeout(NULL, 0, K_NO_WAIT); } if (seg) { net_buf_reserve(seg, BT_L2CAP_CHAN_SEND_RESERVE); - return seg; } - /* Fallback to using global connection tx pool */ - return bt_l2cap_create_pdu_timeout(NULL, 0, K_NO_WAIT); + return seg; } static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch,