diff options
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/hci/command.c | 4 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 25 | ||||
-rw-r--r-- | net/nfc/llcp/commands.c | 32 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.c | 17 |
4 files changed, 63 insertions, 15 deletions
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 07659cfd6d7b..7d99410e6c1a 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
@@ -344,7 +344,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, | |||
344 | return -EADDRINUSE; | 344 | return -EADDRINUSE; |
345 | 345 | ||
346 | if (pipe != NFC_HCI_INVALID_PIPE) | 346 | if (pipe != NFC_HCI_INVALID_PIPE) |
347 | goto pipe_is_open; | 347 | goto open_pipe; |
348 | 348 | ||
349 | switch (dest_gate) { | 349 | switch (dest_gate) { |
350 | case NFC_HCI_LINK_MGMT_GATE: | 350 | case NFC_HCI_LINK_MGMT_GATE: |
@@ -361,6 +361,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, | |||
361 | break; | 361 | break; |
362 | } | 362 | } |
363 | 363 | ||
364 | open_pipe: | ||
364 | r = nfc_hci_open_pipe(hdev, pipe); | 365 | r = nfc_hci_open_pipe(hdev, pipe); |
365 | if (r < 0) { | 366 | if (r < 0) { |
366 | if (pipe_created) | 367 | if (pipe_created) |
@@ -371,7 +372,6 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, | |||
371 | return r; | 372 | return r; |
372 | } | 373 | } |
373 | 374 | ||
374 | pipe_is_open: | ||
375 | hdev->gate2pipe[dest_gate] = pipe; | 375 | hdev->gate2pipe[dest_gate] = pipe; |
376 | 376 | ||
377 | return 0; | 377 | return 0; |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index bc571b0efb92..7bea574d5934 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -33,17 +33,20 @@ | |||
33 | /* Largest headroom needed for outgoing HCI commands */ | 33 | /* Largest headroom needed for outgoing HCI commands */ |
34 | #define HCI_CMDS_HEADROOM 1 | 34 | #define HCI_CMDS_HEADROOM 1 |
35 | 35 | ||
36 | static int nfc_hci_result_to_errno(u8 result) | 36 | int nfc_hci_result_to_errno(u8 result) |
37 | { | 37 | { |
38 | switch (result) { | 38 | switch (result) { |
39 | case NFC_HCI_ANY_OK: | 39 | case NFC_HCI_ANY_OK: |
40 | return 0; | 40 | return 0; |
41 | case NFC_HCI_ANY_E_REG_PAR_UNKNOWN: | ||
42 | return -EOPNOTSUPP; | ||
41 | case NFC_HCI_ANY_E_TIMEOUT: | 43 | case NFC_HCI_ANY_E_TIMEOUT: |
42 | return -ETIME; | 44 | return -ETIME; |
43 | default: | 45 | default: |
44 | return -1; | 46 | return -1; |
45 | } | 47 | } |
46 | } | 48 | } |
49 | EXPORT_SYMBOL(nfc_hci_result_to_errno); | ||
47 | 50 | ||
48 | static void nfc_hci_msg_tx_work(struct work_struct *work) | 51 | static void nfc_hci_msg_tx_work(struct work_struct *work) |
49 | { | 52 | { |
@@ -167,7 +170,7 @@ void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | |||
167 | kfree_skb(skb); | 170 | kfree_skb(skb); |
168 | } | 171 | } |
169 | 172 | ||
170 | static u32 nfc_hci_sak_to_protocol(u8 sak) | 173 | u32 nfc_hci_sak_to_protocol(u8 sak) |
171 | { | 174 | { |
172 | switch (NFC_HCI_TYPE_A_SEL_PROT(sak)) { | 175 | switch (NFC_HCI_TYPE_A_SEL_PROT(sak)) { |
173 | case NFC_HCI_TYPE_A_SEL_PROT_MIFARE: | 176 | case NFC_HCI_TYPE_A_SEL_PROT_MIFARE: |
@@ -182,6 +185,7 @@ static u32 nfc_hci_sak_to_protocol(u8 sak) | |||
182 | return 0xffffffff; | 185 | return 0xffffffff; |
183 | } | 186 | } |
184 | } | 187 | } |
188 | EXPORT_SYMBOL(nfc_hci_sak_to_protocol); | ||
185 | 189 | ||
186 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | 190 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) |
187 | { | 191 | { |
@@ -284,6 +288,12 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
284 | struct sk_buff *skb) | 288 | struct sk_buff *skb) |
285 | { | 289 | { |
286 | int r = 0; | 290 | int r = 0; |
291 | u8 gate = nfc_hci_pipe2gate(hdev, pipe); | ||
292 | |||
293 | if (gate == 0xff) { | ||
294 | pr_err("Discarded event %x to unopened pipe %x\n", event, pipe); | ||
295 | goto exit; | ||
296 | } | ||
287 | 297 | ||
288 | switch (event) { | 298 | switch (event) { |
289 | case NFC_HCI_EVT_TARGET_DISCOVERED: | 299 | case NFC_HCI_EVT_TARGET_DISCOVERED: |
@@ -307,14 +317,11 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
307 | goto exit; | 317 | goto exit; |
308 | } | 318 | } |
309 | 319 | ||
310 | r = nfc_hci_target_discovered(hdev, | 320 | r = nfc_hci_target_discovered(hdev, gate); |
311 | nfc_hci_pipe2gate(hdev, pipe)); | ||
312 | break; | 321 | break; |
313 | default: | 322 | default: |
314 | if (hdev->ops->event_received) { | 323 | if (hdev->ops->event_received) { |
315 | hdev->ops->event_received(hdev, | 324 | hdev->ops->event_received(hdev, gate, event, skb); |
316 | nfc_hci_pipe2gate(hdev, pipe), | ||
317 | event, skb); | ||
318 | return; | 325 | return; |
319 | } | 326 | } |
320 | 327 | ||
@@ -419,6 +426,10 @@ static int hci_dev_version(struct nfc_hci_dev *hdev) | |||
419 | 426 | ||
420 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, | 427 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, |
421 | NFC_HCI_ID_MGMT_VERSION_SW, &skb); | 428 | NFC_HCI_ID_MGMT_VERSION_SW, &skb); |
429 | if (r == -EOPNOTSUPP) { | ||
430 | pr_info("Software/Hardware info not available\n"); | ||
431 | return 0; | ||
432 | } | ||
422 | if (r < 0) | 433 | if (r < 0) |
423 | return r; | 434 | return r; |
424 | 435 | ||
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index ed2d17312d61..df24be48d4da 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -528,6 +528,23 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
528 | if (local == NULL) | 528 | if (local == NULL) |
529 | return -ENODEV; | 529 | return -ENODEV; |
530 | 530 | ||
531 | /* Remote is ready but has not acknowledged our frames */ | ||
532 | if((sock->remote_ready && | ||
533 | skb_queue_len(&sock->tx_pending_queue) >= sock->rw && | ||
534 | skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { | ||
535 | pr_err("Pending queue is full %d frames\n", | ||
536 | skb_queue_len(&sock->tx_pending_queue)); | ||
537 | return -ENOBUFS; | ||
538 | } | ||
539 | |||
540 | /* Remote is not ready and we've been queueing enough frames */ | ||
541 | if ((!sock->remote_ready && | ||
542 | skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { | ||
543 | pr_err("Tx queue is full %d frames\n", | ||
544 | skb_queue_len(&sock->tx_queue)); | ||
545 | return -ENOBUFS; | ||
546 | } | ||
547 | |||
531 | msg_data = kzalloc(len, GFP_KERNEL); | 548 | msg_data = kzalloc(len, GFP_KERNEL); |
532 | if (msg_data == NULL) | 549 | if (msg_data == NULL) |
533 | return -ENOMEM; | 550 | return -ENOMEM; |
@@ -579,7 +596,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | |||
579 | struct sk_buff *pdu; | 596 | struct sk_buff *pdu; |
580 | struct nfc_llcp_local *local; | 597 | struct nfc_llcp_local *local; |
581 | size_t frag_len = 0, remaining_len; | 598 | size_t frag_len = 0, remaining_len; |
582 | u8 *msg_ptr; | 599 | u8 *msg_ptr, *msg_data; |
583 | int err; | 600 | int err; |
584 | 601 | ||
585 | pr_debug("Send UI frame len %zd\n", len); | 602 | pr_debug("Send UI frame len %zd\n", len); |
@@ -588,8 +605,17 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | |||
588 | if (local == NULL) | 605 | if (local == NULL) |
589 | return -ENODEV; | 606 | return -ENODEV; |
590 | 607 | ||
608 | msg_data = kzalloc(len, GFP_KERNEL); | ||
609 | if (msg_data == NULL) | ||
610 | return -ENOMEM; | ||
611 | |||
612 | if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) { | ||
613 | kfree(msg_data); | ||
614 | return -EFAULT; | ||
615 | } | ||
616 | |||
591 | remaining_len = len; | 617 | remaining_len = len; |
592 | msg_ptr = (u8 *) msg->msg_iov; | 618 | msg_ptr = msg_data; |
593 | 619 | ||
594 | while (remaining_len > 0) { | 620 | while (remaining_len > 0) { |
595 | 621 | ||
@@ -616,6 +642,8 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | |||
616 | msg_ptr += frag_len; | 642 | msg_ptr += frag_len; |
617 | } | 643 | } |
618 | 644 | ||
645 | kfree(msg_data); | ||
646 | |||
619 | return len; | 647 | return len; |
620 | } | 648 | } |
621 | 649 | ||
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 2e9ddf34c099..2df87056c6df 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -656,6 +656,8 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
656 | if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | 656 | if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { |
657 | nfc_llcp_send_symm(local->dev); | 657 | nfc_llcp_send_symm(local->dev); |
658 | } else { | 658 | } else { |
659 | struct sk_buff *copy_skb = NULL; | ||
660 | u8 ptype = nfc_llcp_ptype(skb); | ||
659 | int ret; | 661 | int ret; |
660 | 662 | ||
661 | pr_debug("Sending pending skb\n"); | 663 | pr_debug("Sending pending skb\n"); |
@@ -663,22 +665,29 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
663 | DUMP_PREFIX_OFFSET, 16, 1, | 665 | DUMP_PREFIX_OFFSET, 16, 1, |
664 | skb->data, skb->len, true); | 666 | skb->data, skb->len, true); |
665 | 667 | ||
668 | if (ptype == LLCP_PDU_I) | ||
669 | copy_skb = skb_copy(skb, GFP_ATOMIC); | ||
670 | |||
666 | nfc_llcp_send_to_raw_sock(local, skb, | 671 | nfc_llcp_send_to_raw_sock(local, skb, |
667 | NFC_LLCP_DIRECTION_TX); | 672 | NFC_LLCP_DIRECTION_TX); |
668 | 673 | ||
669 | ret = nfc_data_exchange(local->dev, local->target_idx, | 674 | ret = nfc_data_exchange(local->dev, local->target_idx, |
670 | skb, nfc_llcp_recv, local); | 675 | skb, nfc_llcp_recv, local); |
671 | 676 | ||
672 | if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | 677 | if (ret) { |
673 | skb = skb_get(skb); | 678 | kfree_skb(copy_skb); |
674 | skb_queue_tail(&llcp_sock->tx_pending_queue, | 679 | goto out; |
675 | skb); | ||
676 | } | 680 | } |
681 | |||
682 | if (ptype == LLCP_PDU_I && copy_skb) | ||
683 | skb_queue_tail(&llcp_sock->tx_pending_queue, | ||
684 | copy_skb); | ||
677 | } | 685 | } |
678 | } else { | 686 | } else { |
679 | nfc_llcp_send_symm(local->dev); | 687 | nfc_llcp_send_symm(local->dev); |
680 | } | 688 | } |
681 | 689 | ||
690 | out: | ||
682 | mod_timer(&local->link_timer, | 691 | mod_timer(&local->link_timer, |
683 | jiffies + msecs_to_jiffies(2 * local->remote_lto)); | 692 | jiffies + msecs_to_jiffies(2 * local->remote_lto)); |
684 | } | 693 | } |