From patchwork Tue Sep 1 11:51:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 76240 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 00670A04AC; Tue, 1 Sep 2020 13:58:44 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id A3EF21C437; Tue, 1 Sep 2020 13:51:59 +0200 (CEST) Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) by dpdk.org (Postfix) with ESMTP id 4E9601C23F for ; Tue, 1 Sep 2020 13:51:50 +0200 (CEST) X-QQ-mid: bizesmtp5t1598961106tw313owgg Received: from localhost.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Tue, 01 Sep 2020 19:51:46 +0800 (CST) X-QQ-SSF: 01400000000000B0C000000A0000000 X-QQ-FEAT: ++NGk9XhXCNa2HkEdGpBLAqN0+qRGCnEtHEurw4n3JhC1IwFFoAxvU24nPM92 CeFPHSVVmcSaDxUM09DBV7GjrunZMtiGa5zajnO0s5yS7tFc/SKa72DAFrDgxXHVazjuBkW VWUTlDTmkGfY8ji0LBZpHhO20jpOx5UOObtH8T7bAW2mOVAeDKX+qu4l/WeFGQDd9DL5dhj V/cO4oq5e9NwTV6vGOjEtD8wJRET9RffhOsid1FwhXeskuOkxeckH2lfjgprAbTbuYa2qu5 bqVsueUkyUx3GPvsYSkl+Lp9L11UQGhOio2Uy+LQqHIHWod/QmAGyGF3vw+srC8kRJZyzq2 39cDfoIaOF9pBGnH45p/W0IDah0oJjwupxxqM7B X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Tue, 1 Sep 2020 19:51:09 +0800 Message-Id: <20200901115113.1529675-38-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.18.4 In-Reply-To: <20200901115113.1529675-1-jiawenwu@trustnetic.com> References: <20200901115113.1529675-1-jiawenwu@trustnetic.com> X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign5 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v1 38/42] net/txgbe: add DCB packet buffer allocation 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" Add DCB packet buffer allocation and priority flow control support. Signed-off-by: Jiawen Wu --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe.h | 1 + drivers/net/txgbe/base/txgbe_dcb.c | 180 ++++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_dcb.h | 86 +++++++++++++ drivers/net/txgbe/base/txgbe_hw.c | 63 ++++++++++ drivers/net/txgbe/base/txgbe_hw.h | 2 + drivers/net/txgbe/base/txgbe_type.h | 13 ++ drivers/net/txgbe/txgbe_ethdev.c | 98 +++++++++++++++ drivers/net/txgbe/txgbe_ethdev.h | 6 + drivers/net/txgbe/txgbe_rxtx.c | 51 ++++++++ 10 files changed, 501 insertions(+) create mode 100644 drivers/net/txgbe/base/txgbe_dcb.c create mode 100644 drivers/net/txgbe/base/txgbe_dcb.h diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index 069879a7c..13b418f19 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -2,6 +2,7 @@ # Copyright(c) 2015-2020 sources = [ + 'txgbe_dcb.c', 'txgbe_eeprom.c', 'txgbe_hw.c', 'txgbe_mng.c', diff --git a/drivers/net/txgbe/base/txgbe.h b/drivers/net/txgbe/base/txgbe.h index 764caa439..1bb8f3af8 100644 --- a/drivers/net/txgbe/base/txgbe.h +++ b/drivers/net/txgbe/base/txgbe.h @@ -10,5 +10,6 @@ #include "txgbe_eeprom.h" #include "txgbe_phy.h" #include "txgbe_hw.h" +#include "txgbe_dcb.h" #endif /* _TXGBE_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_dcb.c b/drivers/net/txgbe/base/txgbe_dcb.c new file mode 100644 index 000000000..6366da92a --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_dcb.c @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2015-2020 + */ + +#include "txgbe_type.h" +#include "txgbe_hw.h" +#include "txgbe_dcb.h" + +/** + * txgbe_pfc_enable - Enable flow control + * @hw: pointer to hardware structure + * @tc_num: traffic class number + * Enable flow control according to the current settings. + */ +int +txgbe_dcb_pfc_enable(struct txgbe_hw *hw, uint8_t tc_num) +{ + int ret_val = 0; + uint32_t mflcn_reg, fccfg_reg; + uint32_t pause_time; + uint32_t fcrtl, fcrth; + uint8_t i; + uint8_t nb_rx_en; + + /* Validate the water mark configuration */ + if (!hw->fc.pause_time) { + ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS; + goto out; + } + + /* Low water mark of zero causes XOFF floods */ + if (hw->fc.current_mode & txgbe_fc_tx_pause) { + /* High/Low water can not be 0 */ + if (!hw->fc.high_water[tc_num] || + !hw->fc.low_water[tc_num]) { + PMD_INIT_LOG(ERR, "Invalid water mark configuration"); + ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS; + goto out; + } + + if (hw->fc.low_water[tc_num] >= hw->fc.high_water[tc_num]) { + PMD_INIT_LOG(ERR, "Invalid water mark configuration"); + ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS; + goto out; + } + } + /* Negotiate the fc mode to use */ + txgbe_fc_autoneg(hw); + + /* Disable any previous flow control settings */ + mflcn_reg = rd32(hw, TXGBE_RXFCCFG); + mflcn_reg &= ~(TXGBE_RXFCCFG_FC | TXGBE_RXFCCFG_PFC); + + fccfg_reg = rd32(hw, TXGBE_TXFCCFG); + fccfg_reg &= ~(TXGBE_TXFCCFG_FC | TXGBE_TXFCCFG_PFC); + + switch (hw->fc.current_mode) { + case txgbe_fc_none: + /* + * If the count of enabled RX Priority Flow control > 1, + * and the TX pause can not be disabled + */ + nb_rx_en = 0; + for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { + uint32_t reg = rd32(hw, TXGBE_FCWTRHI(i)); + if (reg & TXGBE_FCWTRHI_XOFF) + nb_rx_en++; + } + if (nb_rx_en > 1) + fccfg_reg |= TXGBE_TXFCCFG_PFC; + break; + case txgbe_fc_rx_pause: + /* + * Rx Flow control is enabled and Tx Flow control is + * disabled by software override. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric Rx PAUSE. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + mflcn_reg |= TXGBE_RXFCCFG_PFC; + /* + * If the count of enabled RX Priority Flow control > 1, + * and the TX pause can not be disabled + */ + nb_rx_en = 0; + for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { + uint32_t reg = rd32(hw, TXGBE_FCWTRHI(i)); + if (reg & TXGBE_FCWTRHI_XOFF) + nb_rx_en++; + } + if (nb_rx_en > 1) + fccfg_reg |= TXGBE_TXFCCFG_PFC; + break; + case txgbe_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is + * disabled by software override. + */ + fccfg_reg |= TXGBE_TXFCCFG_PFC; + break; + case txgbe_fc_full: + /* Flow control (both Rx and Tx) is enabled by SW override. */ + mflcn_reg |= TXGBE_RXFCCFG_PFC; + fccfg_reg |= TXGBE_TXFCCFG_PFC; + break; + default: + PMD_DRV_LOG(DEBUG, "Flow control param set incorrectly"); + ret_val = TXGBE_ERR_CONFIG; + goto out; + } + + /* Set 802.3x based flow control settings. */ + wr32(hw, TXGBE_RXFCCFG, mflcn_reg); + wr32(hw, TXGBE_TXFCCFG, fccfg_reg); + + /* Set up and enable Rx high/low water mark thresholds, enable XON. */ + if ((hw->fc.current_mode & txgbe_fc_tx_pause) && + hw->fc.high_water[tc_num]) { + fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[tc_num]) | + TXGBE_FCWTRLO_XON; + fcrth = TXGBE_FCWTRHI_TH(hw->fc.high_water[tc_num]) | + TXGBE_FCWTRHI_XOFF; + } else { + /* + * In order to prevent Tx hangs when the internal Tx + * switch is enabled we must set the high water mark + * to the maximum FCRTH value. This allows the Tx + * switch to function even under heavy Rx workloads. + */ + fcrtl = 0; + fcrth = rd32(hw, TXGBE_PBRXSIZE(tc_num)) - 32; + } + wr32(hw, TXGBE_FCWTRLO(tc_num), fcrtl); + wr32(hw, TXGBE_FCWTRHI(tc_num), fcrth); + + /* Configure pause time (2 TCs per register) */ + pause_time = TXGBE_RXFCFSH_TIME(hw->fc.pause_time); + for (i = 0; i < (TXGBE_DCB_TC_MAX / 2); i++) + wr32(hw, TXGBE_FCXOFFTM(i), pause_time * 0x00010001); + + /* Configure flow control refresh threshold value */ + wr32(hw, TXGBE_RXFCRFSH, pause_time / 2); + +out: + return ret_val; +} + +u8 txgbe_dcb_get_tc_from_up(struct txgbe_dcb_config *cfg, int direction, u8 up) +{ + struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0]; + u8 prio_mask = 1 << up; + u8 tc = cfg->num_tcs.pg_tcs; + + /* If tc is 0 then DCB is likely not enabled or supported */ + if (!tc) + goto out; + + /* + * Test from maximum TC to 1 and report the first match we find. If + * we find no match we can assume that the TC is 0 since the TC must + * be set for all user priorities + */ + for (tc--; tc; tc--) { + if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap) + break; + } +out: + return tc; +} + +void txgbe_dcb_unpack_map_cee(struct txgbe_dcb_config *cfg, int direction, + u8 *map) +{ + u8 up; + + for (up = 0; up < TXGBE_DCB_UP_MAX; up++) + map[up] = txgbe_dcb_get_tc_from_up(cfg, direction, up); +} + diff --git a/drivers/net/txgbe/base/txgbe_dcb.h b/drivers/net/txgbe/base/txgbe_dcb.h new file mode 100644 index 000000000..67de5c54b --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_dcb.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2015-2020 + */ + +#ifndef _TXGBE_DCB_H_ +#define _TXGBE_DCB_H_ + +#include "txgbe_type.h" + +#define TXGBE_DCB_TX_CONFIG 0 +#define TXGBE_DCB_RX_CONFIG 1 + +struct txgbe_dcb_support { + u32 capabilities; /* DCB capabilities */ + + /* Each bit represents a number of TCs configurable in the hw. + * If 8 traffic classes can be configured, the value is 0x80. */ + u8 traffic_classes; + u8 pfc_traffic_classes; +}; + +enum txgbe_dcb_tsa { + txgbe_dcb_tsa_ets = 0, + txgbe_dcb_tsa_group_strict_cee, + txgbe_dcb_tsa_strict +}; + +/* Traffic class bandwidth allocation per direction */ +struct txgbe_dcb_tc_path { + u8 bwg_id; /* Bandwidth Group (BWG) ID */ + u8 bwg_percent; /* % of BWG's bandwidth */ + u8 link_percent; /* % of link bandwidth */ + u8 up_to_tc_bitmap; /* User Priority to Traffic Class mapping */ + u16 data_credits_refill; /* Credit refill amount in 64B granularity */ + u16 data_credits_max; /* Max credits for a configured packet buffer + * in 64B granularity.*/ + enum txgbe_dcb_tsa tsa; /* Link or Group Strict Priority */ +}; + +enum txgbe_dcb_pfc { + txgbe_dcb_pfc_disabled = 0, + txgbe_dcb_pfc_enabled, + txgbe_dcb_pfc_enabled_txonly, + txgbe_dcb_pfc_enabled_rxonly +}; + +/* Traffic class configuration */ +struct txgbe_dcb_tc_config { + struct txgbe_dcb_tc_path path[2]; /* One each for Tx/Rx */ + enum txgbe_dcb_pfc pfc; /* Class based flow control setting */ + + u16 desc_credits_max; /* For Tx Descriptor arbitration */ + u8 tc; /* Traffic class (TC) */ +}; + +enum txgbe_dcb_pba { + /* PBA[0-7] each use 64KB FIFO */ + txgbe_dcb_pba_equal = PBA_STRATEGY_EQUAL, + /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */ + txgbe_dcb_pba_80_48 = PBA_STRATEGY_WEIGHTED +}; + +struct txgbe_dcb_num_tcs { + u8 pg_tcs; + u8 pfc_tcs; +}; + +struct txgbe_dcb_config { + struct txgbe_dcb_tc_config tc_config[TXGBE_DCB_TC_MAX]; + struct txgbe_dcb_support support; + struct txgbe_dcb_num_tcs num_tcs; + u8 bw_percentage[TXGBE_DCB_BWG_MAX][2]; /* One each for Tx/Rx */ + bool pfc_mode_enable; + bool round_robin_enable; + + enum txgbe_dcb_pba rx_pba_cfg; + + u32 link_speed; /* For bandwidth allocation validation purpose */ + bool vt_mode; +}; + +int txgbe_dcb_pfc_enable(struct txgbe_hw *hw, u8 tc_num); +void txgbe_dcb_unpack_map_cee(struct txgbe_dcb_config *, int, u8 *); +u8 txgbe_dcb_get_tc_from_up(struct txgbe_dcb_config *, int, u8); + +#endif /* _TXGBE_DCB_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 164d3b5b8..15ab0213d 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -1757,6 +1757,68 @@ s32 txgbe_get_device_caps(struct txgbe_hw *hw, u16 *device_caps) return 0; } +/** + * txgbe_set_pba - Initialize Rx packet buffer + * @hw: pointer to hardware structure + * @num_pb: number of packet buffers to allocate + * @headroom: reserve n KB of headroom + * @strategy: packet buffer allocation strategy + **/ +void txgbe_set_pba(struct txgbe_hw *hw, int num_pb, u32 headroom, + int strategy) +{ + u32 pbsize = hw->mac.rx_pb_size; + int i = 0; + u32 rxpktsize, txpktsize, txpbthresh; + + UNREFERENCED_PARAMETER(hw); + + /* Reserve headroom */ + pbsize -= headroom; + + if (!num_pb) + num_pb = 1; + + /* Divide remaining packet buffer space amongst the number of packet + * buffers requested using supplied strategy. + */ + switch (strategy) { + case PBA_STRATEGY_WEIGHTED: + /* txgbe_dcb_pba_80_48 strategy weight first half of packet + * buffer with 5/8 of the packet buffer space. + */ + rxpktsize = (pbsize * 5) / (num_pb * 4); + pbsize -= rxpktsize * (num_pb / 2); + rxpktsize <<= 10; + for (; i < (num_pb / 2); i++) + wr32(hw, TXGBE_PBRXSIZE(i), rxpktsize); + /* fall through - configure remaining packet buffers */ + case PBA_STRATEGY_EQUAL: + rxpktsize = (pbsize / (num_pb - i)); + rxpktsize <<= 10; + for (; i < num_pb; i++) + wr32(hw, TXGBE_PBRXSIZE(i), rxpktsize); + break; + default: + break; + } + + /* Only support an equally distributed Tx packet buffer strategy. */ + txpktsize = TXGBE_PBTXSIZE_MAX / num_pb; + txpbthresh = (txpktsize / 1024) - TXGBE_TXPKT_SIZE_MAX; + for (i = 0; i < num_pb; i++) { + wr32(hw, TXGBE_PBTXSIZE(i), txpktsize); + wr32(hw, TXGBE_PBTXDMATH(i), txpbthresh); + } + + /* Clear unused TCs, if any, to zero buffer size*/ + for (; i < TXGBE_MAX_UP; i++) { + wr32(hw, TXGBE_PBRXSIZE(i), 0); + wr32(hw, TXGBE_PBTXSIZE(i), 0); + wr32(hw, TXGBE_PBTXDMATH(i), 0); + } +} + /** * txgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo * @hw: pointer to the hardware structure @@ -2350,6 +2412,7 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) /* Link */ mac->get_link_capabilities = txgbe_get_link_capabilities_raptor; mac->check_link = txgbe_check_mac_link; + mac->setup_pba = txgbe_set_pba; /* Manageability interface */ mac->set_fw_drv_ver = txgbe_hic_set_drv_ver; diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index 047c71ecf..ea65e14bf 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -52,6 +52,8 @@ s32 txgbe_get_wwn_prefix(struct txgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix); s32 txgbe_get_device_caps(struct txgbe_hw *hw, u16 *device_caps); +void txgbe_set_pba(struct txgbe_hw *hw, int num_pb, u32 headroom, + int strategy); void txgbe_clear_tx_pending(struct txgbe_hw *hw); extern s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw); diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 4a30a99db..fcc44ece8 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -6,11 +6,15 @@ #define _TXGBE_TYPE_H_ #define TXGBE_DCB_TC_MAX TXGBE_MAX_UP +#define TXGBE_DCB_UP_MAX TXGBE_MAX_UP +#define TXGBE_DCB_BWG_MAX TXGBE_MAX_UP #define TXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define TXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ #define TXGBE_FRAME_SIZE_MAX (9728) /* Maximum frame size, +FCS */ #define TXGBE_FRAME_SIZE_DFT (1518) /* Default frame size, +FCS */ +#define TXGBE_PBTXSIZE_MAX 0x00028000 /* 160KB Packet Buffer */ +#define TXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */ #define TXGBE_MAX_UP 8 #define TXGBE_MAX_QP (128) @@ -19,6 +23,14 @@ #include "txgbe_status.h" #include "txgbe_osdep.h" #include "txgbe_devids.h" +/* Packet buffer allocation strategies */ +enum { + PBA_STRATEGY_EQUAL = 0, /* Distribute PB space equally */ +#define PBA_STRATEGY_EQUAL PBA_STRATEGY_EQUAL + PBA_STRATEGY_WEIGHTED = 1, /* Weight front half of TCs */ +#define PBA_STRATEGY_WEIGHTED PBA_STRATEGY_WEIGHTED +}; + /* Physical layer type */ #define TXGBE_PHYSICAL_LAYER_UNKNOWN 0 @@ -534,6 +546,7 @@ struct txgbe_mac_info { s32 mc_filter_type; u32 mcft_size; u32 num_rar_entries; + u32 rx_pb_size; u32 max_tx_queues; u32 max_rx_queues; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index cab89f5f8..a72994d08 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -333,6 +333,43 @@ txgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev, return 0; } +static void +txgbe_dcb_init(struct txgbe_hw *hw, struct txgbe_dcb_config *dcb_config) +{ + int i; + u8 bwgp; + struct txgbe_dcb_tc_config *tc; + + UNREFERENCED_PARAMETER(hw); + + dcb_config->num_tcs.pg_tcs = TXGBE_DCB_TC_MAX; + dcb_config->num_tcs.pfc_tcs = TXGBE_DCB_TC_MAX; + bwgp = (u8)(100 / TXGBE_DCB_TC_MAX); + for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { + tc = &dcb_config->tc_config[i]; + tc->path[TXGBE_DCB_TX_CONFIG].bwg_id = i; + tc->path[TXGBE_DCB_TX_CONFIG].bwg_percent = bwgp + (i & 1); + tc->path[TXGBE_DCB_RX_CONFIG].bwg_id = i; + tc->path[TXGBE_DCB_RX_CONFIG].bwg_percent = bwgp + (i & 1); + tc->pfc = txgbe_dcb_pfc_disabled; + } + + /* Initialize default user to priority mapping, UPx->TC0 */ + tc = &dcb_config->tc_config[0]; + tc->path[TXGBE_DCB_TX_CONFIG].up_to_tc_bitmap = 0xFF; + tc->path[TXGBE_DCB_RX_CONFIG].up_to_tc_bitmap = 0xFF; + for (i = 0; i < TXGBE_DCB_BWG_MAX; i++) { + dcb_config->bw_percentage[i][TXGBE_DCB_TX_CONFIG] = 100; + dcb_config->bw_percentage[i][TXGBE_DCB_RX_CONFIG] = 100; + } + dcb_config->rx_pba_cfg = txgbe_dcb_pba_equal; + dcb_config->pfc_mode_enable = false; + dcb_config->vt_mode = true; + dcb_config->round_robin_enable = false; + /* support all DCB capabilities */ + dcb_config->support.capabilities = 0xFF; +} + /* * Ensure that all locks are released before first NVM or PHY access */ @@ -363,6 +400,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) struct txgbe_hw *hw = TXGBE_DEV_HW(eth_dev); struct txgbe_vfta *shadow_vfta = TXGBE_DEV_VFTA(eth_dev); struct txgbe_hwstrip *hwstrip = TXGBE_DEV_HWSTRIP(eth_dev); + struct txgbe_dcb_config *dcb_config = TXGBE_DEV_DCB_CONFIG(eth_dev); struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; const struct rte_memzone *mz; uint32_t ctrl_ext; @@ -427,6 +465,10 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) /* Unlock any pending hardware semaphore */ txgbe_swfw_lock_reset(hw); + /* Initialize DCB configuration*/ + memset(dcb_config, 0, sizeof(struct txgbe_dcb_config)); + txgbe_dcb_init(hw, dcb_config); + /* Get Hardware Flow Control setting */ hw->fc.requested_mode = txgbe_fc_full; hw->fc.current_mode = txgbe_fc_full; @@ -1139,6 +1181,9 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; } + txgbe_configure_pb(dev); + txgbe_configure_port(dev); + err = txgbe_dev_rxtx_start(dev); if (err < 0) { PMD_INIT_LOG(ERR, "Unable to start rxtx queues"); @@ -2552,6 +2597,58 @@ txgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) return -EIO; } +static int +txgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf) +{ + int err; + uint32_t rx_buf_size; + uint32_t max_high_water; + uint8_t tc_num; + uint8_t map[TXGBE_DCB_UP_MAX] = { 0 }; + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_dcb_config *dcb_config = TXGBE_DEV_DCB_CONFIG(dev); + + enum txgbe_fc_mode rte_fcmode_2_txgbe_fcmode[] = { + txgbe_fc_none, + txgbe_fc_rx_pause, + txgbe_fc_tx_pause, + txgbe_fc_full + }; + + PMD_INIT_FUNC_TRACE(); + + txgbe_dcb_unpack_map_cee(dcb_config, TXGBE_DCB_RX_CONFIG, map); + tc_num = map[pfc_conf->priority]; + rx_buf_size = rd32(hw, TXGBE_PBRXSIZE(tc_num)); + PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size); + /* + * At least reserve one Ethernet frame for watermark + * high_water/low_water in kilo bytes for txgbe + */ + max_high_water = (rx_buf_size - RTE_ETHER_MAX_LEN) >> 10; + if ((pfc_conf->fc.high_water > max_high_water) || + (pfc_conf->fc.high_water <= pfc_conf->fc.low_water)) { + PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB"); + PMD_INIT_LOG(ERR, "High_water must <= 0x%x", max_high_water); + return -EINVAL; + } + + hw->fc.requested_mode = rte_fcmode_2_txgbe_fcmode[pfc_conf->fc.mode]; + hw->fc.pause_time = pfc_conf->fc.pause_time; + hw->fc.send_xon = pfc_conf->fc.send_xon; + hw->fc.low_water[tc_num] = pfc_conf->fc.low_water; + hw->fc.high_water[tc_num] = pfc_conf->fc.high_water; + + err = txgbe_dcb_pfc_enable(hw, tc_num); + + /* Not negotiated is not an error case */ + if ((err == 0) || (err == TXGBE_ERR_FC_NOT_NEGOTIATED)) + return 0; + + PMD_INIT_LOG(ERR, "txgbe_dcb_pfc_enable = 0x%x", err); + return -EIO; +} + static int txgbe_add_rar(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr, uint32_t index, uint32_t pool) @@ -2932,6 +3029,7 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = { .dev_led_off = txgbe_dev_led_off, .flow_ctrl_get = txgbe_flow_ctrl_get, .flow_ctrl_set = txgbe_flow_ctrl_set, + .priority_flow_ctrl_set = txgbe_priority_flow_ctrl_set, .mac_addr_add = txgbe_add_rar, .mac_addr_remove = txgbe_remove_rar, .mac_addr_set = txgbe_set_default_mac_addr, diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 667b11127..1166c151d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -92,6 +92,7 @@ struct txgbe_adapter { struct txgbe_stat_mappings stat_mappings; struct txgbe_vfta shadow_vfta; struct txgbe_hwstrip hwstrip; + struct txgbe_dcb_config dcb_config; struct txgbe_vf_info *vfdata; bool rx_bulk_alloc_allowed; }; @@ -126,6 +127,9 @@ int txgbe_vf_representor_uninit(struct rte_eth_dev *ethdev); #define TXGBE_DEV_HWSTRIP(dev) \ (&((struct txgbe_adapter *)(dev)->data->dev_private)->hwstrip) +#define TXGBE_DEV_DCB_CONFIG(dev) \ + (&((struct txgbe_adapter *)(dev)->data->dev_private)->dcb_config) + #define TXGBE_DEV_VFDATA(dev) \ (&((struct txgbe_adapter *)(dev)->data->dev_private)->vfdata) @@ -205,6 +209,8 @@ uint16_t txgbe_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t direction, uint8_t queue, uint8_t msix_vector); +void txgbe_configure_pb(struct rte_eth_dev *dev); +void txgbe_configure_port(struct rte_eth_dev *dev); int txgbe_dev_link_update_share(struct rte_eth_dev *dev, diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index df094408f..e2ab86568 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -2760,6 +2760,57 @@ txgbe_dev_free_queues(struct rte_eth_dev *dev) dev->data->nb_tx_queues = 0; } +void txgbe_configure_pb(struct rte_eth_dev *dev) +{ + struct rte_eth_conf *dev_conf = &(dev->data->dev_conf); + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + + int hdrm; + int tc = dev_conf->rx_adv_conf.dcb_rx_conf.nb_tcs; + + /* Reserve 256KB(/512KB) rx buffer for fdir */ + hdrm = 256; /*KB*/ + + hw->mac.setup_pba(hw, tc, hdrm, PBA_STRATEGY_EQUAL); +} + +void txgbe_configure_port(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + int i = 0; + uint16_t tpids[8] = {RTE_ETHER_TYPE_VLAN, RTE_ETHER_TYPE_QINQ, + 0x9100, 0x9200, + 0x0000, 0x0000, + 0x0000, 0x0000}; + + PMD_INIT_FUNC_TRACE(); + + /* default outer vlan tpid */ + wr32(hw, TXGBE_EXTAG, + TXGBE_EXTAG_ETAG(RTE_ETHER_TYPE_ETAG) | + TXGBE_EXTAG_VLAN(RTE_ETHER_TYPE_QINQ)); + + /* default inner vlan tpid */ + wr32m(hw, TXGBE_VLANCTL, + TXGBE_VLANCTL_TPID_MASK, + TXGBE_VLANCTL_TPID(RTE_ETHER_TYPE_VLAN)); + wr32m(hw, TXGBE_DMATXCTRL, + TXGBE_DMATXCTRL_TPID_MASK, + TXGBE_DMATXCTRL_TPID(RTE_ETHER_TYPE_VLAN)); + + /* default vlan tpid filters */ + for (i = 0; i < 8; i++) { + wr32m(hw, TXGBE_TAGTPID(i/2), + (i % 2 ? TXGBE_TAGTPID_MSB_MASK + : TXGBE_TAGTPID_LSB_MASK), + (i % 2 ? TXGBE_TAGTPID_MSB(tpids[i]) + : TXGBE_TAGTPID_LSB(tpids[i]))); + } + + /* default vxlan port */ + wr32(hw, TXGBE_VXLANPORT, 4789); +} + static int __rte_cold txgbe_alloc_rx_queue_mbufs(struct txgbe_rx_queue *rxq) {