Commit de121989 authored by John W. Linville's avatar John W. Linville

Merge tag 'nfc-fixes-3.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-fixes

Samuel Ortiz <sameo@linux.intel.com> says:

This is the first NFC pull request for 3.9 fixes

With this one we have:

- A fix for properly decreasing socket ack log.
- A timer and works cleanup upon NFC device removal.
- A monitoroing socket cleanup round from llcp_socket_release.
- A proper error report to pending sockets upon NFC device removal.
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parents 66489978 3bbc0ceb
...@@ -68,7 +68,8 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) ...@@ -68,7 +68,8 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
} }
} }
static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
int err)
{ {
struct sock *sk; struct sock *sk;
struct hlist_node *tmp; struct hlist_node *tmp;
...@@ -100,7 +101,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) ...@@ -100,7 +101,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
nfc_llcp_accept_unlink(accept_sk); nfc_llcp_accept_unlink(accept_sk);
if (err)
accept_sk->sk_err = err;
accept_sk->sk_state = LLCP_CLOSED; accept_sk->sk_state = LLCP_CLOSED;
accept_sk->sk_state_change(sk);
bh_unlock_sock(accept_sk); bh_unlock_sock(accept_sk);
...@@ -123,7 +127,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) ...@@ -123,7 +127,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
continue; continue;
} }
if (err)
sk->sk_err = err;
sk->sk_state = LLCP_CLOSED; sk->sk_state = LLCP_CLOSED;
sk->sk_state_change(sk);
bh_unlock_sock(sk); bh_unlock_sock(sk);
...@@ -133,6 +140,36 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) ...@@ -133,6 +140,36 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
} }
write_unlock(&local->sockets.lock); write_unlock(&local->sockets.lock);
/*
* If we want to keep the listening sockets alive,
* we don't touch the RAW ones.
*/
if (listen == true)
return;
write_lock(&local->raw_sockets.lock);
sk_for_each_safe(sk, tmp, &local->raw_sockets.head) {
llcp_sock = nfc_llcp_sock(sk);
bh_lock_sock(sk);
nfc_llcp_socket_purge(llcp_sock);
if (err)
sk->sk_err = err;
sk->sk_state = LLCP_CLOSED;
sk->sk_state_change(sk);
bh_unlock_sock(sk);
sock_orphan(sk);
sk_del_node_init(sk);
}
write_unlock(&local->raw_sockets.lock);
} }
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
...@@ -142,20 +179,25 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) ...@@ -142,20 +179,25 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
return local; return local;
} }
static void local_release(struct kref *ref) static void local_cleanup(struct nfc_llcp_local *local, bool listen)
{ {
struct nfc_llcp_local *local; nfc_llcp_socket_release(local, listen, ENXIO);
local = container_of(ref, struct nfc_llcp_local, ref);
list_del(&local->list);
nfc_llcp_socket_release(local, false);
del_timer_sync(&local->link_timer); del_timer_sync(&local->link_timer);
skb_queue_purge(&local->tx_queue); skb_queue_purge(&local->tx_queue);
cancel_work_sync(&local->tx_work); cancel_work_sync(&local->tx_work);
cancel_work_sync(&local->rx_work); cancel_work_sync(&local->rx_work);
cancel_work_sync(&local->timeout_work); cancel_work_sync(&local->timeout_work);
kfree_skb(local->rx_pending); kfree_skb(local->rx_pending);
}
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);
local_cleanup(local, false);
kfree(local); kfree(local);
} }
...@@ -1348,7 +1390,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) ...@@ -1348,7 +1390,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
return; return;
/* Close and purge all existing sockets */ /* Close and purge all existing sockets */
nfc_llcp_socket_release(local, true); nfc_llcp_socket_release(local, true, 0);
} }
void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
...@@ -1427,6 +1469,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) ...@@ -1427,6 +1469,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
return; return;
} }
local_cleanup(local, false);
nfc_llcp_local_put(local); nfc_llcp_local_put(local);
} }
......
...@@ -278,6 +278,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent, ...@@ -278,6 +278,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
pr_debug("Returning sk state %d\n", sk->sk_state); pr_debug("Returning sk state %d\n", sk->sk_state);
sk_acceptq_removed(parent);
return sk; return sk;
} }
......
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