aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Mason <jdmason@kudzu.us>2011-04-08 07:11:22 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-12 14:22:34 -0400
commit9f9b16458134ba9f06ef6f15369513aa9eebc81c (patch)
treed43804b6c7e2b2b4eea94f5383cb9ba1cdf30a3e
parentcd883a791b55c3c52ce402cd551585fed092d240 (diff)
vxge: spin-lock issue
In vxge_hw_vpath_close, __vxge_hw_vp_terminate memsets the vpath which clobbers the spin lock state, then the driver attempts to acquire the spin lock. Resolve this by not zeroing the lock part of vpath struct, clean-up vpath locking in init, close, and fix locking hole in fw_api call. Issue found by Bob Picco <bpicco@redhat.com> Signed-off-by: Jon Mason <jdmason@kudzu.us> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/vxge/vxge-config.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
index 401bebf59502..32763b2dd73f 100644
--- a/drivers/net/vxge/vxge-config.c
+++ b/drivers/net/vxge/vxge-config.c
@@ -159,16 +159,15 @@ vxge_hw_vpath_fw_api(struct __vxge_hw_virtualpath *vpath, u32 action,
159 u32 fw_memo, u32 offset, u64 *data0, u64 *data1, 159 u32 fw_memo, u32 offset, u64 *data0, u64 *data1,
160 u64 *steer_ctrl) 160 u64 *steer_ctrl)
161{ 161{
162 struct vxge_hw_vpath_reg __iomem *vp_reg; 162 struct vxge_hw_vpath_reg __iomem *vp_reg = vpath->vp_reg;
163 enum vxge_hw_status status; 163 enum vxge_hw_status status;
164 u64 val64; 164 u64 val64;
165 u32 retry = 0, max_retry = 100; 165 u32 retry = 0, max_retry = 3;
166
167 vp_reg = vpath->vp_reg;
168 166
169 if (vpath->vp_open) { 167 spin_lock(&vpath->lock);
170 max_retry = 3; 168 if (!vpath->vp_open) {
171 spin_lock(&vpath->lock); 169 spin_unlock(&vpath->lock);
170 max_retry = 100;
172 } 171 }
173 172
174 writeq(*data0, &vp_reg->rts_access_steer_data0); 173 writeq(*data0, &vp_reg->rts_access_steer_data0);
@@ -1000,7 +999,7 @@ exit:
1000/** 999/**
1001 * vxge_hw_device_hw_info_get - Get the hw information 1000 * vxge_hw_device_hw_info_get - Get the hw information
1002 * Returns the vpath mask that has the bits set for each vpath allocated 1001 * Returns the vpath mask that has the bits set for each vpath allocated
1003 * for the driver, FW version information and the first mac addresse for 1002 * for the driver, FW version information, and the first mac address for
1004 * each vpath 1003 * each vpath
1005 */ 1004 */
1006enum vxge_hw_status __devinit 1005enum vxge_hw_status __devinit
@@ -1064,9 +1063,10 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
1064 1063
1065 val64 = readq(&toc->toc_vpath_pointer[i]); 1064 val64 = readq(&toc->toc_vpath_pointer[i]);
1066 1065
1066 spin_lock_init(&vpath.lock);
1067 vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *) 1067 vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
1068 (bar0 + val64); 1068 (bar0 + val64);
1069 vpath.vp_open = 0; 1069 vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
1070 1070
1071 status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info); 1071 status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info);
1072 if (status != VXGE_HW_OK) 1072 if (status != VXGE_HW_OK)
@@ -1090,7 +1090,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
1090 val64 = readq(&toc->toc_vpath_pointer[i]); 1090 val64 = readq(&toc->toc_vpath_pointer[i]);
1091 vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *) 1091 vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
1092 (bar0 + val64); 1092 (bar0 + val64);
1093 vpath.vp_open = 0; 1093 vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
1094 1094
1095 status = __vxge_hw_vpath_addr_get(&vpath, 1095 status = __vxge_hw_vpath_addr_get(&vpath,
1096 hw_info->mac_addrs[i], 1096 hw_info->mac_addrs[i],
@@ -4646,7 +4646,27 @@ static void __vxge_hw_vp_terminate(struct __vxge_hw_device *hldev, u32 vp_id)
4646 vpath->hldev->tim_int_mask1, vpath->vp_id); 4646 vpath->hldev->tim_int_mask1, vpath->vp_id);
4647 hldev->stats.hw_dev_info_stats.vpath_info[vpath->vp_id] = NULL; 4647 hldev->stats.hw_dev_info_stats.vpath_info[vpath->vp_id] = NULL;
4648 4648
4649 memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath)); 4649 /* If the whole struct __vxge_hw_virtualpath is zeroed, nothing will
4650 * work after the interface is brought down.
4651 */
4652 spin_lock(&vpath->lock);
4653 vpath->vp_open = VXGE_HW_VP_NOT_OPEN;
4654 spin_unlock(&vpath->lock);
4655
4656 vpath->vpmgmt_reg = NULL;
4657 vpath->nofl_db = NULL;
4658 vpath->max_mtu = 0;
4659 vpath->vsport_number = 0;
4660 vpath->max_kdfc_db = 0;
4661 vpath->max_nofl_db = 0;
4662 vpath->ringh = NULL;
4663 vpath->fifoh = NULL;
4664 memset(&vpath->vpath_handles, 0, sizeof(struct list_head));
4665 vpath->stats_block = 0;
4666 vpath->hw_stats = NULL;
4667 vpath->hw_stats_sav = NULL;
4668 vpath->sw_stats = NULL;
4669
4650exit: 4670exit:
4651 return; 4671 return;
4652} 4672}
@@ -4670,7 +4690,7 @@ __vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id,
4670 4690
4671 vpath = &hldev->virtual_paths[vp_id]; 4691 vpath = &hldev->virtual_paths[vp_id];
4672 4692
4673 spin_lock_init(&hldev->virtual_paths[vp_id].lock); 4693 spin_lock_init(&vpath->lock);
4674 vpath->vp_id = vp_id; 4694 vpath->vp_id = vp_id;
4675 vpath->vp_open = VXGE_HW_VP_OPEN; 4695 vpath->vp_open = VXGE_HW_VP_OPEN;
4676 vpath->hldev = hldev; 4696 vpath->hldev = hldev;
@@ -5019,10 +5039,6 @@ enum vxge_hw_status vxge_hw_vpath_close(struct __vxge_hw_vpath_handle *vp)
5019 5039
5020 __vxge_hw_vp_terminate(devh, vp_id); 5040 __vxge_hw_vp_terminate(devh, vp_id);
5021 5041
5022 spin_lock(&vpath->lock);
5023 vpath->vp_open = VXGE_HW_VP_NOT_OPEN;
5024 spin_unlock(&vpath->lock);
5025
5026vpath_close_exit: 5042vpath_close_exit:
5027 return status; 5043 return status;
5028} 5044}