aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-05-04 05:24:16 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-06-04 15:34:28 -0400
commitc7aa12252f5142b9eee2f6e34ca8870a8e7e048c (patch)
treee91c72609e7d13b3a185cf75acd74a8385c736c5
parentf8f5701bdaf9134b1f90e5044a82c66324d2073f (diff)
NFC: Take a reference on the LLCP local pointer when creating a socket
LLCP sockets point to their local LLCP service, so they need to take a reference on it. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--net/nfc/llcp/llcp.c46
-rw-r--r--net/nfc/llcp/llcp.h4
-rw-r--r--net/nfc/llcp/sock.c14
3 files changed, 40 insertions, 24 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 42994fac26d6..0f6dd3a53dca 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -59,8 +59,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
59 release_sock(sk); 59 release_sock(sk);
60 60
61 sock_orphan(sk); 61 sock_orphan(sk);
62
63 s->local = NULL;
64 } 62 }
65 63
66 parent_sk = &parent->sk; 64 parent_sk = &parent->sk;
@@ -83,8 +81,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
83 release_sock(accept_sk); 81 release_sock(accept_sk);
84 82
85 sock_orphan(accept_sk); 83 sock_orphan(accept_sk);
86
87 lsk->local = NULL;
88 } 84 }
89 } 85 }
90 86
@@ -96,13 +92,39 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
96 release_sock(parent_sk); 92 release_sock(parent_sk);
97 93
98 sock_orphan(parent_sk); 94 sock_orphan(parent_sk);
99
100 parent->local = NULL;
101 } 95 }
102 96
103 mutex_unlock(&local->socket_lock); 97 mutex_unlock(&local->socket_lock);
104} 98}
105 99
100struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
101{
102 kref_get(&local->ref);
103
104 return local;
105}
106
107static void local_release(struct kref *ref)
108{
109 struct nfc_llcp_local *local;
110
111 local = container_of(ref, struct nfc_llcp_local, ref);
112
113 list_del(&local->list);
114 nfc_llcp_socket_release(local);
115 del_timer_sync(&local->link_timer);
116 skb_queue_purge(&local->tx_queue);
117 destroy_workqueue(local->tx_wq);
118 destroy_workqueue(local->rx_wq);
119 kfree_skb(local->rx_pending);
120 kfree(local);
121}
122
123int nfc_llcp_local_put(struct nfc_llcp_local *local)
124{
125 return kref_put(&local->ref, local_release);
126}
127
106static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) 128static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local)
107{ 129{
108 mutex_lock(&local->sdp_lock); 130 mutex_lock(&local->sdp_lock);
@@ -612,7 +634,7 @@ enqueue:
612 634
613 new_sock = nfc_llcp_sock(new_sk); 635 new_sock = nfc_llcp_sock(new_sk);
614 new_sock->dev = local->dev; 636 new_sock->dev = local->dev;
615 new_sock->local = local; 637 new_sock->local = nfc_llcp_local_get(local);
616 new_sock->nfc_protocol = sock->nfc_protocol; 638 new_sock->nfc_protocol = sock->nfc_protocol;
617 new_sock->ssap = bound_sap; 639 new_sock->ssap = bound_sap;
618 new_sock->dsap = ssap; 640 new_sock->dsap = ssap;
@@ -943,6 +965,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
943 965
944 local->dev = ndev; 966 local->dev = ndev;
945 INIT_LIST_HEAD(&local->list); 967 INIT_LIST_HEAD(&local->list);
968 kref_init(&local->ref);
946 mutex_init(&local->sdp_lock); 969 mutex_init(&local->sdp_lock);
947 mutex_init(&local->socket_lock); 970 mutex_init(&local->socket_lock);
948 init_timer(&local->link_timer); 971 init_timer(&local->link_timer);
@@ -1015,14 +1038,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
1015 return; 1038 return;
1016 } 1039 }
1017 1040
1018 list_del(&local->list); 1041 nfc_llcp_local_put(local);
1019 nfc_llcp_socket_release(local);
1020 del_timer_sync(&local->link_timer);
1021 skb_queue_purge(&local->tx_queue);
1022 destroy_workqueue(local->tx_wq);
1023 destroy_workqueue(local->rx_wq);
1024 kfree_skb(local->rx_pending);
1025 kfree(local);
1026} 1042}
1027 1043
1028int __init nfc_llcp_init(void) 1044int __init nfc_llcp_init(void)
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 50680ce5ae43..bc619553821b 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -44,6 +44,8 @@ struct nfc_llcp_local {
44 struct list_head list; 44 struct list_head list;
45 struct nfc_dev *dev; 45 struct nfc_dev *dev;
46 46
47 struct kref ref;
48
47 struct mutex sdp_lock; 49 struct mutex sdp_lock;
48 struct mutex socket_lock; 50 struct mutex socket_lock;
49 51
@@ -165,6 +167,8 @@ struct nfc_llcp_sock {
165 167
166 168
167struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); 169struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
170struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
171int nfc_llcp_local_put(struct nfc_llcp_local *local);
168u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, 172u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
169 struct nfc_llcp_sock *sock); 173 struct nfc_llcp_sock *sock);
170u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); 174u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 3f339b19d140..9ac397b17718 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
111 } 111 }
112 112
113 llcp_sock->dev = dev; 113 llcp_sock->dev = dev;
114 llcp_sock->local = local; 114 llcp_sock->local = nfc_llcp_local_get(local);
115 llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; 115 llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
116 llcp_sock->service_name_len = min_t(unsigned int, 116 llcp_sock->service_name_len = min_t(unsigned int,
117 llcp_addr.service_name_len, 117 llcp_addr.service_name_len,
@@ -487,7 +487,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
487 } 487 }
488 488
489 llcp_sock->dev = dev; 489 llcp_sock->dev = dev;
490 llcp_sock->local = local; 490 llcp_sock->local = nfc_llcp_local_get(local);
491 llcp_sock->ssap = nfc_llcp_get_local_ssap(local); 491 llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
492 if (llcp_sock->ssap == LLCP_SAP_MAX) { 492 if (llcp_sock->ssap == LLCP_SAP_MAX) {
493 ret = -ENOMEM; 493 ret = -ENOMEM;
@@ -701,8 +701,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
701 701
702void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) 702void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
703{ 703{
704 struct nfc_llcp_local *local = sock->local;
705
706 kfree(sock->service_name); 704 kfree(sock->service_name);
707 705
708 skb_queue_purge(&sock->tx_queue); 706 skb_queue_purge(&sock->tx_queue);
@@ -710,13 +708,11 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
710 skb_queue_purge(&sock->tx_backlog_queue); 708 skb_queue_purge(&sock->tx_backlog_queue);
711 709
712 list_del_init(&sock->accept_queue); 710 list_del_init(&sock->accept_queue);
713 711 list_del_init(&sock->list);
714 if (local != NULL && sock == local->sockets[sock->ssap])
715 local->sockets[sock->ssap] = NULL;
716 else
717 list_del_init(&sock->list);
718 712
719 sock->parent = NULL; 713 sock->parent = NULL;
714
715 nfc_llcp_local_put(sock->local);
720} 716}
721 717
722static int llcp_sock_create(struct net *net, struct socket *sock, 718static int llcp_sock_create(struct net *net, struct socket *sock,