Bluetooth: Fix bug in l2cap_ertm_send() behavior
[pandora-kernel.git] / net / bluetooth / l2cap.c
index 1b682a5..69f098d 100644 (file)
 
 #define VERSION "2.14"
 
-#ifdef CONFIG_BT_L2CAP_EXT_FEATURES
-static int enable_ertm = 1;
-#else
 static int enable_ertm = 0;
-#endif
-static int max_transmit = L2CAP_DEFAULT_MAX_TX;
-static int tx_window = L2CAP_DEFAULT_TX_WINDOW;
 
 static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
 static u8 l2cap_fixed_chan[8] = { 0x02, };
@@ -401,6 +395,11 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
        l2cap_send_sframe(pi, control);
 }
 
+static inline int __l2cap_no_conn_pending(struct sock *sk)
+{
+       return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
+}
+
 static void l2cap_do_start(struct sock *sk)
 {
        struct l2cap_conn *conn = l2cap_pi(sk)->conn;
@@ -409,12 +408,13 @@ static void l2cap_do_start(struct sock *sk)
                if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
                        return;
 
-               if (l2cap_check_security(sk)) {
+               if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
                        struct l2cap_conn_req req;
                        req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                        req.psm  = l2cap_pi(sk)->psm;
 
                        l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                       l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
                        l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
@@ -464,12 +464,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                }
 
                if (sk->sk_state == BT_CONNECT) {
-                       if (l2cap_check_security(sk)) {
+                       if (l2cap_check_security(sk) &&
+                                       __l2cap_no_conn_pending(sk)) {
                                struct l2cap_conn_req req;
                                req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                                req.psm  = l2cap_pi(sk)->psm;
 
                                l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                               l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
                                l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
@@ -808,9 +810,9 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
                        pi->mode = L2CAP_MODE_ERTM;
                else
                        pi->mode = L2CAP_MODE_BASIC;
-               pi->max_tx = max_transmit;
+               pi->max_tx = L2CAP_DEFAULT_MAX_TX;
                pi->fcs  = L2CAP_FCS_CRC16;
-               pi->tx_win = tx_window;
+               pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
                pi->sec_level = BT_SECURITY_LOW;
                pi->role_switch = 0;
                pi->force_reliable = 0;
@@ -1413,11 +1415,8 @@ static int l2cap_ertm_send(struct sock *sk)
        u16 control, fcs;
        int nsent = 0;
 
-       if (pi->conn_state & L2CAP_CONN_WAIT_F)
-               return 0;
 
-       while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) &&
-                       !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) {
+       while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
 
                if (pi->remote_max_tx &&
                                bt_cb(skb)->retries == pi->remote_max_tx) {
@@ -1790,6 +1789,11 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
                if (pi->mode == L2CAP_MODE_STREAMING) {
                        err = l2cap_streaming_send(sk);
                } else {
+                       if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY &&
+                                       pi->conn_state && L2CAP_CONN_WAIT_F) {
+                               err = len;
+                               break;
+                       }
                        spin_lock_bh(&pi->send_lock);
                        err = l2cap_ertm_send(sk);
                        spin_unlock_bh(&pi->send_lock);
@@ -2912,7 +2916,6 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
                l2cap_pi(sk)->ident = 0;
                l2cap_pi(sk)->dcid = dcid;
                l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-
                l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
 
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
@@ -3377,8 +3380,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
        if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
                __mod_retrans_timer();
 
-       pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-
        spin_lock_bh(&pi->send_lock);
        l2cap_ertm_send(sk);
        spin_unlock_bh(&pi->send_lock);
@@ -3747,7 +3748,7 @@ static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
                l2cap_ertm_reassembly_sdu(sk, skb, control);
                l2cap_pi(sk)->buffer_seq_srej =
                        (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
-               tx_seq++;
+               tx_seq = (tx_seq + 1) % 64;
        }
 }
 
@@ -3783,10 +3784,11 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
                l2cap_send_sframe(pi, control);
 
                new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
-               new->tx_seq = pi->expected_tx_seq++;
+               new->tx_seq = pi->expected_tx_seq;
+               pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
                list_add_tail(&new->list, SREJ_LIST(sk));
        }
-       pi->expected_tx_seq++;
+       pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
 }
 
 static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
@@ -3795,7 +3797,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
        u8 tx_seq = __get_txseq(rx_control);
        u8 req_seq = __get_reqseq(rx_control);
        u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
-       u8 tx_seq_offset, expected_tx_seq_offset;
+       int tx_seq_offset, expected_tx_seq_offset;
        int num_to_ack = (pi->tx_win/6) + 1;
        int err = 0;
 
@@ -4080,7 +4082,8 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
        struct sock *sk;
        struct l2cap_pinfo *pi;
        u16 control, len;
-       u8 tx_seq, req_seq, next_tx_seq_offset, req_seq_offset;
+       u8 tx_seq, req_seq;
+       int next_tx_seq_offset, req_seq_offset;
 
        sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
        if (!sk) {
@@ -4114,7 +4117,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
                skb_pull(skb, 2);
                len = skb->len;
 
-               if (__is_sar_start(control))
+               if (__is_sar_start(control) && __is_iframe(control))
                        len -= 2;
 
                if (pi->fcs == L2CAP_FCS_CRC16)
@@ -4404,6 +4407,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                                req.psm  = l2cap_pi(sk)->psm;
 
                                l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                               l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
                                l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
@@ -4674,12 +4678,6 @@ module_exit(l2cap_exit);
 module_param(enable_ertm, bool, 0644);
 MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode");
 
-module_param(max_transmit, uint, 0644);
-MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)");
-
-module_param(tx_window, uint, 0644);
-MODULE_PARM_DESC(tx_window, "Transmission window size value (default = 63)");
-
 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
 MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
 MODULE_VERSION(VERSION);