aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2005-10-28 18:37:23 -0400
committerRoland Dreier <rolandd@cisco.com>2005-10-28 18:37:23 -0400
commita74968f8c3b1166cfe0942901b56165f06ab6f60 (patch)
tree8b6bfdad7c5a56186bb84a8f282270998f64db0f /drivers/infiniband
parent1993d683f39f77ddb46a662d7146247877d50b8f (diff)
[IB] umad: Fix device lifetime problems
Move ib_umad module to using cdev_alloc() and class_device_create() so that we can handle device lifetime properly. Now we can make sure we keep all of our data structures around until the last way to reach them is gone. Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/user_mad.c268
1 files changed, 159 insertions, 109 deletions
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 17ec0a19dbc0..9e49816d7282 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -64,18 +64,39 @@ enum {
64 IB_UMAD_MINOR_BASE = 0 64 IB_UMAD_MINOR_BASE = 0
65}; 65};
66 66
67/*
68 * Our lifetime rules for these structs are the following: each time a
69 * device special file is opened, we look up the corresponding struct
70 * ib_umad_port by minor in the umad_port[] table while holding the
71 * port_lock. If this lookup succeeds, we take a reference on the
72 * ib_umad_port's struct ib_umad_device while still holding the
73 * port_lock; if the lookup fails, we fail the open(). We drop these
74 * references in the corresponding close().
75 *
76 * In addition to references coming from open character devices, there
77 * is one more reference to each ib_umad_device representing the
78 * module's reference taken when allocating the ib_umad_device in
79 * ib_umad_add_one().
80 *
81 * When destroying an ib_umad_device, we clear all of its
82 * ib_umad_ports from umad_port[] while holding port_lock before
83 * dropping the module's reference to the ib_umad_device. This is
84 * always safe because any open() calls will either succeed and obtain
85 * a reference before we clear the umad_port[] entries, or fail after
86 * we clear the umad_port[] entries.
87 */
88
67struct ib_umad_port { 89struct ib_umad_port {
68 int devnum; 90 struct cdev *dev;
69 struct cdev dev; 91 struct class_device *class_dev;
70 struct class_device class_dev;
71 92
72 int sm_devnum; 93 struct cdev *sm_dev;
73 struct cdev sm_dev; 94 struct class_device *sm_class_dev;
74 struct class_device sm_class_dev;
75 struct semaphore sm_sem; 95 struct semaphore sm_sem;
76 96
77 struct ib_device *ib_dev; 97 struct ib_device *ib_dev;
78 struct ib_umad_device *umad_dev; 98 struct ib_umad_device *umad_dev;
99 int dev_num;
79 u8 port_num; 100 u8 port_num;
80}; 101};
81 102
@@ -102,13 +123,25 @@ struct ib_umad_packet {
102 struct ib_user_mad mad; 123 struct ib_user_mad mad;
103}; 124};
104 125
126static struct class *umad_class;
127
105static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE); 128static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE);
106static spinlock_t map_lock; 129
130static DEFINE_SPINLOCK(port_lock);
131static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS];
107static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2); 132static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2);
108 133
109static void ib_umad_add_one(struct ib_device *device); 134static void ib_umad_add_one(struct ib_device *device);
110static void ib_umad_remove_one(struct ib_device *device); 135static void ib_umad_remove_one(struct ib_device *device);
111 136
137static void ib_umad_release_dev(struct kref *ref)
138{
139 struct ib_umad_device *dev =
140 container_of(ref, struct ib_umad_device, ref);
141
142 kfree(dev);
143}
144
112static int queue_packet(struct ib_umad_file *file, 145static int queue_packet(struct ib_umad_file *file,
113 struct ib_mad_agent *agent, 146 struct ib_mad_agent *agent,
114 struct ib_umad_packet *packet) 147 struct ib_umad_packet *packet)
@@ -534,13 +567,23 @@ static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
534 567
535static int ib_umad_open(struct inode *inode, struct file *filp) 568static int ib_umad_open(struct inode *inode, struct file *filp)
536{ 569{
537 struct ib_umad_port *port = 570 struct ib_umad_port *port;
538 container_of(inode->i_cdev, struct ib_umad_port, dev);
539 struct ib_umad_file *file; 571 struct ib_umad_file *file;
540 572
573 spin_lock(&port_lock);
574 port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE];
575 if (port)
576 kref_get(&port->umad_dev->ref);
577 spin_unlock(&port_lock);
578
579 if (!port)
580 return -ENXIO;
581
541 file = kzalloc(sizeof *file, GFP_KERNEL); 582 file = kzalloc(sizeof *file, GFP_KERNEL);
542 if (!file) 583 if (!file) {
584 kref_put(&port->umad_dev->ref, ib_umad_release_dev);
543 return -ENOMEM; 585 return -ENOMEM;
586 }
544 587
545 spin_lock_init(&file->recv_lock); 588 spin_lock_init(&file->recv_lock);
546 init_rwsem(&file->agent_mutex); 589 init_rwsem(&file->agent_mutex);
@@ -556,6 +599,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
556static int ib_umad_close(struct inode *inode, struct file *filp) 599static int ib_umad_close(struct inode *inode, struct file *filp)
557{ 600{
558 struct ib_umad_file *file = filp->private_data; 601 struct ib_umad_file *file = filp->private_data;
602 struct ib_umad_device *dev = file->port->umad_dev;
559 struct ib_umad_packet *packet, *tmp; 603 struct ib_umad_packet *packet, *tmp;
560 int i; 604 int i;
561 605
@@ -570,6 +614,8 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
570 614
571 kfree(file); 615 kfree(file);
572 616
617 kref_put(&dev->ref, ib_umad_release_dev);
618
573 return 0; 619 return 0;
574} 620}
575 621
@@ -586,30 +632,46 @@ static struct file_operations umad_fops = {
586 632
587static int ib_umad_sm_open(struct inode *inode, struct file *filp) 633static int ib_umad_sm_open(struct inode *inode, struct file *filp)
588{ 634{
589 struct ib_umad_port *port = 635 struct ib_umad_port *port;
590 container_of(inode->i_cdev, struct ib_umad_port, sm_dev);
591 struct ib_port_modify props = { 636 struct ib_port_modify props = {
592 .set_port_cap_mask = IB_PORT_SM 637 .set_port_cap_mask = IB_PORT_SM
593 }; 638 };
594 int ret; 639 int ret;
595 640
641 spin_lock(&port_lock);
642 port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - IB_UMAD_MAX_PORTS];
643 if (port)
644 kref_get(&port->umad_dev->ref);
645 spin_unlock(&port_lock);
646
647 if (!port)
648 return -ENXIO;
649
596 if (filp->f_flags & O_NONBLOCK) { 650 if (filp->f_flags & O_NONBLOCK) {
597 if (down_trylock(&port->sm_sem)) 651 if (down_trylock(&port->sm_sem)) {
598 return -EAGAIN; 652 ret = -EAGAIN;
653 goto fail;
654 }
599 } else { 655 } else {
600 if (down_interruptible(&port->sm_sem)) 656 if (down_interruptible(&port->sm_sem)) {
601 return -ERESTARTSYS; 657 ret = -ERESTARTSYS;
658 goto fail;
659 }
602 } 660 }
603 661
604 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props); 662 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
605 if (ret) { 663 if (ret) {
606 up(&port->sm_sem); 664 up(&port->sm_sem);
607 return ret; 665 goto fail;
608 } 666 }
609 667
610 filp->private_data = port; 668 filp->private_data = port;
611 669
612 return 0; 670 return 0;
671
672fail:
673 kref_put(&port->umad_dev->ref, ib_umad_release_dev);
674 return ret;
613} 675}
614 676
615static int ib_umad_sm_close(struct inode *inode, struct file *filp) 677static int ib_umad_sm_close(struct inode *inode, struct file *filp)
@@ -623,6 +685,8 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
623 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props); 685 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
624 up(&port->sm_sem); 686 up(&port->sm_sem);
625 687
688 kref_put(&port->umad_dev->ref, ib_umad_release_dev);
689
626 return ret; 690 return ret;
627} 691}
628 692
@@ -642,6 +706,9 @@ static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
642{ 706{
643 struct ib_umad_port *port = class_get_devdata(class_dev); 707 struct ib_umad_port *port = class_get_devdata(class_dev);
644 708
709 if (!port)
710 return -ENODEV;
711
645 return sprintf(buf, "%s\n", port->ib_dev->name); 712 return sprintf(buf, "%s\n", port->ib_dev->name);
646} 713}
647static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); 714static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
@@ -650,38 +717,13 @@ static ssize_t show_port(struct class_device *class_dev, char *buf)
650{ 717{
651 struct ib_umad_port *port = class_get_devdata(class_dev); 718 struct ib_umad_port *port = class_get_devdata(class_dev);
652 719
720 if (!port)
721 return -ENODEV;
722
653 return sprintf(buf, "%d\n", port->port_num); 723 return sprintf(buf, "%d\n", port->port_num);
654} 724}
655static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); 725static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
656 726
657static void ib_umad_release_dev(struct kref *ref)
658{
659 struct ib_umad_device *dev =
660 container_of(ref, struct ib_umad_device, ref);
661
662 kfree(dev);
663}
664
665static void ib_umad_release_port(struct class_device *class_dev)
666{
667 struct ib_umad_port *port = class_get_devdata(class_dev);
668
669 if (class_dev == &port->class_dev) {
670 cdev_del(&port->dev);
671 clear_bit(port->devnum, dev_map);
672 } else {
673 cdev_del(&port->sm_dev);
674 clear_bit(port->sm_devnum, dev_map);
675 }
676
677 kref_put(&port->umad_dev->ref, ib_umad_release_dev);
678}
679
680static struct class umad_class = {
681 .name = "infiniband_mad",
682 .release = ib_umad_release_port
683};
684
685static ssize_t show_abi_version(struct class *class, char *buf) 727static ssize_t show_abi_version(struct class *class, char *buf)
686{ 728{
687 return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION); 729 return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION);
@@ -691,89 +733,102 @@ static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
691static int ib_umad_init_port(struct ib_device *device, int port_num, 733static int ib_umad_init_port(struct ib_device *device, int port_num,
692 struct ib_umad_port *port) 734 struct ib_umad_port *port)
693{ 735{
694 spin_lock(&map_lock); 736 spin_lock(&port_lock);
695 port->devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS); 737 port->dev_num = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
696 if (port->devnum >= IB_UMAD_MAX_PORTS) { 738 if (port->dev_num >= IB_UMAD_MAX_PORTS) {
697 spin_unlock(&map_lock); 739 spin_unlock(&port_lock);
698 return -1; 740 return -1;
699 } 741 }
700 port->sm_devnum = find_next_zero_bit(dev_map, IB_UMAD_MAX_PORTS * 2, IB_UMAD_MAX_PORTS); 742 set_bit(port->dev_num, dev_map);
701 if (port->sm_devnum >= IB_UMAD_MAX_PORTS * 2) { 743 spin_unlock(&port_lock);
702 spin_unlock(&map_lock);
703 return -1;
704 }
705 set_bit(port->devnum, dev_map);
706 set_bit(port->sm_devnum, dev_map);
707 spin_unlock(&map_lock);
708 744
709 port->ib_dev = device; 745 port->ib_dev = device;
710 port->port_num = port_num; 746 port->port_num = port_num;
711 init_MUTEX(&port->sm_sem); 747 init_MUTEX(&port->sm_sem);
712 748
713 cdev_init(&port->dev, &umad_fops); 749 port->dev = cdev_alloc();
714 port->dev.owner = THIS_MODULE; 750 if (!port->dev)
715 kobject_set_name(&port->dev.kobj, "umad%d", port->devnum);
716 if (cdev_add(&port->dev, base_dev + port->devnum, 1))
717 return -1; 751 return -1;
718 752 port->dev->owner = THIS_MODULE;
719 port->class_dev.class = &umad_class; 753 port->dev->ops = &umad_fops;
720 port->class_dev.dev = device->dma_device; 754 kobject_set_name(&port->dev->kobj, "umad%d", port->dev_num);
721 port->class_dev.devt = port->dev.dev; 755 if (cdev_add(port->dev, base_dev + port->dev_num, 1))
722
723 snprintf(port->class_dev.class_id, BUS_ID_SIZE, "umad%d", port->devnum);
724
725 if (class_device_register(&port->class_dev))
726 goto err_cdev; 756 goto err_cdev;
727 757
728 class_set_devdata(&port->class_dev, port); 758 port->class_dev = class_device_create(umad_class, port->dev->dev,
729 kref_get(&port->umad_dev->ref); 759 device->dma_device,
760 "umad%d", port->dev_num);
761 if (IS_ERR(port->class_dev))
762 goto err_cdev;
730 763
731 if (class_device_create_file(&port->class_dev, &class_device_attr_ibdev)) 764 if (class_device_create_file(port->class_dev, &class_device_attr_ibdev))
732 goto err_class; 765 goto err_class;
733 if (class_device_create_file(&port->class_dev, &class_device_attr_port)) 766 if (class_device_create_file(port->class_dev, &class_device_attr_port))
734 goto err_class; 767 goto err_class;
735 768
736 cdev_init(&port->sm_dev, &umad_sm_fops); 769 port->sm_dev = cdev_alloc();
737 port->sm_dev.owner = THIS_MODULE; 770 if (!port->sm_dev)
738 kobject_set_name(&port->dev.kobj, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS); 771 goto err_class;
739 if (cdev_add(&port->sm_dev, base_dev + port->sm_devnum, 1)) 772 port->sm_dev->owner = THIS_MODULE;
740 return -1; 773 port->sm_dev->ops = &umad_sm_fops;
741 774 kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num);
742 port->sm_class_dev.class = &umad_class; 775 if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
743 port->sm_class_dev.dev = device->dma_device; 776 goto err_sm_cdev;
744 port->sm_class_dev.devt = port->sm_dev.dev;
745
746 snprintf(port->sm_class_dev.class_id, BUS_ID_SIZE, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);
747 777
748 if (class_device_register(&port->sm_class_dev)) 778 port->sm_class_dev = class_device_create(umad_class, port->sm_dev->dev,
779 device->dma_device,
780 "issm%d", port->dev_num);
781 if (IS_ERR(port->sm_class_dev))
749 goto err_sm_cdev; 782 goto err_sm_cdev;
750 783
751 class_set_devdata(&port->sm_class_dev, port); 784 class_set_devdata(port->class_dev, port);
752 kref_get(&port->umad_dev->ref); 785 class_set_devdata(port->sm_class_dev, port);
753 786
754 if (class_device_create_file(&port->sm_class_dev, &class_device_attr_ibdev)) 787 if (class_device_create_file(port->sm_class_dev, &class_device_attr_ibdev))
755 goto err_sm_class; 788 goto err_sm_class;
756 if (class_device_create_file(&port->sm_class_dev, &class_device_attr_port)) 789 if (class_device_create_file(port->sm_class_dev, &class_device_attr_port))
757 goto err_sm_class; 790 goto err_sm_class;
758 791
792 spin_lock(&port_lock);
793 umad_port[port->dev_num] = port;
794 spin_unlock(&port_lock);
795
759 return 0; 796 return 0;
760 797
761err_sm_class: 798err_sm_class:
762 class_device_unregister(&port->sm_class_dev); 799 class_device_destroy(umad_class, port->sm_dev->dev);
763 800
764err_sm_cdev: 801err_sm_cdev:
765 cdev_del(&port->sm_dev); 802 cdev_del(port->sm_dev);
766 803
767err_class: 804err_class:
768 class_device_unregister(&port->class_dev); 805 class_device_destroy(umad_class, port->dev->dev);
769 806
770err_cdev: 807err_cdev:
771 cdev_del(&port->dev); 808 cdev_del(port->dev);
772 clear_bit(port->devnum, dev_map); 809 clear_bit(port->dev_num, dev_map);
773 810
774 return -1; 811 return -1;
775} 812}
776 813
814static void ib_umad_kill_port(struct ib_umad_port *port)
815{
816 class_set_devdata(port->class_dev, NULL);
817 class_set_devdata(port->sm_class_dev, NULL);
818
819 class_device_destroy(umad_class, port->dev->dev);
820 class_device_destroy(umad_class, port->sm_dev->dev);
821
822 cdev_del(port->dev);
823 cdev_del(port->sm_dev);
824
825 spin_lock(&port_lock);
826 umad_port[port->dev_num] = NULL;
827 spin_unlock(&port_lock);
828
829 clear_bit(port->dev_num, dev_map);
830}
831
777static void ib_umad_add_one(struct ib_device *device) 832static void ib_umad_add_one(struct ib_device *device)
778{ 833{
779 struct ib_umad_device *umad_dev; 834 struct ib_umad_device *umad_dev;
@@ -809,10 +864,8 @@ static void ib_umad_add_one(struct ib_device *device)
809 return; 864 return;
810 865
811err: 866err:
812 while (--i >= s) { 867 while (--i >= s)
813 class_device_unregister(&umad_dev->port[i - s].class_dev); 868 ib_umad_kill_port(&umad_dev->port[i]);
814 class_device_unregister(&umad_dev->port[i - s].sm_class_dev);
815 }
816 869
817 kref_put(&umad_dev->ref, ib_umad_release_dev); 870 kref_put(&umad_dev->ref, ib_umad_release_dev);
818} 871}
@@ -825,10 +878,8 @@ static void ib_umad_remove_one(struct ib_device *device)
825 if (!umad_dev) 878 if (!umad_dev)
826 return; 879 return;
827 880
828 for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) { 881 for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i)
829 class_device_unregister(&umad_dev->port[i].class_dev); 882 ib_umad_kill_port(&umad_dev->port[i]);
830 class_device_unregister(&umad_dev->port[i].sm_class_dev);
831 }
832 883
833 kref_put(&umad_dev->ref, ib_umad_release_dev); 884 kref_put(&umad_dev->ref, ib_umad_release_dev);
834} 885}
@@ -837,8 +888,6 @@ static int __init ib_umad_init(void)
837{ 888{
838 int ret; 889 int ret;
839 890
840 spin_lock_init(&map_lock);
841
842 ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2, 891 ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2,
843 "infiniband_mad"); 892 "infiniband_mad");
844 if (ret) { 893 if (ret) {
@@ -846,13 +895,14 @@ static int __init ib_umad_init(void)
846 goto out; 895 goto out;
847 } 896 }
848 897
849 ret = class_register(&umad_class); 898 umad_class = class_create(THIS_MODULE, "infiniband_mad");
850 if (ret) { 899 if (IS_ERR(umad_class)) {
900 ret = PTR_ERR(umad_class);
851 printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n"); 901 printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n");
852 goto out_chrdev; 902 goto out_chrdev;
853 } 903 }
854 904
855 ret = class_create_file(&umad_class, &class_attr_abi_version); 905 ret = class_create_file(umad_class, &class_attr_abi_version);
856 if (ret) { 906 if (ret) {
857 printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n"); 907 printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");
858 goto out_class; 908 goto out_class;
@@ -867,7 +917,7 @@ static int __init ib_umad_init(void)
867 return 0; 917 return 0;
868 918
869out_class: 919out_class:
870 class_unregister(&umad_class); 920 class_destroy(umad_class);
871 921
872out_chrdev: 922out_chrdev:
873 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2); 923 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
@@ -879,7 +929,7 @@ out:
879static void __exit ib_umad_cleanup(void) 929static void __exit ib_umad_cleanup(void)
880{ 930{
881 ib_unregister_client(&umad_client); 931 ib_unregister_client(&umad_client);
882 class_unregister(&umad_class); 932 class_destroy(umad_class);
883 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2); 933 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
884} 934}
885 935