diff options
Diffstat (limited to 'drivers/net/e1000e/lib.c')
-rw-r--r-- | drivers/net/e1000e/lib.c | 58 |
1 files changed, 15 insertions, 43 deletions
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 5f6b17148d34..2425ed11d5cc 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c | |||
@@ -340,62 +340,34 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) | |||
340 | * @hw: pointer to the HW structure | 340 | * @hw: pointer to the HW structure |
341 | * @mc_addr_list: array of multicast addresses to program | 341 | * @mc_addr_list: array of multicast addresses to program |
342 | * @mc_addr_count: number of multicast addresses to program | 342 | * @mc_addr_count: number of multicast addresses to program |
343 | * @rar_used_count: the first RAR register free to program | ||
344 | * @rar_count: total number of supported Receive Address Registers | ||
345 | * | 343 | * |
346 | * Updates the Receive Address Registers and Multicast Table Array. | 344 | * Updates entire Multicast Table Array. |
347 | * The caller must have a packed mc_addr_list of multicast addresses. | 345 | * The caller must have a packed mc_addr_list of multicast addresses. |
348 | * The parameter rar_count will usually be hw->mac.rar_entry_count | ||
349 | * unless there are workarounds that change this. | ||
350 | **/ | 346 | **/ |
351 | void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, | 347 | void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, |
352 | u8 *mc_addr_list, u32 mc_addr_count, | 348 | u8 *mc_addr_list, u32 mc_addr_count) |
353 | u32 rar_used_count, u32 rar_count) | ||
354 | { | 349 | { |
355 | u32 i; | 350 | u32 hash_value, hash_bit, hash_reg; |
356 | u32 *mcarray = kzalloc(hw->mac.mta_reg_count * sizeof(u32), GFP_ATOMIC); | 351 | int i; |
357 | 352 | ||
358 | if (!mcarray) { | 353 | /* clear mta_shadow */ |
359 | printk(KERN_ERR "multicast array memory allocation failed\n"); | 354 | memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); |
360 | return; | ||
361 | } | ||
362 | 355 | ||
363 | /* | 356 | /* update mta_shadow from mc_addr_list */ |
364 | * Load the first set of multicast addresses into the exact | 357 | for (i = 0; (u32) i < mc_addr_count; i++) { |
365 | * filters (RAR). If there are not enough to fill the RAR | ||
366 | * array, clear the filters. | ||
367 | */ | ||
368 | for (i = rar_used_count; i < rar_count; i++) { | ||
369 | if (mc_addr_count) { | ||
370 | e1000e_rar_set(hw, mc_addr_list, i); | ||
371 | mc_addr_count--; | ||
372 | mc_addr_list += ETH_ALEN; | ||
373 | } else { | ||
374 | E1000_WRITE_REG_ARRAY(hw, E1000_RA, i << 1, 0); | ||
375 | e1e_flush(); | ||
376 | E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1) + 1, 0); | ||
377 | e1e_flush(); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* Load any remaining multicast addresses into the hash table. */ | ||
382 | for (; mc_addr_count > 0; mc_addr_count--) { | ||
383 | u32 hash_value, hash_reg, hash_bit, mta; | ||
384 | hash_value = e1000_hash_mc_addr(hw, mc_addr_list); | 358 | hash_value = e1000_hash_mc_addr(hw, mc_addr_list); |
385 | e_dbg("Hash value = 0x%03X\n", hash_value); | 359 | |
386 | hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); | 360 | hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); |
387 | hash_bit = hash_value & 0x1F; | 361 | hash_bit = hash_value & 0x1F; |
388 | mta = (1 << hash_bit); | ||
389 | mcarray[hash_reg] |= mta; | ||
390 | mc_addr_list += ETH_ALEN; | ||
391 | } | ||
392 | 362 | ||
393 | /* write the hash table completely */ | 363 | hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); |
394 | for (i = 0; i < hw->mac.mta_reg_count; i++) | 364 | mc_addr_list += (ETH_ALEN); |
395 | E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, mcarray[i]); | 365 | } |
396 | 366 | ||
367 | /* replace the entire MTA table */ | ||
368 | for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) | ||
369 | E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); | ||
397 | e1e_flush(); | 370 | e1e_flush(); |
398 | kfree(mcarray); | ||
399 | } | 371 | } |
400 | 372 | ||
401 | /** | 373 | /** |