diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-05-04 05:24:16 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-06-04 15:34:28 -0400 |
commit | c7aa12252f5142b9eee2f6e34ca8870a8e7e048c (patch) | |
tree | e91c72609e7d13b3a185cf75acd74a8385c736c5 /net | |
parent | f8f5701bdaf9134b1f90e5044a82c66324d2073f (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>
Diffstat (limited to 'net')
-rw-r--r-- | net/nfc/llcp/llcp.c | 46 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.h | 4 | ||||
-rw-r--r-- | net/nfc/llcp/sock.c | 14 |
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 | ||
100 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | ||
101 | { | ||
102 | kref_get(&local->ref); | ||
103 | |||
104 | return local; | ||
105 | } | ||
106 | |||
107 | static 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 | |||
123 | int nfc_llcp_local_put(struct nfc_llcp_local *local) | ||
124 | { | ||
125 | return kref_put(&local->ref, local_release); | ||
126 | } | ||
127 | |||
106 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) | 128 | static 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 | ||
1028 | int __init nfc_llcp_init(void) | 1044 | int __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 | ||
167 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 169 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
170 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); | ||
171 | int nfc_llcp_local_put(struct nfc_llcp_local *local); | ||
168 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | 172 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, |
169 | struct nfc_llcp_sock *sock); | 173 | struct nfc_llcp_sock *sock); |
170 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); | 174 | u8 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 | ||
702 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | 702 | void 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 | ||
722 | static int llcp_sock_create(struct net *net, struct socket *sock, | 718 | static int llcp_sock_create(struct net *net, struct socket *sock, |