Skip to content

Commit 200de7c

Browse files
alwa-nordichenrikbrixandersen
authored andcommitted
Bluetooth: Host: Fix bt_l2cap_chan_ops.recv -EINPROGRESS
Fix discrepancy in reference management between calls to `bt_l2cap_chan_ops.recv` when the application returns `-EINPROGRESS`. There are two call sites, `l2cap_chan_le_recv_sdu` and `l2cap_chan_le_recv`, that were inconsistent. `l2cap_chan_le_recv_sdu` moves the reference, and this patch updates `l2cap_chan_le_recv` to do the same. This behavior is also now documented. This bug has existed since the introduction of this feature in 3151d26. Signed-off-by: Aleksander Wasaznik <[email protected]>
1 parent 7066c40 commit 200de7c

File tree

2 files changed

+14
-1
lines changed

2 files changed

+14
-1
lines changed

include/zephyr/bluetooth/l2cap.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,11 @@ struct bt_l2cap_chan_ops {
349349
* @kconfig{CONFIG_BT_L2CAP_SEG_RECV} is enabled and seg_recv is
350350
* supplied.
351351
*
352+
* If the application returns @c -EINPROGRESS, the application takes
353+
* ownership of the reference in @p buf. (I.e. This pointer value can
354+
* simply be given to @ref bt_l2cap_chan_recv_complete without any
355+
* calls @ref net_buf_ref or @ref net_buf_unref.)
356+
*
352357
* @return 0 in case of success or negative value in case of error.
353358
* @return -EINPROGRESS in case where user has to confirm once the data
354359
* has been processed by calling

subsys/bluetooth/host/l2cap.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <zephyr/sys/byteorder.h>
1818
#include <zephyr/sys/math_extras.h>
1919
#include <zephyr/sys/util.h>
20+
#include <zephyr/net_buf.h>
2021

2122
#include <zephyr/bluetooth/hci.h>
2223
#include <zephyr/bluetooth/bluetooth.h>
@@ -2566,6 +2567,7 @@ static void l2cap_chan_le_recv_seg_direct(struct bt_l2cap_le_chan *chan, struct
25662567
static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan,
25672568
struct net_buf *buf)
25682569
{
2570+
struct net_buf *owned_ref;
25692571
uint16_t sdu_len;
25702572
int err;
25712573

@@ -2639,7 +2641,13 @@ static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan,
26392641
return;
26402642
}
26412643

2642-
err = chan->chan.ops->recv(&chan->chan, buf);
2644+
owned_ref = net_buf_ref(buf);
2645+
err = chan->chan.ops->recv(&chan->chan, owned_ref);
2646+
if (err != -EINPROGRESS) {
2647+
net_buf_unref(owned_ref);
2648+
owned_ref = NULL;
2649+
}
2650+
26432651
if (err < 0) {
26442652
if (err != -EINPROGRESS) {
26452653
LOG_ERR("err %d", err);

0 commit comments

Comments
 (0)