Commit c7aa1225 authored by Samuel Ortiz's avatar Samuel Ortiz

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: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent f8f5701b
...@@ -59,8 +59,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) ...@@ -59,8 +59,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
release_sock(sk); release_sock(sk);
sock_orphan(sk); sock_orphan(sk);
s->local = NULL;
} }
parent_sk = &parent->sk; parent_sk = &parent->sk;
...@@ -83,8 +81,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) ...@@ -83,8 +81,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
release_sock(accept_sk); release_sock(accept_sk);
sock_orphan(accept_sk); sock_orphan(accept_sk);
lsk->local = NULL;
} }
} }
...@@ -96,13 +92,39 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) ...@@ -96,13 +92,39 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
release_sock(parent_sk); release_sock(parent_sk);
sock_orphan(parent_sk); sock_orphan(parent_sk);
parent->local = NULL;
} }
mutex_unlock(&local->socket_lock); mutex_unlock(&local->socket_lock);
} }
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
{
kref_get(&local->ref);
return local;
}
static void local_release(struct kref *ref)
{
struct nfc_llcp_local *local;
local = container_of(ref, struct nfc_llcp_local, ref);
list_del(&local->list);
nfc_llcp_socket_release(local);
del_timer_sync(&local->link_timer);
skb_queue_purge(&local->tx_queue);
destroy_workqueue(local->tx_wq);
destroy_workqueue(local->rx_wq);
kfree_skb(local->rx_pending);
kfree(local);
}
int nfc_llcp_local_put(struct nfc_llcp_local *local)
{
return kref_put(&local->ref, local_release);
}
static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local)
{ {
mutex_lock(&local->sdp_lock); mutex_lock(&local->sdp_lock);
...@@ -612,7 +634,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, ...@@ -612,7 +634,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
new_sock = nfc_llcp_sock(new_sk); new_sock = nfc_llcp_sock(new_sk);
new_sock->dev = local->dev; new_sock->dev = local->dev;
new_sock->local = local; new_sock->local = nfc_llcp_local_get(local);
new_sock->nfc_protocol = sock->nfc_protocol; new_sock->nfc_protocol = sock->nfc_protocol;
new_sock->ssap = bound_sap; new_sock->ssap = bound_sap;
new_sock->dsap = ssap; new_sock->dsap = ssap;
...@@ -943,6 +965,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) ...@@ -943,6 +965,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
local->dev = ndev; local->dev = ndev;
INIT_LIST_HEAD(&local->list); INIT_LIST_HEAD(&local->list);
kref_init(&local->ref);
mutex_init(&local->sdp_lock); mutex_init(&local->sdp_lock);
mutex_init(&local->socket_lock); mutex_init(&local->socket_lock);
init_timer(&local->link_timer); init_timer(&local->link_timer);
...@@ -1015,14 +1038,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) ...@@ -1015,14 +1038,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
return; return;
} }
list_del(&local->list); nfc_llcp_local_put(local);
nfc_llcp_socket_release(local);
del_timer_sync(&local->link_timer);
skb_queue_purge(&local->tx_queue);
destroy_workqueue(local->tx_wq);
destroy_workqueue(local->rx_wq);
kfree_skb(local->rx_pending);
kfree(local);
} }
int __init nfc_llcp_init(void) int __init nfc_llcp_init(void)
......
...@@ -44,6 +44,8 @@ struct nfc_llcp_local { ...@@ -44,6 +44,8 @@ struct nfc_llcp_local {
struct list_head list; struct list_head list;
struct nfc_dev *dev; struct nfc_dev *dev;
struct kref ref;
struct mutex sdp_lock; struct mutex sdp_lock;
struct mutex socket_lock; struct mutex socket_lock;
...@@ -165,6 +167,8 @@ struct nfc_llcp_sock { ...@@ -165,6 +167,8 @@ struct nfc_llcp_sock {
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
int nfc_llcp_local_put(struct nfc_llcp_local *local);
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
struct nfc_llcp_sock *sock); struct nfc_llcp_sock *sock);
u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
......
...@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) ...@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
} }
llcp_sock->dev = dev; llcp_sock->dev = dev;
llcp_sock->local = local; llcp_sock->local = nfc_llcp_local_get(local);
llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
llcp_sock->service_name_len = min_t(unsigned int, llcp_sock->service_name_len = min_t(unsigned int,
llcp_addr.service_name_len, llcp_addr.service_name_len,
...@@ -487,7 +487,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, ...@@ -487,7 +487,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
} }
llcp_sock->dev = dev; llcp_sock->dev = dev;
llcp_sock->local = local; llcp_sock->local = nfc_llcp_local_get(local);
llcp_sock->ssap = nfc_llcp_get_local_ssap(local); llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
if (llcp_sock->ssap == LLCP_SAP_MAX) { if (llcp_sock->ssap == LLCP_SAP_MAX) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -701,8 +701,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) ...@@ -701,8 +701,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
{ {
struct nfc_llcp_local *local = sock->local;
kfree(sock->service_name); kfree(sock->service_name);
skb_queue_purge(&sock->tx_queue); skb_queue_purge(&sock->tx_queue);
...@@ -710,13 +708,11 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) ...@@ -710,13 +708,11 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
skb_queue_purge(&sock->tx_backlog_queue); skb_queue_purge(&sock->tx_backlog_queue);
list_del_init(&sock->accept_queue); list_del_init(&sock->accept_queue);
list_del_init(&sock->list);
if (local != NULL && sock == local->sockets[sock->ssap])
local->sockets[sock->ssap] = NULL;
else
list_del_init(&sock->list);
sock->parent = NULL; sock->parent = NULL;
nfc_llcp_local_put(sock->local);
} }
static int llcp_sock_create(struct net *net, struct socket *sock, static int llcp_sock_create(struct net *net, struct socket *sock,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment