diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 1 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 59 |
2 files changed, 35 insertions, 25 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index e5164ff55f27..a7679f8913d2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -464,6 +464,7 @@ struct l2cap_chan { | |||
464 | 464 | ||
465 | __u16 tx_win; | 465 | __u16 tx_win; |
466 | __u16 tx_win_max; | 466 | __u16 tx_win_max; |
467 | __u16 ack_win; | ||
467 | __u8 max_tx; | 468 | __u8 max_tx; |
468 | __u16 retrans_timeout; | 469 | __u16 retrans_timeout; |
469 | __u16 monitor_timeout; | 470 | __u16 monitor_timeout; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9fd05993f5b4..a8964db04bfb 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -431,6 +431,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan) | |||
431 | chan->max_tx = L2CAP_DEFAULT_MAX_TX; | 431 | chan->max_tx = L2CAP_DEFAULT_MAX_TX; |
432 | chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; | 432 | chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; |
433 | chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; | 433 | chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; |
434 | chan->ack_win = L2CAP_DEFAULT_TX_WINDOW; | ||
434 | chan->sec_level = BT_SECURITY_LOW; | 435 | chan->sec_level = BT_SECURITY_LOW; |
435 | 436 | ||
436 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); | 437 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); |
@@ -1877,10 +1878,10 @@ static void l2cap_send_ack(struct l2cap_chan *chan) | |||
1877 | frames_to_ack = 0; | 1878 | frames_to_ack = 0; |
1878 | } | 1879 | } |
1879 | 1880 | ||
1880 | /* Ack now if the tx window is 3/4ths full. | 1881 | /* Ack now if the window is 3/4ths full. |
1881 | * Calculate without mul or div | 1882 | * Calculate without mul or div |
1882 | */ | 1883 | */ |
1883 | threshold = chan->tx_win; | 1884 | threshold = chan->ack_win; |
1884 | threshold += threshold << 1; | 1885 | threshold += threshold << 1; |
1885 | threshold >>= 2; | 1886 | threshold >>= 2; |
1886 | 1887 | ||
@@ -2786,6 +2787,7 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan) | |||
2786 | L2CAP_DEFAULT_TX_WINDOW); | 2787 | L2CAP_DEFAULT_TX_WINDOW); |
2787 | chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; | 2788 | chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; |
2788 | } | 2789 | } |
2790 | chan->ack_win = chan->tx_win; | ||
2789 | } | 2791 | } |
2790 | 2792 | ||
2791 | static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) | 2793 | static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) |
@@ -3175,10 +3177,9 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi | |||
3175 | break; | 3177 | break; |
3176 | 3178 | ||
3177 | case L2CAP_CONF_EWS: | 3179 | case L2CAP_CONF_EWS: |
3178 | chan->tx_win = min_t(u16, val, | 3180 | chan->ack_win = min_t(u16, val, chan->ack_win); |
3179 | L2CAP_DEFAULT_EXT_WINDOW); | ||
3180 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, | 3181 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, |
3181 | chan->tx_win); | 3182 | chan->tx_win); |
3182 | break; | 3183 | break; |
3183 | 3184 | ||
3184 | case L2CAP_CONF_EFS: | 3185 | case L2CAP_CONF_EFS: |
@@ -3207,6 +3208,9 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi | |||
3207 | chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); | 3208 | chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); |
3208 | chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); | 3209 | chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); |
3209 | chan->mps = le16_to_cpu(rfc.max_pdu_size); | 3210 | chan->mps = le16_to_cpu(rfc.max_pdu_size); |
3211 | if (!test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
3212 | chan->ack_win = min_t(u16, chan->ack_win, | ||
3213 | rfc.txwin_size); | ||
3210 | 3214 | ||
3211 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { | 3215 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { |
3212 | chan->local_msdu = le16_to_cpu(efs.msdu); | 3216 | chan->local_msdu = le16_to_cpu(efs.msdu); |
@@ -3268,7 +3272,17 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) | |||
3268 | { | 3272 | { |
3269 | int type, olen; | 3273 | int type, olen; |
3270 | unsigned long val; | 3274 | unsigned long val; |
3271 | struct l2cap_conf_rfc rfc; | 3275 | /* Use sane default values in case a misbehaving remote device |
3276 | * did not send an RFC or extended window size option. | ||
3277 | */ | ||
3278 | u16 txwin_ext = chan->ack_win; | ||
3279 | struct l2cap_conf_rfc rfc = { | ||
3280 | .mode = chan->mode, | ||
3281 | .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), | ||
3282 | .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), | ||
3283 | .max_pdu_size = cpu_to_le16(chan->imtu), | ||
3284 | .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), | ||
3285 | }; | ||
3272 | 3286 | ||
3273 | BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); | 3287 | BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); |
3274 | 3288 | ||
@@ -3278,32 +3292,27 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) | |||
3278 | while (len >= L2CAP_CONF_OPT_SIZE) { | 3292 | while (len >= L2CAP_CONF_OPT_SIZE) { |
3279 | len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); | 3293 | len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); |
3280 | 3294 | ||
3281 | if (type != L2CAP_CONF_RFC) | 3295 | switch (type) { |
3282 | continue; | 3296 | case L2CAP_CONF_RFC: |
3283 | 3297 | if (olen == sizeof(rfc)) | |
3284 | if (olen != sizeof(rfc)) | 3298 | memcpy(&rfc, (void *)val, olen); |
3285 | break; | 3299 | break; |
3286 | 3300 | case L2CAP_CONF_EWS: | |
3287 | memcpy(&rfc, (void *)val, olen); | 3301 | txwin_ext = val; |
3288 | goto done; | 3302 | break; |
3303 | } | ||
3289 | } | 3304 | } |
3290 | 3305 | ||
3291 | /* Use sane default values in case a misbehaving remote device | ||
3292 | * did not send an RFC option. | ||
3293 | */ | ||
3294 | rfc.mode = chan->mode; | ||
3295 | rfc.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); | ||
3296 | rfc.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); | ||
3297 | rfc.max_pdu_size = cpu_to_le16(chan->imtu); | ||
3298 | |||
3299 | BT_ERR("Expected RFC option was not found, using defaults"); | ||
3300 | |||
3301 | done: | ||
3302 | switch (rfc.mode) { | 3306 | switch (rfc.mode) { |
3303 | case L2CAP_MODE_ERTM: | 3307 | case L2CAP_MODE_ERTM: |
3304 | chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); | 3308 | chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); |
3305 | chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); | 3309 | chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); |
3306 | chan->mps = le16_to_cpu(rfc.max_pdu_size); | 3310 | chan->mps = le16_to_cpu(rfc.max_pdu_size); |
3311 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
3312 | chan->ack_win = min_t(u16, chan->ack_win, txwin_ext); | ||
3313 | else | ||
3314 | chan->ack_win = min_t(u16, chan->ack_win, | ||
3315 | rfc.txwin_size); | ||
3307 | break; | 3316 | break; |
3308 | case L2CAP_MODE_STREAMING: | 3317 | case L2CAP_MODE_STREAMING: |
3309 | chan->mps = le16_to_cpu(rfc.max_pdu_size); | 3318 | chan->mps = le16_to_cpu(rfc.max_pdu_size); |