diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 61800a7b6192..8c815c0b1440 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -859,40 +859,50 @@ static inline void l2cap_chan_unlock(struct l2cap_chan *chan) } static inline void l2cap_set_timer(struct l2cap_chan *chan, - struct delayed_work *work, long timeout) + struct delayed_work *work, long timeout, int sync) { BT_DBG("chan %p state %s timeout %ld", chan, state_to_string(chan->state), timeout); /* If delayed work cancelled do not hold(chan) since it is already done with previous set_timer */ - if (!cancel_delayed_work(work)) - l2cap_chan_hold(chan); + if (sync) { + if (!cancel_delayed_work_sync(work)) + l2cap_chan_hold(chan); + } else { + if (!cancel_delayed_work(work)) + l2cap_chan_hold(chan); + } schedule_delayed_work(work, timeout); } static inline bool l2cap_clear_timer(struct l2cap_chan *chan, - struct delayed_work *work) + struct delayed_work *work, int sync) { bool ret; /* put(chan) if delayed work cancelled otherwise it is done in delayed work function */ - ret = cancel_delayed_work(work); + if (sync) + ret = cancel_delayed_work_sync(work); + else + ret = cancel_delayed_work(work); if (ret) l2cap_chan_put(chan); return ret; } -#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) -#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) -#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) -#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) +#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t), 0) +#define __set_chan_timer_sync(c, t) l2cap_set_timer(c, &c->chan_timer, (t), 1) +#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer, 0) +#define __clear_chan_timer_sync(c) l2cap_clear_timer(c, &c->chan_timer, 1) +#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer, 0) +#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer, 0) #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ - msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); -#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer) + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO), 0); +#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer, 0) static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) { diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 72c2f5226d67..46f99a24707c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -290,7 +290,7 @@ static void __set_retrans_timer(struct l2cap_chan *chan) if (!delayed_work_pending(&chan->monitor_timer) && chan->retrans_timeout) { l2cap_set_timer(chan, &chan->retrans_timer, - msecs_to_jiffies(chan->retrans_timeout)); + msecs_to_jiffies(chan->retrans_timeout), 0); } } @@ -299,7 +299,7 @@ static void __set_monitor_timer(struct l2cap_chan *chan) __clear_retrans_timer(chan); if (chan->monitor_timeout) { l2cap_set_timer(chan, &chan->monitor_timer, - msecs_to_jiffies(chan->monitor_timeout)); + msecs_to_jiffies(chan->monitor_timeout), 0); } } @@ -610,7 +610,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) { struct l2cap_conn *conn = chan->conn; - __clear_chan_timer(chan); + __clear_chan_timer_sync(chan); BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err, state_to_string(chan->state)); @@ -1339,7 +1339,7 @@ static void l2cap_chan_ready(struct l2cap_chan *chan) /* This clears all conf flags, including CONF_NOT_COMPLETE */ chan->conf_state = 0; - __clear_chan_timer(chan); + __clear_chan_timer_sync(chan); switch (chan->mode) { case L2CAP_MODE_LE_FLOWCTL: @@ -5317,7 +5317,7 @@ static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result) return; } - __clear_chan_timer(chan); + __clear_chan_timer_sync(chan); if (result == L2CAP_MR_PEND) __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT); @@ -5408,7 +5408,7 @@ static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, return; } - __clear_chan_timer(chan); + __clear_chan_timer_sync(chan); if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) { if (result == L2CAP_MR_COLLISION) { @@ -5509,7 +5509,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, if (!chan) return 0; - __clear_chan_timer(chan); + __clear_chan_timer_sync(chan); if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { chan->local_amp_id = chan->move_id; @@ -7968,7 +7968,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, if (hcon->state == BT_CONNECTED) { if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { - __clear_chan_timer(chan); + __clear_chan_timer_sync(chan); if (l2cap_chan_check_security(chan, true)) l2cap_state_change(chan, BT_CONNECTED); } else @@ -8181,7 +8181,7 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) l2cap_chan_close(chan, ECONNREFUSED); } else { if (chan->sec_level == BT_SECURITY_MEDIUM) - __clear_chan_timer(chan); + __clear_chan_timer_sync(chan); } }