From patchwork Mon Apr 13 06:30:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alvin Zhang X-Patchwork-Id: 68249 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 9506CA0577; Mon, 13 Apr 2020 08:33:22 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D24261C01B; Mon, 13 Apr 2020 08:31:46 +0200 (CEST) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by dpdk.org (Postfix) with ESMTP id EA9341BF30 for ; Mon, 13 Apr 2020 08:31:41 +0200 (CEST) IronPort-SDR: l0FoY9ODsLS0EYxIp7ob2OnUgFvxJxYD77FfHeTLegXo2DiileLXIMUss/7yA5Tozuk4naHAZH HJuoz2qe/75A== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2020 23:31:41 -0700 IronPort-SDR: j8eEAunnoBu1t9LLdnceHi9AVVRJfGqvjOVhndFU/5jx2sJkldYvwHqQF8sOsgFFyaexepDjCv y8dlj9WA41Zg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,377,1580803200"; d="scan'208";a="270987685" Received: from shwdenpg235.ccr.corp.intel.com ([10.240.182.60]) by orsmga002.jf.intel.com with ESMTP; 12 Apr 2020 23:31:39 -0700 From: alvinx.zhang@intel.com To: dev@dpdk.org Cc: xiaolong.ye@intel.com, Alvin Zhang Date: Mon, 13 Apr 2020 14:30:33 +0800 Message-Id: <20200413063037.13728-8-alvinx.zhang@intel.com> X-Mailer: git-send-email 2.21.0.windows.1 In-Reply-To: <20200413063037.13728-1-alvinx.zhang@intel.com> References: <20200413063037.13728-1-alvinx.zhang@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 07/11] net/igc: implement flow control ops X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Alvin Zhang Update feature list too. Signed-off-by: Alvin Zhang --- doc/guides/nics/features/igc.ini | 1 + drivers/net/igc/igc_ethdev.c | 121 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/doc/guides/nics/features/igc.ini b/doc/guides/nics/features/igc.ini index e0bef82..a364e04 100644 --- a/doc/guides/nics/features/igc.ini +++ b/doc/guides/nics/features/igc.ini @@ -27,6 +27,7 @@ Basic stats = Y Extended stats = Y Stats per queue = Y Rx interrupt = Y +Flow control = Y Linux UIO = Y Linux VFIO = Y x86-64 = Y diff --git a/drivers/net/igc/igc_ethdev.c b/drivers/net/igc/igc_ethdev.c index ddb77a4..a135176 100644 --- a/drivers/net/igc/igc_ethdev.c +++ b/drivers/net/igc/igc_ethdev.c @@ -213,6 +213,10 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev, eth_igc_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id); static int eth_igc_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id); +static int +eth_igc_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); +static int +eth_igc_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static const struct eth_dev_ops eth_igc_ops = { .dev_configure = eth_igc_configure, @@ -259,6 +263,8 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev, .queue_stats_mapping_set = eth_igc_queue_stats_mapping_set, .rx_queue_intr_enable = eth_igc_rx_queue_intr_enable, .rx_queue_intr_disable = eth_igc_rx_queue_intr_disable, + .flow_ctrl_get = eth_igc_flow_ctrl_get, + .flow_ctrl_set = eth_igc_flow_ctrl_set, }; /* @@ -2067,6 +2073,121 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev, } static int +eth_igc_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) +{ + struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); + uint32_t ctrl; + int tx_pause; + int rx_pause; + + fc_conf->pause_time = hw->fc.pause_time; + fc_conf->high_water = hw->fc.high_water; + fc_conf->low_water = hw->fc.low_water; + fc_conf->send_xon = hw->fc.send_xon; + fc_conf->autoneg = hw->mac.autoneg; + + /* + * Return rx_pause and tx_pause status according to actual setting of + * the TFCE and RFCE bits in the CTRL register. + */ + ctrl = IGC_READ_REG(hw, IGC_CTRL); + if (ctrl & IGC_CTRL_TFCE) + tx_pause = 1; + else + tx_pause = 0; + + if (ctrl & IGC_CTRL_RFCE) + rx_pause = 1; + else + rx_pause = 0; + + if (rx_pause && tx_pause) + fc_conf->mode = RTE_FC_FULL; + else if (rx_pause) + fc_conf->mode = RTE_FC_RX_PAUSE; + else if (tx_pause) + fc_conf->mode = RTE_FC_TX_PAUSE; + else + fc_conf->mode = RTE_FC_NONE; + + return 0; +} + +static int +eth_igc_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) +{ + struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); + uint32_t rx_buf_size; + uint32_t max_high_water; + uint32_t rctl; + int err; + + if (fc_conf->autoneg != hw->mac.autoneg) + return -ENOTSUP; + + rx_buf_size = igc_get_rx_buffer_size(hw); + PMD_DRV_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size); + + /* At least reserve one Ethernet frame for watermark */ + max_high_water = rx_buf_size - RTE_ETHER_MAX_LEN; + if (fc_conf->high_water > max_high_water || + fc_conf->high_water < fc_conf->low_water) { + PMD_DRV_LOG(ERR, "incorrect high(%u)/low(%u) water " + "value, max is %u", + fc_conf->high_water, fc_conf->low_water, + max_high_water); + return -EINVAL; + } + + switch (fc_conf->mode) { + case RTE_FC_NONE: + hw->fc.requested_mode = igc_fc_none; + break; + case RTE_FC_RX_PAUSE: + hw->fc.requested_mode = igc_fc_rx_pause; + break; + case RTE_FC_TX_PAUSE: + hw->fc.requested_mode = igc_fc_tx_pause; + break; + case RTE_FC_FULL: + hw->fc.requested_mode = igc_fc_full; + break; + default: + PMD_DRV_LOG(ERR, "unsupported fc mode: %u", fc_conf->mode); + return -EINVAL; + } + + hw->fc.pause_time = fc_conf->pause_time; + hw->fc.high_water = fc_conf->high_water; + hw->fc.low_water = fc_conf->low_water; + hw->fc.send_xon = fc_conf->send_xon; + + err = igc_setup_link_generic(hw); + if (err == IGC_SUCCESS) { + /** + * check if we want to forward MAC frames - driver doesn't have + * native capability to do that, so we'll write the registers + * ourselves + **/ + rctl = IGC_READ_REG(hw, IGC_RCTL); + + /* set or clear MFLCN.PMCF bit depending on configuration */ + if (fc_conf->mac_ctrl_frame_fwd != 0) + rctl |= IGC_RCTL_PMCF; + else + rctl &= ~IGC_RCTL_PMCF; + + IGC_WRITE_REG(hw, IGC_RCTL, rctl); + IGC_WRITE_FLUSH(hw); + + return 0; + } + + PMD_DRV_LOG(ERR, "igc_setup_link_generic = 0x%x", err); + return -EIO; +} + +static int eth_igc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, struct rte_pci_device *pci_dev) {