]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
ice: Add support for dynamic interrupt moderation
authorBrett Creeley <brett.creeley@intel.com>
Thu, 20 Sep 2018 00:23:19 +0000 (17:23 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 2 Oct 2018 14:19:30 +0000 (07:19 -0700)
Currently there is no support for dynamic interrupt moderation. This
patch adds some initial code to support this. The following changes
were made:

1. Currently we are using multiple members to store the interrupt
   granularity (itr_gran_25/50/100/200). This is not necessary because
   we can query the device to determine what the interrupt granularity
   should be set to, done by a new function ice_get_itr_intrl_gran.

2. Added intrl to ice_q_vector structure to support interrupt rate
   limiting.

3. Added the function ice_intrl_usecs_to_reg for converting to a value
   in usecs that the device understands.

4. Added call to write to the GLINT_RATE register. Disable intrl by
   default for now.

5. Changed rx/tx_itr_setting to itr_setting because having both seems
   redundant because a ring is either Tx or Rx.

6. Initialize itr_setting for both Tx/Rx rings in ice_vsi_alloc_rings()

Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_common.c
drivers/net/ethernet/intel/ice/ice_hw_autogen.h
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_txrx.h
drivers/net/ethernet/intel/ice/ice_type.h

index fc6bc1233f1033a075b429c203fa271c1df77ec2..0b269c470343ff5d6c60385d33174a7610a7f728 100644 (file)
@@ -230,6 +230,10 @@ struct ice_q_vector {
        u8 num_ring_tx;                 /* total number of tx rings in vector */
        u8 num_ring_rx;                 /* total number of rx rings in vector */
        char name[ICE_INT_NAME_STR_LEN];
+       /* in usecs, need to use ice_intrl_to_usecs_reg() before writing this
+        * value to the device
+        */
+       u8 intrl;
 } ____cacheline_internodealigned_in_smp;
 
 enum ice_pf_flags {
index 9ff29137586900e90b5d86e848b0002fee12e6f5..68fbbb92d50413757a2a8a7892d4be5bbb5816fe 100644 (file)
@@ -597,6 +597,39 @@ void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf)
        ice_debug(hw, ICE_DBG_AQ_MSG, "[ FW Log Msg End ]\n");
 }
 
+/**
+ * ice_get_itr_intrl_gran - determine int/intrl granularity
+ * @hw: pointer to the hw struct
+ *
+ * Determines the itr/intrl granularities based on the maximum aggregate
+ * bandwidth according to the device's configuration during power-on.
+ */
+static enum ice_status ice_get_itr_intrl_gran(struct ice_hw *hw)
+{
+       u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) &
+                        GL_PWR_MODE_CTL_CAR_MAX_BW_M) >>
+                       GL_PWR_MODE_CTL_CAR_MAX_BW_S;
+
+       switch (max_agg_bw) {
+       case ICE_MAX_AGG_BW_200G:
+       case ICE_MAX_AGG_BW_100G:
+       case ICE_MAX_AGG_BW_50G:
+               hw->itr_gran = ICE_ITR_GRAN_ABOVE_25;
+               hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25;
+               break;
+       case ICE_MAX_AGG_BW_25G:
+               hw->itr_gran = ICE_ITR_GRAN_MAX_25;
+               hw->intrl_gran = ICE_INTRL_GRAN_MAX_25;
+               break;
+       default:
+               ice_debug(hw, ICE_DBG_INIT,
+                         "Failed to determine itr/intrl granularity\n");
+               return ICE_ERR_CFG;
+       }
+
+       return 0;
+}
+
 /**
  * ice_init_hw - main hardware initialization routine
  * @hw: pointer to the hardware structure
@@ -621,11 +654,9 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
        if (status)
                return status;
 
-       /* set these values to minimum allowed */
-       hw->itr_gran_200 = ICE_ITR_GRAN_MIN_200;
-       hw->itr_gran_100 = ICE_ITR_GRAN_MIN_100;
-       hw->itr_gran_50 = ICE_ITR_GRAN_MIN_50;
-       hw->itr_gran_25 = ICE_ITR_GRAN_MIN_25;
+       status = ice_get_itr_intrl_gran(hw);
+       if (status)
+               return status;
 
        status = ice_init_all_ctrlq(hw);
        if (status)
index 88f11498804b388ddc0880b3ccbd9db6d24ca78e..9a78d83eaa3e2aadd8047776f96ef28a67e4c7ac 100644 (file)
@@ -88,6 +88,8 @@
 #define GLINT_DYN_CTL_SW_ITR_INDX_M            ICE_M(0x3, 25)
 #define GLINT_DYN_CTL_INTENA_MSK_M             BIT(31)
 #define GLINT_ITR(_i, _INT)                    (0x00154000 + ((_i) * 8192 + (_INT) * 4))
+#define GLINT_RATE(_INT)                       (0x0015A000 + ((_INT) * 4))
+#define GLINT_RATE_INTRL_ENA_M                 BIT(6)
 #define PFINT_FW_CTL                           0x0016C800
 #define PFINT_FW_CTL_MSIX_INDX_M               ICE_M(0x7FF, 0)
 #define PFINT_FW_CTL_ITR_INDX_S                        11
 #define PF_FUNC_RID                            0x0009E880
 #define PF_FUNC_RID_FUNC_NUM_S                 0
 #define PF_FUNC_RID_FUNC_NUM_M                 ICE_M(0x7, 0)
+#define GL_PWR_MODE_CTL                                0x000B820C
+#define GL_PWR_MODE_CTL_CAR_MAX_BW_S           30
+#define GL_PWR_MODE_CTL_CAR_MAX_BW_M           ICE_M(0x3, 30)
 #define GLPRT_BPRCH(_i)                                (0x00381384 + ((_i) * 8))
 #define GLPRT_BPRCL(_i)                                (0x00381380 + ((_i) * 8))
 #define GLPRT_BPTCH(_i)                                (0x00381244 + ((_i) * 8))
index 98e8b7096e47547637313e29e28a944d764aea2d..acf3478a3f3bb62c1bf1ac1fa4dfef7e573e180f 100644 (file)
@@ -1139,6 +1139,7 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
                ring->vsi = vsi;
                ring->dev = &pf->pdev->dev;
                ring->count = vsi->num_desc;
+               ring->itr_setting = ICE_DFLT_TX_ITR;
                vsi->tx_rings[i] = ring;
        }
 
@@ -1158,6 +1159,7 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
                ring->netdev = vsi->netdev;
                ring->dev = &pf->pdev->dev;
                ring->count = vsi->num_desc;
+               ring->itr_setting = ICE_DFLT_RX_ITR;
                vsi->rx_rings[i] = ring;
        }
 
@@ -1595,6 +1597,23 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi)
        return err;
 }
 
+/**
+ * ice_intrl_usec_to_reg - convert interrupt rate limit to register value
+ * @intrl: interrupt rate limit in usecs
+ * @gran: interrupt rate limit granularity in usecs
+ *
+ * This function converts a decimal interrupt rate limit in usecs to the format
+ * expected by firmware.
+ */
+static u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran)
+{
+       u32 val = intrl / gran;
+
+       if (val)
+               return val | GLINT_RATE_INTRL_ENA_M;
+       return 0;
+}
+
 /**
  * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW
  * @vsi: the VSI being configured
@@ -1611,23 +1630,27 @@ void ice_vsi_cfg_msix(struct ice_vsi *vsi)
        for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
                struct ice_q_vector *q_vector = vsi->q_vectors[i];
 
-               itr_gran = hw->itr_gran_200;
+               itr_gran = hw->itr_gran;
+
+               q_vector->intrl = ICE_DFLT_INTRL;
 
                if (q_vector->num_ring_rx) {
                        q_vector->rx.itr =
-                               ITR_TO_REG(vsi->rx_rings[rxq]->rx_itr_setting,
+                               ITR_TO_REG(vsi->rx_rings[rxq]->itr_setting,
                                           itr_gran);
                        q_vector->rx.latency_range = ICE_LOW_LATENCY;
                }
 
                if (q_vector->num_ring_tx) {
                        q_vector->tx.itr =
-                               ITR_TO_REG(vsi->tx_rings[txq]->tx_itr_setting,
+                               ITR_TO_REG(vsi->tx_rings[txq]->itr_setting,
                                           itr_gran);
                        q_vector->tx.latency_range = ICE_LOW_LATENCY;
                }
                wr32(hw, GLINT_ITR(ICE_RX_ITR, vector), q_vector->rx.itr);
                wr32(hw, GLINT_ITR(ICE_TX_ITR, vector), q_vector->tx.itr);
+               wr32(hw, GLINT_RATE(vector),
+                    ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
 
                /* Both Transmit Queue Interrupt Cause Control register
                 * and Receive Queue Interrupt Cause control register
index f51857ead0f3c98d844731ddbcd7b1a680d55437..9638684f75ac83e8b44ca5fba5c927a7d038edf3 100644 (file)
@@ -1406,7 +1406,7 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
               PFINT_FW_CTL_CAUSE_ENA_M);
        wr32(hw, PFINT_FW_CTL, val);
 
-       itr_gran = hw->itr_gran_200;
+       itr_gran = hw->itr_gran;
 
        wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx),
             ITR_TO_REG(ICE_ITR_8K, itr_gran));
index 839fd9ff604341f0d7e8cab9ec4408ab62cd1e88..a9b92974e041e37042673068c9e7aadc8b2082cd 100644 (file)
@@ -104,10 +104,16 @@ enum ice_rx_dtype {
 #define ICE_RX_ITR     ICE_IDX_ITR0
 #define ICE_TX_ITR     ICE_IDX_ITR1
 #define ICE_ITR_DYNAMIC        0x8000  /* use top bit as a flag */
-#define ICE_ITR_8K     0x003E
+#define ICE_ITR_8K     125
+#define ICE_DFLT_TX_ITR        ICE_ITR_8K
+#define ICE_DFLT_RX_ITR        ICE_ITR_8K
+/* apply ITR granularity translation to program the register. itr_gran is either
+ * 2 or 4 usecs so we need to divide by 2 first then shift by that value
+ */
+#define ITR_TO_REG(val, itr_gran) (((val) & ~ICE_ITR_DYNAMIC) >> \
+                                  ((itr_gran) / 2))
 
-/* apply ITR HW granularity translation to program the HW registers */
-#define ITR_TO_REG(val, itr_gran) (((val) & ~ICE_ITR_DYNAMIC) >> (itr_gran))
+#define ICE_DFLT_INTRL 0
 
 /* Legacy or Advanced Mode Queue */
 #define ICE_TX_ADVANCED        0
@@ -130,12 +136,11 @@ struct ice_ring {
        u32 txq_teid;                   /* Added Tx queue TEID */
 
        /* high bit set means dynamic, use accessor routines to read/write.
-        * hardware supports 2us/1us resolution for the ITR registers.
+        * hardware supports 4us/2us resolution for the ITR registers.
         * these values always store the USER setting, and must be converted
         * before programming to a register.
         */
-       u16 rx_itr_setting;
-       u16 tx_itr_setting;
+       u16 itr_setting;
 
        u16 count;                      /* Number of descriptors */
        u16 reg_idx;                    /* HW register index of the ring */
index 87930f68d3fb11fc4456a1111c09ea08f201b69b..f5c8de0ed0eb4373aa4323e61d5523fc0c72885c 100644 (file)
@@ -333,16 +333,26 @@ struct ice_hw {
        u32 fw_build;           /* firmware build number */
 
        struct ice_fw_log_cfg fw_log;
-       /* minimum allowed value for different speeds */
-#define ICE_ITR_GRAN_MIN_200   1
-#define ICE_ITR_GRAN_MIN_100   1
-#define ICE_ITR_GRAN_MIN_50    2
-#define ICE_ITR_GRAN_MIN_25    4
+
+/* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL
+ * register. Used for determining the itr/intrl granularity during
+ * initialization.
+ */
+#define ICE_MAX_AGG_BW_200G    0x0
+#define ICE_MAX_AGG_BW_100G    0X1
+#define ICE_MAX_AGG_BW_50G     0x2
+#define ICE_MAX_AGG_BW_25G     0x3
+       /* ITR granularity for different speeds */
+#define ICE_ITR_GRAN_ABOVE_25  2
+#define ICE_ITR_GRAN_MAX_25    4
        /* ITR granularity in 1 us */
-       u8 itr_gran_200;
-       u8 itr_gran_100;
-       u8 itr_gran_50;
-       u8 itr_gran_25;
+       u8 itr_gran;
+       /* INTRL granularity for different speeds */
+#define ICE_INTRL_GRAN_ABOVE_25        4
+#define ICE_INTRL_GRAN_MAX_25  8
+       /* INTRL granularity in 1 us */
+       u8 intrl_gran;
+
        u8 ucast_shared;        /* true if VSIs can share unicast addr */
 
 };