Fix promisc mode on certain e1000e cards (rhbz 1064516)
This commit is contained in:
parent
2c94f8d1d9
commit
10d5137948
|
@ -0,0 +1,287 @@
|
|||
Bugzilla: 1064516
|
||||
Upstream-status: Sent for 3.16
|
||||
|
||||
From b3e5bf1ff32cbc58c56675498565020460c683cd Mon Sep 17 00:00:00 2001
|
||||
From: David Ertman <davidx.m.ertman@intel.com>
|
||||
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 <vyasevic@redhat.com>
|
||||
Signed-off-by: Dave Ertman <davidx.m.ertman@intel.com>
|
||||
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
|
||||
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
|
||||
|
||||
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
|
||||
|
|
@ -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 <jwboyer@fedoraproject.org>
|
||||
- Fix promisc mode on certain e1000e cards (rhbz 1064516)
|
||||
- Fix i915 backlight issue on gen4 (rhbz 1094066)
|
||||
|
||||
* Mon Jun 09 2014 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
|
|
Loading…
Reference in New Issue