From patchwork Fri Mar 20 02:46:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alvin Zhang X-Patchwork-Id: 66962 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 DA7FDA0583; Fri, 20 Mar 2020 03:52:01 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D06061C07B; Fri, 20 Mar 2020 03:51:14 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id B3EB11BF82 for ; Fri, 20 Mar 2020 03:51:05 +0100 (CET) IronPort-SDR: c5JTSF/0ZErpm1ZzvJz8J97Xr90/oXCOCm4O/NiQv0oZ3IGv4nGb40x1RHLZy22s6J+xyYiGsx lLV/JD6JrrLA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 19:51:05 -0700 IronPort-SDR: udUftF46PZYgXWI3SX7R0HNj15quBQ35Y/kgCrJ1xaJrqzstkE2dBKrLszR0kgMpE7QnZbxwL9 8txX7mqFgTJQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,283,1580803200"; d="scan'208";a="280290179" Received: from unknown (HELO dpdk-zhangalvin-dev.sh.intel.com) ([10.240.183.54]) by fmsmga002.fm.intel.com with ESMTP; 19 Mar 2020 19:51:03 -0700 From: alvinx.zhang@intel.com To: dev@dpdk.org, xiaolong.ye@intel.com, haiyue.wang@intel.com, qi.z.zhang@intel.com, beilei.xing@intel.com Date: Fri, 20 Mar 2020 10:46:08 +0800 Message-Id: <1584672375-376187-8-git-send-email-alvinx.zhang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1584672375-376187-1-git-send-email-alvinx.zhang@intel.com> References: <1583742247-370386-1-git-send-email-alvinx.zhang@intel.com> <1584672375-376187-1-git-send-email-alvinx.zhang@intel.com> Subject: [dpdk-dev] [PATCH v2 07/14] 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 79bfb2d..6e21c5f 100644 --- a/doc/guides/nics/features/igc.ini +++ b/doc/guides/nics/features/igc.ini @@ -26,6 +26,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 1593365..d2cb845 100644 --- a/drivers/net/igc/igc_ethdev.c +++ b/drivers/net/igc/igc_ethdev.c @@ -206,6 +206,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, @@ -252,6 +256,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, }; /* @@ -2060,6 +2066,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) {