aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/rfcomm/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/rfcomm/core.c')
-rw-r--r--net/bluetooth/rfcomm/core.c39
1 files changed, 14 insertions, 25 deletions
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 754b153..5759bb7 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -62,6 +62,7 @@ static DEFINE_MUTEX(rfcomm_mutex);
#define rfcomm_lock() mutex_lock(&rfcomm_mutex)
#define rfcomm_unlock() mutex_unlock(&rfcomm_mutex)
+static unsigned long rfcomm_event;
static LIST_HEAD(session_list);
@@ -119,6 +120,7 @@ static inline void rfcomm_schedule(void)
{
if (!rfcomm_thread)
return;
+ set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
wake_up_process(rfcomm_thread);
}
@@ -409,19 +411,11 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
return err;
}
- /* After L2sock created, increase refcnt immediately
- * It can make connection drop in rfcomm_security_cfm because of refcnt.
- */
- rfcomm_session_hold(s);
-
dlci = __dlci(!s->initiator, channel);
/* Check if DLCI already exists */
- if (rfcomm_dlc_get(s, dlci)) {
- /* decrement refcnt */
- rfcomm_session_put(s);
+ if (rfcomm_dlc_get(s, dlci))
return -EBUSY;
- }
rfcomm_dlc_clear_state(d);
@@ -437,9 +431,6 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
d->mtu = s->mtu;
d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc;
- /* decrement refcnt */
- rfcomm_session_put(s);
-
if (s->state == BT_CONNECTED) {
if (rfcomm_check_security(d))
rfcomm_send_pn(s, 1, d);
@@ -475,6 +466,7 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
switch (d->state) {
case BT_CONNECT:
+ case BT_CONFIG:
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
rfcomm_schedule();
@@ -1156,7 +1148,6 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
if (list_empty(&s->dlcs)) {
s->state = BT_DISCONN;
rfcomm_send_disc(s, 0);
- rfcomm_session_clear_timer(s);
}
break;
@@ -1173,7 +1164,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
/* When socket is closed and we are not RFCOMM
* initiator rfcomm_process_rx already calls
* rfcomm_session_put() */
- if (s->sock->sk->sk_state != BT_CLOSED && !s->initiator)
+ if (s->sock->sk->sk_state != BT_CLOSED)
if (list_empty(&s->dlcs))
rfcomm_session_put(s);
break;
@@ -1864,10 +1855,7 @@ static inline void rfcomm_process_rx(struct rfcomm_session *s)
/* Get data directly from socket receive queue without copying it. */
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
skb_orphan(skb);
- if (!skb_linearize(skb))
- rfcomm_recv_frame(s, skb);
- else
- kfree_skb(skb);
+ rfcomm_recv_frame(s, skb);
}
if (sk->sk_state == BT_CLOSED) {
@@ -2050,18 +2038,19 @@ static int rfcomm_run(void *unused)
rfcomm_add_listener(BDADDR_ANY);
- while (1) {
+ while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
-
- if (kthread_should_stop())
- break;
+ if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
+ /* No pending events. Let's sleep.
+ * Incoming connections and data will wake us up. */
+ schedule();
+ }
+ set_current_state(TASK_RUNNING);
/* Process stuff */
+ clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
rfcomm_process_sessions();
-
- schedule();
}
- __set_current_state(TASK_RUNNING);
rfcomm_kill_listener();