diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-01-28 14:43:00 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-01-28 14:43:00 -0500 |
commit | 4205e6ef4ee747aa81930537b6035086ba5f1e28 (patch) | |
tree | b2ebe2b4621f5f531f283cb9bf0005cd3c04ca7b /net/nfc | |
parent | cef401de7be8c4e155c6746bfccf721a4fa5fab9 (diff) | |
parent | 9ebea3829fac7505e0cd2642fbd13cfa9c038831 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/core.c | 50 | ||||
-rw-r--r-- | net/nfc/hci/command.c | 7 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 57 | ||||
-rw-r--r-- | net/nfc/hci/hcp.c | 7 | ||||
-rw-r--r-- | net/nfc/llcp/commands.c | 2 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.c | 44 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.h | 1 | ||||
-rw-r--r-- | net/nfc/llcp/sock.c | 22 | ||||
-rw-r--r-- | net/nfc/nci/core.c | 2 | ||||
-rw-r--r-- | net/nfc/netlink.c | 1 |
10 files changed, 127 insertions, 66 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c index aa64ea441676..25522e56d350 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -338,7 +338,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
338 | dev->active_target = target; | 338 | dev->active_target = target; |
339 | dev->rf_mode = NFC_RF_INITIATOR; | 339 | dev->rf_mode = NFC_RF_INITIATOR; |
340 | 340 | ||
341 | if (dev->ops->check_presence) | 341 | if (dev->ops->check_presence && !dev->shutting_down) |
342 | mod_timer(&dev->check_pres_timer, jiffies + | 342 | mod_timer(&dev->check_pres_timer, jiffies + |
343 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | 343 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
344 | } | 344 | } |
@@ -429,7 +429,7 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, | |||
429 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, | 429 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, |
430 | cb_context); | 430 | cb_context); |
431 | 431 | ||
432 | if (!rc && dev->ops->check_presence) | 432 | if (!rc && dev->ops->check_presence && !dev->shutting_down) |
433 | mod_timer(&dev->check_pres_timer, jiffies + | 433 | mod_timer(&dev->check_pres_timer, jiffies + |
434 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | 434 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
435 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { | 435 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { |
@@ -684,11 +684,6 @@ static void nfc_release(struct device *d) | |||
684 | 684 | ||
685 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | 685 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); |
686 | 686 | ||
687 | if (dev->ops->check_presence) { | ||
688 | del_timer_sync(&dev->check_pres_timer); | ||
689 | cancel_work_sync(&dev->check_pres_work); | ||
690 | } | ||
691 | |||
692 | nfc_genl_data_exit(&dev->genl_data); | 687 | nfc_genl_data_exit(&dev->genl_data); |
693 | kfree(dev->targets); | 688 | kfree(dev->targets); |
694 | kfree(dev); | 689 | kfree(dev); |
@@ -706,15 +701,16 @@ static void nfc_check_pres_work(struct work_struct *work) | |||
706 | rc = dev->ops->check_presence(dev, dev->active_target); | 701 | rc = dev->ops->check_presence(dev, dev->active_target); |
707 | if (rc == -EOPNOTSUPP) | 702 | if (rc == -EOPNOTSUPP) |
708 | goto exit; | 703 | goto exit; |
709 | if (!rc) { | 704 | if (rc) { |
710 | mod_timer(&dev->check_pres_timer, jiffies + | ||
711 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
712 | } else { | ||
713 | u32 active_target_idx = dev->active_target->idx; | 705 | u32 active_target_idx = dev->active_target->idx; |
714 | device_unlock(&dev->dev); | 706 | device_unlock(&dev->dev); |
715 | nfc_target_lost(dev, active_target_idx); | 707 | nfc_target_lost(dev, active_target_idx); |
716 | return; | 708 | return; |
717 | } | 709 | } |
710 | |||
711 | if (!dev->shutting_down) | ||
712 | mod_timer(&dev->check_pres_timer, jiffies + | ||
713 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
718 | } | 714 | } |
719 | 715 | ||
720 | exit: | 716 | exit: |
@@ -761,6 +757,7 @@ struct nfc_dev *nfc_get_device(unsigned int idx) | |||
761 | */ | 757 | */ |
762 | struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | 758 | struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, |
763 | u32 supported_protocols, | 759 | u32 supported_protocols, |
760 | u32 supported_se, | ||
764 | int tx_headroom, int tx_tailroom) | 761 | int tx_headroom, int tx_tailroom) |
765 | { | 762 | { |
766 | struct nfc_dev *dev; | 763 | struct nfc_dev *dev; |
@@ -778,6 +775,8 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
778 | 775 | ||
779 | dev->ops = ops; | 776 | dev->ops = ops; |
780 | dev->supported_protocols = supported_protocols; | 777 | dev->supported_protocols = supported_protocols; |
778 | dev->supported_se = supported_se; | ||
779 | dev->active_se = NFC_SE_NONE; | ||
781 | dev->tx_headroom = tx_headroom; | 780 | dev->tx_headroom = tx_headroom; |
782 | dev->tx_tailroom = tx_tailroom; | 781 | dev->tx_tailroom = tx_tailroom; |
783 | 782 | ||
@@ -853,26 +852,27 @@ void nfc_unregister_device(struct nfc_dev *dev) | |||
853 | 852 | ||
854 | id = dev->idx; | 853 | id = dev->idx; |
855 | 854 | ||
856 | mutex_lock(&nfc_devlist_mutex); | 855 | if (dev->ops->check_presence) { |
857 | nfc_devlist_generation++; | 856 | device_lock(&dev->dev); |
858 | 857 | dev->shutting_down = true; | |
859 | /* lock to avoid unregistering a device while an operation | 858 | device_unlock(&dev->dev); |
860 | is in progress */ | 859 | del_timer_sync(&dev->check_pres_timer); |
861 | device_lock(&dev->dev); | 860 | cancel_work_sync(&dev->check_pres_work); |
862 | device_del(&dev->dev); | 861 | } |
863 | device_unlock(&dev->dev); | ||
864 | 862 | ||
865 | mutex_unlock(&nfc_devlist_mutex); | 863 | rc = nfc_genl_device_removed(dev); |
864 | if (rc) | ||
865 | pr_debug("The userspace won't be notified that the device %s " | ||
866 | "was removed\n", dev_name(&dev->dev)); | ||
866 | 867 | ||
867 | nfc_llcp_unregister_device(dev); | 868 | nfc_llcp_unregister_device(dev); |
868 | 869 | ||
869 | rc = nfc_genl_device_removed(dev); | 870 | mutex_lock(&nfc_devlist_mutex); |
870 | if (rc) | 871 | nfc_devlist_generation++; |
871 | pr_debug("The userspace won't be notified that the device %s was removed\n", | 872 | device_del(&dev->dev); |
872 | dev_name(&dev->dev)); | 873 | mutex_unlock(&nfc_devlist_mutex); |
873 | 874 | ||
874 | ida_simple_remove(&nfc_index_ida, id); | 875 | ida_simple_remove(&nfc_index_ida, id); |
875 | |||
876 | } | 876 | } |
877 | EXPORT_SYMBOL(nfc_unregister_device); | 877 | EXPORT_SYMBOL(nfc_unregister_device); |
878 | 878 | ||
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 7d99410e6c1a..64f922be9281 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
@@ -280,14 +280,19 @@ static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) | |||
280 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) | 280 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) |
281 | { | 281 | { |
282 | u8 param[2]; | 282 | u8 param[2]; |
283 | size_t param_len = 2; | ||
283 | 284 | ||
284 | /* TODO: Find out what the identity reference data is | 285 | /* TODO: Find out what the identity reference data is |
285 | * and fill param with it. HCI spec 6.1.3.5 */ | 286 | * and fill param with it. HCI spec 6.1.3.5 */ |
286 | 287 | ||
287 | pr_debug("\n"); | 288 | pr_debug("\n"); |
288 | 289 | ||
290 | if (test_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &hdev->quirks)) | ||
291 | param_len = 0; | ||
292 | |||
289 | return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | 293 | return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, |
290 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL); | 294 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, param_len, |
295 | NULL); | ||
291 | } | 296 | } |
292 | 297 | ||
293 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) | 298 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 7bea574d5934..91020b210d87 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -57,6 +57,8 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) | |||
57 | int r = 0; | 57 | int r = 0; |
58 | 58 | ||
59 | mutex_lock(&hdev->msg_tx_mutex); | 59 | mutex_lock(&hdev->msg_tx_mutex); |
60 | if (hdev->shutting_down) | ||
61 | goto exit; | ||
60 | 62 | ||
61 | if (hdev->cmd_pending_msg) { | 63 | if (hdev->cmd_pending_msg) { |
62 | if (timer_pending(&hdev->cmd_timer) == 0) { | 64 | if (timer_pending(&hdev->cmd_timer) == 0) { |
@@ -295,6 +297,12 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
295 | goto exit; | 297 | goto exit; |
296 | } | 298 | } |
297 | 299 | ||
300 | if (hdev->ops->event_received) { | ||
301 | r = hdev->ops->event_received(hdev, gate, event, skb); | ||
302 | if (r <= 0) | ||
303 | goto exit_noskb; | ||
304 | } | ||
305 | |||
298 | switch (event) { | 306 | switch (event) { |
299 | case NFC_HCI_EVT_TARGET_DISCOVERED: | 307 | case NFC_HCI_EVT_TARGET_DISCOVERED: |
300 | if (skb->len < 1) { /* no status data? */ | 308 | if (skb->len < 1) { /* no status data? */ |
@@ -320,17 +328,15 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
320 | r = nfc_hci_target_discovered(hdev, gate); | 328 | r = nfc_hci_target_discovered(hdev, gate); |
321 | break; | 329 | break; |
322 | default: | 330 | default: |
323 | if (hdev->ops->event_received) { | 331 | pr_info("Discarded unknown event %x to gate %x\n", event, gate); |
324 | hdev->ops->event_received(hdev, gate, event, skb); | 332 | r = -EINVAL; |
325 | return; | ||
326 | } | ||
327 | |||
328 | break; | 333 | break; |
329 | } | 334 | } |
330 | 335 | ||
331 | exit: | 336 | exit: |
332 | kfree_skb(skb); | 337 | kfree_skb(skb); |
333 | 338 | ||
339 | exit_noskb: | ||
334 | if (r) { | 340 | if (r) { |
335 | /* TODO: There was an error dispatching the event, | 341 | /* TODO: There was an error dispatching the event, |
336 | * how to propagate up to nfc core? | 342 | * how to propagate up to nfc core? |
@@ -669,8 +675,10 @@ static int hci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | |||
669 | 675 | ||
670 | if (hdev->ops->tm_send) | 676 | if (hdev->ops->tm_send) |
671 | return hdev->ops->tm_send(hdev, skb); | 677 | return hdev->ops->tm_send(hdev, skb); |
672 | else | 678 | |
673 | return -ENOTSUPP; | 679 | kfree_skb(skb); |
680 | |||
681 | return -ENOTSUPP; | ||
674 | } | 682 | } |
675 | 683 | ||
676 | static int hci_check_presence(struct nfc_dev *nfc_dev, | 684 | static int hci_check_presence(struct nfc_dev *nfc_dev, |
@@ -787,7 +795,9 @@ static struct nfc_ops hci_nfc_ops = { | |||
787 | 795 | ||
788 | struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | 796 | struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, |
789 | struct nfc_hci_init_data *init_data, | 797 | struct nfc_hci_init_data *init_data, |
798 | unsigned long quirks, | ||
790 | u32 protocols, | 799 | u32 protocols, |
800 | u32 supported_se, | ||
791 | const char *llc_name, | 801 | const char *llc_name, |
792 | int tx_headroom, | 802 | int tx_headroom, |
793 | int tx_tailroom, | 803 | int tx_tailroom, |
@@ -813,7 +823,7 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | |||
813 | return NULL; | 823 | return NULL; |
814 | } | 824 | } |
815 | 825 | ||
816 | hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, | 826 | hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, supported_se, |
817 | tx_headroom + HCI_CMDS_HEADROOM, | 827 | tx_headroom + HCI_CMDS_HEADROOM, |
818 | tx_tailroom); | 828 | tx_tailroom); |
819 | if (!hdev->ndev) { | 829 | if (!hdev->ndev) { |
@@ -830,6 +840,8 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | |||
830 | 840 | ||
831 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | 841 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); |
832 | 842 | ||
843 | hdev->quirks = quirks; | ||
844 | |||
833 | return hdev; | 845 | return hdev; |
834 | } | 846 | } |
835 | EXPORT_SYMBOL(nfc_hci_allocate_device); | 847 | EXPORT_SYMBOL(nfc_hci_allocate_device); |
@@ -868,6 +880,28 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) | |||
868 | { | 880 | { |
869 | struct hci_msg *msg, *n; | 881 | struct hci_msg *msg, *n; |
870 | 882 | ||
883 | mutex_lock(&hdev->msg_tx_mutex); | ||
884 | |||
885 | if (hdev->cmd_pending_msg) { | ||
886 | if (hdev->cmd_pending_msg->cb) | ||
887 | hdev->cmd_pending_msg->cb( | ||
888 | hdev->cmd_pending_msg->cb_context, | ||
889 | NULL, -ESHUTDOWN); | ||
890 | kfree(hdev->cmd_pending_msg); | ||
891 | hdev->cmd_pending_msg = NULL; | ||
892 | } | ||
893 | |||
894 | hdev->shutting_down = true; | ||
895 | |||
896 | mutex_unlock(&hdev->msg_tx_mutex); | ||
897 | |||
898 | del_timer_sync(&hdev->cmd_timer); | ||
899 | cancel_work_sync(&hdev->msg_tx_work); | ||
900 | |||
901 | cancel_work_sync(&hdev->msg_rx_work); | ||
902 | |||
903 | nfc_unregister_device(hdev->ndev); | ||
904 | |||
871 | skb_queue_purge(&hdev->rx_hcp_frags); | 905 | skb_queue_purge(&hdev->rx_hcp_frags); |
872 | skb_queue_purge(&hdev->msg_rx_queue); | 906 | skb_queue_purge(&hdev->msg_rx_queue); |
873 | 907 | ||
@@ -876,13 +910,6 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) | |||
876 | skb_queue_purge(&msg->msg_frags); | 910 | skb_queue_purge(&msg->msg_frags); |
877 | kfree(msg); | 911 | kfree(msg); |
878 | } | 912 | } |
879 | |||
880 | del_timer_sync(&hdev->cmd_timer); | ||
881 | |||
882 | nfc_unregister_device(hdev->ndev); | ||
883 | |||
884 | cancel_work_sync(&hdev->msg_tx_work); | ||
885 | cancel_work_sync(&hdev->msg_rx_work); | ||
886 | } | 913 | } |
887 | EXPORT_SYMBOL(nfc_hci_unregister_device); | 914 | EXPORT_SYMBOL(nfc_hci_unregister_device); |
888 | 915 | ||
diff --git a/net/nfc/hci/hcp.c b/net/nfc/hci/hcp.c index bc308a7ca609..b6b4109f2343 100644 --- a/net/nfc/hci/hcp.c +++ b/net/nfc/hci/hcp.c | |||
@@ -105,6 +105,13 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, | |||
105 | } | 105 | } |
106 | 106 | ||
107 | mutex_lock(&hdev->msg_tx_mutex); | 107 | mutex_lock(&hdev->msg_tx_mutex); |
108 | |||
109 | if (hdev->shutting_down) { | ||
110 | err = -ESHUTDOWN; | ||
111 | mutex_unlock(&hdev->msg_tx_mutex); | ||
112 | goto out_skb_err; | ||
113 | } | ||
114 | |||
108 | list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue); | 115 | list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue); |
109 | mutex_unlock(&hdev->msg_tx_mutex); | 116 | mutex_unlock(&hdev->msg_tx_mutex); |
110 | 117 | ||
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index df24be48d4da..c6bc3bd95052 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -304,6 +304,8 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) | |||
304 | 304 | ||
305 | skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); | 305 | skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); |
306 | 306 | ||
307 | __net_timestamp(skb); | ||
308 | |||
307 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); | 309 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); |
308 | 310 | ||
309 | return nfc_data_exchange(dev, local->target_idx, skb, | 311 | return nfc_data_exchange(dev, local->target_idx, skb, |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index ec43914c92a9..85bc75c38dea 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -54,7 +54,6 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) | |||
54 | 54 | ||
55 | skb_queue_purge(&sock->tx_queue); | 55 | skb_queue_purge(&sock->tx_queue); |
56 | skb_queue_purge(&sock->tx_pending_queue); | 56 | skb_queue_purge(&sock->tx_pending_queue); |
57 | skb_queue_purge(&sock->tx_backlog_queue); | ||
58 | 57 | ||
59 | if (local == NULL) | 58 | if (local == NULL) |
60 | return; | 59 | return; |
@@ -668,6 +667,8 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
668 | if (ptype == LLCP_PDU_I) | 667 | if (ptype == LLCP_PDU_I) |
669 | copy_skb = skb_copy(skb, GFP_ATOMIC); | 668 | copy_skb = skb_copy(skb, GFP_ATOMIC); |
670 | 669 | ||
670 | __net_timestamp(skb); | ||
671 | |||
671 | nfc_llcp_send_to_raw_sock(local, skb, | 672 | nfc_llcp_send_to_raw_sock(local, skb, |
672 | NFC_LLCP_DIRECTION_TX); | 673 | NFC_LLCP_DIRECTION_TX); |
673 | 674 | ||
@@ -781,9 +782,15 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, | |||
781 | 782 | ||
782 | /* There is no sequence with UI frames */ | 783 | /* There is no sequence with UI frames */ |
783 | skb_pull(skb, LLCP_HEADER_SIZE); | 784 | skb_pull(skb, LLCP_HEADER_SIZE); |
784 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { | 785 | if (!sock_queue_rcv_skb(&llcp_sock->sk, skb)) { |
785 | pr_err("receive queue is full\n"); | 786 | /* |
786 | skb_queue_head(&llcp_sock->tx_backlog_queue, skb); | 787 | * UI frames will be freed from the socket layer, so we |
788 | * need to keep them alive until someone receives them. | ||
789 | */ | ||
790 | skb_get(skb); | ||
791 | } else { | ||
792 | pr_err("Receive queue is full\n"); | ||
793 | kfree_skb(skb); | ||
787 | } | 794 | } |
788 | 795 | ||
789 | nfc_llcp_sock_put(llcp_sock); | 796 | nfc_llcp_sock_put(llcp_sock); |
@@ -976,9 +983,15 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
976 | pr_err("Received out of sequence I PDU\n"); | 983 | pr_err("Received out of sequence I PDU\n"); |
977 | 984 | ||
978 | skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); | 985 | skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); |
979 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { | 986 | if (!sock_queue_rcv_skb(&llcp_sock->sk, skb)) { |
980 | pr_err("receive queue is full\n"); | 987 | /* |
981 | skb_queue_head(&llcp_sock->tx_backlog_queue, skb); | 988 | * I frames will be freed from the socket layer, so we |
989 | * need to keep them alive until someone receives them. | ||
990 | */ | ||
991 | skb_get(skb); | ||
992 | } else { | ||
993 | pr_err("Receive queue is full\n"); | ||
994 | kfree_skb(skb); | ||
982 | } | 995 | } |
983 | } | 996 | } |
984 | 997 | ||
@@ -1245,6 +1258,8 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1245 | print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, | 1258 | print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, |
1246 | 16, 1, skb->data, skb->len, true); | 1259 | 16, 1, skb->data, skb->len, true); |
1247 | 1260 | ||
1261 | __net_timestamp(skb); | ||
1262 | |||
1248 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); | 1263 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); |
1249 | 1264 | ||
1250 | switch (ptype) { | 1265 | switch (ptype) { |
@@ -1296,6 +1311,13 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1296 | local->rx_pending = NULL; | 1311 | local->rx_pending = NULL; |
1297 | } | 1312 | } |
1298 | 1313 | ||
1314 | static void __nfc_llcp_recv(struct nfc_llcp_local *local, struct sk_buff *skb) | ||
1315 | { | ||
1316 | local->rx_pending = skb; | ||
1317 | del_timer(&local->link_timer); | ||
1318 | schedule_work(&local->rx_work); | ||
1319 | } | ||
1320 | |||
1299 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | 1321 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) |
1300 | { | 1322 | { |
1301 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; | 1323 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; |
@@ -1306,9 +1328,7 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
1306 | return; | 1328 | return; |
1307 | } | 1329 | } |
1308 | 1330 | ||
1309 | local->rx_pending = skb_get(skb); | 1331 | __nfc_llcp_recv(local, skb); |
1310 | del_timer(&local->link_timer); | ||
1311 | schedule_work(&local->rx_work); | ||
1312 | } | 1332 | } |
1313 | 1333 | ||
1314 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | 1334 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) |
@@ -1319,9 +1339,7 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | |||
1319 | if (local == NULL) | 1339 | if (local == NULL) |
1320 | return -ENODEV; | 1340 | return -ENODEV; |
1321 | 1341 | ||
1322 | local->rx_pending = skb_get(skb); | 1342 | __nfc_llcp_recv(local, skb); |
1323 | del_timer(&local->link_timer); | ||
1324 | schedule_work(&local->rx_work); | ||
1325 | 1343 | ||
1326 | return 0; | 1344 | return 0; |
1327 | } | 1345 | } |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 0d62366f8cc3..0eae5c509504 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -121,7 +121,6 @@ struct nfc_llcp_sock { | |||
121 | 121 | ||
122 | struct sk_buff_head tx_queue; | 122 | struct sk_buff_head tx_queue; |
123 | struct sk_buff_head tx_pending_queue; | 123 | struct sk_buff_head tx_pending_queue; |
124 | struct sk_buff_head tx_backlog_queue; | ||
125 | 124 | ||
126 | struct list_head accept_queue; | 125 | struct list_head accept_queue; |
127 | struct sock *parent; | 126 | struct sock *parent; |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index fea22eb41b82..5332751943a9 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -672,25 +672,27 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
672 | copied = min_t(unsigned int, rlen, len); | 672 | copied = min_t(unsigned int, rlen, len); |
673 | 673 | ||
674 | cskb = skb; | 674 | cskb = skb; |
675 | if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) { | 675 | if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) { |
676 | if (!(flags & MSG_PEEK)) | 676 | if (!(flags & MSG_PEEK)) |
677 | skb_queue_head(&sk->sk_receive_queue, skb); | 677 | skb_queue_head(&sk->sk_receive_queue, skb); |
678 | return -EFAULT; | 678 | return -EFAULT; |
679 | } | 679 | } |
680 | 680 | ||
681 | sock_recv_timestamp(msg, sk, skb); | ||
682 | |||
681 | if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { | 683 | if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { |
682 | struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); | 684 | struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); |
683 | struct sockaddr_nfc_llcp sockaddr; | 685 | struct sockaddr_nfc_llcp *sockaddr = |
686 | (struct sockaddr_nfc_llcp *) msg->msg_name; | ||
684 | 687 | ||
685 | pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); | 688 | msg->msg_namelen = sizeof(struct sockaddr_nfc_llcp); |
686 | 689 | ||
687 | sockaddr.sa_family = AF_NFC; | 690 | pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); |
688 | sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP; | ||
689 | sockaddr.dsap = ui_cb->dsap; | ||
690 | sockaddr.ssap = ui_cb->ssap; | ||
691 | 691 | ||
692 | memcpy(msg->msg_name, &sockaddr, sizeof(sockaddr)); | 692 | sockaddr->sa_family = AF_NFC; |
693 | msg->msg_namelen = sizeof(sockaddr); | 693 | sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP; |
694 | sockaddr->dsap = ui_cb->dsap; | ||
695 | sockaddr->ssap = ui_cb->ssap; | ||
694 | } | 696 | } |
695 | 697 | ||
696 | /* Mark read part of skb as used */ | 698 | /* Mark read part of skb as used */ |
@@ -806,7 +808,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
806 | llcp_sock->reserved_ssap = LLCP_SAP_MAX; | 808 | llcp_sock->reserved_ssap = LLCP_SAP_MAX; |
807 | skb_queue_head_init(&llcp_sock->tx_queue); | 809 | skb_queue_head_init(&llcp_sock->tx_queue); |
808 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | 810 | skb_queue_head_init(&llcp_sock->tx_pending_queue); |
809 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | ||
810 | INIT_LIST_HEAD(&llcp_sock->accept_queue); | 811 | INIT_LIST_HEAD(&llcp_sock->accept_queue); |
811 | 812 | ||
812 | if (sock != NULL) | 813 | if (sock != NULL) |
@@ -821,7 +822,6 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | |||
821 | 822 | ||
822 | skb_queue_purge(&sock->tx_queue); | 823 | skb_queue_purge(&sock->tx_queue); |
823 | skb_queue_purge(&sock->tx_pending_queue); | 824 | skb_queue_purge(&sock->tx_pending_queue); |
824 | skb_queue_purge(&sock->tx_backlog_queue); | ||
825 | 825 | ||
826 | list_del_init(&sock->accept_queue); | 826 | list_del_init(&sock->accept_queue); |
827 | 827 | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 5f98dc1bf039..48ada0ec749e 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -658,6 +658,7 @@ static struct nfc_ops nci_nfc_ops = { | |||
658 | */ | 658 | */ |
659 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, | 659 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, |
660 | __u32 supported_protocols, | 660 | __u32 supported_protocols, |
661 | __u32 supported_se, | ||
661 | int tx_headroom, int tx_tailroom) | 662 | int tx_headroom, int tx_tailroom) |
662 | { | 663 | { |
663 | struct nci_dev *ndev; | 664 | struct nci_dev *ndev; |
@@ -680,6 +681,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, | |||
680 | 681 | ||
681 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, | 682 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, |
682 | supported_protocols, | 683 | supported_protocols, |
684 | supported_se, | ||
683 | tx_headroom + NCI_DATA_HDR_SIZE, | 685 | tx_headroom + NCI_DATA_HDR_SIZE, |
684 | tx_tailroom); | 686 | tx_tailroom); |
685 | if (!ndev->nfc_dev) | 687 | if (!ndev->nfc_dev) |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 3568ae16786d..504b883439f1 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -366,6 +366,7 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | |||
366 | if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || | 366 | if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || |
367 | nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || | 367 | nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || |
368 | nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || | 368 | nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || |
369 | nla_put_u32(msg, NFC_ATTR_SE, dev->supported_se) || | ||
369 | nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) || | 370 | nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) || |
370 | nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode)) | 371 | nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode)) |
371 | goto nla_put_failure; | 372 | goto nla_put_failure; |