diff options
author | Carolyn Wyborny <carolyn.wyborny@intel.com> | 2011-10-13 20:13:49 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-10-21 06:19:39 -0400 |
commit | 1128c756bef8285db3bbde5b26d4a6b4c7e2e613 (patch) | |
tree | 265057e706f6d147c72099deb2b21f2fd74b6b33 /drivers/net | |
parent | b6e0c419f040cee87813660bb4efd1fe43a8ebee (diff) |
igb: VFTA Table Fix for i350 devices
Due to a hardware problem, writes to the VFTA register can
theoretically fail. Although the likelihood of this is very low.
This patch adds a shadow vfta in the adapter struct for reading
and adds new write functions for these devices to work around the problem.
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@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')
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_82575.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_mac.c | 56 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_mac.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 6 |
5 files changed, 65 insertions, 4 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 6580cea796c5..7881fb95a25b 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c | |||
@@ -1051,7 +1051,10 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw) | |||
1051 | 1051 | ||
1052 | /* Disabling VLAN filtering */ | 1052 | /* Disabling VLAN filtering */ |
1053 | hw_dbg("Initializing the IEEE VLAN\n"); | 1053 | hw_dbg("Initializing the IEEE VLAN\n"); |
1054 | igb_clear_vfta(hw); | 1054 | if (hw->mac.type == e1000_i350) |
1055 | igb_clear_vfta_i350(hw); | ||
1056 | else | ||
1057 | igb_clear_vfta(hw); | ||
1055 | 1058 | ||
1056 | /* Setup the receive address */ | 1059 | /* Setup the receive address */ |
1057 | igb_init_rx_addrs(hw, rar_count); | 1060 | igb_init_rx_addrs(hw, rar_count); |
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index bad3e1425ffb..73aac082c44d 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c | |||
@@ -117,6 +117,50 @@ static void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) | |||
117 | wrfl(); | 117 | wrfl(); |
118 | } | 118 | } |
119 | 119 | ||
120 | /* Due to a hw errata, if the host tries to configure the VFTA register | ||
121 | * while performing queries from the BMC or DMA, then the VFTA in some | ||
122 | * cases won't be written. | ||
123 | */ | ||
124 | |||
125 | /** | ||
126 | * igb_clear_vfta_i350 - Clear VLAN filter table | ||
127 | * @hw: pointer to the HW structure | ||
128 | * | ||
129 | * Clears the register array which contains the VLAN filter table by | ||
130 | * setting all the values to 0. | ||
131 | **/ | ||
132 | void igb_clear_vfta_i350(struct e1000_hw *hw) | ||
133 | { | ||
134 | u32 offset; | ||
135 | int i; | ||
136 | |||
137 | for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { | ||
138 | for (i = 0; i < 10; i++) | ||
139 | array_wr32(E1000_VFTA, offset, 0); | ||
140 | |||
141 | wrfl(); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * igb_write_vfta_i350 - Write value to VLAN filter table | ||
147 | * @hw: pointer to the HW structure | ||
148 | * @offset: register offset in VLAN filter table | ||
149 | * @value: register value written to VLAN filter table | ||
150 | * | ||
151 | * Writes value at the given offset in the register array which stores | ||
152 | * the VLAN filter table. | ||
153 | **/ | ||
154 | void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) | ||
155 | { | ||
156 | int i; | ||
157 | |||
158 | for (i = 0; i < 10; i++) | ||
159 | array_wr32(E1000_VFTA, offset, value); | ||
160 | |||
161 | wrfl(); | ||
162 | } | ||
163 | |||
120 | /** | 164 | /** |
121 | * igb_init_rx_addrs - Initialize receive address's | 165 | * igb_init_rx_addrs - Initialize receive address's |
122 | * @hw: pointer to the HW structure | 166 | * @hw: pointer to the HW structure |
@@ -155,9 +199,12 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) | |||
155 | { | 199 | { |
156 | u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; | 200 | u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; |
157 | u32 mask = 1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); | 201 | u32 mask = 1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); |
158 | u32 vfta = array_rd32(E1000_VFTA, index); | 202 | u32 vfta; |
203 | struct igb_adapter *adapter = hw->back; | ||
159 | s32 ret_val = 0; | 204 | s32 ret_val = 0; |
160 | 205 | ||
206 | vfta = adapter->shadow_vfta[index]; | ||
207 | |||
161 | /* bit was set/cleared before we started */ | 208 | /* bit was set/cleared before we started */ |
162 | if ((!!(vfta & mask)) == add) { | 209 | if ((!!(vfta & mask)) == add) { |
163 | ret_val = -E1000_ERR_CONFIG; | 210 | ret_val = -E1000_ERR_CONFIG; |
@@ -167,8 +214,11 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) | |||
167 | else | 214 | else |
168 | vfta &= ~mask; | 215 | vfta &= ~mask; |
169 | } | 216 | } |
170 | 217 | if (hw->mac.type == e1000_i350) | |
171 | igb_write_vfta(hw, index, vfta); | 218 | igb_write_vfta_i350(hw, index, vfta); |
219 | else | ||
220 | igb_write_vfta(hw, index, vfta); | ||
221 | adapter->shadow_vfta[index] = vfta; | ||
172 | 222 | ||
173 | return ret_val; | 223 | return ret_val; |
174 | } | 224 | } |
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h index 4927f61fbbc8..e45996b4ea34 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.h +++ b/drivers/net/ethernet/intel/igb/e1000_mac.h | |||
@@ -60,6 +60,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, | |||
60 | 60 | ||
61 | void igb_clear_hw_cntrs_base(struct e1000_hw *hw); | 61 | void igb_clear_hw_cntrs_base(struct e1000_hw *hw); |
62 | void igb_clear_vfta(struct e1000_hw *hw); | 62 | void igb_clear_vfta(struct e1000_hw *hw); |
63 | void igb_clear_vfta_i350(struct e1000_hw *hw); | ||
63 | s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); | 64 | s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); |
64 | void igb_config_collision_dist(struct e1000_hw *hw); | 65 | void igb_config_collision_dist(struct e1000_hw *hw); |
65 | void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); | 66 | void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); |
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 559443015cc5..c69feebf2653 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h | |||
@@ -363,6 +363,7 @@ struct igb_adapter { | |||
363 | u32 rss_queues; | 363 | u32 rss_queues; |
364 | u32 wvbr; | 364 | u32 wvbr; |
365 | int node; | 365 | int node; |
366 | u32 *shadow_vfta; | ||
366 | }; | 367 | }; |
367 | 368 | ||
368 | #define IGB_FLAG_HAS_MSI (1 << 0) | 369 | #define IGB_FLAG_HAS_MSI (1 << 0) |
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b1863531e03f..ced544499f1b 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -2206,6 +2206,7 @@ static void __devexit igb_remove(struct pci_dev *pdev) | |||
2206 | pci_release_selected_regions(pdev, | 2206 | pci_release_selected_regions(pdev, |
2207 | pci_select_bars(pdev, IORESOURCE_MEM)); | 2207 | pci_select_bars(pdev, IORESOURCE_MEM)); |
2208 | 2208 | ||
2209 | kfree(adapter->shadow_vfta); | ||
2209 | free_netdev(netdev); | 2210 | free_netdev(netdev); |
2210 | 2211 | ||
2211 | pci_disable_pcie_error_reporting(pdev); | 2212 | pci_disable_pcie_error_reporting(pdev); |
@@ -2438,6 +2439,11 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) | |||
2438 | ((adapter->rss_queues > 1) && (adapter->vfs_allocated_count > 6))) | 2439 | ((adapter->rss_queues > 1) && (adapter->vfs_allocated_count > 6))) |
2439 | adapter->flags |= IGB_FLAG_QUEUE_PAIRS; | 2440 | adapter->flags |= IGB_FLAG_QUEUE_PAIRS; |
2440 | 2441 | ||
2442 | /* Setup and initialize a copy of the hw vlan table array */ | ||
2443 | adapter->shadow_vfta = kzalloc(sizeof(u32) * | ||
2444 | E1000_VLAN_FILTER_TBL_SIZE, | ||
2445 | GFP_ATOMIC); | ||
2446 | |||
2441 | /* This call may decrease the number of queues */ | 2447 | /* This call may decrease the number of queues */ |
2442 | if (igb_init_interrupt_scheme(adapter)) { | 2448 | if (igb_init_interrupt_scheme(adapter)) { |
2443 | dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); | 2449 | dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); |