This change introduces new function i40e_get_lpi_counters() reading
Low Power Idle (LPI) mode counters from Energy Efficient Ethernet (EEE)
statistics. Since reading EEE statistics requires running DNL script,
function i40e_aq_run_phy_activity() able to run it, was implemented.

i40e_lpi_stat_update() was introduced as helper function for retrieving
LPI counters' values relative to given offsets.

This change also fixes order of fields in struct
i40e_aqc_run_phy_activity and introduces union in the struct
providing more descriptive names of fields depending on usage
(command or response).

Signed-off-by: Piotr Pietruszewski <piotr.pietruszew...@intel.com>
Reviewed-by: Paul M Stillwell Jr <paul.m.stillwell...@intel.com>
Reviewed-by: Kirsher Jeffrey T <jeffrey.t.kirs...@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong...@intel.com>
---
 drivers/net/i40e/base/i40e_adminq_cmd.h |  26 ++++--
 drivers/net/i40e/base/i40e_common.c     | 113 ++++++++++++++++++++++++
 drivers/net/i40e/base/i40e_prototype.h  |  12 +++
 3 files changed, 145 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_adminq_cmd.h 
b/drivers/net/i40e/base/i40e_adminq_cmd.h
index 9179bbe8f..7b4703449 100644
--- a/drivers/net/i40e/base/i40e_adminq_cmd.h
+++ b/drivers/net/i40e/base/i40e_adminq_cmd.h
@@ -2276,15 +2276,29 @@ enum i40e_aq_phy_reg_type {
        I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3
 };
 
+#pragma pack(1)
 /* Run PHY Activity (0x0626) */
 struct i40e_aqc_run_phy_activity {
-       __le16  activity_id;
-       u8      flags;
-       u8      reserved1;
-       __le32  control;
-       __le32  data;
-       u8      reserved2[4];
+       u8      cmd_flags;
+       __le16  activity_id;
+#define I40E_AQ_RUN_PHY_ACTIVITY_ACTIVITY_ID_USER_DEFINED      0x10
+       u8      reserved;
+       union {
+               struct {
+                       __le32  dnl_opcode;
+#define I40E_AQ_RUN_PHY_ACTIVITY_DNL_OPCODE_GET_EEE_STATISTICS 0x801b
+                       __le32  data;
+                       u8      reserved2[4];
+               } cmd;
+               struct {
+                       __le32  cmd_status;
+#define I40E_AQ_RUN_PHY_ACTIVITY_CMD_STATUS_SUCCESS            0x4
+                       __le32  data0;
+                       __le32  data1;
+               } resp;
+       } params;
 };
+#pragma pack()
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
 
diff --git a/drivers/net/i40e/base/i40e_common.c 
b/drivers/net/i40e/base/i40e_common.c
index 80921349a..b03a6bef2 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -7115,6 +7115,74 @@ enum i40e_status_code i40e_get_phy_lpi_status(struct 
i40e_hw *hw,
 
        return ret;
 }
+
+/**
+ * i40e_get_lpi_counters - read LPI counters from EEE statistics
+ * @hw: pointer to the hw struct
+ * @tx_counter: pointer to memory for TX LPI counter
+ * @rx_counter: pointer to memory for RX LPI counter
+ *
+ * Read Low Power Idle (LPI) mode counters from Energy Efficient
+ * Ethernet (EEE) statistics.
+ **/
+enum i40e_status_code i40e_get_lpi_counters(struct i40e_hw *hw,
+                                           u32 *tx_counter, u32 *rx_counter)
+{
+       enum i40e_status_code retval;
+       u32 cmd_status;
+
+       retval = i40e_aq_run_phy_activity(hw,
+                       I40E_AQ_RUN_PHY_ACTIVITY_ACTIVITY_ID_USER_DEFINED,
+                       I40E_AQ_RUN_PHY_ACTIVITY_DNL_OPCODE_GET_EEE_STATISTICS,
+                       &cmd_status, tx_counter, rx_counter, NULL);
+
+       if (cmd_status != I40E_AQ_RUN_PHY_ACTIVITY_CMD_STATUS_SUCCESS)
+               retval = I40E_ERR_ADMIN_QUEUE_ERROR;
+
+       return retval;
+}
+
+/**
+ * i40e_lpi_stat_update - update LPI counters with values relative to offset
+ * @hw: pointer to the hw struct
+ * @offset_loaded: flag indicating need of writing current value to offset
+ * @tx_offset: pointer to offset of TX LPI counter
+ * @tx_stat: pointer to value of TX LPI counter
+ * @rx_offset: pointer to offset of RX LPI counter
+ * @rx_stat: pointer to value of RX LPI counter
+ *
+ * Update Low Power Idle (LPI) mode counters while having regard to passed
+ * offsets.
+ **/
+enum i40e_status_code i40e_lpi_stat_update(struct i40e_hw *hw,
+                                          bool offset_loaded, u64 *tx_offset,
+                                          u64 *tx_stat, u64 *rx_offset,
+                                          u64 *rx_stat)
+{
+       enum i40e_status_code retval;
+       u32 tx_counter, rx_counter;
+
+       retval = i40e_get_lpi_counters(hw, &tx_counter, &rx_counter);
+       if (retval)
+               goto err;
+
+       if (!offset_loaded) {
+               *tx_offset = tx_counter;
+               *rx_offset = rx_counter;
+       }
+
+       if (tx_counter >= *tx_offset)
+               *tx_stat = (u32)(tx_counter - *tx_offset);
+       else
+               *tx_stat = (u32)((tx_counter + BIT_ULL(32)) - *tx_offset);
+
+       if (rx_counter >= *rx_offset)
+               *rx_stat = (u32)(rx_counter - *rx_offset);
+       else
+               *rx_stat = (u32)((rx_counter + BIT_ULL(32)) - *rx_offset);
+err:
+       return retval;
+}
 #endif /* PF_DRIVER */
 
 /**
@@ -7378,6 +7446,51 @@ enum i40e_status_code i40e_aq_get_phy_register(struct 
i40e_hw *hw,
        return status;
 }
 
+/**
+ * i40e_aq_run_phy_activity
+ * @hw: pointer to the hw struct
+ * @activity_id: ID of DNL activity to run
+ * @dnl_opcode: opcode passed to DNL script
+ * @cmd_status: pointer to memory to write return value of DNL script
+ * @data0: pointer to memory for first 4 bytes of data returned by DNL script
+ * @data1: pointer to memory for last 4 bytes of data returned by DNL script
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Run DNL admin command.
+ **/
+enum i40e_status_code
+i40e_aq_run_phy_activity(struct i40e_hw *hw, u16 activity_id, u32 dnl_opcode,
+                        u32 *cmd_status, u32 *data0, u32 *data1,
+                        struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aqc_run_phy_activity *cmd;
+       enum i40e_status_code retval;
+       struct i40e_aq_desc desc;
+
+       cmd = (struct i40e_aqc_run_phy_activity *)&desc.params.raw;
+
+       if (!cmd_status || !data0 || !data1) {
+               retval = I40E_ERR_PARAM;
+               goto err;
+       }
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_run_phy_activity);
+
+       cmd->activity_id = CPU_TO_LE16(activity_id);
+       cmd->params.cmd.dnl_opcode = CPU_TO_LE32(dnl_opcode);
+
+       retval = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+       if (retval)
+               goto err;
+
+       *cmd_status = LE32_TO_CPU(cmd->params.resp.cmd_status);
+       *data0 = LE32_TO_CPU(cmd->params.resp.data0);
+       *data1 = LE32_TO_CPU(cmd->params.resp.data1);
+err:
+       return retval;
+}
+
 #endif /* PF_DRIVER */
 #ifdef VF_DRIVER
 
diff --git a/drivers/net/i40e/base/i40e_prototype.h 
b/drivers/net/i40e/base/i40e_prototype.h
index 4d1b007b8..eaaeb5eea 100644
--- a/drivers/net/i40e/base/i40e_prototype.h
+++ b/drivers/net/i40e/base/i40e_prototype.h
@@ -76,6 +76,12 @@ enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw 
*hw,
 
 enum i40e_status_code i40e_get_phy_lpi_status(struct i40e_hw *hw,
                                              struct i40e_hw_port_stats *stats);
+enum i40e_status_code i40e_get_lpi_counters(struct i40e_hw *hw, u32 
*tx_counter,
+                                           u32 *rx_counter);
+enum i40e_status_code i40e_lpi_stat_update(struct i40e_hw *hw,
+                                          bool offset_loaded, u64 *tx_offset,
+                                          u64 *tx_stat, u64 *rx_offset,
+                                          u64 *rx_stat);
 /* admin send queue commands */
 
 enum i40e_status_code i40e_aq_get_firmware_version(struct i40e_hw *hw,
@@ -563,6 +569,12 @@ enum i40e_status_code i40e_aq_get_phy_register(struct 
i40e_hw *hw,
                                u8 phy_select, u8 dev_addr, bool page_change,
                                u32 reg_addr, u32 *reg_val,
                                struct i40e_asq_cmd_details *cmd_details);
+#ifdef PF_DRIVER
+enum i40e_status_code
+i40e_aq_run_phy_activity(struct i40e_hw *hw, u16 activity_id, u32 opcode,
+                        u32 *cmd_status, u32 *data0, u32 *data1,
+                        struct i40e_asq_cmd_details *cmd_details);
+#endif
 
 enum i40e_status_code i40e_aq_set_arp_proxy_config(struct i40e_hw *hw,
                        struct i40e_aqc_arp_proxy_data *proxy_config,
-- 
2.17.1

Reply via email to