]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.drivers/cxgb3-get_drvinfo-deadlock.patch
Revert "Move xen patchset to new version's subdir."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / cxgb3-get_drvinfo-deadlock.patch
CommitLineData
00e5a55c
BS
1From: Steve Wise <swise@opengridcomputing.com>
2Subject: RDMA/cxgb3: deadlock in iw_cxgb3 can cause hang when configuring interface.
3References: bnc#430998
4
5When the iw_cxgb3 module's cxgb3_client "add" func gets called by the
6cxgb3 module, the iwarp driver ends up calling the ethtool ops get_drvinfo
7function in cxgb3 to get the fw version and other info. Currently the
8iwarp driver grabs the rtnl lock around this down call to serialize.
9As of 2.6.27 or so, things changed such that the rtnl lock is held around
10the call to the netdev driver open function. Also the cxgb3_client "add"
11function doesn't get called if the device is down.
12
13So, if you load cxgb3, then load iw_cxgb3, then ifconfig up the device,
14the iw_cxgb3 add func gets called with the rtnl_lock held. If you
15load cxgb3, ifconfig up the device, then load iw_cxgb3, the add func
16gets called without the rtnl_lock held. The former causes the deadlock,
17the latter does not.
18
19In addition, there are iw_cxgb3 sysfs handlers that also can call
20down into cxgb3 to gather the fw and hw versions. These can be called
21concurrently on different processors and at any time. Thus we need to
22push this serialization down in the cxgb3 driver get_drvinfo func.
23
24The fix is to remove rtnl lock usage, and use a per-device lock in cxgb3.
25
26Signed-off-by: Steve Wise <swise@opengridcomputing.com>
27Acked-by: Divy Le Ray <divy@chelsio.com>
28Acked-by: John Jolly <jjolly@suse.de>
29
30---
31 drivers/infiniband/hw/cxgb3/iwch_provider.c | 6 ------
32 drivers/net/cxgb3/cxgb3_main.c | 2 ++
33 2 files changed, 2 insertions(+), 6 deletions(-)
34
35--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
36+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
37@@ -1102,9 +1102,7 @@ static u64 fw_vers_string_to_u64(struct
38 char *cp, *next;
39 unsigned fw_maj, fw_min, fw_mic;
40
41- rtnl_lock();
42 lldev->ethtool_ops->get_drvinfo(lldev, &info);
43- rtnl_unlock();
44
45 next = info.fw_version + 1;
46 cp = strsep(&next, ".");
47@@ -1195,9 +1193,7 @@ static ssize_t show_fw_ver(struct device
48 struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
49
50 PDBG("%s dev 0x%p\n", __func__, dev);
51- rtnl_lock();
52 lldev->ethtool_ops->get_drvinfo(lldev, &info);
53- rtnl_unlock();
54 return sprintf(buf, "%s\n", info.fw_version);
55 }
56
57@@ -1210,9 +1206,7 @@ static ssize_t show_hca(struct device *d
58 struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
59
60 PDBG("%s dev 0x%p\n", __func__, dev);
61- rtnl_lock();
62 lldev->ethtool_ops->get_drvinfo(lldev, &info);
63- rtnl_unlock();
64 return sprintf(buf, "%s\n", info.driver);
65 }
66
67--- a/drivers/net/cxgb3/cxgb3_main.c
68+++ b/drivers/net/cxgb3/cxgb3_main.c
69@@ -1298,8 +1298,10 @@ static void get_drvinfo(struct net_devic
70 u32 fw_vers = 0;
71 u32 tp_vers = 0;
72
73+ spin_lock(&adapter->stats_lock);
74 t3_get_fw_version(adapter, &fw_vers);
75 t3_get_tp_version(adapter, &tp_vers);
76+ spin_unlock(&adapter->stats_lock);
77
78 strcpy(info->driver, DRV_NAME);
79 strcpy(info->version, DRV_VERSION);