Bluetooth: L2CAP: Don't try to send on disconnected channel
We could start executing the work item after the channel has been disconnected or destroyed, due to a race condition. Double-check we are connected before attempting to send data. Signed-off-by: Jonathan Rico <jonathan.rico@nordicsemi.no>
This commit is contained in:
parent
57b94080b2
commit
e4364413c2
|
@ -899,6 +899,22 @@ static struct net_buf *l2cap_chan_le_get_tx_buf(struct bt_l2cap_le_chan *ch)
|
|||
static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch,
|
||||
struct net_buf *buf);
|
||||
|
||||
/** @brief Get @c chan->state.
|
||||
*
|
||||
* This field does not exist when @kconfig{CONFIG_BT_L2CAP_DYNAMIC_CHANNEL} is
|
||||
* disabled. In that case, this function returns @ref BT_L2CAP_CONNECTED since
|
||||
* the struct can only represent static channels in that case and static
|
||||
* channels are always connected.
|
||||
*/
|
||||
static bt_l2cap_chan_state_t bt_l2cap_chan_get_state(struct bt_l2cap_chan *chan)
|
||||
{
|
||||
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
||||
return BT_L2CAP_LE_CHAN(chan)->state;
|
||||
#else
|
||||
return BT_L2CAP_CONNECTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void l2cap_chan_tx_process(struct k_work *work)
|
||||
{
|
||||
struct bt_l2cap_le_chan *ch;
|
||||
|
@ -907,6 +923,11 @@ static void l2cap_chan_tx_process(struct k_work *work)
|
|||
|
||||
ch = CONTAINER_OF(k_work_delayable_from_work(work), struct bt_l2cap_le_chan, tx_work);
|
||||
|
||||
if (bt_l2cap_chan_get_state(&ch->chan) != BT_L2CAP_CONNECTED) {
|
||||
LOG_DBG("Cannot send on non-connected channel");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Resume tx in case there are buffers in the queue */
|
||||
while ((buf = l2cap_chan_le_get_tx_buf(ch))) {
|
||||
/* Here buf is either:
|
||||
|
@ -2214,22 +2235,6 @@ static void l2cap_chan_shutdown(struct bt_l2cap_chan *chan)
|
|||
}
|
||||
}
|
||||
|
||||
/** @brief Get @c chan->state.
|
||||
*
|
||||
* This field does not exist when @kconfig{CONFIG_BT_L2CAP_DYNAMIC_CHANNEL} is
|
||||
* disabled. In that case, this function returns @ref BT_L2CAP_CONNECTED since
|
||||
* the struct can only represent static channels in that case and static
|
||||
* channels are always connected.
|
||||
*/
|
||||
static inline bt_l2cap_chan_state_t bt_l2cap_chan_get_state(struct bt_l2cap_chan *chan)
|
||||
{
|
||||
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
||||
return BT_L2CAP_LE_CHAN(chan)->state;
|
||||
#else
|
||||
return BT_L2CAP_CONNECTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
|
||||
uint16_t credits)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue