ice: Add support for dynamic interrupt moderation
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>
This commit is contained in:
parent
ca4929b6df
commit
9e4ab4c29a
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
@ -173,6 +175,9 @@
|
|||
#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))
|
||||
|
|
|
@ -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 @@ err_cfg_txqs:
|
|||
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
|
||||
|
|
|
@ -1406,7 +1406,7 @@ skip_req_irq:
|
|||
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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue