aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cnic.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2010-10-13 10:06:50 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-14 13:45:55 -0400
commita3ceeeb8f11d74f26e3dfca40ded911a82402db5 (patch)
treeec30fde13baa7880a48a6353ef5ff0af6bd67185 /drivers/net/cnic.c
parentcd801536c236e287f1d3eeee428abf9ffd523ede (diff)
cnic: Decouple uio close from cnic shutdown
During cnic shutdown, the original driver code requires userspace to close the uio device within a few seconds. This doesn't always happen as the userapp may be hung or otherwise take a long time to close. The system may crash when this happens. We fix the problem by decoupling the uio structures from the cnic structures during cnic shutdown. We do not unregister the uio device until the cnic driver is unloaded. This eliminates the unreliable wait loop for uio to close. All uio structures are kept in a linked list. If the device is shutdown and later brought back up again, the uio strcture will be found in the linked list and coupled back to the cnic structures. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cnic.c')
-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)