From 10d51379489e6e3076a831464642b42181f3788f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 11 Jun 2014 16:15:57 -0400 Subject: [PATCH] Fix promisc mode on certain e1000e cards (rhbz 1064516) --- ...-to-write-SHRA-turns-on-PROMISC-mode.patch | 287 ++++++++++++++++++ kernel.spec | 7 + 2 files changed, 294 insertions(+) create mode 100644 e1000e-Failure-to-write-SHRA-turns-on-PROMISC-mode.patch diff --git a/e1000e-Failure-to-write-SHRA-turns-on-PROMISC-mode.patch b/e1000e-Failure-to-write-SHRA-turns-on-PROMISC-mode.patch new file mode 100644 index 000000000..1e51db493 --- /dev/null +++ b/e1000e-Failure-to-write-SHRA-turns-on-PROMISC-mode.patch @@ -0,0 +1,287 @@ +Bugzilla: 1064516 +Upstream-status: Sent for 3.16 + +From b3e5bf1ff32cbc58c56675498565020460c683cd Mon Sep 17 00:00:00 2001 +From: David Ertman +Date: Tue, 6 May 2014 03:50:17 +0000 +Subject: e1000e: Failure to write SHRA turns on PROMISC mode + +Previously, the check to turn on promiscuous mode only took into account +the total number of SHared Receive Address (SHRA) registers and if the +request was for a register within that range. It is possible that the +Management Engine might have locked a number of SHRA and not allowed a +new address to be written to the requested register. + +Add a function to determine the number of unlocked SHRA registers. Then +determine if the number of registers available is sufficient for our needs, +if not then return -ENOMEM so that UNICAST PROMISC mode is activated. + +Since the method by which ME claims SHRA registers is non-deterministic, +also add a return value to the function attempting to write an address +to a SHRA, and return a -E1000_ERR_CONFIG if the write fails. The error +will be passed up the function chain and allow the driver to also set +UNICAST PROMISC when this happens. + +Cc: Vlad Yasevich +Signed-off-by: Dave Ertman +Tested-by: Aaron Brown +Signed-off-by: Jeff Kirsher + +diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c +index a5f6b11..08f22f3 100644 +--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c ++++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c +@@ -1365,6 +1365,7 @@ static const struct e1000_mac_operations es2_mac_ops = { + .setup_led = e1000e_setup_led_generic, + .config_collision_dist = e1000e_config_collision_dist_generic, + .rar_set = e1000e_rar_set_generic, ++ .rar_get_count = e1000e_rar_get_count_generic, + }; + + static const struct e1000_phy_operations es2_phy_ops = { +diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c +index e0aa7f1..218481e 100644 +--- a/drivers/net/ethernet/intel/e1000e/82571.c ++++ b/drivers/net/ethernet/intel/e1000e/82571.c +@@ -1896,6 +1896,7 @@ static const struct e1000_mac_operations e82571_mac_ops = { + .config_collision_dist = e1000e_config_collision_dist_generic, + .read_mac_addr = e1000_read_mac_addr_82571, + .rar_set = e1000e_rar_set_generic, ++ .rar_get_count = e1000e_rar_get_count_generic, + }; + + static const struct e1000_phy_operations e82_phy_ops_igp = { +diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h +index 6b3de5f..72f5475 100644 +--- a/drivers/net/ethernet/intel/e1000e/hw.h ++++ b/drivers/net/ethernet/intel/e1000e/hw.h +@@ -469,8 +469,9 @@ struct e1000_mac_operations { + s32 (*setup_led)(struct e1000_hw *); + void (*write_vfta)(struct e1000_hw *, u32, u32); + void (*config_collision_dist)(struct e1000_hw *); +- void (*rar_set)(struct e1000_hw *, u8 *, u32); ++ int (*rar_set)(struct e1000_hw *, u8 *, u32); + s32 (*read_mac_addr)(struct e1000_hw *); ++ u32 (*rar_get_count)(struct e1000_hw *); + }; + + /* When to use various PHY register access functions: +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c +index 5f55395..b75862d 100644 +--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c +@@ -139,8 +139,9 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); + static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); + static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); + static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); +-static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); +-static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); ++static int e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); ++static int e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); ++static u32 e1000_rar_get_count_pch_lpt(struct e1000_hw *hw); + static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); + static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); + static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force); +@@ -704,6 +705,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) + mac->ops.rar_set = e1000_rar_set_pch_lpt; + mac->ops.setup_physical_interface = + e1000_setup_copper_link_pch_lpt; ++ mac->ops.rar_get_count = e1000_rar_get_count_pch_lpt; + } + + /* Enable PCS Lock-loss workaround for ICH8 */ +@@ -1668,7 +1670,7 @@ static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw) + * contain the MAC address but RAR[1-6] are reserved for manageability (ME). + * Use SHRA[0-3] in place of those reserved for ME. + **/ +-static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) ++static int e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) + { + u32 rar_low, rar_high; + +@@ -1690,7 +1692,7 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) + e1e_flush(); + ew32(RAH(index), rar_high); + e1e_flush(); +- return; ++ return 0; + } + + /* RAR[1-6] are owned by manageability. Skip those and program the +@@ -1713,7 +1715,7 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) + /* verify the register updates */ + if ((er32(SHRAL(index - 1)) == rar_low) && + (er32(SHRAH(index - 1)) == rar_high)) +- return; ++ return 0; + + e_dbg("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n", + (index - 1), er32(FWSM)); +@@ -1721,6 +1723,43 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) + + out: + e_dbg("Failed to write receive address at index %d\n", index); ++ return -E1000_ERR_CONFIG; ++} ++ ++/** ++ * e1000_rar_get_count_pch_lpt - Get the number of available SHRA ++ * @hw: pointer to the HW structure ++ * ++ * Get the number of available receive registers that the Host can ++ * program. SHRA[0-10] are the shared receive address registers ++ * that are shared between the Host and manageability engine (ME). ++ * ME can reserve any number of addresses and the host needs to be ++ * able to tell how many available registers it has access to. ++ **/ ++static u32 e1000_rar_get_count_pch_lpt(struct e1000_hw *hw) ++{ ++ u32 wlock_mac; ++ u32 num_entries; ++ ++ wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK; ++ wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT; ++ ++ switch (wlock_mac) { ++ case 0: ++ /* All SHRA[0..10] and RAR[0] available */ ++ num_entries = hw->mac.rar_entry_count; ++ break; ++ case 1: ++ /* Only RAR[0] available */ ++ num_entries = 1; ++ break; ++ default: ++ /* SHRA[0..(wlock_mac - 1)] available + RAR[0] */ ++ num_entries = wlock_mac + 1; ++ break; ++ } ++ ++ return num_entries; + } + + /** +@@ -1734,7 +1773,7 @@ out: + * contain the MAC address. SHRA[0-10] are the shared receive address + * registers that are shared between the Host and manageability engine (ME). + **/ +-static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) ++static int e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) + { + u32 rar_low, rar_high; + u32 wlock_mac; +@@ -1756,7 +1795,7 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) + e1e_flush(); + ew32(RAH(index), rar_high); + e1e_flush(); +- return; ++ return 0; + } + + /* The manageability engine (ME) can lock certain SHRAR registers that +@@ -1788,12 +1827,13 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) + /* verify the register updates */ + if ((er32(SHRAL_PCH_LPT(index - 1)) == rar_low) && + (er32(SHRAH_PCH_LPT(index - 1)) == rar_high)) +- return; ++ return 0; + } + } + + out: + e_dbg("Failed to write receive address at index %d\n", index); ++ return -E1000_ERR_CONFIG; + } + + /** +@@ -4977,6 +5017,7 @@ static const struct e1000_mac_operations ich8_mac_ops = { + /* id_led_init dependent on mac type */ + .config_collision_dist = e1000e_config_collision_dist_generic, + .rar_set = e1000e_rar_set_generic, ++ .rar_get_count = e1000e_rar_get_count_generic, + }; + + static const struct e1000_phy_operations ich8_phy_ops = { +diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c +index baa0a46..8c386f3a 100644 +--- a/drivers/net/ethernet/intel/e1000e/mac.c ++++ b/drivers/net/ethernet/intel/e1000e/mac.c +@@ -211,6 +211,11 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) + return 0; + } + ++u32 e1000e_rar_get_count_generic(struct e1000_hw *hw) ++{ ++ return hw->mac.rar_entry_count; ++} ++ + /** + * e1000e_rar_set_generic - Set receive address register + * @hw: pointer to the HW structure +@@ -220,7 +225,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) + * Sets the receive address array register at index to the address passed + * in by addr. + **/ +-void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) ++int e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) + { + u32 rar_low, rar_high; + +@@ -244,6 +249,8 @@ void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) + e1e_flush(); + ew32(RAH(index), rar_high); + e1e_flush(); ++ ++ return 0; + } + + /** +diff --git a/drivers/net/ethernet/intel/e1000e/mac.h b/drivers/net/ethernet/intel/e1000e/mac.h +index 4e81c28..0513d90 100644 +--- a/drivers/net/ethernet/intel/e1000e/mac.h ++++ b/drivers/net/ethernet/intel/e1000e/mac.h +@@ -61,7 +61,8 @@ void e1000e_update_adaptive(struct e1000_hw *hw); + void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); + + void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); +-void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); ++u32 e1000e_rar_get_count_generic(struct e1000_hw *hw); ++int e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); + void e1000e_config_collision_dist_generic(struct e1000_hw *hw); + + #endif +diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c +index e4207ef..6084e6b 100644 +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -3311,9 +3311,11 @@ static int e1000e_write_uc_addr_list(struct net_device *netdev) + { + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; +- unsigned int rar_entries = hw->mac.rar_entry_count; ++ unsigned int rar_entries; + int count = 0; + ++ rar_entries = hw->mac.ops.rar_get_count(hw); ++ + /* save a rar entry for our hardware address */ + rar_entries--; + +@@ -3332,9 +3334,13 @@ static int e1000e_write_uc_addr_list(struct net_device *netdev) + * combining + */ + netdev_for_each_uc_addr(ha, netdev) { ++ int rval; ++ + if (!rar_entries) + break; +- hw->mac.ops.rar_set(hw, ha->addr, rar_entries--); ++ rval = hw->mac.ops.rar_set(hw, ha->addr, rar_entries--); ++ if (rval < 0) ++ return -ENOMEM; + count++; + } + } +-- +cgit v0.10.1 + diff --git a/kernel.spec b/kernel.spec index 7afea0aa9..065160aec 100644 --- a/kernel.spec +++ b/kernel.spec @@ -725,6 +725,9 @@ Patch26014: acpi-video-Add-use_native_backlight-quirk-for-HP-Pro.patch #rhbz 1094066 Patch25096: drm-i915-set-backlight-duty-cycle-after-backlight-enable-for-gen4.patch +#rhbz 1064516 +Patch25098: e1000e-Failure-to-write-SHRA-turns-on-PROMISC-mode.patch + # END OF PATCH DEFINITIONS %endif @@ -1418,6 +1421,9 @@ ApplyPatch acpi-video-Add-use_native_backlight-quirk-for-HP-Pro.patch #rhbz 1094066 ApplyPatch drm-i915-set-backlight-duty-cycle-after-backlight-enable-for-gen4.patch +#rhbz 1064516 +ApplyPatch e1000e-Failure-to-write-SHRA-turns-on-PROMISC-mode.patch + # END OF PATCH APPLICATIONS %endif @@ -2231,6 +2237,7 @@ fi # || || %changelog * Wed Jun 11 2014 Josh Boyer +- Fix promisc mode on certain e1000e cards (rhbz 1064516) - Fix i915 backlight issue on gen4 (rhbz 1094066) * Mon Jun 09 2014 Josh Boyer