@@ -2328,6 +2328,12 @@ static void e1000_set_rx_mode(struct net_device *netdev)
int mta_reg_count = (hw->mac_type == e1000_ich8lan) ?
E1000_NUM_MTA_REGISTERS_ICH8LAN :
E1000_NUM_MTA_REGISTERS;
+ u32 *mcarray = kzalloc(512, GFP_ATOMIC);
+
+ if (!mcarray) {
+ DPRINTK(PROBE, ERR, "memory allocation failed\n");
+ return;
+ }
if (hw->mac_type == e1000_ich8lan)
rar_entries = E1000_RAR_ENTRIES_ICH8LAN;
@@ -2394,22 +2400,38 @@ static void e1000_set_rx_mode(struct net_device *netdev)
}
WARN_ON(uc_ptr != NULL);
- /* clear the old settings from the multicast hash table */
-
- for (i = 0; i < mta_reg_count; i++) {
- E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
- E1000_WRITE_FLUSH();
- }
-
/* load any remaining addresses into the hash table */
for (; mc_ptr; mc_ptr = mc_ptr->next) {
+ u32 hash_reg, hash_bit, mta;
hash_value = e1000_hash_mc_addr(hw, mc_ptr->da_addr);
- e1000_mta_set(hw, hash_value);
+ hash_reg = (hash_value >> 5) & 0x7F;
+ hash_bit = hash_value & 0x1F;
+ mta = (1 << hash_bit);
+ mcarray[hash_reg] |= mta;
}
+ /* write the hash table completely, write from bottom to avoid
+ * stupid write combining chipsets, and flushing each write */
+ for (i = mta_reg_count - 1; i >= 0 ; i--) {
+ /* If we are on an 82544 and we are trying to write an odd
+ * offset in the MTA, save off the previous entry before
+ * writing and restore the old value after writing.
+ */
+ if ((hw->mac_type == e1000_82544) && ((i & 1) == 1)) {
+ u32 temp = E1000_READ_REG_ARRAY(hw, MTA, (i - 1));
+ E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]);
+ E1000_WRITE_REG_ARRAY(hw, MTA, (i - 1), temp);
+ } else {
+ E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]);
+ }
+ }
+ E1000_WRITE_FLUSH();
+
if (hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
+
+ kfree(mcarray);
}
/* Need to wait a few seconds after link up to get diagnostic information from