i40e: implement and use Rx CTL helper functions
authorShannon Nelson <shannon.nelson@intel.com>
Thu, 18 Feb 2016 00:12:20 +0000 (16:12 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 19 Feb 2016 07:59:15 +0000 (23:59 -0800)
Use the new AdminQ functions for safely accessing the Rx control
registers that may be affected by heavy small packet traffic.

Change-ID: Ibb00983e8dcba71f4b760222a609a5fcaa726f18
Signed-off-by: Shannon Nelson <shannon.nelson@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_common.c
drivers/net/ethernet/intel/i40e/i40e_prototype.h
drivers/net/ethernet/intel/i40evf/i40e_common.c
drivers/net/ethernet/intel/i40evf/i40e_prototype.h

index 3a57e59..74d9599 100644 (file)
@@ -1328,7 +1328,7 @@ void i40e_clear_hw(struct i40e_hw *hw)
        num_vf_int = (val & I40E_GLPCI_CNF2_MSI_X_VF_N_MASK) >>
                     I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT;
 
-       val = rd32(hw, I40E_PFLAN_QALLOC);
+       val = i40e_read_rx_ctl(hw, I40E_PFLAN_QALLOC);
        base_queue = (val & I40E_PFLAN_QALLOC_FIRSTQ_MASK) >>
                     I40E_PFLAN_QALLOC_FIRSTQ_SHIFT;
        j = (val & I40E_PFLAN_QALLOC_LASTQ_MASK) >>
@@ -3882,7 +3882,7 @@ i40e_status i40e_set_filter_control(struct i40e_hw *hw,
                return ret;
 
        /* Read the PF Queue Filter control register */
-       val = rd32(hw, I40E_PFQF_CTL_0);
+       val = i40e_read_rx_ctl(hw, I40E_PFQF_CTL_0);
 
        /* Program required PE hash buckets for the PF */
        val &= ~I40E_PFQF_CTL_0_PEHSIZE_MASK;
@@ -3919,7 +3919,7 @@ i40e_status i40e_set_filter_control(struct i40e_hw *hw,
        if (settings->enable_macvlan)
                val |= I40E_PFQF_CTL_0_MACVLAN_ENA_MASK;
 
-       wr32(hw, I40E_PFQF_CTL_0, val);
+       i40e_write_rx_ctl(hw, I40E_PFQF_CTL_0, val);
 
        return 0;
 }
@@ -4575,3 +4575,125 @@ restore_config:
                                         phy_addr, led_ctl);
        return status;
 }
+
+/**
+ * i40e_aq_rx_ctl_read_register - use FW to read from an Rx control register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: ptr to register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Use the firmware to read the Rx control register,
+ * especially useful if the Rx unit is under heavy pressure
+ **/
+i40e_status i40e_aq_rx_ctl_read_register(struct i40e_hw *hw,
+                               u32 reg_addr, u32 *reg_val,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_rx_ctl_reg_read_write *cmd_resp =
+               (struct i40e_aqc_rx_ctl_reg_read_write *)&desc.params.raw;
+       i40e_status status;
+
+       if (!reg_val)
+               return I40E_ERR_PARAM;
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_rx_ctl_reg_read);
+
+       cmd_resp->address = cpu_to_le32(reg_addr);
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       if (status == 0)
+               *reg_val = le32_to_cpu(cmd_resp->value);
+
+       return status;
+}
+
+/**
+ * i40e_read_rx_ctl - read from an Rx control register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ **/
+u32 i40e_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr)
+{
+       i40e_status status = 0;
+       bool use_register;
+       int retry = 5;
+       u32 val = 0;
+
+       use_register = (hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver < 5);
+       if (!use_register) {
+do_retry:
+               status = i40e_aq_rx_ctl_read_register(hw, reg_addr, &val, NULL);
+               if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN && retry) {
+                       usleep_range(1000, 2000);
+                       retry--;
+                       goto do_retry;
+               }
+       }
+
+       /* if the AQ access failed, try the old-fashioned way */
+       if (status || use_register)
+               val = rd32(hw, reg_addr);
+
+       return val;
+}
+
+/**
+ * i40e_aq_rx_ctl_write_register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Use the firmware to write to an Rx control register,
+ * especially useful if the Rx unit is under heavy pressure
+ **/
+i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
+                               u32 reg_addr, u32 reg_val,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_rx_ctl_reg_read_write *cmd =
+               (struct i40e_aqc_rx_ctl_reg_read_write *)&desc.params.raw;
+       i40e_status status;
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_rx_ctl_reg_write);
+
+       cmd->address = cpu_to_le32(reg_addr);
+       cmd->value = cpu_to_le32(reg_val);
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       return status;
+}
+
+/**
+ * i40e_write_rx_ctl - write to an Rx control register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: register value
+ **/
+void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
+{
+       i40e_status status = 0;
+       bool use_register;
+       int retry = 5;
+
+       use_register = (hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver < 5);
+       if (!use_register) {
+do_retry:
+               status = i40e_aq_rx_ctl_write_register(hw, reg_addr,
+                                                      reg_val, NULL);
+               if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN && retry) {
+                       usleep_range(1000, 2000);
+                       retry--;
+                       goto do_retry;
+               }
+       }
+
+       /* if the AQ access failed, try the old-fashioned way */
+       if (status || use_register)
+               wr32(hw, reg_addr, reg_val);
+}
index ca2f7ac..d51eee5 100644 (file)
@@ -342,6 +342,14 @@ i40e_status i40e_aq_debug_dump(struct i40e_hw *hw, u8 cluster_id,
                               struct i40e_asq_cmd_details *cmd_details);
 void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
                                                    u16 vsi_seid);
+i40e_status i40e_aq_rx_ctl_read_register(struct i40e_hw *hw,
+                               u32 reg_addr, u32 *reg_val,
+                               struct i40e_asq_cmd_details *cmd_details);
+u32 i40e_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr);
+i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
+                               u32 reg_addr, u32 reg_val,
+                               struct i40e_asq_cmd_details *cmd_details);
+void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
 i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
                                   u16 reg, u8 phy_addr, u16 *value);
 i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
index 938783e..771ac6a 100644 (file)
@@ -903,6 +903,131 @@ struct i40e_rx_ptype_decoded i40evf_ptype_lookup[] = {
        I40E_PTT_UNUSED_ENTRY(255)
 };
 
+/**
+ * i40evf_aq_rx_ctl_read_register - use FW to read from an Rx control register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: ptr to register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Use the firmware to read the Rx control register,
+ * especially useful if the Rx unit is under heavy pressure
+ **/
+i40e_status i40evf_aq_rx_ctl_read_register(struct i40e_hw *hw,
+                               u32 reg_addr, u32 *reg_val,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_rx_ctl_reg_read_write *cmd_resp =
+               (struct i40e_aqc_rx_ctl_reg_read_write *)&desc.params.raw;
+       i40e_status status;
+
+       if (!reg_val)
+               return I40E_ERR_PARAM;
+
+       i40evf_fill_default_direct_cmd_desc(&desc,
+                                           i40e_aqc_opc_rx_ctl_reg_read);
+
+       cmd_resp->address = cpu_to_le32(reg_addr);
+
+       status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       if (status == 0)
+               *reg_val = le32_to_cpu(cmd_resp->value);
+
+       return status;
+}
+
+/**
+ * i40evf_read_rx_ctl - read from an Rx control register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ **/
+u32 i40evf_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr)
+{
+       i40e_status status = 0;
+       bool use_register;
+       int retry = 5;
+       u32 val = 0;
+
+       use_register = (hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver < 5);
+       if (!use_register) {
+do_retry:
+               status = i40evf_aq_rx_ctl_read_register(hw, reg_addr,
+                                                       &val, NULL);
+               if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN && retry) {
+                       usleep_range(1000, 2000);
+                       retry--;
+                       goto do_retry;
+               }
+       }
+
+       /* if the AQ access failed, try the old-fashioned way */
+       if (status || use_register)
+               val = rd32(hw, reg_addr);
+
+       return val;
+}
+
+/**
+ * i40evf_aq_rx_ctl_write_register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Use the firmware to write to an Rx control register,
+ * especially useful if the Rx unit is under heavy pressure
+ **/
+i40e_status i40evf_aq_rx_ctl_write_register(struct i40e_hw *hw,
+                               u32 reg_addr, u32 reg_val,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_rx_ctl_reg_read_write *cmd =
+               (struct i40e_aqc_rx_ctl_reg_read_write *)&desc.params.raw;
+       i40e_status status;
+
+       i40evf_fill_default_direct_cmd_desc(&desc,
+                                           i40e_aqc_opc_rx_ctl_reg_write);
+
+       cmd->address = cpu_to_le32(reg_addr);
+       cmd->value = cpu_to_le32(reg_val);
+
+       status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       return status;
+}
+
+/**
+ * i40evf_write_rx_ctl - write to an Rx control register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: register value
+ **/
+void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
+{
+       i40e_status status = 0;
+       bool use_register;
+       int retry = 5;
+
+       use_register = (hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver < 5);
+       if (!use_register) {
+do_retry:
+               status = i40evf_aq_rx_ctl_write_register(hw, reg_addr,
+                                                        reg_val, NULL);
+               if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN && retry) {
+                       usleep_range(1000, 2000);
+                       retry--;
+                       goto do_retry;
+               }
+       }
+
+       /* if the AQ access failed, try the old-fashioned way */
+       if (status || use_register)
+               wr32(hw, reg_addr, reg_val);
+}
+
 /**
  * i40e_aq_send_msg_to_pf
  * @hw: pointer to the hardware structure
index fa34d85..d89d521 100644 (file)
@@ -103,6 +103,14 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
                                struct i40e_asq_cmd_details *cmd_details);
 void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
                                                    u16 vsi_seid);
+i40e_status i40evf_aq_rx_ctl_read_register(struct i40e_hw *hw,
+                               u32 reg_addr, u32 *reg_val,
+                               struct i40e_asq_cmd_details *cmd_details);
+u32 i40evf_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr);
+i40e_status i40evf_aq_rx_ctl_write_register(struct i40e_hw *hw,
+                               u32 reg_addr, u32 reg_val,
+                               struct i40e_asq_cmd_details *cmd_details);
+void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
 i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
                                   u16 reg, u8 phy_addr, u16 *value);
 i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,