aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-12-02 03:09:26 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-12-02 03:26:50 -0500
commit0bd49fc75aab94a7bf3cd2f7c70e03b600635c65 (patch)
tree54ed21b90f1c0921ff545fd9e4259cbcad4a09c6
parentf6af675ef5489c69fc3d4faf8c6f477df3cbf8b9 (diff)
Bluetooth: Track both local and remote L2CAP fixed channel mask
To pave the way for future fixed channels to be added easily we should track both the local and remote mask on a per-L2CAP connection (struct l2cap_conn) basis. So far the code has used a global variable in a racy way which anyway needs fixing. This patch renames the existing conn->fixed_chan_mask that tracked the remote mask to conn->remote_fixed_chan and adds a new variable conn->local_fixed_chan to track the local mask. Since the HS support info is now available in the local mask we can remove the conn->hs_enabled variable. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/l2cap.h4
-rw-r--r--net/bluetooth/l2cap_core.c37
2 files changed, 20 insertions, 21 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 061e648052c8..d71dc3579354 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -619,8 +619,8 @@ struct l2cap_conn {
619 unsigned int mtu; 619 unsigned int mtu;
620 620
621 __u32 feat_mask; 621 __u32 feat_mask;
622 __u8 fixed_chan_mask; 622 __u8 remote_fixed_chan;
623 bool hs_enabled; 623 __u8 local_fixed_chan;
624 624
625 __u8 info_state; 625 __u8 info_state;
626 __u8 info_ident; 626 __u8 info_ident;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index c2d1489c228c..43349ed4c249 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -46,7 +46,6 @@
46bool disable_ertm; 46bool disable_ertm;
47 47
48static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; 48static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
49static u8 l2cap_fixed_chan[8] = { L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS, };
50 49
51static LIST_HEAD(chan_list); 50static LIST_HEAD(chan_list);
52static DEFINE_RWLOCK(chan_list_lock); 51static DEFINE_RWLOCK(chan_list_lock);
@@ -1120,10 +1119,10 @@ static bool __amp_capable(struct l2cap_chan *chan)
1120 struct hci_dev *hdev; 1119 struct hci_dev *hdev;
1121 bool amp_available = false; 1120 bool amp_available = false;
1122 1121
1123 if (!conn->hs_enabled) 1122 if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
1124 return false; 1123 return false;
1125 1124
1126 if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) 1125 if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
1127 return false; 1126 return false;
1128 1127
1129 read_lock(&hci_dev_list_lock); 1128 read_lock(&hci_dev_list_lock);
@@ -3096,12 +3095,14 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
3096 3095
3097static inline bool __l2cap_ews_supported(struct l2cap_conn *conn) 3096static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
3098{ 3097{
3099 return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; 3098 return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
3099 (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
3100} 3100}
3101 3101
3102static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) 3102static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3103{ 3103{
3104 return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW; 3104 return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
3105 (conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
3105} 3106}
3106 3107
3107static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, 3108static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
@@ -3330,7 +3331,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
3330 break; 3331 break;
3331 3332
3332 case L2CAP_CONF_EWS: 3333 case L2CAP_CONF_EWS:
3333 if (!chan->conn->hs_enabled) 3334 if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
3334 return -ECONNREFUSED; 3335 return -ECONNREFUSED;
3335 3336
3336 set_bit(FLAG_EXT_CTRL, &chan->flags); 3337 set_bit(FLAG_EXT_CTRL, &chan->flags);
@@ -4334,7 +4335,7 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
4334 if (!disable_ertm) 4335 if (!disable_ertm)
4335 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING 4336 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
4336 | L2CAP_FEAT_FCS; 4337 | L2CAP_FEAT_FCS;
4337 if (conn->hs_enabled) 4338 if (conn->local_fixed_chan & L2CAP_FC_A2MP)
4338 feat_mask |= L2CAP_FEAT_EXT_FLOW 4339 feat_mask |= L2CAP_FEAT_EXT_FLOW
4339 | L2CAP_FEAT_EXT_WINDOW; 4340 | L2CAP_FEAT_EXT_WINDOW;
4340 4341
@@ -4345,14 +4346,10 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
4345 u8 buf[12]; 4346 u8 buf[12];
4346 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; 4347 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4347 4348
4348 if (conn->hs_enabled)
4349 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
4350 else
4351 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
4352
4353 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); 4349 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4354 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); 4350 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
4355 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); 4351 rsp->data[0] = conn->local_fixed_chan;
4352 memset(rsp->data + 1, 0, 7);
4356 l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), 4353 l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
4357 buf); 4354 buf);
4358 } else { 4355 } else {
@@ -4418,7 +4415,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4418 break; 4415 break;
4419 4416
4420 case L2CAP_IT_FIXED_CHAN: 4417 case L2CAP_IT_FIXED_CHAN:
4421 conn->fixed_chan_mask = rsp->data[0]; 4418 conn->remote_fixed_chan = rsp->data[0];
4422 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 4419 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
4423 conn->info_ident = 0; 4420 conn->info_ident = 0;
4424 4421
@@ -4442,7 +4439,7 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
4442 if (cmd_len != sizeof(*req)) 4439 if (cmd_len != sizeof(*req))
4443 return -EPROTO; 4440 return -EPROTO;
4444 4441
4445 if (!conn->hs_enabled) 4442 if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
4446 return -EINVAL; 4443 return -EINVAL;
4447 4444
4448 psm = le16_to_cpu(req->psm); 4445 psm = le16_to_cpu(req->psm);
@@ -4872,7 +4869,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
4872 4869
4873 BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); 4870 BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
4874 4871
4875 if (!conn->hs_enabled) 4872 if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
4876 return -EINVAL; 4873 return -EINVAL;
4877 4874
4878 chan = l2cap_get_chan_by_dcid(conn, icid); 4875 chan = l2cap_get_chan_by_dcid(conn, icid);
@@ -6964,9 +6961,11 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
6964 6961
6965 conn->feat_mask = 0; 6962 conn->feat_mask = 0;
6966 6963
6967 if (hcon->type == ACL_LINK) 6964 conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
6968 conn->hs_enabled = test_bit(HCI_HS_ENABLED, 6965
6969 &hcon->hdev->dev_flags); 6966 if (hcon->type == ACL_LINK &&
6967 test_bit(HCI_HS_ENABLED, &hcon->hdev->dev_flags))
6968 conn->local_fixed_chan |= L2CAP_FC_A2MP;
6970 6969
6971 mutex_init(&conn->ident_lock); 6970 mutex_init(&conn->ident_lock);
6972 mutex_init(&conn->chan_lock); 6971 mutex_init(&conn->chan_lock);