diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-10-04 14:06:47 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-10-04 14:06:47 -0400 |
commit | d6222fb0d669307a49e2a96aad86c156a9bb9551 (patch) | |
tree | 99c821e5823999b99e7fd49fb840d18cbb89b238 | |
parent | 76ed94be65c8bd80b565865c186dd9f24bb2f23b (diff) | |
parent | c510eae377c773241ff0b6369a8f3581da941a51 (diff) |
Merge branch 'master' of git://github.com/padovan/bluetooth-next
-rw-r--r-- | drivers/bluetooth/btusb.c | 6 | ||||
-rw-r--r-- | include/net/bluetooth/l2cap.h | 3 | ||||
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 30 | ||||
-rw-r--r-- | net/bluetooth/bnep/core.c | 5 | ||||
-rw-r--r-- | net/bluetooth/cmtp/core.c | 5 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 14 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 20 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 10 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 255 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 5 |
10 files changed, 157 insertions, 196 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9cbac6b445e1..675246a6f7ef 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[] = { | |||
60 | /* Generic Bluetooth USB device */ | 60 | /* Generic Bluetooth USB device */ |
61 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, | 61 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, |
62 | 62 | ||
63 | /* Broadcom SoftSailing reporting vendor specific */ | ||
64 | { USB_DEVICE(0x05ac, 0x21e1) }, | ||
65 | |||
63 | /* Apple MacBookPro 7,1 */ | 66 | /* Apple MacBookPro 7,1 */ |
64 | { USB_DEVICE(0x05ac, 0x8213) }, | 67 | { USB_DEVICE(0x05ac, 0x8213) }, |
65 | 68 | ||
@@ -708,8 +711,7 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
708 | break; | 711 | break; |
709 | 712 | ||
710 | case HCI_ACLDATA_PKT: | 713 | case HCI_ACLDATA_PKT: |
711 | if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 && | 714 | if (!data->bulk_tx_ep) |
712 | hdev->conn_hash.le_num < 1)) | ||
713 | return -ENODEV; | 715 | return -ENODEV; |
714 | 716 | ||
715 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 717 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7f878b9d5642..ab90ae0970a6 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -354,8 +354,8 @@ struct l2cap_chan { | |||
354 | __u8 retry_count; | 354 | __u8 retry_count; |
355 | __u8 num_acked; | 355 | __u8 num_acked; |
356 | __u16 sdu_len; | 356 | __u16 sdu_len; |
357 | __u16 partial_sdu_len; | ||
358 | struct sk_buff *sdu; | 357 | struct sk_buff *sdu; |
358 | struct sk_buff *sdu_last_frag; | ||
359 | 359 | ||
360 | __u8 remote_tx_win; | 360 | __u8 remote_tx_win; |
361 | __u8 remote_max_tx; | 361 | __u8 remote_max_tx; |
@@ -448,7 +448,6 @@ enum { | |||
448 | #define L2CAP_CONF_MAX_CONF_RSP 2 | 448 | #define L2CAP_CONF_MAX_CONF_RSP 2 |
449 | 449 | ||
450 | enum { | 450 | enum { |
451 | CONN_SAR_SDU, | ||
452 | CONN_SREJ_SENT, | 451 | CONN_SREJ_SENT, |
453 | CONN_WAIT_F, | 452 | CONN_WAIT_F, |
454 | CONN_SREJ_ACT, | 453 | CONN_SREJ_ACT, |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 117e0d161780..062124cd89cf 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -349,7 +349,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
349 | } | 349 | } |
350 | 350 | ||
351 | chunk = min_t(unsigned int, skb->len, size); | 351 | chunk = min_t(unsigned int, skb->len, size); |
352 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { | 352 | if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) { |
353 | skb_queue_head(&sk->sk_receive_queue, skb); | 353 | skb_queue_head(&sk->sk_receive_queue, skb); |
354 | if (!copied) | 354 | if (!copied) |
355 | copied = -EFAULT; | 355 | copied = -EFAULT; |
@@ -361,7 +361,33 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
361 | sock_recv_ts_and_drops(msg, sk, skb); | 361 | sock_recv_ts_and_drops(msg, sk, skb); |
362 | 362 | ||
363 | if (!(flags & MSG_PEEK)) { | 363 | if (!(flags & MSG_PEEK)) { |
364 | skb_pull(skb, chunk); | 364 | int skb_len = skb_headlen(skb); |
365 | |||
366 | if (chunk <= skb_len) { | ||
367 | __skb_pull(skb, chunk); | ||
368 | } else { | ||
369 | struct sk_buff *frag; | ||
370 | |||
371 | __skb_pull(skb, skb_len); | ||
372 | chunk -= skb_len; | ||
373 | |||
374 | skb_walk_frags(skb, frag) { | ||
375 | if (chunk <= frag->len) { | ||
376 | /* Pulling partial data */ | ||
377 | skb->len -= chunk; | ||
378 | skb->data_len -= chunk; | ||
379 | __skb_pull(frag, chunk); | ||
380 | break; | ||
381 | } else if (frag->len) { | ||
382 | /* Pulling all frag data */ | ||
383 | chunk -= frag->len; | ||
384 | skb->len -= frag->len; | ||
385 | skb->data_len -= frag->len; | ||
386 | __skb_pull(frag, frag->len); | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | |||
365 | if (skb->len) { | 391 | if (skb->len) { |
366 | skb_queue_head(&sk->sk_receive_queue, skb); | 392 | skb_queue_head(&sk->sk_receive_queue, skb); |
367 | break; | 393 | break; |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index d9edfe8bf9d6..91bcd3a961ec 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -492,7 +492,10 @@ static int bnep_session(void *arg) | |||
492 | /* RX */ | 492 | /* RX */ |
493 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 493 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { |
494 | skb_orphan(skb); | 494 | skb_orphan(skb); |
495 | bnep_rx_frame(s, skb); | 495 | if (!skb_linearize(skb)) |
496 | bnep_rx_frame(s, skb); | ||
497 | else | ||
498 | kfree_skb(skb); | ||
496 | } | 499 | } |
497 | 500 | ||
498 | if (sk->sk_state != BT_CONNECTED) | 501 | if (sk->sk_state != BT_CONNECTED) |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 521baa4fe835..7d00ddf9e9dc 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
@@ -302,7 +302,10 @@ static int cmtp_session(void *arg) | |||
302 | 302 | ||
303 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 303 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { |
304 | skb_orphan(skb); | 304 | skb_orphan(skb); |
305 | cmtp_recv_frame(session, skb); | 305 | if (!skb_linearize(skb)) |
306 | cmtp_recv_frame(session, skb); | ||
307 | else | ||
308 | kfree_skb(skb); | ||
306 | } | 309 | } |
307 | 310 | ||
308 | cmtp_process_transmit(session); | 311 | cmtp_process_transmit(session); |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index c2df7bf1d374..c1c597e3e198 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -56,15 +56,15 @@ static void hci_le_connect(struct hci_conn *conn) | |||
56 | conn->sec_level = BT_SECURITY_LOW; | 56 | conn->sec_level = BT_SECURITY_LOW; |
57 | 57 | ||
58 | memset(&cp, 0, sizeof(cp)); | 58 | memset(&cp, 0, sizeof(cp)); |
59 | cp.scan_interval = cpu_to_le16(0x0004); | 59 | cp.scan_interval = cpu_to_le16(0x0060); |
60 | cp.scan_window = cpu_to_le16(0x0004); | 60 | cp.scan_window = cpu_to_le16(0x0030); |
61 | bacpy(&cp.peer_addr, &conn->dst); | 61 | bacpy(&cp.peer_addr, &conn->dst); |
62 | cp.peer_addr_type = conn->dst_type; | 62 | cp.peer_addr_type = conn->dst_type; |
63 | cp.conn_interval_min = cpu_to_le16(0x0008); | 63 | cp.conn_interval_min = cpu_to_le16(0x0028); |
64 | cp.conn_interval_max = cpu_to_le16(0x0100); | 64 | cp.conn_interval_max = cpu_to_le16(0x0038); |
65 | cp.supervision_timeout = cpu_to_le16(0x0064); | 65 | cp.supervision_timeout = cpu_to_le16(0x002a); |
66 | cp.min_ce_len = cpu_to_le16(0x0001); | 66 | cp.min_ce_len = cpu_to_le16(0x0000); |
67 | cp.max_ce_len = cpu_to_le16(0x0001); | 67 | cp.max_ce_len = cpu_to_le16(0x0000); |
68 | 68 | ||
69 | hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | 69 | hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); |
70 | } | 70 | } |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 35083f2aa2ea..d7d96b6b1f0d 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -2174,7 +2174,10 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff | |||
2174 | hci_dev_lock(hdev); | 2174 | hci_dev_lock(hdev); |
2175 | 2175 | ||
2176 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 2176 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
2177 | if (conn && conn->state == BT_CONNECTED) { | 2177 | if (!conn) |
2178 | goto unlock; | ||
2179 | |||
2180 | if (conn->state == BT_CONNECTED) { | ||
2178 | hci_conn_hold(conn); | 2181 | hci_conn_hold(conn); |
2179 | conn->disc_timeout = HCI_PAIRING_TIMEOUT; | 2182 | conn->disc_timeout = HCI_PAIRING_TIMEOUT; |
2180 | hci_conn_put(conn); | 2183 | hci_conn_put(conn); |
@@ -2194,6 +2197,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff | |||
2194 | mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); | 2197 | mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); |
2195 | } | 2198 | } |
2196 | 2199 | ||
2200 | unlock: | ||
2197 | hci_dev_unlock(hdev); | 2201 | hci_dev_unlock(hdev); |
2198 | } | 2202 | } |
2199 | 2203 | ||
@@ -2834,19 +2838,17 @@ unlock: | |||
2834 | static inline void hci_le_adv_report_evt(struct hci_dev *hdev, | 2838 | static inline void hci_le_adv_report_evt(struct hci_dev *hdev, |
2835 | struct sk_buff *skb) | 2839 | struct sk_buff *skb) |
2836 | { | 2840 | { |
2837 | struct hci_ev_le_advertising_info *ev; | 2841 | u8 num_reports = skb->data[0]; |
2838 | u8 num_reports; | 2842 | void *ptr = &skb->data[1]; |
2839 | |||
2840 | num_reports = skb->data[0]; | ||
2841 | ev = (void *) &skb->data[1]; | ||
2842 | 2843 | ||
2843 | hci_dev_lock(hdev); | 2844 | hci_dev_lock(hdev); |
2844 | 2845 | ||
2845 | hci_add_adv_entry(hdev, ev); | 2846 | while (num_reports--) { |
2847 | struct hci_ev_le_advertising_info *ev = ptr; | ||
2846 | 2848 | ||
2847 | while (--num_reports) { | ||
2848 | ev = (void *) (ev->data + ev->length + 1); | ||
2849 | hci_add_adv_entry(hdev, ev); | 2849 | hci_add_adv_entry(hdev, ev); |
2850 | |||
2851 | ptr += sizeof(*ev) + ev->length + 1; | ||
2850 | } | 2852 | } |
2851 | 2853 | ||
2852 | hci_dev_unlock(hdev); | 2854 | hci_dev_unlock(hdev); |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index b83979c548b2..075a3e920caf 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -716,12 +716,18 @@ static int hidp_session(void *arg) | |||
716 | 716 | ||
717 | while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { | 717 | while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { |
718 | skb_orphan(skb); | 718 | skb_orphan(skb); |
719 | hidp_recv_ctrl_frame(session, skb); | 719 | if (!skb_linearize(skb)) |
720 | hidp_recv_ctrl_frame(session, skb); | ||
721 | else | ||
722 | kfree_skb(skb); | ||
720 | } | 723 | } |
721 | 724 | ||
722 | while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) { | 725 | while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) { |
723 | skb_orphan(skb); | 726 | skb_orphan(skb); |
724 | hidp_recv_intr_frame(session, skb); | 727 | if (!skb_linearize(skb)) |
728 | hidp_recv_intr_frame(session, skb); | ||
729 | else | ||
730 | kfree_skb(skb); | ||
725 | } | 731 | } |
726 | 732 | ||
727 | hidp_process_transmit(session); | 733 | hidp_process_transmit(session); |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 1611b3544bb1..8cd12917733b 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -1245,7 +1245,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) | |||
1245 | __clear_retrans_timer(chan); | 1245 | __clear_retrans_timer(chan); |
1246 | } | 1246 | } |
1247 | 1247 | ||
1248 | void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) | 1248 | static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) |
1249 | { | 1249 | { |
1250 | struct hci_conn *hcon = chan->conn->hcon; | 1250 | struct hci_conn *hcon = chan->conn->hcon; |
1251 | u16 flags; | 1251 | u16 flags; |
@@ -1261,7 +1261,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) | |||
1261 | hci_send_acl(hcon, skb, flags); | 1261 | hci_send_acl(hcon, skb, flags); |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | void l2cap_streaming_send(struct l2cap_chan *chan) | 1264 | static void l2cap_streaming_send(struct l2cap_chan *chan) |
1265 | { | 1265 | { |
1266 | struct sk_buff *skb; | 1266 | struct sk_buff *skb; |
1267 | u16 control, fcs; | 1267 | u16 control, fcs; |
@@ -1327,7 +1327,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) | |||
1327 | l2cap_do_send(chan, tx_skb); | 1327 | l2cap_do_send(chan, tx_skb); |
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | int l2cap_ertm_send(struct l2cap_chan *chan) | 1330 | static int l2cap_ertm_send(struct l2cap_chan *chan) |
1331 | { | 1331 | { |
1332 | struct sk_buff *skb, *tx_skb; | 1332 | struct sk_buff *skb, *tx_skb; |
1333 | u16 control, fcs; | 1333 | u16 control, fcs; |
@@ -1465,7 +1465,7 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in | |||
1465 | return sent; | 1465 | return sent; |
1466 | } | 1466 | } |
1467 | 1467 | ||
1468 | struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) | 1468 | static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) |
1469 | { | 1469 | { |
1470 | struct sock *sk = chan->sk; | 1470 | struct sock *sk = chan->sk; |
1471 | struct l2cap_conn *conn = chan->conn; | 1471 | struct l2cap_conn *conn = chan->conn; |
@@ -1495,7 +1495,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr | |||
1495 | return skb; | 1495 | return skb; |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) | 1498 | static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) |
1499 | { | 1499 | { |
1500 | struct sock *sk = chan->sk; | 1500 | struct sock *sk = chan->sk; |
1501 | struct l2cap_conn *conn = chan->conn; | 1501 | struct l2cap_conn *conn = chan->conn; |
@@ -1572,7 +1572,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, | |||
1572 | return skb; | 1572 | return skb; |
1573 | } | 1573 | } |
1574 | 1574 | ||
1575 | int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) | 1575 | static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) |
1576 | { | 1576 | { |
1577 | struct sk_buff *skb; | 1577 | struct sk_buff *skb; |
1578 | struct sk_buff_head sar_queue; | 1578 | struct sk_buff_head sar_queue; |
@@ -3128,102 +3128,104 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, | |||
3128 | return 0; | 3128 | return 0; |
3129 | } | 3129 | } |
3130 | 3130 | ||
3131 | static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) | 3131 | static void append_skb_frag(struct sk_buff *skb, |
3132 | struct sk_buff *new_frag, struct sk_buff **last_frag) | ||
3132 | { | 3133 | { |
3133 | struct sk_buff *_skb; | 3134 | /* skb->len reflects data in skb as well as all fragments |
3134 | int err; | 3135 | * skb->data_len reflects only data in fragments |
3136 | */ | ||
3137 | if (!skb_has_frag_list(skb)) | ||
3138 | skb_shinfo(skb)->frag_list = new_frag; | ||
3139 | |||
3140 | new_frag->next = NULL; | ||
3141 | |||
3142 | (*last_frag)->next = new_frag; | ||
3143 | *last_frag = new_frag; | ||
3144 | |||
3145 | skb->len += new_frag->len; | ||
3146 | skb->data_len += new_frag->len; | ||
3147 | skb->truesize += new_frag->truesize; | ||
3148 | } | ||
3149 | |||
3150 | static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) | ||
3151 | { | ||
3152 | int err = -EINVAL; | ||
3135 | 3153 | ||
3136 | switch (control & L2CAP_CTRL_SAR) { | 3154 | switch (control & L2CAP_CTRL_SAR) { |
3137 | case L2CAP_SDU_UNSEGMENTED: | 3155 | case L2CAP_SDU_UNSEGMENTED: |
3138 | if (test_bit(CONN_SAR_SDU, &chan->conn_state)) | 3156 | if (chan->sdu) |
3139 | goto drop; | 3157 | break; |
3140 | 3158 | ||
3141 | return chan->ops->recv(chan->data, skb); | 3159 | err = chan->ops->recv(chan->data, skb); |
3160 | break; | ||
3142 | 3161 | ||
3143 | case L2CAP_SDU_START: | 3162 | case L2CAP_SDU_START: |
3144 | if (test_bit(CONN_SAR_SDU, &chan->conn_state)) | 3163 | if (chan->sdu) |
3145 | goto drop; | 3164 | break; |
3146 | 3165 | ||
3147 | chan->sdu_len = get_unaligned_le16(skb->data); | 3166 | chan->sdu_len = get_unaligned_le16(skb->data); |
3167 | skb_pull(skb, 2); | ||
3148 | 3168 | ||
3149 | if (chan->sdu_len > chan->imtu) | 3169 | if (chan->sdu_len > chan->imtu) { |
3150 | goto disconnect; | 3170 | err = -EMSGSIZE; |
3151 | 3171 | break; | |
3152 | chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC); | 3172 | } |
3153 | if (!chan->sdu) | ||
3154 | return -ENOMEM; | ||
3155 | 3173 | ||
3156 | /* pull sdu_len bytes only after alloc, because of Local Busy | 3174 | if (skb->len >= chan->sdu_len) |
3157 | * condition we have to be sure that this will be executed | 3175 | break; |
3158 | * only once, i.e., when alloc does not fail */ | ||
3159 | skb_pull(skb, 2); | ||
3160 | 3176 | ||
3161 | memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); | 3177 | chan->sdu = skb; |
3178 | chan->sdu_last_frag = skb; | ||
3162 | 3179 | ||
3163 | set_bit(CONN_SAR_SDU, &chan->conn_state); | 3180 | skb = NULL; |
3164 | chan->partial_sdu_len = skb->len; | 3181 | err = 0; |
3165 | break; | 3182 | break; |
3166 | 3183 | ||
3167 | case L2CAP_SDU_CONTINUE: | 3184 | case L2CAP_SDU_CONTINUE: |
3168 | if (!test_bit(CONN_SAR_SDU, &chan->conn_state)) | ||
3169 | goto disconnect; | ||
3170 | |||
3171 | if (!chan->sdu) | 3185 | if (!chan->sdu) |
3172 | goto disconnect; | 3186 | break; |
3173 | 3187 | ||
3174 | chan->partial_sdu_len += skb->len; | 3188 | append_skb_frag(chan->sdu, skb, |
3175 | if (chan->partial_sdu_len > chan->sdu_len) | 3189 | &chan->sdu_last_frag); |
3176 | goto drop; | 3190 | skb = NULL; |
3177 | 3191 | ||
3178 | memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); | 3192 | if (chan->sdu->len >= chan->sdu_len) |
3193 | break; | ||
3179 | 3194 | ||
3195 | err = 0; | ||
3180 | break; | 3196 | break; |
3181 | 3197 | ||
3182 | case L2CAP_SDU_END: | 3198 | case L2CAP_SDU_END: |
3183 | if (!test_bit(CONN_SAR_SDU, &chan->conn_state)) | ||
3184 | goto disconnect; | ||
3185 | |||
3186 | if (!chan->sdu) | 3199 | if (!chan->sdu) |
3187 | goto disconnect; | 3200 | break; |
3188 | |||
3189 | chan->partial_sdu_len += skb->len; | ||
3190 | |||
3191 | if (chan->partial_sdu_len > chan->imtu) | ||
3192 | goto drop; | ||
3193 | 3201 | ||
3194 | if (chan->partial_sdu_len != chan->sdu_len) | 3202 | append_skb_frag(chan->sdu, skb, |
3195 | goto drop; | 3203 | &chan->sdu_last_frag); |
3204 | skb = NULL; | ||
3196 | 3205 | ||
3197 | memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); | 3206 | if (chan->sdu->len != chan->sdu_len) |
3207 | break; | ||
3198 | 3208 | ||
3199 | _skb = skb_clone(chan->sdu, GFP_ATOMIC); | 3209 | err = chan->ops->recv(chan->data, chan->sdu); |
3200 | if (!_skb) { | ||
3201 | return -ENOMEM; | ||
3202 | } | ||
3203 | 3210 | ||
3204 | err = chan->ops->recv(chan->data, _skb); | 3211 | if (!err) { |
3205 | if (err < 0) { | 3212 | /* Reassembly complete */ |
3206 | kfree_skb(_skb); | 3213 | chan->sdu = NULL; |
3207 | return err; | 3214 | chan->sdu_last_frag = NULL; |
3215 | chan->sdu_len = 0; | ||
3208 | } | 3216 | } |
3209 | |||
3210 | clear_bit(CONN_SAR_SDU, &chan->conn_state); | ||
3211 | |||
3212 | kfree_skb(chan->sdu); | ||
3213 | break; | 3217 | break; |
3214 | } | 3218 | } |
3215 | 3219 | ||
3216 | kfree_skb(skb); | 3220 | if (err) { |
3217 | return 0; | 3221 | kfree_skb(skb); |
3218 | 3222 | kfree_skb(chan->sdu); | |
3219 | drop: | 3223 | chan->sdu = NULL; |
3220 | kfree_skb(chan->sdu); | 3224 | chan->sdu_last_frag = NULL; |
3221 | chan->sdu = NULL; | 3225 | chan->sdu_len = 0; |
3226 | } | ||
3222 | 3227 | ||
3223 | disconnect: | 3228 | return err; |
3224 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
3225 | kfree_skb(skb); | ||
3226 | return 0; | ||
3227 | } | 3229 | } |
3228 | 3230 | ||
3229 | static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) | 3231 | static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) |
@@ -3277,99 +3279,6 @@ void l2cap_chan_busy(struct l2cap_chan *chan, int busy) | |||
3277 | } | 3279 | } |
3278 | } | 3280 | } |
3279 | 3281 | ||
3280 | static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) | ||
3281 | { | ||
3282 | struct sk_buff *_skb; | ||
3283 | int err = -EINVAL; | ||
3284 | |||
3285 | /* | ||
3286 | * TODO: We have to notify the userland if some data is lost with the | ||
3287 | * Streaming Mode. | ||
3288 | */ | ||
3289 | |||
3290 | switch (control & L2CAP_CTRL_SAR) { | ||
3291 | case L2CAP_SDU_UNSEGMENTED: | ||
3292 | if (test_bit(CONN_SAR_SDU, &chan->conn_state)) { | ||
3293 | kfree_skb(chan->sdu); | ||
3294 | break; | ||
3295 | } | ||
3296 | |||
3297 | err = chan->ops->recv(chan->data, skb); | ||
3298 | if (!err) | ||
3299 | return 0; | ||
3300 | |||
3301 | break; | ||
3302 | |||
3303 | case L2CAP_SDU_START: | ||
3304 | if (test_bit(CONN_SAR_SDU, &chan->conn_state)) { | ||
3305 | kfree_skb(chan->sdu); | ||
3306 | break; | ||
3307 | } | ||
3308 | |||
3309 | chan->sdu_len = get_unaligned_le16(skb->data); | ||
3310 | skb_pull(skb, 2); | ||
3311 | |||
3312 | if (chan->sdu_len > chan->imtu) { | ||
3313 | err = -EMSGSIZE; | ||
3314 | break; | ||
3315 | } | ||
3316 | |||
3317 | chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC); | ||
3318 | if (!chan->sdu) { | ||
3319 | err = -ENOMEM; | ||
3320 | break; | ||
3321 | } | ||
3322 | |||
3323 | memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); | ||
3324 | |||
3325 | set_bit(CONN_SAR_SDU, &chan->conn_state); | ||
3326 | chan->partial_sdu_len = skb->len; | ||
3327 | err = 0; | ||
3328 | break; | ||
3329 | |||
3330 | case L2CAP_SDU_CONTINUE: | ||
3331 | if (!test_bit(CONN_SAR_SDU, &chan->conn_state)) | ||
3332 | break; | ||
3333 | |||
3334 | memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); | ||
3335 | |||
3336 | chan->partial_sdu_len += skb->len; | ||
3337 | if (chan->partial_sdu_len > chan->sdu_len) | ||
3338 | kfree_skb(chan->sdu); | ||
3339 | else | ||
3340 | err = 0; | ||
3341 | |||
3342 | break; | ||
3343 | |||
3344 | case L2CAP_SDU_END: | ||
3345 | if (!test_bit(CONN_SAR_SDU, &chan->conn_state)) | ||
3346 | break; | ||
3347 | |||
3348 | memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); | ||
3349 | |||
3350 | clear_bit(CONN_SAR_SDU, &chan->conn_state); | ||
3351 | chan->partial_sdu_len += skb->len; | ||
3352 | |||
3353 | if (chan->partial_sdu_len > chan->imtu) | ||
3354 | goto drop; | ||
3355 | |||
3356 | if (chan->partial_sdu_len == chan->sdu_len) { | ||
3357 | _skb = skb_clone(chan->sdu, GFP_ATOMIC); | ||
3358 | err = chan->ops->recv(chan->data, _skb); | ||
3359 | if (err < 0) | ||
3360 | kfree_skb(_skb); | ||
3361 | } | ||
3362 | err = 0; | ||
3363 | |||
3364 | drop: | ||
3365 | kfree_skb(chan->sdu); | ||
3366 | break; | ||
3367 | } | ||
3368 | |||
3369 | kfree_skb(skb); | ||
3370 | return err; | ||
3371 | } | ||
3372 | |||
3373 | static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) | 3282 | static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) |
3374 | { | 3283 | { |
3375 | struct sk_buff *skb; | 3284 | struct sk_buff *skb; |
@@ -3384,7 +3293,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) | |||
3384 | 3293 | ||
3385 | skb = skb_dequeue(&chan->srej_q); | 3294 | skb = skb_dequeue(&chan->srej_q); |
3386 | control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; | 3295 | control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; |
3387 | err = l2cap_ertm_reassembly_sdu(chan, skb, control); | 3296 | err = l2cap_reassemble_sdu(chan, skb, control); |
3388 | 3297 | ||
3389 | if (err < 0) { | 3298 | if (err < 0) { |
3390 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 3299 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); |
@@ -3544,7 +3453,7 @@ expected: | |||
3544 | return 0; | 3453 | return 0; |
3545 | } | 3454 | } |
3546 | 3455 | ||
3547 | err = l2cap_ertm_reassembly_sdu(chan, skb, rx_control); | 3456 | err = l2cap_reassemble_sdu(chan, skb, rx_control); |
3548 | chan->buffer_seq = (chan->buffer_seq + 1) % 64; | 3457 | chan->buffer_seq = (chan->buffer_seq + 1) % 64; |
3549 | if (err < 0) { | 3458 | if (err < 0) { |
3550 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 3459 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); |
@@ -3860,12 +3769,20 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3860 | 3769 | ||
3861 | tx_seq = __get_txseq(control); | 3770 | tx_seq = __get_txseq(control); |
3862 | 3771 | ||
3863 | if (chan->expected_tx_seq == tx_seq) | 3772 | if (chan->expected_tx_seq != tx_seq) { |
3864 | chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; | 3773 | /* Frame(s) missing - must discard partial SDU */ |
3865 | else | 3774 | kfree_skb(chan->sdu); |
3866 | chan->expected_tx_seq = (tx_seq + 1) % 64; | 3775 | chan->sdu = NULL; |
3776 | chan->sdu_last_frag = NULL; | ||
3777 | chan->sdu_len = 0; | ||
3867 | 3778 | ||
3868 | l2cap_streaming_reassembly_sdu(chan, skb, control); | 3779 | /* TODO: Notify userland of missing data */ |
3780 | } | ||
3781 | |||
3782 | chan->expected_tx_seq = (tx_seq + 1) % 64; | ||
3783 | |||
3784 | if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE) | ||
3785 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
3869 | 3786 | ||
3870 | goto done; | 3787 | goto done; |
3871 | 3788 | ||
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 5ba3f6df665c..38b618c96de6 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -1853,7 +1853,10 @@ static inline void rfcomm_process_rx(struct rfcomm_session *s) | |||
1853 | /* Get data directly from socket receive queue without copying it. */ | 1853 | /* Get data directly from socket receive queue without copying it. */ |
1854 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 1854 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { |
1855 | skb_orphan(skb); | 1855 | skb_orphan(skb); |
1856 | rfcomm_recv_frame(s, skb); | 1856 | if (!skb_linearize(skb)) |
1857 | rfcomm_recv_frame(s, skb); | ||
1858 | else | ||
1859 | kfree_skb(skb); | ||
1857 | } | 1860 | } |
1858 | 1861 | ||
1859 | if (sk->sk_state == BT_CLOSED) { | 1862 | if (sk->sk_state == BT_CLOSED) { |