From patchwork Thu Sep 20 00:23:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anirudh Venkataramanan X-Patchwork-Id: 972043 X-Patchwork-Delegate: jeffrey.t.kirsher@intel.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=osuosl.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=intel-wired-lan-bounces@osuosl.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42FyBt5Mlqz9sBJ for ; Thu, 20 Sep 2018 10:23:50 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 58F7B88209; Thu, 20 Sep 2018 00:23:49 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id S-foy18zhYrC; Thu, 20 Sep 2018 00:23:43 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by whitealder.osuosl.org (Postfix) with ESMTP id 1C186882D0; Thu, 20 Sep 2018 00:23:36 +0000 (UTC) X-Original-To: intel-wired-lan@lists.osuosl.org Delivered-To: intel-wired-lan@lists.osuosl.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by ash.osuosl.org (Postfix) with ESMTP id 8D3661C08AF for ; Thu, 20 Sep 2018 00:23:32 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 89CCC201F5 for ; Thu, 20 Sep 2018 00:23:32 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ugUdfLPb7iY6 for ; Thu, 20 Sep 2018 00:23:29 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by silver.osuosl.org (Postfix) with ESMTPS id 3BF093096D for ; Thu, 20 Sep 2018 00:23:25 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Sep 2018 17:23:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,396,1531810800"; d="scan'208";a="265057708" Received: from shasta.jf.intel.com ([10.166.241.11]) by fmsmga006.fm.intel.com with ESMTP; 19 Sep 2018 17:23:20 -0700 From: Anirudh Venkataramanan To: intel-wired-lan@lists.osuosl.org Date: Wed, 19 Sep 2018 17:23:19 -0700 Message-Id: <20180920002319.10971-17-anirudh.venkataramanan@intel.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180920002319.10971-1-anirudh.venkataramanan@intel.com> References: <20180920002319.10971-1-anirudh.venkataramanan@intel.com> Subject: [Intel-wired-lan] [PATCH 16/16] ice: Add support for dynamic interrupt moderation X-BeenThere: intel-wired-lan@osuosl.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Intel Wired Ethernet Linux Kernel Driver Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-wired-lan-bounces@osuosl.org Sender: "Intel-wired-lan" From: Brett Creeley 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 Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers --- drivers/net/ethernet/intel/ice/ice.h | 4 +++ drivers/net/ethernet/intel/ice/ice_common.c | 41 ++++++++++++++++++++++--- drivers/net/ethernet/intel/ice/ice_hw_autogen.h | 5 +++ drivers/net/ethernet/intel/ice/ice_lib.c | 29 +++++++++++++++-- drivers/net/ethernet/intel/ice/ice_main.c | 2 +- drivers/net/ethernet/intel/ice/ice_txrx.h | 17 ++++++---- 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 88d13157ab5b..28002936a0cb 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 { 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 { diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 78315bb6431c..e9e5c601b321 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -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) 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 @@ #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)) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 0d341652fb92..d67d7005916c 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) 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 diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index e244317915a3..4aa6b849a6cc 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -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)); 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 { #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 */ 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 { 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 */ };