diff options
| -rw-r--r-- | include/net/bluetooth/hci_core.h | 3 | ||||
| -rw-r--r-- | net/bluetooth/hci_core.c | 148 |
2 files changed, 1 insertions, 150 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ad957f336ead..a056c2bfeb81 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
| @@ -185,7 +185,6 @@ struct amp_assoc { | |||
| 185 | 185 | ||
| 186 | #define HCI_MAX_PAGES 3 | 186 | #define HCI_MAX_PAGES 3 |
| 187 | 187 | ||
| 188 | #define NUM_REASSEMBLY 4 | ||
| 189 | struct hci_dev { | 188 | struct hci_dev { |
| 190 | struct list_head list; | 189 | struct list_head list; |
| 191 | struct mutex lock; | 190 | struct mutex lock; |
| @@ -327,7 +326,6 @@ struct hci_dev { | |||
| 327 | struct sk_buff_head cmd_q; | 326 | struct sk_buff_head cmd_q; |
| 328 | 327 | ||
| 329 | struct sk_buff *sent_cmd; | 328 | struct sk_buff *sent_cmd; |
| 330 | struct sk_buff *reassembly[NUM_REASSEMBLY]; | ||
| 331 | 329 | ||
| 332 | struct mutex req_lock; | 330 | struct mutex req_lock; |
| 333 | wait_queue_head_t req_wait_q; | 331 | wait_queue_head_t req_wait_q; |
| @@ -1012,7 +1010,6 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
| 1012 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); | 1010 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); |
| 1013 | 1011 | ||
| 1014 | int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); | 1012 | int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); |
| 1015 | int hci_recv_stream_fragment(struct hci_dev *hdev, const void *data, int count); | ||
| 1016 | 1013 | ||
| 1017 | void hci_init_sysfs(struct hci_dev *hdev); | 1014 | void hci_init_sysfs(struct hci_dev *hdev); |
| 1018 | void hci_conn_init_sysfs(struct hci_conn *conn); | 1015 | void hci_conn_init_sysfs(struct hci_conn *conn); |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index c9e7cafb245a..476709bd068a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -3200,7 +3200,7 @@ EXPORT_SYMBOL(hci_register_dev); | |||
| 3200 | /* Unregister HCI device */ | 3200 | /* Unregister HCI device */ |
| 3201 | void hci_unregister_dev(struct hci_dev *hdev) | 3201 | void hci_unregister_dev(struct hci_dev *hdev) |
| 3202 | { | 3202 | { |
| 3203 | int i, id; | 3203 | int id; |
| 3204 | 3204 | ||
| 3205 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | 3205 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); |
| 3206 | 3206 | ||
| @@ -3214,9 +3214,6 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
| 3214 | 3214 | ||
| 3215 | hci_dev_do_close(hdev); | 3215 | hci_dev_do_close(hdev); |
| 3216 | 3216 | ||
| 3217 | for (i = 0; i < NUM_REASSEMBLY; i++) | ||
| 3218 | kfree_skb(hdev->reassembly[i]); | ||
| 3219 | |||
| 3220 | cancel_work_sync(&hdev->power_on); | 3217 | cancel_work_sync(&hdev->power_on); |
| 3221 | 3218 | ||
| 3222 | if (!test_bit(HCI_INIT, &hdev->flags) && | 3219 | if (!test_bit(HCI_INIT, &hdev->flags) && |
| @@ -3320,149 +3317,6 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3320 | } | 3317 | } |
| 3321 | EXPORT_SYMBOL(hci_recv_frame); | 3318 | EXPORT_SYMBOL(hci_recv_frame); |
| 3322 | 3319 | ||
| 3323 | static int hci_reassembly(struct hci_dev *hdev, int type, const void *data, | ||
| 3324 | int count, __u8 index) | ||
| 3325 | { | ||
| 3326 | int len = 0; | ||
| 3327 | int hlen = 0; | ||
| 3328 | int remain = count; | ||
| 3329 | struct sk_buff *skb; | ||
| 3330 | struct bt_skb_cb *scb; | ||
| 3331 | |||
| 3332 | if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || | ||
| 3333 | index >= NUM_REASSEMBLY) | ||
| 3334 | return -EILSEQ; | ||
| 3335 | |||
| 3336 | skb = hdev->reassembly[index]; | ||
| 3337 | |||
| 3338 | if (!skb) { | ||
| 3339 | switch (type) { | ||
| 3340 | case HCI_ACLDATA_PKT: | ||
| 3341 | len = HCI_MAX_FRAME_SIZE; | ||
| 3342 | hlen = HCI_ACL_HDR_SIZE; | ||
| 3343 | break; | ||
| 3344 | case HCI_EVENT_PKT: | ||
| 3345 | len = HCI_MAX_EVENT_SIZE; | ||
| 3346 | hlen = HCI_EVENT_HDR_SIZE; | ||
| 3347 | break; | ||
| 3348 | case HCI_SCODATA_PKT: | ||
| 3349 | len = HCI_MAX_SCO_SIZE; | ||
| 3350 | hlen = HCI_SCO_HDR_SIZE; | ||
| 3351 | break; | ||
| 3352 | } | ||
| 3353 | |||
| 3354 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
| 3355 | if (!skb) | ||
| 3356 | return -ENOMEM; | ||
| 3357 | |||
| 3358 | scb = (void *) skb->cb; | ||
| 3359 | scb->expect = hlen; | ||
| 3360 | scb->pkt_type = type; | ||
| 3361 | |||
| 3362 | hdev->reassembly[index] = skb; | ||
| 3363 | } | ||
| 3364 | |||
| 3365 | while (count) { | ||
| 3366 | scb = (void *) skb->cb; | ||
| 3367 | len = min_t(uint, scb->expect, count); | ||
| 3368 | |||
| 3369 | memcpy(skb_put(skb, len), data, len); | ||
| 3370 | |||
| 3371 | count -= len; | ||
| 3372 | data += len; | ||
| 3373 | scb->expect -= len; | ||
| 3374 | remain = count; | ||
| 3375 | |||
| 3376 | switch (type) { | ||
| 3377 | case HCI_EVENT_PKT: | ||
| 3378 | if (skb->len == HCI_EVENT_HDR_SIZE) { | ||
| 3379 | struct hci_event_hdr *h = hci_event_hdr(skb); | ||
| 3380 | scb->expect = h->plen; | ||
| 3381 | |||
| 3382 | if (skb_tailroom(skb) < scb->expect) { | ||
| 3383 | kfree_skb(skb); | ||
| 3384 | hdev->reassembly[index] = NULL; | ||
| 3385 | return -ENOMEM; | ||
| 3386 | } | ||
| 3387 | } | ||
| 3388 | break; | ||
| 3389 | |||
| 3390 | case HCI_ACLDATA_PKT: | ||
| 3391 | if (skb->len == HCI_ACL_HDR_SIZE) { | ||
| 3392 | struct hci_acl_hdr *h = hci_acl_hdr(skb); | ||
| 3393 | scb->expect = __le16_to_cpu(h->dlen); | ||
| 3394 | |||
| 3395 | if (skb_tailroom(skb) < scb->expect) { | ||
| 3396 | kfree_skb(skb); | ||
| 3397 | hdev->reassembly[index] = NULL; | ||
| 3398 | return -ENOMEM; | ||
| 3399 | } | ||
| 3400 | } | ||
| 3401 | break; | ||
| 3402 | |||
| 3403 | case HCI_SCODATA_PKT: | ||
| 3404 | if (skb->len == HCI_SCO_HDR_SIZE) { | ||
| 3405 | struct hci_sco_hdr *h = hci_sco_hdr(skb); | ||
| 3406 | scb->expect = h->dlen; | ||
| 3407 | |||
| 3408 | if (skb_tailroom(skb) < scb->expect) { | ||
| 3409 | kfree_skb(skb); | ||
| 3410 | hdev->reassembly[index] = NULL; | ||
| 3411 | return -ENOMEM; | ||
| 3412 | } | ||
| 3413 | } | ||
| 3414 | break; | ||
| 3415 | } | ||
| 3416 | |||
| 3417 | if (scb->expect == 0) { | ||
| 3418 | /* Complete frame */ | ||
| 3419 | |||
| 3420 | bt_cb(skb)->pkt_type = type; | ||
| 3421 | hci_recv_frame(hdev, skb); | ||
| 3422 | |||
| 3423 | hdev->reassembly[index] = NULL; | ||
| 3424 | return remain; | ||
| 3425 | } | ||
| 3426 | } | ||
| 3427 | |||
| 3428 | return remain; | ||
| 3429 | } | ||
| 3430 | |||
| 3431 | #define STREAM_REASSEMBLY 0 | ||
| 3432 | |||
| 3433 | int hci_recv_stream_fragment(struct hci_dev *hdev, const void *data, int count) | ||
| 3434 | { | ||
| 3435 | int type; | ||
| 3436 | int rem = 0; | ||
| 3437 | |||
| 3438 | while (count) { | ||
| 3439 | struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY]; | ||
| 3440 | |||
| 3441 | if (!skb) { | ||
| 3442 | const struct { char type; } *pkt; | ||
| 3443 | |||
| 3444 | /* Start of the frame */ | ||
| 3445 | pkt = data; | ||
| 3446 | type = pkt->type; | ||
| 3447 | |||
| 3448 | data++; | ||
| 3449 | count--; | ||
| 3450 | } else | ||
| 3451 | type = bt_cb(skb)->pkt_type; | ||
| 3452 | |||
| 3453 | rem = hci_reassembly(hdev, type, data, count, | ||
| 3454 | STREAM_REASSEMBLY); | ||
| 3455 | if (rem < 0) | ||
| 3456 | return rem; | ||
| 3457 | |||
| 3458 | data += (count - rem); | ||
| 3459 | count = rem; | ||
| 3460 | } | ||
| 3461 | |||
| 3462 | return rem; | ||
| 3463 | } | ||
| 3464 | EXPORT_SYMBOL(hci_recv_stream_fragment); | ||
| 3465 | |||
| 3466 | /* ---- Interface to upper protocols ---- */ | 3320 | /* ---- Interface to upper protocols ---- */ |
| 3467 | 3321 | ||
| 3468 | int hci_register_cb(struct hci_cb *cb) | 3322 | int hci_register_cb(struct hci_cb *cb) |
