i40e: Further implementation of LLDP
authorAleksandr Loktionov <aleksandr.loktionov@intel.com>
Thu, 28 Feb 2019 17:52:52 +0000 (09:52 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 3 May 2019 21:31:34 +0000 (14:31 -0700)
This code implements driver code changes necessary for LLDP
Agent support. Modified i40e_aq_start_lldp() and
i40e_aq_stop_lldp() adding false parameter whether LLDP state
should be persistent across power cycles.

Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_prototype.h
drivers/net/ethernet/intel/i40e/i40e_type.h

index 45f6adc8ff2f923b326ccc5b060ff402cb7e2ad1..243dcd4bec191f6fee7c83d11b9f3cbf6e2d2083 100644 (file)
@@ -608,6 +608,11 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
             hw->aq.api_min_ver >= 7))
                hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE;
 
+       if (hw->aq.api_maj_ver > 1 ||
+           (hw->aq.api_maj_ver == 1 &&
+            hw->aq.api_min_ver >= 8))
+               hw->flags |= I40E_HW_FLAG_FW_LLDP_PERSISTENT;
+
        if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
                ret_code = I40E_ERR_FIRMWARE_API_VERSION;
                goto init_adminq_free_arq;
index 522058a7d4be82cb298de24992350ca5a56dfdb1..abcf79eb32612db66d9cb1a8c6e9916c680e996c 100644 (file)
@@ -261,6 +261,7 @@ enum i40e_admin_queue_opc {
        i40e_aqc_opc_get_cee_dcb_cfg    = 0x0A07,
        i40e_aqc_opc_lldp_set_local_mib = 0x0A08,
        i40e_aqc_opc_lldp_stop_start_spec_agent = 0x0A09,
+       i40e_aqc_opc_lldp_restore               = 0x0A0A,
 
        /* Tunnel commands */
        i40e_aqc_opc_add_udp_tunnel     = 0x0B00,
@@ -2498,18 +2499,19 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_tlv);
 /* Stop LLDP (direct 0x0A05) */
 struct i40e_aqc_lldp_stop {
        u8      command;
-#define I40E_AQ_LLDP_AGENT_STOP                0x0
-#define I40E_AQ_LLDP_AGENT_SHUTDOWN    0x1
+#define I40E_AQ_LLDP_AGENT_STOP                        0x0
+#define I40E_AQ_LLDP_AGENT_SHUTDOWN            0x1
+#define I40E_AQ_LLDP_AGENT_STOP_PERSIST                0x2
        u8      reserved[15];
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop);
 
 /* Start LLDP (direct 0x0A06) */
-
 struct i40e_aqc_lldp_start {
        u8      command;
-#define I40E_AQ_LLDP_AGENT_START       0x1
+#define I40E_AQ_LLDP_AGENT_START               0x1
+#define I40E_AQ_LLDP_AGENT_START_PERSIST       0x2
        u8      reserved[15];
 };
 
@@ -2633,6 +2635,16 @@ struct i40e_aqc_lldp_stop_start_specific_agent {
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop_start_specific_agent);
 
+/* Restore LLDP Agent factory settings (direct 0x0A0A) */
+struct i40e_aqc_lldp_restore {
+       u8      command;
+#define I40E_AQ_LLDP_AGENT_RESTORE_NOT         0x0
+#define I40E_AQ_LLDP_AGENT_RESTORE             0x1
+       u8      reserved[15];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_restore);
+
 /* Add Udp Tunnel command and completion (direct 0x0B00) */
 struct i40e_aqc_add_udp_tunnel {
        __le16  udp_port;
index dd6b3b3ac5c6d59b4436560fee2506ee69f6420e..e7d500f92a9020aa0a1e5525a44305c19c930c8e 100644 (file)
@@ -3623,15 +3623,55 @@ i40e_status i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
        return status;
 }
 
+/**
+ * i40e_aq_restore_lldp
+ * @hw: pointer to the hw struct
+ * @setting: pointer to factory setting variable or NULL
+ * @restore: True if factory settings should be restored
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Restore LLDP Agent factory settings if @restore set to True. In other case
+ * only returns factory setting in AQ response.
+ **/
+enum i40e_status_code
+i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore,
+                    struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_lldp_restore *cmd =
+               (struct i40e_aqc_lldp_restore *)&desc.params.raw;
+       i40e_status status;
+
+       if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)) {
+               i40e_debug(hw, I40E_DEBUG_ALL,
+                          "Restore LLDP not supported by current FW version.\n");
+               return I40E_ERR_DEVICE_NOT_SUPPORTED;
+       }
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_restore);
+
+       if (restore)
+               cmd->command |= I40E_AQ_LLDP_AGENT_RESTORE;
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       if (setting)
+               *setting = cmd->command & 1;
+
+       return status;
+}
+
 /**
  * i40e_aq_stop_lldp
  * @hw: pointer to the hw struct
  * @shutdown_agent: True if LLDP Agent needs to be Shutdown
+ * @persist: True if stop of LLDP should be persistent across power cycles
  * @cmd_details: pointer to command details structure or NULL
  *
  * Stop or Shutdown the embedded LLDP Agent
  **/
 i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
+                               bool persist,
                                struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
@@ -3644,6 +3684,14 @@ i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
        if (shutdown_agent)
                cmd->command |= I40E_AQ_LLDP_AGENT_SHUTDOWN;
 
+       if (persist) {
+               if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)
+                       cmd->command |= I40E_AQ_LLDP_AGENT_STOP_PERSIST;
+               else
+                       i40e_debug(hw, I40E_DEBUG_ALL,
+                                  "Persistent Stop LLDP not supported by current FW version.\n");
+       }
+
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
        return status;
@@ -3653,13 +3701,14 @@ i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
  * i40e_aq_start_lldp
  * @hw: pointer to the hw struct
  * @buff: buffer for result
+ * @persist: True if start of LLDP should be persistent across power cycles
  * @buff_size: buffer size
  * @cmd_details: pointer to command details structure or NULL
  *
  * Start the embedded LLDP Agent on all ports.
  **/
-i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
-                               struct i40e_asq_cmd_details *cmd_details)
+i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, bool persist,
+                              struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
        struct i40e_aqc_lldp_start *cmd =
@@ -3669,6 +3718,15 @@ i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
        i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_start);
 
        cmd->command = I40E_AQ_LLDP_AGENT_START;
+
+       if (persist) {
+               if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)
+                       cmd->command |= I40E_AQ_LLDP_AGENT_START_PERSIST;
+               else
+                       i40e_debug(hw, I40E_DEBUG_ALL,
+                                  "Persistent Start LLDP not supported by current FW version.\n");
+       }
+
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
        return status;
index c67d485d6f99a9ea0028b8b5b7b84450f61c1891..7ea4f09229e43cf395789afd793079a8b5c42677 100644 (file)
@@ -1321,7 +1321,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                if (strncmp(&cmd_buf[5], "stop", 4) == 0) {
                        int ret;
 
-                       ret = i40e_aq_stop_lldp(&pf->hw, false, NULL);
+                       ret = i40e_aq_stop_lldp(&pf->hw, false, false, NULL);
                        if (ret) {
                                dev_info(&pf->pdev->dev,
                                         "Stop LLDP AQ command failed =0x%x\n",
@@ -1358,7 +1358,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                                /* Continue and start FW LLDP anyways */
                        }
 
-                       ret = i40e_aq_start_lldp(&pf->hw, NULL);
+                       ret = i40e_aq_start_lldp(&pf->hw, false, NULL);
                        if (ret) {
                                dev_info(&pf->pdev->dev,
                                         "Start LLDP AQ command failed =0x%x\n",
index 0d923c13c9a1aec17c30e9fc8632957d48e3cdc0..32e137499063743f487f1c09aaf3440067fbee37 100644 (file)
@@ -4958,7 +4958,7 @@ flags_complete:
                if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) {
                        struct i40e_dcbx_config *dcbcfg;
 
-                       i40e_aq_stop_lldp(&pf->hw, true, NULL);
+                       i40e_aq_stop_lldp(&pf->hw, true, false, NULL);
                        i40e_aq_set_dcb_parameters(&pf->hw, true, NULL);
                        /* reset local_dcbx_config to default */
                        dcbcfg = &pf->hw.local_dcbx_config;
@@ -4973,7 +4973,7 @@ flags_complete:
                        dcbcfg->pfc.willing = 1;
                        dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
                } else {
-                       i40e_aq_start_lldp(&pf->hw, NULL);
+                       i40e_aq_start_lldp(&pf->hw, false, NULL);
                }
        }
 
index 3e15df1d5f52ec4c3ebde19ede43594a9d274629..54c172c50479e438abbbea31dff44eb53aed204f 100644 (file)
@@ -14132,7 +14132,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         */
        if (pf->hw_features & I40E_HW_STOP_FW_LLDP) {
                dev_info(&pdev->dev, "Stopping firmware LLDP agent.\n");
-               i40e_aq_stop_lldp(hw, true, NULL);
+               i40e_aq_stop_lldp(hw, true, false, NULL);
        }
 
        /* allow a platform config to override the HW addr */
index 663c8bf4d3d81ea4f42f9ba11c71f6a2849b8d9e..882627073dcea8ab12a66c4b5f4bd391b125900a 100644 (file)
@@ -203,14 +203,18 @@ i40e_status i40e_aq_get_lldp_mib(struct i40e_hw *hw, u8 bridge_type,
 i40e_status i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
                                bool enable_update,
                                struct i40e_asq_cmd_details *cmd_details);
+enum i40e_status_code
+i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore,
+                    struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
+                             bool persist,
                                struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_dcb_parameters(struct i40e_hw *hw,
                                       bool dcb_enable,
                                       struct i40e_asq_cmd_details
                                       *cmd_details);
-i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
-                               struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, bool persist,
+                              struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_get_cee_dcb_config(struct i40e_hw *hw,
                                       void *buff, u16 buff_size,
                                       struct i40e_asq_cmd_details *cmd_details);
index 79420bcc7414818d7081dc28c13e9c6d75567213..820af0043cc8a41e7e280ae102078dbab90154ac 100644 (file)
@@ -616,6 +616,7 @@ struct i40e_hw {
 #define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE  BIT_ULL(2)
 #define I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK BIT_ULL(3)
 #define I40E_HW_FLAG_FW_LLDP_STOPPABLE      BIT_ULL(4)
+#define I40E_HW_FLAG_FW_LLDP_PERSISTENT     BIT_ULL(5)
        u64 flags;
 
        /* Used in set switch config AQ command */