aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/cnic.c56
1 files changed, 42 insertions, 14 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index e8f2836b6301..3f923a78e22e 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -60,6 +60,7 @@ MODULE_LICENSE("GPL");
60MODULE_VERSION(CNIC_MODULE_VERSION); 60MODULE_VERSION(CNIC_MODULE_VERSION);
61 61
62static LIST_HEAD(cnic_dev_list); 62static LIST_HEAD(cnic_dev_list);
63static LIST_HEAD(cnic_udev_list);
63static DEFINE_RWLOCK(cnic_dev_lock); 64static DEFINE_RWLOCK(cnic_dev_lock);
64static DEFINE_MUTEX(cnic_lock); 65static DEFINE_MUTEX(cnic_lock);
65 66
@@ -101,13 +102,14 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
101 rtnl_lock(); 102 rtnl_lock();
102 dev = udev->dev; 103 dev = udev->dev;
103 104
104 if (!test_bit(CNIC_F_CNIC_UP, &dev->flags)) { 105 if (!dev || !test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
105 rtnl_unlock(); 106 rtnl_unlock();
106 return -ENODEV; 107 return -ENODEV;
107 } 108 }
108 109
109 udev->uio_dev = iminor(inode); 110 udev->uio_dev = iminor(inode);
110 111
112 cnic_shutdown_rings(dev);
111 cnic_init_rings(dev); 113 cnic_init_rings(dev);
112 rtnl_unlock(); 114 rtnl_unlock();
113 115
@@ -117,9 +119,6 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
117static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode) 119static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
118{ 120{
119 struct cnic_uio_dev *udev = uinfo->priv; 121 struct cnic_uio_dev *udev = uinfo->priv;
120 struct cnic_dev *dev = udev->dev;
121
122 cnic_shutdown_rings(dev);
123 122
124 udev->uio_dev = -1; 123 udev->uio_dev = -1;
125 return 0; 124 return 0;
@@ -787,6 +786,9 @@ static void __cnic_free_uio(struct cnic_uio_dev *udev)
787 udev->l2_ring, udev->l2_ring_map); 786 udev->l2_ring, udev->l2_ring_map);
788 udev->l2_ring = NULL; 787 udev->l2_ring = NULL;
789 } 788 }
789
790 pci_dev_put(udev->pdev);
791 kfree(udev);
790} 792}
791 793
792static void cnic_free_uio(struct cnic_uio_dev *udev) 794static void cnic_free_uio(struct cnic_uio_dev *udev)
@@ -794,6 +796,9 @@ static void cnic_free_uio(struct cnic_uio_dev *udev)
794 if (!udev) 796 if (!udev)
795 return; 797 return;
796 798
799 write_lock(&cnic_dev_lock);
800 list_del_init(&udev->list);
801 write_unlock(&cnic_dev_lock);
797 __cnic_free_uio(udev); 802 __cnic_free_uio(udev);
798} 803}
799 804
@@ -801,14 +806,9 @@ static void cnic_free_resc(struct cnic_dev *dev)
801{ 806{
802 struct cnic_local *cp = dev->cnic_priv; 807 struct cnic_local *cp = dev->cnic_priv;
803 struct cnic_uio_dev *udev = cp->udev; 808 struct cnic_uio_dev *udev = cp->udev;
804 int i = 0;
805 809
806 if (udev) { 810 if (udev) {
807 while (udev->uio_dev != -1 && i < 15) { 811 udev->dev = NULL;
808 msleep(100);
809 i++;
810 }
811 cnic_free_uio(udev);
812 cp->udev = NULL; 812 cp->udev = NULL;
813 } 813 }
814 814
@@ -916,6 +916,17 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
916 struct cnic_local *cp = dev->cnic_priv; 916 struct cnic_local *cp = dev->cnic_priv;
917 struct cnic_uio_dev *udev; 917 struct cnic_uio_dev *udev;
918 918
919 read_lock(&cnic_dev_lock);
920 list_for_each_entry(udev, &cnic_udev_list, list) {
921 if (udev->pdev == dev->pcidev) {
922 udev->dev = dev;
923 cp->udev = udev;
924 read_unlock(&cnic_dev_lock);
925 return 0;
926 }
927 }
928 read_unlock(&cnic_dev_lock);
929
919 udev = kzalloc(sizeof(struct cnic_uio_dev), GFP_ATOMIC); 930 udev = kzalloc(sizeof(struct cnic_uio_dev), GFP_ATOMIC);
920 if (!udev) 931 if (!udev)
921 return -ENOMEM; 932 return -ENOMEM;
@@ -939,6 +950,12 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
939 if (!udev->l2_buf) 950 if (!udev->l2_buf)
940 return -ENOMEM; 951 return -ENOMEM;
941 952
953 write_lock(&cnic_dev_lock);
954 list_add(&udev->list, &cnic_udev_list);
955 write_unlock(&cnic_dev_lock);
956
957 pci_dev_get(udev->pdev);
958
942 cp->udev = udev; 959 cp->udev = udev;
943 960
944 return 0; 961 return 0;
@@ -954,8 +971,6 @@ static int cnic_init_uio(struct cnic_dev *dev)
954 if (!udev) 971 if (!udev)
955 return -ENOMEM; 972 return -ENOMEM;
956 973
957 udev->uio_dev = -1;
958
959 uinfo = &udev->cnic_uinfo; 974 uinfo = &udev->cnic_uinfo;
960 975
961 uinfo->mem[0].addr = dev->netdev->base_addr; 976 uinfo->mem[0].addr = dev->netdev->base_addr;
@@ -996,9 +1011,15 @@ static int cnic_init_uio(struct cnic_dev *dev)
996 uinfo->open = cnic_uio_open; 1011 uinfo->open = cnic_uio_open;
997 uinfo->release = cnic_uio_close; 1012 uinfo->release = cnic_uio_close;
998 1013
999 uinfo->priv = udev; 1014 if (udev->uio_dev == -1) {
1015 if (!uinfo->priv) {
1016 uinfo->priv = udev;
1000 1017
1001 ret = uio_register_device(&udev->pdev->dev, uinfo); 1018 ret = uio_register_device(&udev->pdev->dev, uinfo);
1019 }
1020 } else {
1021 cnic_init_rings(dev);
1022 }
1002 1023
1003 return ret; 1024 return ret;
1004} 1025}
@@ -4559,6 +4580,7 @@ static void cnic_stop_hw(struct cnic_dev *dev)
4559 msleep(100); 4580 msleep(100);
4560 i++; 4581 i++;
4561 } 4582 }
4583 cnic_shutdown_rings(dev);
4562 clear_bit(CNIC_F_CNIC_UP, &dev->flags); 4584 clear_bit(CNIC_F_CNIC_UP, &dev->flags);
4563 rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL); 4585 rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL);
4564 synchronize_rcu(); 4586 synchronize_rcu();
@@ -4834,6 +4856,7 @@ static struct notifier_block cnic_netdev_notifier = {
4834static void cnic_release(void) 4856static void cnic_release(void)
4835{ 4857{
4836 struct cnic_dev *dev; 4858 struct cnic_dev *dev;
4859 struct cnic_uio_dev *udev;
4837 4860
4838 while (!list_empty(&cnic_dev_list)) { 4861 while (!list_empty(&cnic_dev_list)) {
4839 dev = list_entry(cnic_dev_list.next, struct cnic_dev, list); 4862 dev = list_entry(cnic_dev_list.next, struct cnic_dev, list);
@@ -4847,6 +4870,11 @@ static void cnic_release(void)
4847 list_del_init(&dev->list); 4870 list_del_init(&dev->list);
4848 cnic_free_dev(dev); 4871 cnic_free_dev(dev);
4849 } 4872 }
4873 while (!list_empty(&cnic_udev_list)) {
4874 udev = list_entry(cnic_udev_list.next, struct cnic_uio_dev,
4875 list);
4876 cnic_free_uio(udev);
4877 }
4850} 4878}
4851 4879
4852static int __init cnic_init(void) 4880static int __init cnic_init(void)