From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id EBC68A04AC; Tue, 1 Sep 2020 13:58:19 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 01ED01C2F2; Tue, 1 Sep 2020 13:51:57 +0200 (CEST) Received: from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166]) by dpdk.org (Postfix) with ESMTP id 48DC31C20D for ; Tue, 1 Sep 2020 13:51:48 +0200 (CEST) X-QQ-mid: bizesmtp5t1598961103tiwc40z4c Received: from localhost.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Tue, 01 Sep 2020 19:51:43 +0800 (CST) X-QQ-SSF: 01400000000000B0C000000A0000000 X-QQ-FEAT: Br92wPWbhaeHlyE5QCaseUhYdCMdQp3LBCv3P2auK4/duZvAQUIOguunaW2QC LIEidMdGGNz+Y2cO3qV1v+HHHLIdo2qyPb71emowmfDVxJAYjHGYIKkcWVCWoD31VV1KUON mvB4sW+I7s3IQZ0/vL2MnCPpPbV+D4IG5pqTRc8bLWAcBeHLQSahlOJZSr4jrGXam5o2mWZ s77BMTvsEJynGWfVRxVY6Lew9pgEaY355g9v0taWfFi9e+3wxPyXuCeEYmMxc0Urrx6o9N6 i86ObKvgzEz2WIj3H86HJ1LMHp7XIx1DpUkjZg5Ekp1Wv9nP4dPjIPo7EHzB7QppOFfyTbO A9bsZS+l3q4bU8SvWM= X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Tue, 1 Sep 2020 19:51:06 +0800 Message-Id: <20200901115113.1529675-35-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 35/42] net/txgbe: add VLAN handle support 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 VLAN filter, tpid, offload and strip set support. Signed-off-by: Jiawen Wu --- drivers/net/txgbe/txgbe_ethdev.c | 370 +++++++++++++++++++++++++++++++ drivers/net/txgbe/txgbe_ethdev.h | 32 +++ 2 files changed, 402 insertions(+) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 54c97f81c..5e0b800ef 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -41,6 +41,8 @@ static void txgbe_dev_close(struct rte_eth_dev *dev); static int txgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); static int txgbe_dev_stats_reset(struct rte_eth_dev *dev); +static void txgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue); +static void txgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue); static void txgbe_dev_link_status_print(struct rte_eth_dev *dev); static int txgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on); @@ -53,6 +55,24 @@ static void txgbe_dev_interrupt_handler(void *param); static void txgbe_dev_interrupt_delayed_handler(void *param); static void txgbe_configure_msix(struct rte_eth_dev *dev); +#define TXGBE_SET_HWSTRIP(h, q) do {\ + uint32_t idx = (q) / (sizeof((h)->bitmap[0]) * NBBY); \ + uint32_t bit = (q) % (sizeof((h)->bitmap[0]) * NBBY); \ + (h)->bitmap[idx] |= 1 << bit;\ + } while (0) + +#define TXGBE_CLEAR_HWSTRIP(h, q) do {\ + uint32_t idx = (q) / (sizeof((h)->bitmap[0]) * NBBY); \ + uint32_t bit = (q) % (sizeof((h)->bitmap[0]) * NBBY); \ + (h)->bitmap[idx] &= ~(1 << bit);\ + } while (0) + +#define TXGBE_GET_HWSTRIP(h, q, r) do {\ + uint32_t idx = (q) / (sizeof((h)->bitmap[0]) * NBBY); \ + uint32_t bit = (q) % (sizeof((h)->bitmap[0]) * NBBY); \ + (r) = (h)->bitmap[idx] >> bit & 1;\ + } while (0) + /* * The set of PCI devices this driver supports */ @@ -341,6 +361,8 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 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 rte_intr_handle *intr_handle = &pci_dev->intr_handle; const struct rte_memzone *mz; uint32_t ctrl_ext; @@ -488,6 +510,12 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) */ eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; + /* initialize the vfta */ + memset(shadow_vfta, 0, sizeof(*shadow_vfta)); + + /* initialize the hw strip bitmap*/ + memset(hwstrip, 0, sizeof(*hwstrip)); + /* initialize PF if max_vfs not zero */ txgbe_pf_host_init(eth_dev); @@ -620,6 +648,335 @@ static struct rte_pci_driver rte_txgbe_pmd = { .remove = eth_txgbe_pci_remove, }; +static int +txgbe_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_vfta *shadow_vfta = TXGBE_DEV_VFTA(dev); + uint32_t vfta; + uint32_t vid_idx; + uint32_t vid_bit; + + vid_idx = (uint32_t)((vlan_id >> 5) & 0x7F); + vid_bit = (uint32_t)(1 << (vlan_id & 0x1F)); + vfta = rd32(hw, TXGBE_VLANTBL(vid_idx)); + if (on) + vfta |= vid_bit; + else + vfta &= ~vid_bit; + wr32(hw, TXGBE_VLANTBL(vid_idx), vfta); + + /* update local VFTA copy */ + shadow_vfta->vfta[vid_idx] = vfta; + + return 0; +} + +static void +txgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_rx_queue *rxq; + bool restart; + uint32_t rxcfg, rxbal, rxbah; + + if (on) + txgbe_vlan_hw_strip_enable(dev, queue); + else + txgbe_vlan_hw_strip_disable(dev, queue); + + rxq = dev->data->rx_queues[queue]; + rxbal = rd32(hw, TXGBE_RXBAL(rxq->reg_idx)); + rxbah = rd32(hw, TXGBE_RXBAH(rxq->reg_idx)); + rxcfg = rd32(hw, TXGBE_RXCFG(rxq->reg_idx)); + if (rxq->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) { + restart = (rxcfg & TXGBE_RXCFG_ENA) && + !(rxcfg & TXGBE_RXCFG_VLAN); + rxcfg |= TXGBE_RXCFG_VLAN; + } else { + restart = (rxcfg & TXGBE_RXCFG_ENA) && + (rxcfg & TXGBE_RXCFG_VLAN); + rxcfg &= ~TXGBE_RXCFG_VLAN; + } + rxcfg &= ~TXGBE_RXCFG_ENA; + + if (restart) { + /* set vlan strip for ring */ + txgbe_dev_rx_queue_stop(dev, queue); + wr32(hw, TXGBE_RXBAL(rxq->reg_idx), rxbal); + wr32(hw, TXGBE_RXBAH(rxq->reg_idx), rxbah); + wr32(hw, TXGBE_RXCFG(rxq->reg_idx), rxcfg); + txgbe_dev_rx_queue_start(dev, queue); + } +} + +static int +txgbe_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + int ret = 0; + uint32_t portctrl, vlan_ext, qinq; + + portctrl = rd32(hw, TXGBE_PORTCTL); + + vlan_ext = (portctrl & TXGBE_PORTCTL_VLANEXT); + qinq = vlan_ext && (portctrl & TXGBE_PORTCTL_QINQ); + switch (vlan_type) { + case ETH_VLAN_TYPE_INNER: + if (vlan_ext) { + wr32m(hw, TXGBE_VLANCTL, + TXGBE_VLANCTL_TPID_MASK, + TXGBE_VLANCTL_TPID(tpid)); + wr32m(hw, TXGBE_DMATXCTRL, + TXGBE_DMATXCTRL_TPID_MASK, + TXGBE_DMATXCTRL_TPID(tpid)); + } else { + ret = -ENOTSUP; + PMD_DRV_LOG(ERR, "Inner type is not supported" + " by single VLAN"); + } + + if (qinq) { + wr32m(hw, TXGBE_TAGTPID(0), + TXGBE_TAGTPID_LSB_MASK, + TXGBE_TAGTPID_LSB(tpid)); + } + break; + case ETH_VLAN_TYPE_OUTER: + if (vlan_ext) { + /* Only the high 16-bits is valid */ + wr32m(hw, TXGBE_EXTAG, + TXGBE_EXTAG_VLAN_MASK, + TXGBE_EXTAG_VLAN(tpid)); + } else { + wr32m(hw, TXGBE_VLANCTL, + TXGBE_VLANCTL_TPID_MASK, + TXGBE_VLANCTL_TPID(tpid)); + wr32m(hw, TXGBE_DMATXCTRL, + TXGBE_DMATXCTRL_TPID_MASK, + TXGBE_DMATXCTRL_TPID(tpid)); + } + + if (qinq) { + wr32m(hw, TXGBE_TAGTPID(0), + TXGBE_TAGTPID_MSB_MASK, + TXGBE_TAGTPID_MSB(tpid)); + } + break; + default: + PMD_DRV_LOG(ERR, "Unsupported VLAN type %d", vlan_type); + return -EINVAL; + } + + return ret; +} + +void +txgbe_vlan_hw_filter_disable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t vlnctrl; + + PMD_INIT_FUNC_TRACE(); + + /* Filter Table Disable */ + vlnctrl = rd32(hw, TXGBE_VLANCTL); + vlnctrl &= ~TXGBE_VLANCTL_VFE; + wr32(hw, TXGBE_VLANCTL, vlnctrl); +} + +void +txgbe_vlan_hw_filter_enable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_vfta *shadow_vfta = TXGBE_DEV_VFTA(dev); + uint32_t vlnctrl; + uint16_t i; + + PMD_INIT_FUNC_TRACE(); + + /* Filter Table Enable */ + vlnctrl = rd32(hw, TXGBE_VLANCTL); + vlnctrl &= ~TXGBE_VLANCTL_CFIENA; + vlnctrl |= TXGBE_VLANCTL_VFE; + wr32(hw, TXGBE_VLANCTL, vlnctrl); + + /* write whatever is in local vfta copy */ + for (i = 0; i < TXGBE_VFTA_SIZE; i++) + wr32(hw, TXGBE_VLANTBL(i), shadow_vfta->vfta[i]); +} + +void +txgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on) +{ + struct txgbe_hwstrip *hwstrip = TXGBE_DEV_HWSTRIP(dev); + struct txgbe_rx_queue *rxq; + + if (queue >= TXGBE_MAX_RX_QUEUE_NUM) + return; + + if (on) + TXGBE_SET_HWSTRIP(hwstrip, queue); + else + TXGBE_CLEAR_HWSTRIP(hwstrip, queue); + + if (queue >= dev->data->nb_rx_queues) + return; + + rxq = dev->data->rx_queues[queue]; + + if (on) { + rxq->vlan_flags = PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED; + rxq->offloads |= DEV_RX_OFFLOAD_VLAN_STRIP; + } else { + rxq->vlan_flags = PKT_RX_VLAN; + rxq->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP; + } +} + +static void +txgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t ctrl; + + PMD_INIT_FUNC_TRACE(); + + ctrl = rd32(hw, TXGBE_RXCFG(queue)); + ctrl &= ~TXGBE_RXCFG_VLAN; + wr32(hw, TXGBE_RXCFG(queue), ctrl); + + /* record those setting for HW strip per queue */ + txgbe_vlan_hw_strip_bitmap_set(dev, queue, 0); +} + +static void +txgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t ctrl; + + PMD_INIT_FUNC_TRACE(); + + ctrl = rd32(hw, TXGBE_RXCFG(queue)); + ctrl |= TXGBE_RXCFG_VLAN; + wr32(hw, TXGBE_RXCFG(queue), ctrl); + + /* record those setting for HW strip per queue */ + txgbe_vlan_hw_strip_bitmap_set(dev, queue, 1); +} + +static void +txgbe_vlan_hw_extend_disable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t ctrl; + + PMD_INIT_FUNC_TRACE(); + + ctrl = rd32(hw, TXGBE_PORTCTL); + ctrl &= ~TXGBE_PORTCTL_VLANEXT; + ctrl &= ~TXGBE_PORTCTL_QINQ; + wr32(hw, TXGBE_PORTCTL, ctrl); +} + +static void +txgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; + struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode; + uint32_t ctrl; + + PMD_INIT_FUNC_TRACE(); + + ctrl = rd32(hw, TXGBE_PORTCTL); + ctrl |= TXGBE_PORTCTL_VLANEXT; + if (rxmode->offloads & DEV_RX_OFFLOAD_QINQ_STRIP || + txmode->offloads & DEV_TX_OFFLOAD_QINQ_INSERT) + ctrl |= TXGBE_PORTCTL_QINQ; + wr32(hw, TXGBE_PORTCTL, ctrl); +} + +void +txgbe_vlan_hw_strip_config(struct rte_eth_dev *dev) +{ + struct txgbe_rx_queue *rxq; + uint16_t i; + + PMD_INIT_FUNC_TRACE(); + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + + if (rxq->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) { + txgbe_vlan_strip_queue_set(dev, i, 1); + } else { + txgbe_vlan_strip_queue_set(dev, i, 0); + } + } +} + +void +txgbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev, int mask) +{ + uint16_t i; + struct rte_eth_rxmode *rxmode; + struct txgbe_rx_queue *rxq; + + if (mask & ETH_VLAN_STRIP_MASK) { + rxmode = &dev->data->dev_conf.rxmode; + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + rxq->offloads |= DEV_RX_OFFLOAD_VLAN_STRIP; + } + else + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + rxq->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP; + } + } +} + +static int +txgbe_vlan_offload_config(struct rte_eth_dev *dev, int mask) +{ + struct rte_eth_rxmode *rxmode; + rxmode = &dev->data->dev_conf.rxmode; + + if (mask & ETH_VLAN_STRIP_MASK) { + txgbe_vlan_hw_strip_config(dev); + } + + if (mask & ETH_VLAN_FILTER_MASK) { + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) + txgbe_vlan_hw_filter_enable(dev); + else + txgbe_vlan_hw_filter_disable(dev); + } + + if (mask & ETH_VLAN_EXTEND_MASK) { + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_EXTEND) + txgbe_vlan_hw_extend_enable(dev); + else + txgbe_vlan_hw_extend_disable(dev); + } + + return 0; +} + +static int +txgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask) +{ + txgbe_config_vlan_strip_on_all_queues(dev, mask); + + txgbe_vlan_offload_config(dev, mask); + + return 0; +} static int @@ -691,6 +1048,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) bool link_up = false, negotiate = 0; uint32_t speed = 0; uint32_t allowed_speeds = 0; + int mask = 0; int status; uint32_t *link_speeds; @@ -763,6 +1121,14 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; } + mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | + ETH_VLAN_EXTEND_MASK; + err = txgbe_vlan_offload_config(dev, mask); + if (err) { + PMD_INIT_LOG(ERR, "Unable to set VLAN offload"); + goto error; + } + err = txgbe_dev_rxtx_start(dev); if (err < 0) { PMD_INIT_LOG(ERR, "Unable to start rxtx queues"); @@ -2430,6 +2796,10 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = { .fw_version_get = txgbe_fw_version_get, .dev_infos_get = txgbe_dev_info_get, .dev_supported_ptypes_get = txgbe_dev_supported_ptypes_get, + .vlan_filter_set = txgbe_vlan_filter_set, + .vlan_tpid_set = txgbe_vlan_tpid_set, + .vlan_offload_set = txgbe_vlan_offload_set, + .vlan_strip_queue_set = txgbe_vlan_strip_queue_set, .rx_queue_start = txgbe_dev_rx_queue_start, .rx_queue_stop = txgbe_dev_rx_queue_stop, .tx_queue_start = txgbe_dev_tx_queue_start, diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 017d708ae..5319f42b3 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -24,8 +24,16 @@ * Defines that were not part of txgbe_type.h as they are not used by the * FreeBSD driver. */ +#define TXGBE_VFTA_SIZE 128 #define TXGBE_VLAN_TAG_SIZE 4 #define TXGBE_HKEY_MAX_INDEX 10 +/*Default value of Max Rx Queue*/ +#define TXGBE_MAX_RX_QUEUE_NUM 128 + +#ifndef NBBY +#define NBBY 8 /* number of bits in a byte */ +#endif +#define TXGBE_HWSTRIP_BITMAP_SIZE (TXGBE_MAX_RX_QUEUE_NUM / (sizeof(uint32_t) * NBBY)) #define TXGBE_QUEUE_ITR_INTERVAL_DEFAULT 500 /* 500us */ @@ -61,6 +69,14 @@ struct txgbe_stat_mappings { uint32_t rqsm[TXGBE_NB_STAT_MAPPING]; }; +struct txgbe_vfta { + uint32_t vfta[TXGBE_VFTA_SIZE]; +}; + +struct txgbe_hwstrip { + uint32_t bitmap[TXGBE_HWSTRIP_BITMAP_SIZE]; +}; + struct txgbe_vf_info { uint8_t api_version; uint16_t switch_domain_id; @@ -74,6 +90,8 @@ struct txgbe_adapter { struct txgbe_hw_stats stats; struct txgbe_interrupt intr; struct txgbe_stat_mappings stat_mappings; + struct txgbe_vfta shadow_vfta; + struct txgbe_hwstrip hwstrip; struct txgbe_vf_info *vfdata; bool rx_bulk_alloc_allowed; }; @@ -102,6 +120,12 @@ int txgbe_vf_representor_uninit(struct rte_eth_dev *ethdev); #define TXGBE_DEV_STAT_MAPPINGS(dev) \ (&((struct txgbe_adapter *)(dev)->data->dev_private)->stat_mappings) +#define TXGBE_DEV_VFTA(dev) \ + (&((struct txgbe_adapter *)(dev)->data->dev_private)->shadow_vfta) + +#define TXGBE_DEV_HWSTRIP(dev) \ + (&((struct txgbe_adapter *)(dev)->data->dev_private)->hwstrip) + #define TXGBE_DEV_VFDATA(dev) \ (&((struct txgbe_adapter *)(dev)->data->dev_private)->vfdata) @@ -229,4 +253,12 @@ void txgbe_dev_setup_link_alarm_handler(void *param); void txgbe_read_stats_registers(struct txgbe_hw *hw, struct txgbe_hw_stats *hw_stats); +void txgbe_vlan_hw_filter_enable(struct rte_eth_dev *dev); +void txgbe_vlan_hw_filter_disable(struct rte_eth_dev *dev); +void txgbe_vlan_hw_strip_config(struct rte_eth_dev *dev); +void txgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, + uint16_t queue, bool on); +void txgbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev, + int mask); + #endif /* _TXGBE_ETHDEV_H_ */ -- 2.18.4