},
};
- 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;
++ int portid;
+ };
+
+ 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("portid %d\n", w->portid);
- pr_debug("NETLINK_URELEASE event from id %d\n", n->portid);
+ mutex_lock(&nfc_devlist_mutex);
nfc_device_iter_init(&iter);
dev = nfc_device_iter_next(&iter);
while (dev) {
- if (dev->genl_data.poll_req_portid == n->portid) {
+ mutex_lock(&dev->genl_data.genl_data_mutex);
+
- if (dev->genl_data.poll_req_pid == w->pid) {
++ if (dev->genl_data.poll_req_portid == w->portid) {
nfc_stop_poll(dev);
- dev->genl_data.poll_req_pid = 0;
+ dev->genl_data.poll_req_portid = 0;
}
+
+ mutex_unlock(&dev->genl_data.genl_data_mutex);
+
dev = nfc_device_iter_next(&iter);
}
nfc_device_iter_exit(&iter);
- pr_debug("NETLINK_URELEASE event from id %d\n", n->pid);
+ 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;
+
- w->pid = n->pid;
++ pr_debug("NETLINK_URELEASE event from id %d\n", n->portid);
+
+ w = kmalloc(sizeof(*w), GFP_ATOMIC);
+ if (w) {
+ INIT_WORK((struct work_struct *) w, nfc_urelease_event_work);
++ w->portid = n->portid;
+ schedule_work((struct work_struct *) w);
+ }
+
out:
return NOTIFY_DONE;
}