aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorCarolyn Wyborny <carolyn.wyborny@intel.com>2011-10-13 20:13:49 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-10-21 06:19:39 -0400
commit1128c756bef8285db3bbde5b26d4a6b4c7e2e613 (patch)
tree265057e706f6d147c72099deb2b21f2fd74b6b33 /drivers/net
parentb6e0c419f040cee87813660bb4efd1fe43a8ebee (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.c5
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.c56
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.h1
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h1
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c6
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 **/
132void 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 **/
154void 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
61void igb_clear_hw_cntrs_base(struct e1000_hw *hw); 61void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
62void igb_clear_vfta(struct e1000_hw *hw); 62void igb_clear_vfta(struct e1000_hw *hw);
63void igb_clear_vfta_i350(struct e1000_hw *hw);
63s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); 64s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
64void igb_config_collision_dist(struct e1000_hw *hw); 65void igb_config_collision_dist(struct e1000_hw *hw);
65void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); 66void 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");