aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/nfc/pn533.c15
-rw-r--r--include/linux/nfc.h11
-rw-r--r--net/nfc/llcp/commands.c2
-rw-r--r--net/nfc/llcp/llcp.c60
-rw-r--r--net/nfc/llcp/llcp.h3
-rw-r--r--net/nfc/llcp/sock.c90
-rw-r--r--net/nfc/netlink.c46
7 files changed, 202 insertions, 25 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index d123444404c8..97c440a8cd61 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -716,7 +716,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
716 void *arg, gfp_t flags) 716 void *arg, gfp_t flags)
717{ 717{
718 struct pn533_cmd *cmd; 718 struct pn533_cmd *cmd;
719 int rc; 719 int rc = 0;
720 720
721 nfc_dev_dbg(&dev->interface->dev, "%s", __func__); 721 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
722 722
@@ -729,16 +729,16 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
729 if (!rc) 729 if (!rc)
730 dev->cmd_pending = 1; 730 dev->cmd_pending = 1;
731 731
732 mutex_unlock(&dev->cmd_lock); 732 goto unlock;
733
734 return rc;
735 } 733 }
736 734
737 nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__); 735 nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__);
738 736
739 cmd = kzalloc(sizeof(struct pn533_cmd), flags); 737 cmd = kzalloc(sizeof(struct pn533_cmd), flags);
740 if (!cmd) 738 if (!cmd) {
741 return -ENOMEM; 739 rc = -ENOMEM;
740 goto unlock;
741 }
742 742
743 INIT_LIST_HEAD(&cmd->queue); 743 INIT_LIST_HEAD(&cmd->queue);
744 cmd->out_frame = out_frame; 744 cmd->out_frame = out_frame;
@@ -750,9 +750,10 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
750 750
751 list_add_tail(&cmd->queue, &dev->cmd_queue); 751 list_add_tail(&cmd->queue, &dev->cmd_queue);
752 752
753unlock:
753 mutex_unlock(&dev->cmd_lock); 754 mutex_unlock(&dev->cmd_lock);
754 755
755 return 0; 756 return rc;
756} 757}
757 758
758struct pn533_sync_cmd_response { 759struct pn533_sync_cmd_response {
diff --git a/include/linux/nfc.h b/include/linux/nfc.h
index 6189f27e305b..d908d17da56d 100644
--- a/include/linux/nfc.h
+++ b/include/linux/nfc.h
@@ -183,4 +183,15 @@ struct sockaddr_nfc_llcp {
183 183
184#define NFC_HEADER_SIZE 1 184#define NFC_HEADER_SIZE 1
185 185
186/**
187 * Pseudo-header info for raw socket packets
188 * First byte is the adapter index
189 * Second byte contains flags
190 * - 0x01 - Direction (0=RX, 1=TX)
191 * - 0x02-0x80 - Reserved
192 **/
193#define NFC_LLCP_RAW_HEADER_SIZE 2
194#define NFC_LLCP_DIRECTION_RX 0x00
195#define NFC_LLCP_DIRECTION_TX 0x01
196
186#endif /*__LINUX_NFC_H */ 197#endif /*__LINUX_NFC_H */
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index b982b5b890d7..c45ccd6c094c 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -312,6 +312,8 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
312 312
313 skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); 313 skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM);
314 314
315 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX);
316
315 return nfc_data_exchange(dev, local->target_idx, skb, 317 return nfc_data_exchange(dev, local->target_idx, skb,
316 nfc_llcp_recv, local); 318 nfc_llcp_recv, local);
317} 319}
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 90ef4a176819..c12c5ef3d036 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -56,7 +56,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
56 sk_for_each_safe(sk, node, tmp, &local->sockets.head) { 56 sk_for_each_safe(sk, node, tmp, &local->sockets.head) {
57 llcp_sock = nfc_llcp_sock(sk); 57 llcp_sock = nfc_llcp_sock(sk);
58 58
59 lock_sock(sk); 59 bh_lock_sock(sk);
60 60
61 if (sk->sk_state == LLCP_CONNECTED) 61 if (sk->sk_state == LLCP_CONNECTED)
62 nfc_put_device(llcp_sock->dev); 62 nfc_put_device(llcp_sock->dev);
@@ -68,26 +68,26 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
68 list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, 68 list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue,
69 accept_queue) { 69 accept_queue) {
70 accept_sk = &lsk->sk; 70 accept_sk = &lsk->sk;
71 lock_sock(accept_sk); 71 bh_lock_sock(accept_sk);
72 72
73 nfc_llcp_accept_unlink(accept_sk); 73 nfc_llcp_accept_unlink(accept_sk);
74 74
75 accept_sk->sk_state = LLCP_CLOSED; 75 accept_sk->sk_state = LLCP_CLOSED;
76 76
77 release_sock(accept_sk); 77 bh_unlock_sock(accept_sk);
78 78
79 sock_orphan(accept_sk); 79 sock_orphan(accept_sk);
80 } 80 }
81 81
82 if (listen == true) { 82 if (listen == true) {
83 release_sock(sk); 83 bh_unlock_sock(sk);
84 continue; 84 continue;
85 } 85 }
86 } 86 }
87 87
88 sk->sk_state = LLCP_CLOSED; 88 sk->sk_state = LLCP_CLOSED;
89 89
90 release_sock(sk); 90 bh_unlock_sock(sk);
91 91
92 sock_orphan(sk); 92 sock_orphan(sk);
93 93
@@ -558,6 +558,46 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
558 sock->recv_ack_n = (sock->recv_n - 1) % 16; 558 sock->recv_ack_n = (sock->recv_n - 1) % 16;
559} 559}
560 560
561void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
562 struct sk_buff *skb, u8 direction)
563{
564 struct hlist_node *node;
565 struct sk_buff *skb_copy = NULL, *nskb;
566 struct sock *sk;
567 u8 *data;
568
569 read_lock(&local->raw_sockets.lock);
570
571 sk_for_each(sk, node, &local->raw_sockets.head) {
572 if (sk->sk_state != LLCP_BOUND)
573 continue;
574
575 if (skb_copy == NULL) {
576 skb_copy = __pskb_copy(skb, NFC_LLCP_RAW_HEADER_SIZE,
577 GFP_ATOMIC);
578
579 if (skb_copy == NULL)
580 continue;
581
582 data = skb_push(skb_copy, NFC_LLCP_RAW_HEADER_SIZE);
583
584 data[0] = local->dev ? local->dev->idx : 0xFF;
585 data[1] = direction;
586 }
587
588 nskb = skb_clone(skb_copy, GFP_ATOMIC);
589 if (!nskb)
590 continue;
591
592 if (sock_queue_rcv_skb(sk, nskb))
593 kfree_skb(nskb);
594 }
595
596 read_unlock(&local->raw_sockets.lock);
597
598 kfree_skb(skb_copy);
599}
600
561static void nfc_llcp_tx_work(struct work_struct *work) 601static void nfc_llcp_tx_work(struct work_struct *work)
562{ 602{
563 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, 603 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
@@ -578,6 +618,9 @@ static void nfc_llcp_tx_work(struct work_struct *work)
578 DUMP_PREFIX_OFFSET, 16, 1, 618 DUMP_PREFIX_OFFSET, 16, 1,
579 skb->data, skb->len, true); 619 skb->data, skb->len, true);
580 620
621 nfc_llcp_send_to_raw_sock(local, skb,
622 NFC_LLCP_DIRECTION_TX);
623
581 ret = nfc_data_exchange(local->dev, local->target_idx, 624 ret = nfc_data_exchange(local->dev, local->target_idx,
582 skb, nfc_llcp_recv, local); 625 skb, nfc_llcp_recv, local);
583 626
@@ -1022,6 +1065,8 @@ static void nfc_llcp_rx_work(struct work_struct *work)
1022 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, 1065 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET,
1023 16, 1, skb->data, skb->len, true); 1066 16, 1, skb->data, skb->len, true);
1024 1067
1068 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
1069
1025 switch (ptype) { 1070 switch (ptype) {
1026 case LLCP_PDU_SYMM: 1071 case LLCP_PDU_SYMM:
1027 pr_debug("SYMM\n"); 1072 pr_debug("SYMM\n");
@@ -1156,8 +1201,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
1156 1201
1157 INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work); 1202 INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work);
1158 1203
1159 local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); 1204 rwlock_init(&local->sockets.lock);
1160 local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); 1205 rwlock_init(&local->connecting_sockets.lock);
1206 rwlock_init(&local->raw_sockets.lock);
1161 1207
1162 nfc_llcp_build_gb(local); 1208 nfc_llcp_build_gb(local);
1163 1209
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index af395c9ceb03..fdb2d24e60bd 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -86,6 +86,7 @@ struct nfc_llcp_local {
86 /* sockets array */ 86 /* sockets array */
87 struct llcp_sock_list sockets; 87 struct llcp_sock_list sockets;
88 struct llcp_sock_list connecting_sockets; 88 struct llcp_sock_list connecting_sockets;
89 struct llcp_sock_list raw_sockets;
89}; 90};
90 91
91struct nfc_llcp_sock { 92struct nfc_llcp_sock {
@@ -184,6 +185,8 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
184u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); 185u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
185void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); 186void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap);
186int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock); 187int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock);
188void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
189 struct sk_buff *skb, u8 direction);
187 190
188/* Sock API */ 191/* Sock API */
189struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp); 192struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 6e188d4020ba..40f056debf9a 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -142,6 +142,60 @@ error:
142 return ret; 142 return ret;
143} 143}
144 144
145static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
146 int alen)
147{
148 struct sock *sk = sock->sk;
149 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
150 struct nfc_llcp_local *local;
151 struct nfc_dev *dev;
152 struct sockaddr_nfc_llcp llcp_addr;
153 int len, ret = 0;
154
155 if (!addr || addr->sa_family != AF_NFC)
156 return -EINVAL;
157
158 pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
159
160 memset(&llcp_addr, 0, sizeof(llcp_addr));
161 len = min_t(unsigned int, sizeof(llcp_addr), alen);
162 memcpy(&llcp_addr, addr, len);
163
164 lock_sock(sk);
165
166 if (sk->sk_state != LLCP_CLOSED) {
167 ret = -EBADFD;
168 goto error;
169 }
170
171 dev = nfc_get_device(llcp_addr.dev_idx);
172 if (dev == NULL) {
173 ret = -ENODEV;
174 goto error;
175 }
176
177 local = nfc_llcp_find_local(dev);
178 if (local == NULL) {
179 ret = -ENODEV;
180 goto put_dev;
181 }
182
183 llcp_sock->dev = dev;
184 llcp_sock->local = nfc_llcp_local_get(local);
185 llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
186
187 nfc_llcp_sock_link(&local->raw_sockets, sk);
188
189 sk->sk_state = LLCP_BOUND;
190
191put_dev:
192 nfc_put_device(dev);
193
194error:
195 release_sock(sk);
196 return ret;
197}
198
145static int llcp_sock_listen(struct socket *sock, int backlog) 199static int llcp_sock_listen(struct socket *sock, int backlog)
146{ 200{
147 struct sock *sk = sock->sk; 201 struct sock *sk = sock->sk;
@@ -418,7 +472,10 @@ static int llcp_sock_release(struct socket *sock)
418 472
419 release_sock(sk); 473 release_sock(sk);
420 474
421 nfc_llcp_sock_unlink(&local->sockets, sk); 475 if (sock->type == SOCK_RAW)
476 nfc_llcp_sock_unlink(&local->raw_sockets, sk);
477 else
478 nfc_llcp_sock_unlink(&local->sockets, sk);
422 479
423out: 480out:
424 sock_orphan(sk); 481 sock_orphan(sk);
@@ -614,7 +671,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
614 if (!(flags & MSG_PEEK)) { 671 if (!(flags & MSG_PEEK)) {
615 672
616 /* SOCK_STREAM: re-queue skb if it contains unreceived data */ 673 /* SOCK_STREAM: re-queue skb if it contains unreceived data */
617 if (sk->sk_type == SOCK_STREAM) { 674 if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_RAW) {
618 skb_pull(skb, copied); 675 skb_pull(skb, copied);
619 if (skb->len) { 676 if (skb->len) {
620 skb_queue_head(&sk->sk_receive_queue, skb); 677 skb_queue_head(&sk->sk_receive_queue, skb);
@@ -655,6 +712,26 @@ static const struct proto_ops llcp_sock_ops = {
655 .mmap = sock_no_mmap, 712 .mmap = sock_no_mmap,
656}; 713};
657 714
715static const struct proto_ops llcp_rawsock_ops = {
716 .family = PF_NFC,
717 .owner = THIS_MODULE,
718 .bind = llcp_raw_sock_bind,
719 .connect = sock_no_connect,
720 .release = llcp_sock_release,
721 .socketpair = sock_no_socketpair,
722 .accept = sock_no_accept,
723 .getname = llcp_sock_getname,
724 .poll = llcp_sock_poll,
725 .ioctl = sock_no_ioctl,
726 .listen = sock_no_listen,
727 .shutdown = sock_no_shutdown,
728 .setsockopt = sock_no_setsockopt,
729 .getsockopt = sock_no_getsockopt,
730 .sendmsg = sock_no_sendmsg,
731 .recvmsg = llcp_sock_recvmsg,
732 .mmap = sock_no_mmap,
733};
734
658static void llcp_sock_destruct(struct sock *sk) 735static void llcp_sock_destruct(struct sock *sk)
659{ 736{
660 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); 737 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -732,10 +809,15 @@ static int llcp_sock_create(struct net *net, struct socket *sock,
732 809
733 pr_debug("%p\n", sock); 810 pr_debug("%p\n", sock);
734 811
735 if (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM) 812 if (sock->type != SOCK_STREAM &&
813 sock->type != SOCK_DGRAM &&
814 sock->type != SOCK_RAW)
736 return -ESOCKTNOSUPPORT; 815 return -ESOCKTNOSUPPORT;
737 816
738 sock->ops = &llcp_sock_ops; 817 if (sock->type == SOCK_RAW)
818 sock->ops = &llcp_rawsock_ops;
819 else
820 sock->ops = &llcp_sock_ops;
739 821
740 sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC); 822 sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC);
741 if (sk == NULL) 823 if (sk == NULL)
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 4c51714ee741..baa6af9500df 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -761,31 +761,63 @@ static struct genl_ops nfc_genl_ops[] = {
761 }, 761 },
762}; 762};
763 763
764static int nfc_genl_rcv_nl_event(struct notifier_block *this, 764
765 unsigned long event, void *ptr) 765struct urelease_work {
766 struct work_struct w;
767 int pid;
768};
769
770static void nfc_urelease_event_work(struct work_struct *work)
766{ 771{
767 struct netlink_notify *n = ptr; 772 struct urelease_work *w = container_of(work, struct urelease_work, w);
768 struct class_dev_iter iter; 773 struct class_dev_iter iter;
769 struct nfc_dev *dev; 774 struct nfc_dev *dev;
770 775
771 if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC) 776 pr_debug("pid %d\n", w->pid);
772 goto out;
773 777
774 pr_debug("NETLINK_URELEASE event from id %d\n", n->pid); 778 mutex_lock(&nfc_devlist_mutex);
775 779
776 nfc_device_iter_init(&iter); 780 nfc_device_iter_init(&iter);
777 dev = nfc_device_iter_next(&iter); 781 dev = nfc_device_iter_next(&iter);
778 782
779 while (dev) { 783 while (dev) {
780 if (dev->genl_data.poll_req_pid == n->pid) { 784 mutex_lock(&dev->genl_data.genl_data_mutex);
785
786 if (dev->genl_data.poll_req_pid == w->pid) {
781 nfc_stop_poll(dev); 787 nfc_stop_poll(dev);
782 dev->genl_data.poll_req_pid = 0; 788 dev->genl_data.poll_req_pid = 0;
783 } 789 }
790
791 mutex_unlock(&dev->genl_data.genl_data_mutex);
792
784 dev = nfc_device_iter_next(&iter); 793 dev = nfc_device_iter_next(&iter);
785 } 794 }
786 795
787 nfc_device_iter_exit(&iter); 796 nfc_device_iter_exit(&iter);
788 797
798 mutex_unlock(&nfc_devlist_mutex);
799
800 kfree(w);
801}
802
803static int nfc_genl_rcv_nl_event(struct notifier_block *this,
804 unsigned long event, void *ptr)
805{
806 struct netlink_notify *n = ptr;
807 struct urelease_work *w;
808
809 if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC)
810 goto out;
811
812 pr_debug("NETLINK_URELEASE event from id %d\n", n->pid);
813
814 w = kmalloc(sizeof(*w), GFP_ATOMIC);
815 if (w) {
816 INIT_WORK((struct work_struct *) w, nfc_urelease_event_work);
817 w->pid = n->pid;
818 schedule_work((struct work_struct *) w);
819 }
820
789out: 821out:
790 return NOTIFY_DONE; 822 return NOTIFY_DONE;
791} 823}