diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-09-28 10:55:00 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-09-28 10:55:43 -0400 |
commit | 97ea6d0f3eb019891038cd2dfddb749d6bf219be (patch) | |
tree | 3b7d2f31ab27b4cd5546b0ab72bb9a0c3bdfd008 /net/nfc/netlink.c | |
parent | 8a14e8bf386434732eed6678120fe52acee6244a (diff) | |
parent | 50b78b2a6500d0e97c204c1b6c51df8c17358bbe (diff) | |
download | linux-97ea6d0f3eb019891038cd2dfddb749d6bf219be.tar.bz2 |
Merge tag 'nfc-next-3.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-3.0
So says Samuel Ortiz <sameo@linux.intel.com>:
The 2nd NFC pull request for 3.7.
- A couple of wrong context sleep fixes.
- An LLCP rwlock intizialisation fix.
- A missing mutex unlocking for pn533.
- LLCP raw sockets support. This is going to be used for NFC sniffing.
- A build fix for llc_shdlc. It fixes a build error triggered by code that's
living in wireless-next.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/nfc/netlink.c')
-rw-r--r-- | net/nfc/netlink.c | 46 |
1 files changed, 39 insertions, 7 deletions
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[] = { }, }; -static int nfc_genl_rcv_nl_event(struct notifier_block *this, - unsigned long event, void *ptr) + +struct urelease_work { + struct work_struct w; + int pid; +}; + +static void nfc_urelease_event_work(struct work_struct *work) { - struct netlink_notify *n = ptr; + struct urelease_work *w = container_of(work, struct urelease_work, w); struct class_dev_iter iter; struct nfc_dev *dev; - if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC) - goto out; + pr_debug("pid %d\n", w->pid); - pr_debug("NETLINK_URELEASE event from id %d\n", n->pid); + mutex_lock(&nfc_devlist_mutex); nfc_device_iter_init(&iter); dev = nfc_device_iter_next(&iter); while (dev) { - if (dev->genl_data.poll_req_pid == n->pid) { + mutex_lock(&dev->genl_data.genl_data_mutex); + + if (dev->genl_data.poll_req_pid == w->pid) { nfc_stop_poll(dev); dev->genl_data.poll_req_pid = 0; } + + mutex_unlock(&dev->genl_data.genl_data_mutex); + dev = nfc_device_iter_next(&iter); } nfc_device_iter_exit(&iter); + mutex_unlock(&nfc_devlist_mutex); + + kfree(w); +} + +static int nfc_genl_rcv_nl_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct netlink_notify *n = ptr; + struct urelease_work *w; + + if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC) + goto out; + + pr_debug("NETLINK_URELEASE event from id %d\n", n->pid); + + w = kmalloc(sizeof(*w), GFP_ATOMIC); + if (w) { + INIT_WORK((struct work_struct *) w, nfc_urelease_event_work); + w->pid = n->pid; + schedule_work((struct work_struct *) w); + } + out: return NOTIFY_DONE; } |