Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142
Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index c2486a5..6dac31f 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -62,6 +62,7 @@
#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 @@
{
if (!rfcomm_thread)
return;
+ set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
wake_up_process(rfcomm_thread);
}
@@ -230,8 +232,6 @@
static inline int rfcomm_check_security(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
- struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
-
__u8 auth_type;
switch (d->sec_level) {
@@ -246,7 +246,8 @@
break;
}
- return hci_conn_security(conn->hcon, d->sec_level, auth_type);
+ return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level,
+ auth_type);
}
static void rfcomm_session_timeout(unsigned long arg)
@@ -708,10 +709,10 @@
/* Set L2CAP options */
sk = sock->sk;
lock_sock(sk);
- l2cap_pi(sk)->chan->imtu = l2cap_mtu;
- l2cap_pi(sk)->chan->sec_level = sec_level;
+ l2cap_pi(sk)->imtu = l2cap_mtu;
+ l2cap_pi(sk)->sec_level = sec_level;
if (l2cap_ertm)
- l2cap_pi(sk)->chan->mode = L2CAP_MODE_ERTM;
+ l2cap_pi(sk)->mode = L2CAP_MODE_ERTM;
release_sock(sk);
s = rfcomm_session_add(sock, BT_BOUND);
@@ -1239,7 +1240,6 @@
void rfcomm_dlc_accept(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
- struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
BT_DBG("dlc %p", d);
@@ -1253,7 +1253,7 @@
rfcomm_dlc_unlock(d);
if (d->role_switch)
- hci_conn_switch_role(conn->hcon, 0x00);
+ hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00);
rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
}
@@ -1852,7 +1852,10 @@
/* Get data directly from socket receive queue without copying it. */
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
skb_orphan(skb);
- rfcomm_recv_frame(s, skb);
+ if (!skb_linearize(skb))
+ rfcomm_recv_frame(s, skb);
+ else
+ kfree_skb(skb);
}
if (sk->sk_state == BT_CLOSED) {
@@ -1889,8 +1892,7 @@
/* We should adjust MTU on incoming sessions.
* L2CAP MTU minus UIH header and FCS. */
- s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu,
- l2cap_pi(nsock->sk)->chan->imtu) - 5;
+ s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5;
rfcomm_schedule();
} else
@@ -1909,7 +1911,7 @@
/* We can adjust MTU on outgoing sessions.
* L2CAP MTU minus UIH header and FCS. */
- s->mtu = min(l2cap_pi(sk)->chan->omtu, l2cap_pi(sk)->chan->imtu) - 5;
+ s->mtu = min(l2cap_pi(sk)->omtu, l2cap_pi(sk)->imtu) - 5;
rfcomm_send_sabm(s, 0);
break;
@@ -1992,7 +1994,7 @@
/* Set L2CAP options */
sk = sock->sk;
lock_sock(sk);
- l2cap_pi(sk)->chan->imtu = l2cap_mtu;
+ l2cap_pi(sk)->imtu = l2cap_mtu;
release_sock(sk);
/* Start listening on the socket */
@@ -2035,18 +2037,19 @@
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();
@@ -2092,7 +2095,7 @@
if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
continue;
- if (!status && hci_conn_check_secure(conn, d->sec_level))
+ if (!status)
set_bit(RFCOMM_AUTH_ACCEPT, &d->flags);
else
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index b02f0d4..66cc1f0 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -485,6 +485,11 @@
lock_sock(sk);
+ if (sk->sk_state != BT_LISTEN) {
+ err = -EBADFD;
+ goto done;
+ }
+
if (sk->sk_type != SOCK_STREAM) {
err = -EINVAL;
goto done;
@@ -496,20 +501,19 @@
/* Wait for an incoming connection. (wake-one). */
add_wait_queue_exclusive(sk_sleep(sk), &wait);
- while (1) {
+ while (!(nsk = bt_accept_dequeue(sk, newsock))) {
set_current_state(TASK_INTERRUPTIBLE);
-
- if (sk->sk_state != BT_LISTEN) {
- err = -EBADFD;
+ if (!timeo) {
+ err = -EAGAIN;
break;
}
- nsk = bt_accept_dequeue(sk, newsock);
- if (nsk)
- break;
+ release_sock(sk);
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
- if (!timeo) {
- err = -EAGAIN;
+ if (sk->sk_state != BT_LISTEN) {
+ err = -EBADFD;
break;
}
@@ -517,12 +521,8 @@
err = sock_intr_errno(timeo);
break;
}
-
- release_sock(sk);
- timeo = schedule_timeout(timeo);
- lock_sock(sk);
}
- __set_current_state(TASK_RUNNING);
+ set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
if (err)
@@ -679,8 +679,7 @@
{
struct sock *sk = sock->sk;
struct bt_security sec;
- int err = 0;
- size_t len;
+ int len, err = 0;
u32 opt;
BT_DBG("sk %p", sk);
@@ -742,8 +741,8 @@
static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
+ struct sock *l2cap_sk;
struct rfcomm_conninfo cinfo;
- struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
int len, err = 0;
u32 opt;
@@ -786,10 +785,10 @@
break;
}
+ l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.hci_handle = conn->hcon->handle;
- memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
+ cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle;
+ memcpy(cinfo.dev_class, l2cap_pi(l2cap_sk)->conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
if (copy_to_user(optval, (char *) &cinfo, len))