aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2009-03-25 18:05:21 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-26 04:09:59 -0400
commita72d2b2cc63994cb8d592a004bf5331be6905814 (patch)
treec55a5b6d1f471e0aae21881d3bce8b047c46baa4 /drivers/net/e1000e
parent12d04a3c12b420f23398b4d650127642469a60a6 (diff)
e1000e: fix loss of multicast packets
e1000e (and e1000, igb, ixgbe, ixgb) all do a series of operations each time a multicast address is added. The flow goes something like 1) stack adds one multicast address 2) stack passes whole current list of unicast and multicast addresses to driver 3) driver clears entire list in hardware 4) driver programs each multicast address using iomem in a loop This was causing multicast packets to be lost during the reprogramming process. reference with test program: http://kerneltrap.org/mailarchive/linux-netdev/2009/3/14/5160514/thread Thanks to Dave Boutcher for his report and test program. This driver fix prepares an array all at once in memory and programs it in one shot to the hardware, not requiring an "erase" cycle. It would still be possible for packets to be dropped while the receiver is off during reprogramming. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> CC: Dave Boutcher <daveboutcher@gmail.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r--drivers/net/e1000e/lib.c62
1 files changed, 18 insertions, 44 deletions
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index ac2f34e1836d..18a4f5902f3b 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -159,41 +159,6 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
159} 159}
160 160
161/** 161/**
162 * e1000_mta_set - Set multicast filter table address
163 * @hw: pointer to the HW structure
164 * @hash_value: determines the MTA register and bit to set
165 *
166 * The multicast table address is a register array of 32-bit registers.
167 * The hash_value is used to determine what register the bit is in, the
168 * current value is read, the new bit is OR'd in and the new value is
169 * written back into the register.
170 **/
171static void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
172{
173 u32 hash_bit, hash_reg, mta;
174
175 /*
176 * The MTA is a register array of 32-bit registers. It is
177 * treated like an array of (32*mta_reg_count) bits. We want to
178 * set bit BitArray[hash_value]. So we figure out what register
179 * the bit is in, read it, OR in the new bit, then write
180 * back the new value. The (hw->mac.mta_reg_count - 1) serves as a
181 * mask to bits 31:5 of the hash value which gives us the
182 * register we're modifying. The hash bit within that register
183 * is determined by the lower 5 bits of the hash value.
184 */
185 hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
186 hash_bit = hash_value & 0x1F;
187
188 mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);
189
190 mta |= (1 << hash_bit);
191
192 E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);
193 e1e_flush();
194}
195
196/**
197 * e1000_hash_mc_addr - Generate a multicast hash value 162 * e1000_hash_mc_addr - Generate a multicast hash value
198 * @hw: pointer to the HW structure 163 * @hw: pointer to the HW structure
199 * @mc_addr: pointer to a multicast address 164 * @mc_addr: pointer to a multicast address
@@ -281,8 +246,13 @@ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
281 u8 *mc_addr_list, u32 mc_addr_count, 246 u8 *mc_addr_list, u32 mc_addr_count,
282 u32 rar_used_count, u32 rar_count) 247 u32 rar_used_count, u32 rar_count)
283{ 248{
284 u32 hash_value;
285 u32 i; 249 u32 i;
250 u32 *mcarray = kzalloc(hw->mac.mta_reg_count * sizeof(u32), GFP_ATOMIC);
251
252 if (!mcarray) {
253 printk(KERN_ERR "multicast array memory allocation failed\n");
254 return;
255 }
286 256
287 /* 257 /*
288 * Load the first set of multicast addresses into the exact 258 * Load the first set of multicast addresses into the exact
@@ -302,20 +272,24 @@ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
302 } 272 }
303 } 273 }
304 274
305 /* Clear the old settings from the MTA */
306 hw_dbg(hw, "Clearing MTA\n");
307 for (i = 0; i < hw->mac.mta_reg_count; i++) {
308 E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
309 e1e_flush();
310 }
311
312 /* Load any remaining multicast addresses into the hash table. */ 275 /* Load any remaining multicast addresses into the hash table. */
313 for (; mc_addr_count > 0; mc_addr_count--) { 276 for (; mc_addr_count > 0; mc_addr_count--) {
277 u32 hash_value, hash_reg, hash_bit, mta;
314 hash_value = e1000_hash_mc_addr(hw, mc_addr_list); 278 hash_value = e1000_hash_mc_addr(hw, mc_addr_list);
315 hw_dbg(hw, "Hash value = 0x%03X\n", hash_value); 279 hw_dbg(hw, "Hash value = 0x%03X\n", hash_value);
316 e1000_mta_set(hw, hash_value); 280 hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
281 hash_bit = hash_value & 0x1F;
282 mta = (1 << hash_bit);
283 mcarray[hash_reg] |= mta;
317 mc_addr_list += ETH_ALEN; 284 mc_addr_list += ETH_ALEN;
318 } 285 }
286
287 /* write the hash table completely */
288 for (i = 0; i < hw->mac.mta_reg_count; i++)
289 E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, mcarray[i]);
290
291 e1e_flush();
292 kfree(mcarray);
319} 293}
320 294
321/** 295/**