diff options
author | Brett Creeley <brett.creeley@intel.com> | 2018-09-19 20:23:19 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2018-10-02 10:19:30 -0400 |
commit | 9e4ab4c29a62d2ccbf4be42707669be2f42d391c (patch) | |
tree | 54327122a0cddba67d650678f355f808e4966844 | |
parent | ca4929b6df7c729c375c486c0ca53decb0eae9f5 (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_common.c | 41 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_hw_autogen.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_lib.c | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_main.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_txrx.h | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_type.h | 28 |
7 files changed, 102 insertions, 24 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index fc6bc1233f10..0b269c470343 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h | |||
@@ -230,6 +230,10 @@ struct ice_q_vector { | |||
230 | u8 num_ring_tx; /* total number of tx rings in vector */ | 230 | u8 num_ring_tx; /* total number of tx rings in vector */ |
231 | u8 num_ring_rx; /* total number of rx rings in vector */ | 231 | u8 num_ring_rx; /* total number of rx rings in vector */ |
232 | char name[ICE_INT_NAME_STR_LEN]; | 232 | char name[ICE_INT_NAME_STR_LEN]; |
233 | /* in usecs, need to use ice_intrl_to_usecs_reg() before writing this | ||
234 | * value to the device | ||
235 | */ | ||
236 | u8 intrl; | ||
233 | } ____cacheline_internodealigned_in_smp; | 237 | } ____cacheline_internodealigned_in_smp; |
234 | 238 | ||
235 | enum ice_pf_flags { | 239 | enum ice_pf_flags { |
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 9ff291375869..68fbbb92d504 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c | |||
@@ -598,6 +598,39 @@ void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf) | |||
598 | } | 598 | } |
599 | 599 | ||
600 | /** | 600 | /** |
601 | * ice_get_itr_intrl_gran - determine int/intrl granularity | ||
602 | * @hw: pointer to the hw struct | ||
603 | * | ||
604 | * Determines the itr/intrl granularities based on the maximum aggregate | ||
605 | * bandwidth according to the device's configuration during power-on. | ||
606 | */ | ||
607 | static enum ice_status ice_get_itr_intrl_gran(struct ice_hw *hw) | ||
608 | { | ||
609 | u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) & | ||
610 | GL_PWR_MODE_CTL_CAR_MAX_BW_M) >> | ||
611 | GL_PWR_MODE_CTL_CAR_MAX_BW_S; | ||
612 | |||
613 | switch (max_agg_bw) { | ||
614 | case ICE_MAX_AGG_BW_200G: | ||
615 | case ICE_MAX_AGG_BW_100G: | ||
616 | case ICE_MAX_AGG_BW_50G: | ||
617 | hw->itr_gran = ICE_ITR_GRAN_ABOVE_25; | ||
618 | hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25; | ||
619 | break; | ||
620 | case ICE_MAX_AGG_BW_25G: | ||
621 | hw->itr_gran = ICE_ITR_GRAN_MAX_25; | ||
622 | hw->intrl_gran = ICE_INTRL_GRAN_MAX_25; | ||
623 | break; | ||
624 | default: | ||
625 | ice_debug(hw, ICE_DBG_INIT, | ||
626 | "Failed to determine itr/intrl granularity\n"); | ||
627 | return ICE_ERR_CFG; | ||
628 | } | ||
629 | |||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | /** | ||
601 | * ice_init_hw - main hardware initialization routine | 634 | * ice_init_hw - main hardware initialization routine |
602 | * @hw: pointer to the hardware structure | 635 | * @hw: pointer to the hardware structure |
603 | */ | 636 | */ |
@@ -621,11 +654,9 @@ enum ice_status ice_init_hw(struct ice_hw *hw) | |||
621 | if (status) | 654 | if (status) |
622 | return status; | 655 | return status; |
623 | 656 | ||
624 | /* set these values to minimum allowed */ | 657 | status = ice_get_itr_intrl_gran(hw); |
625 | hw->itr_gran_200 = ICE_ITR_GRAN_MIN_200; | 658 | if (status) |
626 | hw->itr_gran_100 = ICE_ITR_GRAN_MIN_100; | 659 | return status; |
627 | hw->itr_gran_50 = ICE_ITR_GRAN_MIN_50; | ||
628 | hw->itr_gran_25 = ICE_ITR_GRAN_MIN_25; | ||
629 | 660 | ||
630 | status = ice_init_all_ctrlq(hw); | 661 | status = ice_init_all_ctrlq(hw); |
631 | if (status) | 662 | if (status) |
diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index 88f11498804b..9a78d83eaa3e 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h | |||
@@ -88,6 +88,8 @@ | |||
88 | #define GLINT_DYN_CTL_SW_ITR_INDX_M ICE_M(0x3, 25) | 88 | #define GLINT_DYN_CTL_SW_ITR_INDX_M ICE_M(0x3, 25) |
89 | #define GLINT_DYN_CTL_INTENA_MSK_M BIT(31) | 89 | #define GLINT_DYN_CTL_INTENA_MSK_M BIT(31) |
90 | #define GLINT_ITR(_i, _INT) (0x00154000 + ((_i) * 8192 + (_INT) * 4)) | 90 | #define GLINT_ITR(_i, _INT) (0x00154000 + ((_i) * 8192 + (_INT) * 4)) |
91 | #define GLINT_RATE(_INT) (0x0015A000 + ((_INT) * 4)) | ||
92 | #define GLINT_RATE_INTRL_ENA_M BIT(6) | ||
91 | #define PFINT_FW_CTL 0x0016C800 | 93 | #define PFINT_FW_CTL 0x0016C800 |
92 | #define PFINT_FW_CTL_MSIX_INDX_M ICE_M(0x7FF, 0) | 94 | #define PFINT_FW_CTL_MSIX_INDX_M ICE_M(0x7FF, 0) |
93 | #define PFINT_FW_CTL_ITR_INDX_S 11 | 95 | #define PFINT_FW_CTL_ITR_INDX_S 11 |
@@ -173,6 +175,9 @@ | |||
173 | #define PF_FUNC_RID 0x0009E880 | 175 | #define PF_FUNC_RID 0x0009E880 |
174 | #define PF_FUNC_RID_FUNC_NUM_S 0 | 176 | #define PF_FUNC_RID_FUNC_NUM_S 0 |
175 | #define PF_FUNC_RID_FUNC_NUM_M ICE_M(0x7, 0) | 177 | #define PF_FUNC_RID_FUNC_NUM_M ICE_M(0x7, 0) |
178 | #define GL_PWR_MODE_CTL 0x000B820C | ||
179 | #define GL_PWR_MODE_CTL_CAR_MAX_BW_S 30 | ||
180 | #define GL_PWR_MODE_CTL_CAR_MAX_BW_M ICE_M(0x3, 30) | ||
176 | #define GLPRT_BPRCH(_i) (0x00381384 + ((_i) * 8)) | 181 | #define GLPRT_BPRCH(_i) (0x00381384 + ((_i) * 8)) |
177 | #define GLPRT_BPRCL(_i) (0x00381380 + ((_i) * 8)) | 182 | #define GLPRT_BPRCL(_i) (0x00381380 + ((_i) * 8)) |
178 | #define GLPRT_BPTCH(_i) (0x00381244 + ((_i) * 8)) | 183 | #define GLPRT_BPTCH(_i) (0x00381244 + ((_i) * 8)) |
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 98e8b7096e47..acf3478a3f3b 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c | |||
@@ -1139,6 +1139,7 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi) | |||
1139 | ring->vsi = vsi; | 1139 | ring->vsi = vsi; |
1140 | ring->dev = &pf->pdev->dev; | 1140 | ring->dev = &pf->pdev->dev; |
1141 | ring->count = vsi->num_desc; | 1141 | ring->count = vsi->num_desc; |
1142 | ring->itr_setting = ICE_DFLT_TX_ITR; | ||
1142 | vsi->tx_rings[i] = ring; | 1143 | vsi->tx_rings[i] = ring; |
1143 | } | 1144 | } |
1144 | 1145 | ||
@@ -1158,6 +1159,7 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi) | |||
1158 | ring->netdev = vsi->netdev; | 1159 | ring->netdev = vsi->netdev; |
1159 | ring->dev = &pf->pdev->dev; | 1160 | ring->dev = &pf->pdev->dev; |
1160 | ring->count = vsi->num_desc; | 1161 | ring->count = vsi->num_desc; |
1162 | ring->itr_setting = ICE_DFLT_RX_ITR; | ||
1161 | vsi->rx_rings[i] = ring; | 1163 | vsi->rx_rings[i] = ring; |
1162 | } | 1164 | } |
1163 | 1165 | ||
@@ -1596,6 +1598,23 @@ err_cfg_txqs: | |||
1596 | } | 1598 | } |
1597 | 1599 | ||
1598 | /** | 1600 | /** |
1601 | * ice_intrl_usec_to_reg - convert interrupt rate limit to register value | ||
1602 | * @intrl: interrupt rate limit in usecs | ||
1603 | * @gran: interrupt rate limit granularity in usecs | ||
1604 | * | ||
1605 | * This function converts a decimal interrupt rate limit in usecs to the format | ||
1606 | * expected by firmware. | ||
1607 | */ | ||
1608 | static u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran) | ||
1609 | { | ||
1610 | u32 val = intrl / gran; | ||
1611 | |||
1612 | if (val) | ||
1613 | return val | GLINT_RATE_INTRL_ENA_M; | ||
1614 | return 0; | ||
1615 | } | ||
1616 | |||
1617 | /** | ||
1599 | * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW | 1618 | * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW |
1600 | * @vsi: the VSI being configured | 1619 | * @vsi: the VSI being configured |
1601 | */ | 1620 | */ |
@@ -1611,23 +1630,27 @@ void ice_vsi_cfg_msix(struct ice_vsi *vsi) | |||
1611 | for (i = 0; i < vsi->num_q_vectors; i++, vector++) { | 1630 | for (i = 0; i < vsi->num_q_vectors; i++, vector++) { |
1612 | struct ice_q_vector *q_vector = vsi->q_vectors[i]; | 1631 | struct ice_q_vector *q_vector = vsi->q_vectors[i]; |
1613 | 1632 | ||
1614 | itr_gran = hw->itr_gran_200; | 1633 | itr_gran = hw->itr_gran; |
1634 | |||
1635 | q_vector->intrl = ICE_DFLT_INTRL; | ||
1615 | 1636 | ||
1616 | if (q_vector->num_ring_rx) { | 1637 | if (q_vector->num_ring_rx) { |
1617 | q_vector->rx.itr = | 1638 | q_vector->rx.itr = |
1618 | ITR_TO_REG(vsi->rx_rings[rxq]->rx_itr_setting, | 1639 | ITR_TO_REG(vsi->rx_rings[rxq]->itr_setting, |
1619 | itr_gran); | 1640 | itr_gran); |
1620 | q_vector->rx.latency_range = ICE_LOW_LATENCY; | 1641 | q_vector->rx.latency_range = ICE_LOW_LATENCY; |
1621 | } | 1642 | } |
1622 | 1643 | ||
1623 | if (q_vector->num_ring_tx) { | 1644 | if (q_vector->num_ring_tx) { |
1624 | q_vector->tx.itr = | 1645 | q_vector->tx.itr = |
1625 | ITR_TO_REG(vsi->tx_rings[txq]->tx_itr_setting, | 1646 | ITR_TO_REG(vsi->tx_rings[txq]->itr_setting, |
1626 | itr_gran); | 1647 | itr_gran); |
1627 | q_vector->tx.latency_range = ICE_LOW_LATENCY; | 1648 | q_vector->tx.latency_range = ICE_LOW_LATENCY; |
1628 | } | 1649 | } |
1629 | wr32(hw, GLINT_ITR(ICE_RX_ITR, vector), q_vector->rx.itr); | 1650 | wr32(hw, GLINT_ITR(ICE_RX_ITR, vector), q_vector->rx.itr); |
1630 | wr32(hw, GLINT_ITR(ICE_TX_ITR, vector), q_vector->tx.itr); | 1651 | wr32(hw, GLINT_ITR(ICE_TX_ITR, vector), q_vector->tx.itr); |
1652 | wr32(hw, GLINT_RATE(vector), | ||
1653 | ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); | ||
1631 | 1654 | ||
1632 | /* Both Transmit Queue Interrupt Cause Control register | 1655 | /* Both Transmit Queue Interrupt Cause Control register |
1633 | * and Receive Queue Interrupt Cause control register | 1656 | * and Receive Queue Interrupt Cause control register |
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index f51857ead0f3..9638684f75ac 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c | |||
@@ -1406,7 +1406,7 @@ skip_req_irq: | |||
1406 | PFINT_FW_CTL_CAUSE_ENA_M); | 1406 | PFINT_FW_CTL_CAUSE_ENA_M); |
1407 | wr32(hw, PFINT_FW_CTL, val); | 1407 | wr32(hw, PFINT_FW_CTL, val); |
1408 | 1408 | ||
1409 | itr_gran = hw->itr_gran_200; | 1409 | itr_gran = hw->itr_gran; |
1410 | 1410 | ||
1411 | wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx), | 1411 | wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx), |
1412 | ITR_TO_REG(ICE_ITR_8K, itr_gran)); | 1412 | ITR_TO_REG(ICE_ITR_8K, itr_gran)); |
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h index 839fd9ff6043..a9b92974e041 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.h +++ b/drivers/net/ethernet/intel/ice/ice_txrx.h | |||
@@ -104,10 +104,16 @@ enum ice_rx_dtype { | |||
104 | #define ICE_RX_ITR ICE_IDX_ITR0 | 104 | #define ICE_RX_ITR ICE_IDX_ITR0 |
105 | #define ICE_TX_ITR ICE_IDX_ITR1 | 105 | #define ICE_TX_ITR ICE_IDX_ITR1 |
106 | #define ICE_ITR_DYNAMIC 0x8000 /* use top bit as a flag */ | 106 | #define ICE_ITR_DYNAMIC 0x8000 /* use top bit as a flag */ |
107 | #define ICE_ITR_8K 0x003E | 107 | #define ICE_ITR_8K 125 |
108 | #define ICE_DFLT_TX_ITR ICE_ITR_8K | ||
109 | #define ICE_DFLT_RX_ITR ICE_ITR_8K | ||
110 | /* apply ITR granularity translation to program the register. itr_gran is either | ||
111 | * 2 or 4 usecs so we need to divide by 2 first then shift by that value | ||
112 | */ | ||
113 | #define ITR_TO_REG(val, itr_gran) (((val) & ~ICE_ITR_DYNAMIC) >> \ | ||
114 | ((itr_gran) / 2)) | ||
108 | 115 | ||
109 | /* apply ITR HW granularity translation to program the HW registers */ | 116 | #define ICE_DFLT_INTRL 0 |
110 | #define ITR_TO_REG(val, itr_gran) (((val) & ~ICE_ITR_DYNAMIC) >> (itr_gran)) | ||
111 | 117 | ||
112 | /* Legacy or Advanced Mode Queue */ | 118 | /* Legacy or Advanced Mode Queue */ |
113 | #define ICE_TX_ADVANCED 0 | 119 | #define ICE_TX_ADVANCED 0 |
@@ -130,12 +136,11 @@ struct ice_ring { | |||
130 | u32 txq_teid; /* Added Tx queue TEID */ | 136 | u32 txq_teid; /* Added Tx queue TEID */ |
131 | 137 | ||
132 | /* high bit set means dynamic, use accessor routines to read/write. | 138 | /* high bit set means dynamic, use accessor routines to read/write. |
133 | * hardware supports 2us/1us resolution for the ITR registers. | 139 | * hardware supports 4us/2us resolution for the ITR registers. |
134 | * these values always store the USER setting, and must be converted | 140 | * these values always store the USER setting, and must be converted |
135 | * before programming to a register. | 141 | * before programming to a register. |
136 | */ | 142 | */ |
137 | u16 rx_itr_setting; | 143 | u16 itr_setting; |
138 | u16 tx_itr_setting; | ||
139 | 144 | ||
140 | u16 count; /* Number of descriptors */ | 145 | u16 count; /* Number of descriptors */ |
141 | u16 reg_idx; /* HW register index of the ring */ | 146 | u16 reg_idx; /* HW register index of the ring */ |
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 87930f68d3fb..f5c8de0ed0eb 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h | |||
@@ -333,16 +333,26 @@ struct ice_hw { | |||
333 | u32 fw_build; /* firmware build number */ | 333 | u32 fw_build; /* firmware build number */ |
334 | 334 | ||
335 | struct ice_fw_log_cfg fw_log; | 335 | struct ice_fw_log_cfg fw_log; |
336 | /* minimum allowed value for different speeds */ | 336 | |
337 | #define ICE_ITR_GRAN_MIN_200 1 | 337 | /* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL |
338 | #define ICE_ITR_GRAN_MIN_100 1 | 338 | * register. Used for determining the itr/intrl granularity during |
339 | #define ICE_ITR_GRAN_MIN_50 2 | 339 | * initialization. |
340 | #define ICE_ITR_GRAN_MIN_25 4 | 340 | */ |
341 | #define ICE_MAX_AGG_BW_200G 0x0 | ||
342 | #define ICE_MAX_AGG_BW_100G 0X1 | ||
343 | #define ICE_MAX_AGG_BW_50G 0x2 | ||
344 | #define ICE_MAX_AGG_BW_25G 0x3 | ||
345 | /* ITR granularity for different speeds */ | ||
346 | #define ICE_ITR_GRAN_ABOVE_25 2 | ||
347 | #define ICE_ITR_GRAN_MAX_25 4 | ||
341 | /* ITR granularity in 1 us */ | 348 | /* ITR granularity in 1 us */ |
342 | u8 itr_gran_200; | 349 | u8 itr_gran; |
343 | u8 itr_gran_100; | 350 | /* INTRL granularity for different speeds */ |
344 | u8 itr_gran_50; | 351 | #define ICE_INTRL_GRAN_ABOVE_25 4 |
345 | u8 itr_gran_25; | 352 | #define ICE_INTRL_GRAN_MAX_25 8 |
353 | /* INTRL granularity in 1 us */ | ||
354 | u8 intrl_gran; | ||
355 | |||
346 | u8 ucast_shared; /* true if VSIs can share unicast addr */ | 356 | u8 ucast_shared; /* true if VSIs can share unicast addr */ |
347 | 357 | ||
348 | }; | 358 | }; |