diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-12-03 13:46:03 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-12-03 13:46:03 -0500 |
commit | 06ef5c4bbb9816e7a7eb44917f11c2e3375fb51a (patch) | |
tree | cac94ec09e789a6e5162d1925ee944075bf6eef6 /net/bluetooth/l2cap_core.c | |
parent | 55cec505559dade9e7776de8f3d23fc3e54e091d (diff) | |
parent | 0b27a4b97cb1874503c78453c0903df53c0c86b2 (diff) |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 100 |
1 files changed, 51 insertions, 49 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b52f66d22437..2c78208d793e 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -53,8 +53,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); -static void l2cap_send_disconn_req(struct l2cap_conn *conn, - struct l2cap_chan *chan, int err); +static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, struct sk_buff_head *skbs, u8 event); @@ -632,7 +631,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && conn->hcon->type == ACL_LINK) { __set_chan_timer(chan, sk->sk_sndtimeo); - l2cap_send_disconn_req(conn, chan, reason); + l2cap_send_disconn_req(chan, reason); } else l2cap_chan_del(chan, reason); break; @@ -1014,6 +1013,7 @@ static bool __amp_capable(struct l2cap_chan *chan) struct l2cap_conn *conn = chan->conn; if (enable_hs && + hci_amp_capable() && chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED && conn->fixed_chan_mask & L2CAP_FC_A2MP) return true; @@ -1180,10 +1180,10 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) } } -static void l2cap_send_disconn_req(struct l2cap_conn *conn, - struct l2cap_chan *chan, int err) +static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) { struct sock *sk = chan->sk; + struct l2cap_conn *conn = chan->conn; struct l2cap_disconn_req req; if (!conn) @@ -1960,7 +1960,7 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) if (chan->max_tx != 0 && bt_cb(skb)->control.retries > chan->max_tx) { BT_DBG("Retry limit exceeded (%d)", chan->max_tx); - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); l2cap_seq_list_clear(&chan->retrans_list); break; } @@ -2666,7 +2666,7 @@ static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, __set_monitor_timer(chan); chan->retry_count++; } else { - l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); + l2cap_send_disconn_req(chan, ECONNABORTED); } break; default: @@ -3106,18 +3106,17 @@ done: if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) l2cap_add_opt_efs(&ptr, chan); - if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) - break; - - if (chan->fcs == L2CAP_FCS_NONE || - test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { - chan->fcs = L2CAP_FCS_NONE; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); - } - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, chan->tx_win); + + if (chan->conn->feat_mask & L2CAP_FEAT_FCS) + if (chan->fcs == L2CAP_FCS_NONE || + test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { + chan->fcs = L2CAP_FCS_NONE; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, + chan->fcs); + } break; case L2CAP_MODE_STREAMING: @@ -3139,14 +3138,13 @@ done: if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) l2cap_add_opt_efs(&ptr, chan); - if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) - break; - - if (chan->fcs == L2CAP_FCS_NONE || - test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { - chan->fcs = L2CAP_FCS_NONE; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); - } + if (chan->conn->feat_mask & L2CAP_FEAT_FCS) + if (chan->fcs == L2CAP_FCS_NONE || + test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { + chan->fcs = L2CAP_FCS_NONE; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, + chan->fcs); + } break; } @@ -3198,7 +3196,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) case L2CAP_CONF_FCS: if (val == L2CAP_FCS_NONE) - set_bit(CONF_NO_FCS_RECV, &chan->conf_state); + set_bit(CONF_RECV_NO_FCS, &chan->conf_state); break; case L2CAP_CONF_EFS: @@ -3433,6 +3431,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), (unsigned long) &efs); break; + + case L2CAP_CONF_FCS: + if (*result == L2CAP_CONF_PENDING) + if (val == L2CAP_FCS_NONE) + set_bit(CONF_RECV_NO_FCS, + &chan->conf_state); + break; } } @@ -3802,7 +3807,7 @@ static inline void set_default_fcs(struct l2cap_chan *chan) */ if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) chan->fcs = L2CAP_FCS_NONE; - else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) + else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) chan->fcs = L2CAP_FCS_CRC16; } @@ -3877,7 +3882,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, /* Complete config. */ len = l2cap_parse_conf_req(chan, rsp); if (len < 0) { - l2cap_send_disconn_req(conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); goto unlock; } @@ -3899,7 +3904,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, err = l2cap_ertm_init(chan); if (err < 0) - l2cap_send_disconn_req(chan->conn, chan, -err); + l2cap_send_disconn_req(chan, -err); else l2cap_chan_ready(chan); @@ -3967,7 +3972,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, len = l2cap_parse_conf_rsp(chan, rsp->data, len, buf, &result); if (len < 0) { - l2cap_send_disconn_req(conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); goto done; } @@ -3988,7 +3993,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, char req[64]; if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { - l2cap_send_disconn_req(conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); goto done; } @@ -3997,7 +4002,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, len = l2cap_parse_conf_rsp(chan, rsp->data, len, req, &result); if (len < 0) { - l2cap_send_disconn_req(conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); goto done; } @@ -4013,7 +4018,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, l2cap_chan_set_err(chan, ECONNRESET); __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); - l2cap_send_disconn_req(conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); goto done; } @@ -4030,7 +4035,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, err = l2cap_ertm_init(chan); if (err < 0) - l2cap_send_disconn_req(chan->conn, chan, -err); + l2cap_send_disconn_req(chan, -err); else l2cap_chan_ready(chan); } @@ -4392,7 +4397,7 @@ static void l2cap_logical_fail(struct l2cap_chan *chan) /* Logical link setup failed */ if (chan->state != BT_CONNECTED) { /* Create channel failure, disconnect */ - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); return; } @@ -4435,7 +4440,7 @@ static void l2cap_logical_finish_create(struct l2cap_chan *chan, err = l2cap_ertm_init(chan); if (err < 0) - l2cap_send_disconn_req(chan->conn, chan, -err); + l2cap_send_disconn_req(chan, -err); else l2cap_chan_ready(chan); } @@ -5400,7 +5405,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan, if (control->reqseq == chan->next_tx_seq) { BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); return; } @@ -5414,7 +5419,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan, if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { BT_DBG("Retry limit exceeded (%d)", chan->max_tx); - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); return; } @@ -5458,7 +5463,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan, if (control->reqseq == chan->next_tx_seq) { BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); return; } @@ -5467,7 +5472,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan, if (chan->max_tx && skb && bt_cb(skb)->control.retries >= chan->max_tx) { BT_DBG("Retry limit exceeded (%d)", chan->max_tx); - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); return; } @@ -5651,8 +5656,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan, break; case L2CAP_TXSEQ_INVALID: default: - l2cap_send_disconn_req(chan->conn, chan, - ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); break; } break; @@ -5785,8 +5789,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, break; case L2CAP_TXSEQ_INVALID: default: - l2cap_send_disconn_req(chan->conn, chan, - ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); break; } break; @@ -5981,7 +5984,7 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", control->reqseq, chan->next_tx_seq, chan->expected_ack_seq); - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); } return err; @@ -6050,7 +6053,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) len -= L2CAP_FCS_SIZE; if (len > chan->mps) { - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); goto drop; } @@ -6075,8 +6078,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) } if (err) - l2cap_send_disconn_req(chan->conn, chan, - ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); } else { const u8 rx_func_to_event[4] = { L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, @@ -6093,7 +6095,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) if (len != 0) { BT_ERR("Trailing bytes: %d in sframe", len); - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); goto drop; } @@ -6104,7 +6106,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) event = rx_func_to_event[control->super]; if (l2cap_rx(chan, control, skb, event)) - l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan, ECONNRESET); } return 0; |