diff options
author | Matthew Vick <matthew.vick@intel.com> | 2013-03-22 03:34:20 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2013-04-24 21:05:19 -0400 |
commit | d44e7a9a1f1e56918f8e937dcf750626ac5ad9b4 (patch) | |
tree | 889ddc1e236a4e3af2eabdefdfa824e2eccae27f /drivers/net/ethernet/intel | |
parent | 0ba96d3d91882ae27083d8de8634ce0fae20dee6 (diff) |
igb: Add SMBI semaphore to I210/I211
It was previously thought that, since I210/I211 are single port devices,
they did not need the SMBI semaphore. This is not the case. Add support for
the SMBI semaphore.
Signed-off-by: Matthew Vick <matthew.vick@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_82575.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_hw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_i210.c | 65 |
3 files changed, 43 insertions, 26 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index c9bba39d50bd..6cb0ca2869b9 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c | |||
@@ -389,6 +389,9 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw) | |||
389 | dev_spec->eee_disable = false; | 389 | dev_spec->eee_disable = false; |
390 | else | 390 | else |
391 | dev_spec->eee_disable = true; | 391 | dev_spec->eee_disable = true; |
392 | /* Allow a single clear of the SW semaphore on I210 and newer */ | ||
393 | if (mac->type >= e1000_i210) | ||
394 | dev_spec->clear_semaphore_once = true; | ||
392 | /* physical interface link setup */ | 395 | /* physical interface link setup */ |
393 | mac->ops.setup_physical_interface = | 396 | mac->ops.setup_physical_interface = |
394 | (hw->phy.media_type == e1000_media_type_copper) | 397 | (hw->phy.media_type == e1000_media_type_copper) |
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h index 1138ccaf95ff..f1dbab920286 100644 --- a/drivers/net/ethernet/intel/igb/e1000_hw.h +++ b/drivers/net/ethernet/intel/igb/e1000_hw.h | |||
@@ -529,6 +529,7 @@ struct e1000_dev_spec_82575 { | |||
529 | bool sgmii_active; | 529 | bool sgmii_active; |
530 | bool global_device_reset; | 530 | bool global_device_reset; |
531 | bool eee_disable; | 531 | bool eee_disable; |
532 | bool clear_semaphore_once; | ||
532 | }; | 533 | }; |
533 | 534 | ||
534 | struct e1000_hw { | 535 | struct e1000_hw { |
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c index 9764cd3610e5..ddb3cf51b9b9 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.c +++ b/drivers/net/ethernet/intel/igb/e1000_i210.c | |||
@@ -44,10 +44,42 @@ | |||
44 | static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) | 44 | static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) |
45 | { | 45 | { |
46 | u32 swsm; | 46 | u32 swsm; |
47 | s32 ret_val = E1000_SUCCESS; | ||
48 | s32 timeout = hw->nvm.word_size + 1; | 47 | s32 timeout = hw->nvm.word_size + 1; |
49 | s32 i = 0; | 48 | s32 i = 0; |
50 | 49 | ||
50 | /* Get the SW semaphore */ | ||
51 | while (i < timeout) { | ||
52 | swsm = rd32(E1000_SWSM); | ||
53 | if (!(swsm & E1000_SWSM_SMBI)) | ||
54 | break; | ||
55 | |||
56 | udelay(50); | ||
57 | i++; | ||
58 | } | ||
59 | |||
60 | if (i == timeout) { | ||
61 | /* In rare circumstances, the SW semaphore may already be held | ||
62 | * unintentionally. Clear the semaphore once before giving up. | ||
63 | */ | ||
64 | if (hw->dev_spec._82575.clear_semaphore_once) { | ||
65 | hw->dev_spec._82575.clear_semaphore_once = false; | ||
66 | igb_put_hw_semaphore(hw); | ||
67 | for (i = 0; i < timeout; i++) { | ||
68 | swsm = rd32(E1000_SWSM); | ||
69 | if (!(swsm & E1000_SWSM_SMBI)) | ||
70 | break; | ||
71 | |||
72 | udelay(50); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* If we do not have the semaphore here, we have to give up. */ | ||
77 | if (i == timeout) { | ||
78 | hw_dbg("Driver can't access device - SMBI bit is set.\n"); | ||
79 | return -E1000_ERR_NVM; | ||
80 | } | ||
81 | } | ||
82 | |||
51 | /* Get the FW semaphore. */ | 83 | /* Get the FW semaphore. */ |
52 | for (i = 0; i < timeout; i++) { | 84 | for (i = 0; i < timeout; i++) { |
53 | swsm = rd32(E1000_SWSM); | 85 | swsm = rd32(E1000_SWSM); |
@@ -64,12 +96,10 @@ static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) | |||
64 | /* Release semaphores */ | 96 | /* Release semaphores */ |
65 | igb_put_hw_semaphore(hw); | 97 | igb_put_hw_semaphore(hw); |
66 | hw_dbg("Driver can't access the NVM\n"); | 98 | hw_dbg("Driver can't access the NVM\n"); |
67 | ret_val = -E1000_ERR_NVM; | 99 | return -E1000_ERR_NVM; |
68 | goto out; | ||
69 | } | 100 | } |
70 | 101 | ||
71 | out: | 102 | return E1000_SUCCESS; |
72 | return ret_val; | ||
73 | } | 103 | } |
74 | 104 | ||
75 | /** | 105 | /** |
@@ -99,23 +129,6 @@ void igb_release_nvm_i210(struct e1000_hw *hw) | |||
99 | } | 129 | } |
100 | 130 | ||
101 | /** | 131 | /** |
102 | * igb_put_hw_semaphore_i210 - Release hardware semaphore | ||
103 | * @hw: pointer to the HW structure | ||
104 | * | ||
105 | * Release hardware semaphore used to access the PHY or NVM | ||
106 | **/ | ||
107 | static void igb_put_hw_semaphore_i210(struct e1000_hw *hw) | ||
108 | { | ||
109 | u32 swsm; | ||
110 | |||
111 | swsm = rd32(E1000_SWSM); | ||
112 | |||
113 | swsm &= ~E1000_SWSM_SWESMBI; | ||
114 | |||
115 | wr32(E1000_SWSM, swsm); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore | 132 | * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore |
120 | * @hw: pointer to the HW structure | 133 | * @hw: pointer to the HW structure |
121 | * @mask: specifies which semaphore to acquire | 134 | * @mask: specifies which semaphore to acquire |
@@ -138,11 +151,11 @@ s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) | |||
138 | } | 151 | } |
139 | 152 | ||
140 | swfw_sync = rd32(E1000_SW_FW_SYNC); | 153 | swfw_sync = rd32(E1000_SW_FW_SYNC); |
141 | if (!(swfw_sync & fwmask)) | 154 | if (!(swfw_sync & (fwmask | swmask))) |
142 | break; | 155 | break; |
143 | 156 | ||
144 | /* Firmware currently using resource (fwmask) */ | 157 | /* Firmware currently using resource (fwmask) */ |
145 | igb_put_hw_semaphore_i210(hw); | 158 | igb_put_hw_semaphore(hw); |
146 | mdelay(5); | 159 | mdelay(5); |
147 | i++; | 160 | i++; |
148 | } | 161 | } |
@@ -156,7 +169,7 @@ s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) | |||
156 | swfw_sync |= swmask; | 169 | swfw_sync |= swmask; |
157 | wr32(E1000_SW_FW_SYNC, swfw_sync); | 170 | wr32(E1000_SW_FW_SYNC, swfw_sync); |
158 | 171 | ||
159 | igb_put_hw_semaphore_i210(hw); | 172 | igb_put_hw_semaphore(hw); |
160 | out: | 173 | out: |
161 | return ret_val; | 174 | return ret_val; |
162 | } | 175 | } |
@@ -180,7 +193,7 @@ void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) | |||
180 | swfw_sync &= ~mask; | 193 | swfw_sync &= ~mask; |
181 | wr32(E1000_SW_FW_SYNC, swfw_sync); | 194 | wr32(E1000_SW_FW_SYNC, swfw_sync); |
182 | 195 | ||
183 | igb_put_hw_semaphore_i210(hw); | 196 | igb_put_hw_semaphore(hw); |
184 | } | 197 | } |
185 | 198 | ||
186 | /** | 199 | /** |