summaryrefslogtreecommitdiffstats
path: root/include/net/bluetooth/l2cap.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/bluetooth/l2cap.h')
-rw-r--r--include/net/bluetooth/l2cap.h29
1 files changed, 21 insertions, 8 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index f141fbecfa4..9572cbd12a7 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -595,32 +595,45 @@ enum {
FLAG_EFS_ENABLE,
};
+static inline void l2cap_chan_hold(struct l2cap_chan *c)
+{
+ atomic_inc(&c->refcnt);
+}
+
+static inline void l2cap_chan_put(struct l2cap_chan *c)
+{
+ if (atomic_dec_and_test(&c->refcnt))
+ kfree(c);
+}
+
static inline void l2cap_set_timer(struct l2cap_chan *chan,
struct delayed_work *work, long timeout)
{
BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout);
- cancel_delayed_work_sync(work);
-
+ if (!__cancel_delayed_work(work))
+ l2cap_chan_hold(chan);
schedule_delayed_work(work, timeout);
}
-static inline void l2cap_clear_timer(struct delayed_work *work)
+static inline void l2cap_clear_timer(struct l2cap_chan *chan,
+ struct delayed_work *work)
{
- cancel_delayed_work_sync(work);
+ if (__cancel_delayed_work(work))
+ l2cap_chan_put(chan);
}
#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
-#define __clear_chan_timer(c) l2cap_clear_timer(&c->chan_timer)
+#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
L2CAP_DEFAULT_RETRANS_TO);
-#define __clear_retrans_timer(c) l2cap_clear_timer(&c->retrans_timer)
+#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
L2CAP_DEFAULT_MONITOR_TO);
-#define __clear_monitor_timer(c) l2cap_clear_timer(&c->monitor_timer)
+#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
L2CAP_DEFAULT_ACK_TO);
-#define __clear_ack_timer(c) l2cap_clear_timer(&c->ack_timer)
+#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2)
{