diff options
Diffstat (limited to 'net/nfc/netlink.c')
-rw-r--r-- | net/nfc/netlink.c | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 4c51714ee741..c1b5285cbde7 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -58,7 +58,7 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | |||
58 | { | 58 | { |
59 | void *hdr; | 59 | void *hdr; |
60 | 60 | ||
61 | hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, | 61 | hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, |
62 | &nfc_genl_family, flags, NFC_CMD_GET_TARGET); | 62 | &nfc_genl_family, flags, NFC_CMD_GET_TARGET); |
63 | if (!hdr) | 63 | if (!hdr) |
64 | return -EMSGSIZE; | 64 | return -EMSGSIZE; |
@@ -165,7 +165,7 @@ int nfc_genl_targets_found(struct nfc_dev *dev) | |||
165 | struct sk_buff *msg; | 165 | struct sk_buff *msg; |
166 | void *hdr; | 166 | void *hdr; |
167 | 167 | ||
168 | dev->genl_data.poll_req_pid = 0; | 168 | dev->genl_data.poll_req_portid = 0; |
169 | 169 | ||
170 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | 170 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
171 | if (!msg) | 171 | if (!msg) |
@@ -347,13 +347,13 @@ free_msg: | |||
347 | } | 347 | } |
348 | 348 | ||
349 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | 349 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, |
350 | u32 pid, u32 seq, | 350 | u32 portid, u32 seq, |
351 | struct netlink_callback *cb, | 351 | struct netlink_callback *cb, |
352 | int flags) | 352 | int flags) |
353 | { | 353 | { |
354 | void *hdr; | 354 | void *hdr; |
355 | 355 | ||
356 | hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags, | 356 | hdr = genlmsg_put(msg, portid, seq, &nfc_genl_family, flags, |
357 | NFC_CMD_GET_DEVICE); | 357 | NFC_CMD_GET_DEVICE); |
358 | if (!hdr) | 358 | if (!hdr) |
359 | return -EMSGSIZE; | 359 | return -EMSGSIZE; |
@@ -401,7 +401,7 @@ static int nfc_genl_dump_devices(struct sk_buff *skb, | |||
401 | while (dev) { | 401 | while (dev) { |
402 | int rc; | 402 | int rc; |
403 | 403 | ||
404 | rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid, | 404 | rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).portid, |
405 | cb->nlh->nlmsg_seq, cb, NLM_F_MULTI); | 405 | cb->nlh->nlmsg_seq, cb, NLM_F_MULTI); |
406 | if (rc < 0) | 406 | if (rc < 0) |
407 | break; | 407 | break; |
@@ -520,7 +520,7 @@ static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info) | |||
520 | goto out_putdev; | 520 | goto out_putdev; |
521 | } | 521 | } |
522 | 522 | ||
523 | rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq, | 523 | rc = nfc_genl_send_device(msg, dev, info->snd_portid, info->snd_seq, |
524 | NULL, 0); | 524 | NULL, 0); |
525 | if (rc < 0) | 525 | if (rc < 0) |
526 | goto out_free; | 526 | goto out_free; |
@@ -611,7 +611,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
611 | 611 | ||
612 | rc = nfc_start_poll(dev, im_protocols, tm_protocols); | 612 | rc = nfc_start_poll(dev, im_protocols, tm_protocols); |
613 | if (!rc) | 613 | if (!rc) |
614 | dev->genl_data.poll_req_pid = info->snd_pid; | 614 | dev->genl_data.poll_req_portid = info->snd_portid; |
615 | 615 | ||
616 | mutex_unlock(&dev->genl_data.genl_data_mutex); | 616 | mutex_unlock(&dev->genl_data.genl_data_mutex); |
617 | 617 | ||
@@ -645,13 +645,13 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info) | |||
645 | 645 | ||
646 | mutex_lock(&dev->genl_data.genl_data_mutex); | 646 | mutex_lock(&dev->genl_data.genl_data_mutex); |
647 | 647 | ||
648 | if (dev->genl_data.poll_req_pid != info->snd_pid) { | 648 | if (dev->genl_data.poll_req_portid != info->snd_portid) { |
649 | rc = -EBUSY; | 649 | rc = -EBUSY; |
650 | goto out; | 650 | goto out; |
651 | } | 651 | } |
652 | 652 | ||
653 | rc = nfc_stop_poll(dev); | 653 | rc = nfc_stop_poll(dev); |
654 | dev->genl_data.poll_req_pid = 0; | 654 | dev->genl_data.poll_req_portid = 0; |
655 | 655 | ||
656 | out: | 656 | out: |
657 | mutex_unlock(&dev->genl_data.genl_data_mutex); | 657 | mutex_unlock(&dev->genl_data.genl_data_mutex); |
@@ -761,38 +761,70 @@ static struct genl_ops nfc_genl_ops[] = { | |||
761 | }, | 761 | }, |
762 | }; | 762 | }; |
763 | 763 | ||
764 | static int nfc_genl_rcv_nl_event(struct notifier_block *this, | 764 | |
765 | unsigned long event, void *ptr) | 765 | struct urelease_work { |
766 | struct work_struct w; | ||
767 | int portid; | ||
768 | }; | ||
769 | |||
770 | static void nfc_urelease_event_work(struct work_struct *work) | ||
766 | { | 771 | { |
767 | struct netlink_notify *n = ptr; | 772 | struct urelease_work *w = container_of(work, struct urelease_work, w); |
768 | struct class_dev_iter iter; | 773 | struct class_dev_iter iter; |
769 | struct nfc_dev *dev; | 774 | struct nfc_dev *dev; |
770 | 775 | ||
771 | if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC) | 776 | pr_debug("portid %d\n", w->portid); |
772 | goto out; | ||
773 | 777 | ||
774 | pr_debug("NETLINK_URELEASE event from id %d\n", n->pid); | 778 | mutex_lock(&nfc_devlist_mutex); |
775 | 779 | ||
776 | nfc_device_iter_init(&iter); | 780 | nfc_device_iter_init(&iter); |
777 | dev = nfc_device_iter_next(&iter); | 781 | dev = nfc_device_iter_next(&iter); |
778 | 782 | ||
779 | while (dev) { | 783 | while (dev) { |
780 | if (dev->genl_data.poll_req_pid == n->pid) { | 784 | mutex_lock(&dev->genl_data.genl_data_mutex); |
785 | |||
786 | if (dev->genl_data.poll_req_portid == w->portid) { | ||
781 | nfc_stop_poll(dev); | 787 | nfc_stop_poll(dev); |
782 | dev->genl_data.poll_req_pid = 0; | 788 | dev->genl_data.poll_req_portid = 0; |
783 | } | 789 | } |
790 | |||
791 | mutex_unlock(&dev->genl_data.genl_data_mutex); | ||
792 | |||
784 | dev = nfc_device_iter_next(&iter); | 793 | dev = nfc_device_iter_next(&iter); |
785 | } | 794 | } |
786 | 795 | ||
787 | nfc_device_iter_exit(&iter); | 796 | nfc_device_iter_exit(&iter); |
788 | 797 | ||
798 | mutex_unlock(&nfc_devlist_mutex); | ||
799 | |||
800 | kfree(w); | ||
801 | } | ||
802 | |||
803 | static int nfc_genl_rcv_nl_event(struct notifier_block *this, | ||
804 | unsigned long event, void *ptr) | ||
805 | { | ||
806 | struct netlink_notify *n = ptr; | ||
807 | struct urelease_work *w; | ||
808 | |||
809 | if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC) | ||
810 | goto out; | ||
811 | |||
812 | pr_debug("NETLINK_URELEASE event from id %d\n", n->portid); | ||
813 | |||
814 | w = kmalloc(sizeof(*w), GFP_ATOMIC); | ||
815 | if (w) { | ||
816 | INIT_WORK((struct work_struct *) w, nfc_urelease_event_work); | ||
817 | w->portid = n->portid; | ||
818 | schedule_work((struct work_struct *) w); | ||
819 | } | ||
820 | |||
789 | out: | 821 | out: |
790 | return NOTIFY_DONE; | 822 | return NOTIFY_DONE; |
791 | } | 823 | } |
792 | 824 | ||
793 | void nfc_genl_data_init(struct nfc_genl_data *genl_data) | 825 | void nfc_genl_data_init(struct nfc_genl_data *genl_data) |
794 | { | 826 | { |
795 | genl_data->poll_req_pid = 0; | 827 | genl_data->poll_req_portid = 0; |
796 | mutex_init(&genl_data->genl_data_mutex); | 828 | mutex_init(&genl_data->genl_data_mutex); |
797 | } | 829 | } |
798 | 830 | ||