net/i40e/base: fix WoL failure on PF reset
authorJingjing Wu <jingjing.wu@intel.com>
Sat, 10 Dec 2016 11:24:42 +0000 (19:24 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:39:27 +0000 (19:39 +0100)
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>
drivers/net/i40e/base/i40e_adminq_cmd.h
drivers/net/i40e/base/i40e_common.c

index 19af8b5..d4d2a7a 100644 (file)
@@ -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;
index 1095e68..e9376dd 100644 (file)
@@ -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));