diff mbox

[dpdk-dev,v3,20/31] net/i40e/base: fix wol failure on PF reset

Message ID 1481369093-102492-21-git-send-email-jingjing.wu@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers show

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Jingjing Wu Dec. 10, 2016, 11:24 a.m. UTC
By default the device clears all MAC filter information on PF Reset.
However, this will cause Wake-On-LAN to fail because the wake filters
are deleted on transition to D3 power state. To get around this,
firmware is adding functionality to preserve certain MAC filters during
PFR. These bits allow the driver tell the FW which filters to preserve.

Set the datalen field and add I40E_AQ_FLAG_BUF/I40E_AQ_FLAG_RD flags in the
desc struct for the WoL/Proxy AQ descriptors. The WoL/Proxy AQ commands
were failing because these were missing.

Fixes: 3c89193a36fd ("i40e/base: support WOL config for X722")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_adminq_cmd.h |  5 ++++-
 drivers/net/i40e/base/i40e_common.c     | 16 +++++++++++++++-
 2 files changed, 19 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/drivers/net/i40e/base/i40e_adminq_cmd.h b/drivers/net/i40e/base/i40e_adminq_cmd.h
index 19af8b5..d4d2a7a 100644
--- a/drivers/net/i40e/base/i40e_adminq_cmd.h
+++ b/drivers/net/i40e/base/i40e_adminq_cmd.h
@@ -541,7 +541,8 @@  struct i40e_aqc_mac_address_read {
 #define I40E_AQC_PORT_ADDR_VALID	0x40
 #define I40E_AQC_WOL_ADDR_VALID		0x80
 #define I40E_AQC_MC_MAG_EN_VALID	0x100
-#define I40E_AQC_ADDR_VALID_MASK	0x1F0
+#define I40E_AQC_WOL_PRESERVE_STATUS	0x200
+#define I40E_AQC_ADDR_VALID_MASK	0x3F0
 	u8	reserved[6];
 	__le32	addr_high;
 	__le32	addr_low;
@@ -562,6 +563,7 @@  I40E_CHECK_STRUCT_LEN(24, i40e_aqc_mac_address_read_data);
 struct i40e_aqc_mac_address_write {
 	__le16	command_flags;
 #define I40E_AQC_MC_MAG_EN		0x0100
+#define I40E_AQC_WOL_PRESERVE_ON_PFR	0x0200
 #define I40E_AQC_WRITE_TYPE_LAA_ONLY	0x0000
 #define I40E_AQC_WRITE_TYPE_LAA_WOL	0x4000
 #define I40E_AQC_WRITE_TYPE_PORT	0x8000
@@ -601,6 +603,7 @@  struct i40e_aqc_set_wol_filter {
 	__le16 cmd_flags;
 #define I40E_AQC_SET_WOL_FILTER				0x8000
 #define I40E_AQC_SET_WOL_FILTER_NO_TCO_WOL		0x4000
+#define I40E_AQC_SET_WOL_FILTER_WOL_PRESERVE_ON_PFR	0x2000
 #define I40E_AQC_SET_WOL_FILTER_ACTION_CLEAR		0
 #define I40E_AQC_SET_WOL_FILTER_ACTION_SET		1
 	__le16 valid_flags;
diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index 1095e68..e9376dd 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -6804,10 +6804,13 @@  enum i40e_status_code i40e_aq_set_arp_proxy_config(struct i40e_hw *hw,
 
 	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_proxy_config);
 
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
 	desc.params.external.addr_high =
 				  CPU_TO_LE32(I40E_HI_DWORD((u64)proxy_config));
 	desc.params.external.addr_low =
 				  CPU_TO_LE32(I40E_LO_DWORD((u64)proxy_config));
+	desc.datalen = sizeof(struct i40e_aqc_arp_proxy_data);
 
 	status = i40e_asq_send_command(hw, &desc, proxy_config,
 				       sizeof(struct i40e_aqc_arp_proxy_data),
@@ -6838,10 +6841,13 @@  enum i40e_status_code i40e_aq_set_ns_proxy_table_entry(struct i40e_hw *hw,
 	i40e_fill_default_direct_cmd_desc(&desc,
 				i40e_aqc_opc_set_ns_proxy_table_entry);
 
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
 	desc.params.external.addr_high =
 		CPU_TO_LE32(I40E_HI_DWORD((u64)ns_proxy_table_entry));
 	desc.params.external.addr_low =
 		CPU_TO_LE32(I40E_LO_DWORD((u64)ns_proxy_table_entry));
+	desc.datalen = sizeof(struct i40e_aqc_ns_proxy_data);
 
 	status = i40e_asq_send_command(hw, &desc, ns_proxy_table_entry,
 				       sizeof(struct i40e_aqc_ns_proxy_data),
@@ -6888,9 +6894,11 @@  enum i40e_status_code i40e_aq_set_clear_wol_filter(struct i40e_hw *hw,
 	if (set_filter) {
 		if (!filter)
 			return  I40E_ERR_PARAM;
+
 		cmd_flags |= I40E_AQC_SET_WOL_FILTER;
-		buff_len = sizeof(*filter);
+		cmd_flags |= I40E_AQC_SET_WOL_FILTER_WOL_PRESERVE_ON_PFR;
 	}
+
 	if (no_wol_tco)
 		cmd_flags |= I40E_AQC_SET_WOL_FILTER_NO_TCO_WOL;
 	cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
@@ -6901,6 +6909,12 @@  enum i40e_status_code i40e_aq_set_clear_wol_filter(struct i40e_hw *hw,
 		valid_flags |= I40E_AQC_SET_WOL_FILTER_NO_TCO_ACTION_VALID;
 	cmd->valid_flags = CPU_TO_LE16(valid_flags);
 
+	buff_len = sizeof(*filter);
+	desc.datalen = buff_len;
+
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
+
 	cmd->address_high = CPU_TO_LE32(I40E_HI_DWORD((u64)filter));
 	cmd->address_low = CPU_TO_LE32(I40E_LO_DWORD((u64)filter));