diff options
Diffstat (limited to 'src/dpdk22/drivers/net/fm10k/fm10k_ethdev.c')
-rw-r--r-- | src/dpdk22/drivers/net/fm10k/fm10k_ethdev.c | 2780 |
1 files changed, 0 insertions, 2780 deletions
diff --git a/src/dpdk22/drivers/net/fm10k/fm10k_ethdev.c b/src/dpdk22/drivers/net/fm10k/fm10k_ethdev.c deleted file mode 100644 index e4aed94b..00000000 --- a/src/dpdk22/drivers/net/fm10k/fm10k_ethdev.c +++ /dev/null @@ -1,2780 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memzone.h> -#include <rte_string_fns.h> -#include <rte_dev.h> -#include <rte_spinlock.h> - -#include "fm10k.h" -#include "base/fm10k_api.h" - -/* Default delay to acquire mailbox lock */ -#define FM10K_MBXLOCK_DELAY_US 20 -#define UINT64_LOWER_32BITS_MASK 0x00000000ffffffffULL - -#define MAIN_VSI_POOL_NUMBER 0 - -/* Max try times to acquire switch status */ -#define MAX_QUERY_SWITCH_STATE_TIMES 10 -/* Wait interval to get switch status */ -#define WAIT_SWITCH_MSG_US 100000 -/* Number of chars per uint32 type */ -#define CHARS_PER_UINT32 (sizeof(uint32_t)) -#define BIT_MASK_PER_UINT32 ((1 << CHARS_PER_UINT32) - 1) - -static void fm10k_close_mbx_service(struct fm10k_hw *hw); -static void fm10k_dev_promiscuous_enable(struct rte_eth_dev *dev); -static void fm10k_dev_promiscuous_disable(struct rte_eth_dev *dev); -static void fm10k_dev_allmulticast_enable(struct rte_eth_dev *dev); -static void fm10k_dev_allmulticast_disable(struct rte_eth_dev *dev); -static inline int fm10k_glort_valid(struct fm10k_hw *hw); -static int -fm10k_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); -static void fm10k_MAC_filter_set(struct rte_eth_dev *dev, - const u8 *mac, bool add, uint32_t pool); -static void fm10k_tx_queue_release(void *queue); -static void fm10k_rx_queue_release(void *queue); -static void fm10k_set_rx_function(struct rte_eth_dev *dev); -static void fm10k_set_tx_function(struct rte_eth_dev *dev); - -struct fm10k_xstats_name_off { - char name[RTE_ETH_XSTATS_NAME_SIZE]; - unsigned offset; -}; - -struct fm10k_xstats_name_off fm10k_hw_stats_strings[] = { - {"completion_timeout_count", offsetof(struct fm10k_hw_stats, timeout)}, - {"unsupported_requests_count", offsetof(struct fm10k_hw_stats, ur)}, - {"completer_abort_count", offsetof(struct fm10k_hw_stats, ca)}, - {"unsupported_message_count", offsetof(struct fm10k_hw_stats, um)}, - {"checksum_error_count", offsetof(struct fm10k_hw_stats, xec)}, - {"vlan_dropped", offsetof(struct fm10k_hw_stats, vlan_drop)}, - {"loopback_dropped", offsetof(struct fm10k_hw_stats, loopback_drop)}, - {"rx_mbuf_allocation_errors", offsetof(struct fm10k_hw_stats, - nodesc_drop)}, -}; - -#define FM10K_NB_HW_XSTATS (sizeof(fm10k_hw_stats_strings) / \ - sizeof(fm10k_hw_stats_strings[0])) - -struct fm10k_xstats_name_off fm10k_hw_stats_rx_q_strings[] = { - {"packets", offsetof(struct fm10k_hw_stats_q, rx_packets)}, - {"bytes", offsetof(struct fm10k_hw_stats_q, rx_bytes)}, - {"dropped", offsetof(struct fm10k_hw_stats_q, rx_drops)}, -}; - -#define FM10K_NB_RX_Q_XSTATS (sizeof(fm10k_hw_stats_rx_q_strings) / \ - sizeof(fm10k_hw_stats_rx_q_strings[0])) - -struct fm10k_xstats_name_off fm10k_hw_stats_tx_q_strings[] = { - {"packets", offsetof(struct fm10k_hw_stats_q, tx_packets)}, - {"bytes", offsetof(struct fm10k_hw_stats_q, tx_bytes)}, -}; - -#define FM10K_NB_TX_Q_XSTATS (sizeof(fm10k_hw_stats_tx_q_strings) / \ - sizeof(fm10k_hw_stats_tx_q_strings[0])) - -#define FM10K_NB_XSTATS (FM10K_NB_HW_XSTATS + FM10K_MAX_QUEUES_PF * \ - (FM10K_NB_RX_Q_XSTATS + FM10K_NB_TX_Q_XSTATS)) - -static void -fm10k_mbx_initlock(struct fm10k_hw *hw) -{ - rte_spinlock_init(FM10K_DEV_PRIVATE_TO_MBXLOCK(hw->back)); -} - -static void -fm10k_mbx_lock(struct fm10k_hw *hw) -{ - while (!rte_spinlock_trylock(FM10K_DEV_PRIVATE_TO_MBXLOCK(hw->back))) - rte_delay_us(FM10K_MBXLOCK_DELAY_US); -} - -static void -fm10k_mbx_unlock(struct fm10k_hw *hw) -{ - rte_spinlock_unlock(FM10K_DEV_PRIVATE_TO_MBXLOCK(hw->back)); -} - -/* Stubs needed for linkage when vPMD is disabled */ -int __attribute__((weak)) -fm10k_rx_vec_condition_check(__rte_unused struct rte_eth_dev *dev) -{ - return -1; -} - -uint16_t __attribute__((weak)) -fm10k_recv_pkts_vec( - __rte_unused void *rx_queue, - __rte_unused struct rte_mbuf **rx_pkts, - __rte_unused uint16_t nb_pkts) -{ - return 0; -} - -uint16_t __attribute__((weak)) -fm10k_recv_scattered_pkts_vec( - __rte_unused void *rx_queue, - __rte_unused struct rte_mbuf **rx_pkts, - __rte_unused uint16_t nb_pkts) -{ - return 0; -} - -int __attribute__((weak)) -fm10k_rxq_vec_setup(__rte_unused struct fm10k_rx_queue *rxq) - -{ - return -1; -} - -void __attribute__((weak)) -fm10k_rx_queue_release_mbufs_vec( - __rte_unused struct fm10k_rx_queue *rxq) -{ - return; -} - -void __attribute__((weak)) -fm10k_txq_vec_setup(__rte_unused struct fm10k_tx_queue *txq) -{ - return; -} - -int __attribute__((weak)) -fm10k_tx_vec_condition_check(__rte_unused struct fm10k_tx_queue *txq) -{ - return -1; -} - -uint16_t __attribute__((weak)) -fm10k_xmit_pkts_vec(__rte_unused void *tx_queue, - __rte_unused struct rte_mbuf **tx_pkts, - __rte_unused uint16_t nb_pkts) -{ - return 0; -} - -/* - * reset queue to initial state, allocate software buffers used when starting - * device. - * return 0 on success - * return -ENOMEM if buffers cannot be allocated - * return -EINVAL if buffers do not satisfy alignment condition - */ -static inline int -rx_queue_reset(struct fm10k_rx_queue *q) -{ - static const union fm10k_rx_desc zero = {{0} }; - uint64_t dma_addr; - int i, diag; - PMD_INIT_FUNC_TRACE(); - - diag = rte_mempool_get_bulk(q->mp, (void **)q->sw_ring, q->nb_desc); - if (diag != 0) - return -ENOMEM; - - for (i = 0; i < q->nb_desc; ++i) { - fm10k_pktmbuf_reset(q->sw_ring[i], q->port_id); - if (!fm10k_addr_alignment_valid(q->sw_ring[i])) { - rte_mempool_put_bulk(q->mp, (void **)q->sw_ring, - q->nb_desc); - return -EINVAL; - } - dma_addr = MBUF_DMA_ADDR_DEFAULT(q->sw_ring[i]); - q->hw_ring[i].q.pkt_addr = dma_addr; - q->hw_ring[i].q.hdr_addr = dma_addr; - } - - /* initialize extra software ring entries. Space for these extra - * entries is always allocated. - */ - memset(&q->fake_mbuf, 0x0, sizeof(q->fake_mbuf)); - for (i = 0; i < q->nb_fake_desc; ++i) { - q->sw_ring[q->nb_desc + i] = &q->fake_mbuf; - q->hw_ring[q->nb_desc + i] = zero; - } - - q->next_dd = 0; - q->next_alloc = 0; - q->next_trigger = q->alloc_thresh - 1; - FM10K_PCI_REG_WRITE(q->tail_ptr, q->nb_desc - 1); - q->rxrearm_start = 0; - q->rxrearm_nb = 0; - - return 0; -} - -/* - * clean queue, descriptor rings, free software buffers used when stopping - * device. - */ -static inline void -rx_queue_clean(struct fm10k_rx_queue *q) -{ - union fm10k_rx_desc zero = {.q = {0, 0, 0, 0} }; - uint32_t i; - PMD_INIT_FUNC_TRACE(); - - /* zero descriptor rings */ - for (i = 0; i < q->nb_desc; ++i) - q->hw_ring[i] = zero; - - /* zero faked descriptors */ - for (i = 0; i < q->nb_fake_desc; ++i) - q->hw_ring[q->nb_desc + i] = zero; - - /* vPMD driver has a different way of releasing mbufs. */ - if (q->rx_using_sse) { - fm10k_rx_queue_release_mbufs_vec(q); - return; - } - - /* free software buffers */ - for (i = 0; i < q->nb_desc; ++i) { - if (q->sw_ring[i]) { - rte_pktmbuf_free_seg(q->sw_ring[i]); - q->sw_ring[i] = NULL; - } - } -} - -/* - * free all queue memory used when releasing the queue (i.e. configure) - */ -static inline void -rx_queue_free(struct fm10k_rx_queue *q) -{ - PMD_INIT_FUNC_TRACE(); - if (q) { - PMD_INIT_LOG(DEBUG, "Freeing rx queue %p", q); - rx_queue_clean(q); - if (q->sw_ring) { - rte_free(q->sw_ring); - q->sw_ring = NULL; - } - rte_free(q); - q = NULL; - } -} - -/* - * disable RX queue, wait unitl HW finished necessary flush operation - */ -static inline int -rx_queue_disable(struct fm10k_hw *hw, uint16_t qnum) -{ - uint32_t reg, i; - - reg = FM10K_READ_REG(hw, FM10K_RXQCTL(qnum)); - FM10K_WRITE_REG(hw, FM10K_RXQCTL(qnum), - reg & ~FM10K_RXQCTL_ENABLE); - - /* Wait 100us at most */ - for (i = 0; i < FM10K_QUEUE_DISABLE_TIMEOUT; i++) { - rte_delay_us(1); - reg = FM10K_READ_REG(hw, FM10K_RXQCTL(qnum)); - if (!(reg & FM10K_RXQCTL_ENABLE)) - break; - } - - if (i == FM10K_QUEUE_DISABLE_TIMEOUT) - return -1; - - return 0; -} - -/* - * reset queue to initial state, allocate software buffers used when starting - * device - */ -static inline void -tx_queue_reset(struct fm10k_tx_queue *q) -{ - PMD_INIT_FUNC_TRACE(); - q->last_free = 0; - q->next_free = 0; - q->nb_used = 0; - q->nb_free = q->nb_desc - 1; - fifo_reset(&q->rs_tracker, (q->nb_desc + 1) / q->rs_thresh); - FM10K_PCI_REG_WRITE(q->tail_ptr, 0); -} - -/* - * clean queue, descriptor rings, free software buffers used when stopping - * device - */ -static inline void -tx_queue_clean(struct fm10k_tx_queue *q) -{ - struct fm10k_tx_desc zero = {0, 0, 0, 0, 0, 0}; - uint32_t i; - PMD_INIT_FUNC_TRACE(); - - /* zero descriptor rings */ - for (i = 0; i < q->nb_desc; ++i) - q->hw_ring[i] = zero; - - /* free software buffers */ - for (i = 0; i < q->nb_desc; ++i) { - if (q->sw_ring[i]) { - rte_pktmbuf_free_seg(q->sw_ring[i]); - q->sw_ring[i] = NULL; - } - } -} - -/* - * free all queue memory used when releasing the queue (i.e. configure) - */ -static inline void -tx_queue_free(struct fm10k_tx_queue *q) -{ - PMD_INIT_FUNC_TRACE(); - if (q) { - PMD_INIT_LOG(DEBUG, "Freeing tx queue %p", q); - tx_queue_clean(q); - if (q->rs_tracker.list) { - rte_free(q->rs_tracker.list); - q->rs_tracker.list = NULL; - } - if (q->sw_ring) { - rte_free(q->sw_ring); - q->sw_ring = NULL; - } - rte_free(q); - q = NULL; - } -} - -/* - * disable TX queue, wait unitl HW finished necessary flush operation - */ -static inline int -tx_queue_disable(struct fm10k_hw *hw, uint16_t qnum) -{ - uint32_t reg, i; - - reg = FM10K_READ_REG(hw, FM10K_TXDCTL(qnum)); - FM10K_WRITE_REG(hw, FM10K_TXDCTL(qnum), - reg & ~FM10K_TXDCTL_ENABLE); - - /* Wait 100us at most */ - for (i = 0; i < FM10K_QUEUE_DISABLE_TIMEOUT; i++) { - rte_delay_us(1); - reg = FM10K_READ_REG(hw, FM10K_TXDCTL(qnum)); - if (!(reg & FM10K_TXDCTL_ENABLE)) - break; - } - - if (i == FM10K_QUEUE_DISABLE_TIMEOUT) - return -1; - - return 0; -} - -static int -fm10k_check_mq_mode(struct rte_eth_dev *dev) -{ - enum rte_eth_rx_mq_mode rx_mq_mode = dev->data->dev_conf.rxmode.mq_mode; - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct rte_eth_vmdq_rx_conf *vmdq_conf; - uint16_t nb_rx_q = dev->data->nb_rx_queues; - - vmdq_conf = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; - - if (rx_mq_mode & ETH_MQ_RX_DCB_FLAG) { - PMD_INIT_LOG(ERR, "DCB mode is not supported."); - return -EINVAL; - } - - if (!(rx_mq_mode & ETH_MQ_RX_VMDQ_FLAG)) - return 0; - - if (hw->mac.type == fm10k_mac_vf) { - PMD_INIT_LOG(ERR, "VMDQ mode is not supported in VF."); - return -EINVAL; - } - - /* Check VMDQ queue pool number */ - if (vmdq_conf->nb_queue_pools > - sizeof(vmdq_conf->pool_map[0].pools) * CHAR_BIT || - vmdq_conf->nb_queue_pools > nb_rx_q) { - PMD_INIT_LOG(ERR, "Too many of queue pools: %d", - vmdq_conf->nb_queue_pools); - return -EINVAL; - } - - return 0; -} - -static const struct fm10k_txq_ops def_txq_ops = { - .reset = tx_queue_reset, -}; - -static int -fm10k_dev_configure(struct rte_eth_dev *dev) -{ - int ret; - - PMD_INIT_FUNC_TRACE(); - - if (dev->data->dev_conf.rxmode.hw_strip_crc == 0) - PMD_INIT_LOG(WARNING, "fm10k always strip CRC"); - /* multipe queue mode checking */ - ret = fm10k_check_mq_mode(dev); - if (ret != 0) { - PMD_DRV_LOG(ERR, "fm10k_check_mq_mode fails with %d.", - ret); - return ret; - } - - return 0; -} - -/* fls = find last set bit = 32 minus the number of leading zeros */ -#ifndef fls -#define fls(x) (((x) == 0) ? 0 : (32 - __builtin_clz((x)))) -#endif - -static void -fm10k_dev_vmdq_rx_configure(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct rte_eth_vmdq_rx_conf *vmdq_conf; - uint32_t i; - - vmdq_conf = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; - - for (i = 0; i < vmdq_conf->nb_pool_maps; i++) { - if (!vmdq_conf->pool_map[i].pools) - continue; - fm10k_mbx_lock(hw); - fm10k_update_vlan(hw, vmdq_conf->pool_map[i].vlan_id, 0, true); - fm10k_mbx_unlock(hw); - } -} - -static void -fm10k_dev_pf_main_vsi_reset(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - - /* Add default mac address */ - fm10k_MAC_filter_set(dev, hw->mac.addr, true, - MAIN_VSI_POOL_NUMBER); -} - -static void -fm10k_dev_rss_configure(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct rte_eth_conf *dev_conf = &dev->data->dev_conf; - uint32_t mrqc, *key, i, reta, j; - uint64_t hf; - -#define RSS_KEY_SIZE 40 - static uint8_t rss_intel_key[RSS_KEY_SIZE] = { - 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, - 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, - 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, - 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, - 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA, - }; - - if (dev->data->nb_rx_queues == 1 || - dev_conf->rxmode.mq_mode != ETH_MQ_RX_RSS || - dev_conf->rx_adv_conf.rss_conf.rss_hf == 0) - return; - - /* random key is rss_intel_key (default) or user provided (rss_key) */ - if (dev_conf->rx_adv_conf.rss_conf.rss_key == NULL) - key = (uint32_t *)rss_intel_key; - else - key = (uint32_t *)dev_conf->rx_adv_conf.rss_conf.rss_key; - - /* Now fill our hash function seeds, 4 bytes at a time */ - for (i = 0; i < RSS_KEY_SIZE / sizeof(*key); ++i) - FM10K_WRITE_REG(hw, FM10K_RSSRK(0, i), key[i]); - - /* - * Fill in redirection table - * The byte-swap is needed because NIC registers are in - * little-endian order. - */ - reta = 0; - for (i = 0, j = 0; i < FM10K_MAX_RSS_INDICES; i++, j++) { - if (j == dev->data->nb_rx_queues) - j = 0; - reta = (reta << CHAR_BIT) | j; - if ((i & 3) == 3) - FM10K_WRITE_REG(hw, FM10K_RETA(0, i >> 2), - rte_bswap32(reta)); - } - - /* - * Generate RSS hash based on packet types, TCP/UDP - * port numbers and/or IPv4/v6 src and dst addresses - */ - hf = dev_conf->rx_adv_conf.rss_conf.rss_hf; - mrqc = 0; - mrqc |= (hf & ETH_RSS_IPV4) ? FM10K_MRQC_IPV4 : 0; - mrqc |= (hf & ETH_RSS_IPV6) ? FM10K_MRQC_IPV6 : 0; - mrqc |= (hf & ETH_RSS_IPV6_EX) ? FM10K_MRQC_IPV6 : 0; - mrqc |= (hf & ETH_RSS_NONFRAG_IPV4_TCP) ? FM10K_MRQC_TCP_IPV4 : 0; - mrqc |= (hf & ETH_RSS_NONFRAG_IPV6_TCP) ? FM10K_MRQC_TCP_IPV6 : 0; - mrqc |= (hf & ETH_RSS_IPV6_TCP_EX) ? FM10K_MRQC_TCP_IPV6 : 0; - mrqc |= (hf & ETH_RSS_NONFRAG_IPV4_UDP) ? FM10K_MRQC_UDP_IPV4 : 0; - mrqc |= (hf & ETH_RSS_NONFRAG_IPV6_UDP) ? FM10K_MRQC_UDP_IPV6 : 0; - mrqc |= (hf & ETH_RSS_IPV6_UDP_EX) ? FM10K_MRQC_UDP_IPV6 : 0; - - if (mrqc == 0) { - PMD_INIT_LOG(ERR, "Specified RSS mode 0x%"PRIx64"is not" - "supported", hf); - return; - } - - FM10K_WRITE_REG(hw, FM10K_MRQC(0), mrqc); -} - -static void -fm10k_dev_logic_port_update(struct rte_eth_dev *dev, - uint16_t nb_lport_old, uint16_t nb_lport_new) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t i; - - fm10k_mbx_lock(hw); - /* Disable previous logic ports */ - if (nb_lport_old) - hw->mac.ops.update_lport_state(hw, hw->mac.dglort_map, - nb_lport_old, false); - /* Enable new logic ports */ - hw->mac.ops.update_lport_state(hw, hw->mac.dglort_map, - nb_lport_new, true); - fm10k_mbx_unlock(hw); - - for (i = 0; i < nb_lport_new; i++) { - /* Set unicast mode by default. App can change - * to other mode in other API func. - */ - fm10k_mbx_lock(hw); - hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map + i, - FM10K_XCAST_MODE_NONE); - fm10k_mbx_unlock(hw); - } -} - -static void -fm10k_dev_mq_rx_configure(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct rte_eth_vmdq_rx_conf *vmdq_conf; - struct rte_eth_conf *dev_conf = &dev->data->dev_conf; - struct fm10k_macvlan_filter_info *macvlan; - uint16_t nb_queue_pools = 0; /* pool number in configuration */ - uint16_t nb_lport_new, nb_lport_old; - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - vmdq_conf = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; - - fm10k_dev_rss_configure(dev); - - /* only PF supports VMDQ */ - if (hw->mac.type != fm10k_mac_pf) - return; - - if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG) - nb_queue_pools = vmdq_conf->nb_queue_pools; - - /* no pool number change, no need to update logic port and VLAN/MAC */ - if (macvlan->nb_queue_pools == nb_queue_pools) - return; - - nb_lport_old = macvlan->nb_queue_pools ? macvlan->nb_queue_pools : 1; - nb_lport_new = nb_queue_pools ? nb_queue_pools : 1; - fm10k_dev_logic_port_update(dev, nb_lport_old, nb_lport_new); - - /* reset MAC/VLAN as it's based on VMDQ or PF main VSI */ - memset(dev->data->mac_addrs, 0, - ETHER_ADDR_LEN * FM10K_MAX_MACADDR_NUM); - ether_addr_copy((const struct ether_addr *)hw->mac.addr, - &dev->data->mac_addrs[0]); - memset(macvlan, 0, sizeof(*macvlan)); - macvlan->nb_queue_pools = nb_queue_pools; - - if (nb_queue_pools) - fm10k_dev_vmdq_rx_configure(dev); - else - fm10k_dev_pf_main_vsi_reset(dev); -} - -static int -fm10k_dev_tx_init(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int i, ret; - struct fm10k_tx_queue *txq; - uint64_t base_addr; - uint32_t size; - - /* Disable TXINT to avoid possible interrupt */ - for (i = 0; i < hw->mac.max_queues; i++) - FM10K_WRITE_REG(hw, FM10K_TXINT(i), - 3 << FM10K_TXINT_TIMER_SHIFT); - - /* Setup TX queue */ - for (i = 0; i < dev->data->nb_tx_queues; ++i) { - txq = dev->data->tx_queues[i]; - base_addr = txq->hw_ring_phys_addr; - size = txq->nb_desc * sizeof(struct fm10k_tx_desc); - - /* disable queue to avoid issues while updating state */ - ret = tx_queue_disable(hw, i); - if (ret) { - PMD_INIT_LOG(ERR, "failed to disable queue %d", i); - return -1; - } - - /* set location and size for descriptor ring */ - FM10K_WRITE_REG(hw, FM10K_TDBAL(i), - base_addr & UINT64_LOWER_32BITS_MASK); - FM10K_WRITE_REG(hw, FM10K_TDBAH(i), - base_addr >> (CHAR_BIT * sizeof(uint32_t))); - FM10K_WRITE_REG(hw, FM10K_TDLEN(i), size); - } - - /* set up vector or scalar TX function as appropriate */ - fm10k_set_tx_function(dev); - - return 0; -} - -static int -fm10k_dev_rx_init(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int i, ret; - struct fm10k_rx_queue *rxq; - uint64_t base_addr; - uint32_t size; - uint32_t rxdctl = FM10K_RXDCTL_WRITE_BACK_MIN_DELAY; - uint16_t buf_size; - - /* Disable RXINT to avoid possible interrupt */ - for (i = 0; i < hw->mac.max_queues; i++) - FM10K_WRITE_REG(hw, FM10K_RXINT(i), - 3 << FM10K_RXINT_TIMER_SHIFT); - - /* Setup RX queues */ - for (i = 0; i < dev->data->nb_rx_queues; ++i) { - rxq = dev->data->rx_queues[i]; - base_addr = rxq->hw_ring_phys_addr; - size = rxq->nb_desc * sizeof(union fm10k_rx_desc); - - /* disable queue to avoid issues while updating state */ - ret = rx_queue_disable(hw, i); - if (ret) { - PMD_INIT_LOG(ERR, "failed to disable queue %d", i); - return -1; - } - - /* Setup the Base and Length of the Rx Descriptor Ring */ - FM10K_WRITE_REG(hw, FM10K_RDBAL(i), - base_addr & UINT64_LOWER_32BITS_MASK); - FM10K_WRITE_REG(hw, FM10K_RDBAH(i), - base_addr >> (CHAR_BIT * sizeof(uint32_t))); - FM10K_WRITE_REG(hw, FM10K_RDLEN(i), size); - - /* Configure the Rx buffer size for one buff without split */ - buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mp) - - RTE_PKTMBUF_HEADROOM); - /* As RX buffer is aligned to 512B within mbuf, some bytes are - * reserved for this purpose, and the worst case could be 511B. - * But SRR reg assumes all buffers have the same size. In order - * to fill the gap, we'll have to consider the worst case and - * assume 512B is reserved. If we don't do so, it's possible - * for HW to overwrite data to next mbuf. - */ - buf_size -= FM10K_RX_DATABUF_ALIGN; - - FM10K_WRITE_REG(hw, FM10K_SRRCTL(i), - buf_size >> FM10K_SRRCTL_BSIZEPKT_SHIFT); - - /* It adds dual VLAN length for supporting dual VLAN */ - if ((dev->data->dev_conf.rxmode.max_rx_pkt_len + - 2 * FM10K_VLAN_TAG_SIZE) > buf_size || - dev->data->dev_conf.rxmode.enable_scatter) { - uint32_t reg; - dev->data->scattered_rx = 1; - reg = FM10K_READ_REG(hw, FM10K_SRRCTL(i)); - reg |= FM10K_SRRCTL_BUFFER_CHAINING_EN; - FM10K_WRITE_REG(hw, FM10K_SRRCTL(i), reg); - } - - /* Enable drop on empty, it's RO for VF */ - if (hw->mac.type == fm10k_mac_pf && rxq->drop_en) - rxdctl |= FM10K_RXDCTL_DROP_ON_EMPTY; - - FM10K_WRITE_REG(hw, FM10K_RXDCTL(i), rxdctl); - FM10K_WRITE_FLUSH(hw); - } - - /* Configure VMDQ/RSS if applicable */ - fm10k_dev_mq_rx_configure(dev); - - /* Decide the best RX function */ - fm10k_set_rx_function(dev); - - return 0; -} - -static int -fm10k_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int err = -1; - uint32_t reg; - struct fm10k_rx_queue *rxq; - - PMD_INIT_FUNC_TRACE(); - - if (rx_queue_id < dev->data->nb_rx_queues) { - rxq = dev->data->rx_queues[rx_queue_id]; - err = rx_queue_reset(rxq); - if (err == -ENOMEM) { - PMD_INIT_LOG(ERR, "Failed to alloc memory : %d", err); - return err; - } else if (err == -EINVAL) { - PMD_INIT_LOG(ERR, "Invalid buffer address alignment :" - " %d", err); - return err; - } - - /* Setup the HW Rx Head and Tail Descriptor Pointers - * Note: this must be done AFTER the queue is enabled on real - * hardware, but BEFORE the queue is enabled when using the - * emulation platform. Do it in both places for now and remove - * this comment and the following two register writes when the - * emulation platform is no longer being used. - */ - FM10K_WRITE_REG(hw, FM10K_RDH(rx_queue_id), 0); - FM10K_WRITE_REG(hw, FM10K_RDT(rx_queue_id), rxq->nb_desc - 1); - - /* Set PF ownership flag for PF devices */ - reg = FM10K_READ_REG(hw, FM10K_RXQCTL(rx_queue_id)); - if (hw->mac.type == fm10k_mac_pf) - reg |= FM10K_RXQCTL_PF; - reg |= FM10K_RXQCTL_ENABLE; - /* enable RX queue */ - FM10K_WRITE_REG(hw, FM10K_RXQCTL(rx_queue_id), reg); - FM10K_WRITE_FLUSH(hw); - - /* Setup the HW Rx Head and Tail Descriptor Pointers - * Note: this must be done AFTER the queue is enabled - */ - FM10K_WRITE_REG(hw, FM10K_RDH(rx_queue_id), 0); - FM10K_WRITE_REG(hw, FM10K_RDT(rx_queue_id), rxq->nb_desc - 1); - dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED; - } - - return err; -} - -static int -fm10k_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - - PMD_INIT_FUNC_TRACE(); - - if (rx_queue_id < dev->data->nb_rx_queues) { - /* Disable RX queue */ - rx_queue_disable(hw, rx_queue_id); - - /* Free mbuf and clean HW ring */ - rx_queue_clean(dev->data->rx_queues[rx_queue_id]); - dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED; - } - - return 0; -} - -static int -fm10k_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - /** @todo - this should be defined in the shared code */ -#define FM10K_TXDCTL_WRITE_BACK_MIN_DELAY 0x00010000 - uint32_t txdctl = FM10K_TXDCTL_WRITE_BACK_MIN_DELAY; - int err = 0; - - PMD_INIT_FUNC_TRACE(); - - if (tx_queue_id < dev->data->nb_tx_queues) { - struct fm10k_tx_queue *q = dev->data->tx_queues[tx_queue_id]; - - q->ops->reset(q); - - /* reset head and tail pointers */ - FM10K_WRITE_REG(hw, FM10K_TDH(tx_queue_id), 0); - FM10K_WRITE_REG(hw, FM10K_TDT(tx_queue_id), 0); - - /* enable TX queue */ - FM10K_WRITE_REG(hw, FM10K_TXDCTL(tx_queue_id), - FM10K_TXDCTL_ENABLE | txdctl); - FM10K_WRITE_FLUSH(hw); - dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED; - } else - err = -1; - - return err; -} - -static int -fm10k_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - - PMD_INIT_FUNC_TRACE(); - - if (tx_queue_id < dev->data->nb_tx_queues) { - tx_queue_disable(hw, tx_queue_id); - tx_queue_clean(dev->data->tx_queues[tx_queue_id]); - dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED; - } - - return 0; -} - -static inline int fm10k_glort_valid(struct fm10k_hw *hw) -{ - return ((hw->mac.dglort_map & FM10K_DGLORTMAP_NONE) - != FM10K_DGLORTMAP_NONE); -} - -static void -fm10k_dev_promiscuous_enable(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int status; - - PMD_INIT_FUNC_TRACE(); - - /* Return if it didn't acquire valid glort range */ - if (!fm10k_glort_valid(hw)) - return; - - fm10k_mbx_lock(hw); - status = hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, - FM10K_XCAST_MODE_PROMISC); - fm10k_mbx_unlock(hw); - - if (status != FM10K_SUCCESS) - PMD_INIT_LOG(ERR, "Failed to enable promiscuous mode"); -} - -static void -fm10k_dev_promiscuous_disable(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint8_t mode; - int status; - - PMD_INIT_FUNC_TRACE(); - - /* Return if it didn't acquire valid glort range */ - if (!fm10k_glort_valid(hw)) - return; - - if (dev->data->all_multicast == 1) - mode = FM10K_XCAST_MODE_ALLMULTI; - else - mode = FM10K_XCAST_MODE_NONE; - - fm10k_mbx_lock(hw); - status = hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, - mode); - fm10k_mbx_unlock(hw); - - if (status != FM10K_SUCCESS) - PMD_INIT_LOG(ERR, "Failed to disable promiscuous mode"); -} - -static void -fm10k_dev_allmulticast_enable(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int status; - - PMD_INIT_FUNC_TRACE(); - - /* Return if it didn't acquire valid glort range */ - if (!fm10k_glort_valid(hw)) - return; - - /* If promiscuous mode is enabled, it doesn't make sense to enable - * allmulticast and disable promiscuous since fm10k only can select - * one of the modes. - */ - if (dev->data->promiscuous) { - PMD_INIT_LOG(INFO, "Promiscuous mode is enabled, "\ - "needn't enable allmulticast"); - return; - } - - fm10k_mbx_lock(hw); - status = hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, - FM10K_XCAST_MODE_ALLMULTI); - fm10k_mbx_unlock(hw); - - if (status != FM10K_SUCCESS) - PMD_INIT_LOG(ERR, "Failed to enable allmulticast mode"); -} - -static void -fm10k_dev_allmulticast_disable(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int status; - - PMD_INIT_FUNC_TRACE(); - - /* Return if it didn't acquire valid glort range */ - if (!fm10k_glort_valid(hw)) - return; - - if (dev->data->promiscuous) { - PMD_INIT_LOG(ERR, "Failed to disable allmulticast mode "\ - "since promisc mode is enabled"); - return; - } - - fm10k_mbx_lock(hw); - /* Change mode to unicast mode */ - status = hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, - FM10K_XCAST_MODE_NONE); - fm10k_mbx_unlock(hw); - - if (status != FM10K_SUCCESS) - PMD_INIT_LOG(ERR, "Failed to disable allmulticast mode"); -} - -static void -fm10k_dev_dglort_map_configure(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t dglortdec, pool_len, rss_len, i; - uint16_t nb_queue_pools; - struct fm10k_macvlan_filter_info *macvlan; - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - nb_queue_pools = macvlan->nb_queue_pools; - pool_len = nb_queue_pools ? fls(nb_queue_pools - 1) : 0; - rss_len = fls(dev->data->nb_rx_queues - 1) - pool_len; - dglortdec = (rss_len << FM10K_DGLORTDEC_RSSLENGTH_SHIFT) | pool_len; - - /* Establish only MAP 0 as valid */ - FM10K_WRITE_REG(hw, FM10K_DGLORTMAP(0), FM10K_DGLORTMAP_ANY); - - /* Configure VMDQ/RSS DGlort Decoder */ - FM10K_WRITE_REG(hw, FM10K_DGLORTDEC(0), dglortdec); - - /* Invalidate all other GLORT entries */ - for (i = 1; i < FM10K_DGLORT_COUNT; i++) - FM10K_WRITE_REG(hw, FM10K_DGLORTMAP(i), - FM10K_DGLORTMAP_NONE); -} - -#define BSIZEPKT_ROUNDUP ((1 << FM10K_SRRCTL_BSIZEPKT_SHIFT) - 1) -static int -fm10k_dev_start(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int i, diag; - - PMD_INIT_FUNC_TRACE(); - - /* stop, init, then start the hw */ - diag = fm10k_stop_hw(hw); - if (diag != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "Hardware stop failed: %d", diag); - return -EIO; - } - - diag = fm10k_init_hw(hw); - if (diag != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "Hardware init failed: %d", diag); - return -EIO; - } - - diag = fm10k_start_hw(hw); - if (diag != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "Hardware start failed: %d", diag); - return -EIO; - } - - diag = fm10k_dev_tx_init(dev); - if (diag) { - PMD_INIT_LOG(ERR, "TX init failed: %d", diag); - return diag; - } - - diag = fm10k_dev_rx_init(dev); - if (diag) { - PMD_INIT_LOG(ERR, "RX init failed: %d", diag); - return diag; - } - - if (hw->mac.type == fm10k_mac_pf) - fm10k_dev_dglort_map_configure(dev); - - for (i = 0; i < dev->data->nb_rx_queues; i++) { - struct fm10k_rx_queue *rxq; - rxq = dev->data->rx_queues[i]; - - if (rxq->rx_deferred_start) - continue; - diag = fm10k_dev_rx_queue_start(dev, i); - if (diag != 0) { - int j; - for (j = 0; j < i; ++j) - rx_queue_clean(dev->data->rx_queues[j]); - return diag; - } - } - - for (i = 0; i < dev->data->nb_tx_queues; i++) { - struct fm10k_tx_queue *txq; - txq = dev->data->tx_queues[i]; - - if (txq->tx_deferred_start) - continue; - diag = fm10k_dev_tx_queue_start(dev, i); - if (diag != 0) { - int j; - for (j = 0; j < i; ++j) - tx_queue_clean(dev->data->tx_queues[j]); - for (j = 0; j < dev->data->nb_rx_queues; ++j) - rx_queue_clean(dev->data->rx_queues[j]); - return diag; - } - } - - /* Update default vlan when not in VMDQ mode */ - if (!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG)) - fm10k_vlan_filter_set(dev, hw->mac.default_vid, true); - - return 0; -} - -static void -fm10k_dev_stop(struct rte_eth_dev *dev) -{ - int i; - - PMD_INIT_FUNC_TRACE(); - - if (dev->data->tx_queues) - for (i = 0; i < dev->data->nb_tx_queues; i++) - fm10k_dev_tx_queue_stop(dev, i); - - if (dev->data->rx_queues) - for (i = 0; i < dev->data->nb_rx_queues; i++) - fm10k_dev_rx_queue_stop(dev, i); -} - -static void -fm10k_dev_queue_release(struct rte_eth_dev *dev) -{ - int i; - - PMD_INIT_FUNC_TRACE(); - - if (dev->data->tx_queues) { - for (i = 0; i < dev->data->nb_tx_queues; i++) { - struct fm10k_tx_queue *txq = dev->data->tx_queues[i]; - - tx_queue_free(txq); - } - } - - if (dev->data->rx_queues) { - for (i = 0; i < dev->data->nb_rx_queues; i++) - fm10k_rx_queue_release(dev->data->rx_queues[i]); - } -} - -static void -fm10k_dev_close(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint16_t nb_lport; - struct fm10k_macvlan_filter_info *macvlan; - - PMD_INIT_FUNC_TRACE(); - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - nb_lport = macvlan->nb_queue_pools ? macvlan->nb_queue_pools : 1; - fm10k_mbx_lock(hw); - hw->mac.ops.update_lport_state(hw, hw->mac.dglort_map, - nb_lport, false); - fm10k_mbx_unlock(hw); - - /* Stop mailbox service first */ - fm10k_close_mbx_service(hw); - fm10k_dev_stop(dev); - fm10k_dev_queue_release(dev); - fm10k_stop_hw(hw); -} - -static int -fm10k_link_update(struct rte_eth_dev *dev, - __rte_unused int wait_to_complete) -{ - PMD_INIT_FUNC_TRACE(); - - /* The host-interface link is always up. The speed is ~50Gbps per Gen3 - * x8 PCIe interface. For now, we leave the speed undefined since there - * is no 50Gbps Ethernet. */ - dev->data->dev_link.link_speed = 0; - dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; - dev->data->dev_link.link_status = 1; - - return 0; -} - -static int -fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, - unsigned n) -{ - struct fm10k_hw_stats *hw_stats = - FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private); - unsigned i, q, count = 0; - - if (n < FM10K_NB_XSTATS) - return FM10K_NB_XSTATS; - - /* Global stats */ - for (i = 0; i < FM10K_NB_HW_XSTATS; i++) { - snprintf(xstats[count].name, sizeof(xstats[count].name), - "%s", fm10k_hw_stats_strings[count].name); - xstats[count].value = *(uint64_t *)(((char *)hw_stats) + - fm10k_hw_stats_strings[count].offset); - count++; - } - - /* PF queue stats */ - for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) { - for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) { - snprintf(xstats[count].name, sizeof(xstats[count].name), - "rx_q%u_%s", q, - fm10k_hw_stats_rx_q_strings[i].name); - xstats[count].value = - *(uint64_t *)(((char *)&hw_stats->q[q]) + - fm10k_hw_stats_rx_q_strings[i].offset); - count++; - } - for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) { - snprintf(xstats[count].name, sizeof(xstats[count].name), - "tx_q%u_%s", q, - fm10k_hw_stats_tx_q_strings[i].name); - xstats[count].value = - *(uint64_t *)(((char *)&hw_stats->q[q]) + - fm10k_hw_stats_tx_q_strings[i].offset); - count++; - } - } - - return FM10K_NB_XSTATS; -} - -static void -fm10k_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) -{ - uint64_t ipackets, opackets, ibytes, obytes; - struct fm10k_hw *hw = - FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct fm10k_hw_stats *hw_stats = - FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private); - int i; - - PMD_INIT_FUNC_TRACE(); - - fm10k_update_hw_stats(hw, hw_stats); - - ipackets = opackets = ibytes = obytes = 0; - for (i = 0; (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) && - (i < hw->mac.max_queues); ++i) { - stats->q_ipackets[i] = hw_stats->q[i].rx_packets.count; - stats->q_opackets[i] = hw_stats->q[i].tx_packets.count; - stats->q_ibytes[i] = hw_stats->q[i].rx_bytes.count; - stats->q_obytes[i] = hw_stats->q[i].tx_bytes.count; - ipackets += stats->q_ipackets[i]; - opackets += stats->q_opackets[i]; - ibytes += stats->q_ibytes[i]; - obytes += stats->q_obytes[i]; - } - stats->ipackets = ipackets; - stats->opackets = opackets; - stats->ibytes = ibytes; - stats->obytes = obytes; -} - -static void -fm10k_stats_reset(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct fm10k_hw_stats *hw_stats = - FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private); - - PMD_INIT_FUNC_TRACE(); - - memset(hw_stats, 0, sizeof(*hw_stats)); - fm10k_rebind_hw_stats(hw, hw_stats); -} - -static void -fm10k_dev_infos_get(struct rte_eth_dev *dev, - struct rte_eth_dev_info *dev_info) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - - PMD_INIT_FUNC_TRACE(); - - dev_info->min_rx_bufsize = FM10K_MIN_RX_BUF_SIZE; - dev_info->max_rx_pktlen = FM10K_MAX_PKT_SIZE; - dev_info->max_rx_queues = hw->mac.max_queues; - dev_info->max_tx_queues = hw->mac.max_queues; - dev_info->max_mac_addrs = FM10K_MAX_MACADDR_NUM; - dev_info->max_hash_mac_addrs = 0; - dev_info->max_vfs = dev->pci_dev->max_vfs; - dev_info->vmdq_pool_base = 0; - dev_info->vmdq_queue_base = 0; - dev_info->max_vmdq_pools = ETH_32_POOLS; - dev_info->vmdq_queue_num = FM10K_MAX_QUEUES_PF; - dev_info->rx_offload_capa = - DEV_RX_OFFLOAD_VLAN_STRIP | - DEV_RX_OFFLOAD_IPV4_CKSUM | - DEV_RX_OFFLOAD_UDP_CKSUM | - DEV_RX_OFFLOAD_TCP_CKSUM; - dev_info->tx_offload_capa = - DEV_TX_OFFLOAD_VLAN_INSERT | - DEV_TX_OFFLOAD_IPV4_CKSUM | - DEV_TX_OFFLOAD_UDP_CKSUM | - DEV_TX_OFFLOAD_TCP_CKSUM | - DEV_TX_OFFLOAD_TCP_TSO; - - dev_info->hash_key_size = FM10K_RSSRK_SIZE * sizeof(uint32_t); - dev_info->reta_size = FM10K_MAX_RSS_INDICES; - - dev_info->default_rxconf = (struct rte_eth_rxconf) { - .rx_thresh = { - .pthresh = FM10K_DEFAULT_RX_PTHRESH, - .hthresh = FM10K_DEFAULT_RX_HTHRESH, - .wthresh = FM10K_DEFAULT_RX_WTHRESH, - }, - .rx_free_thresh = FM10K_RX_FREE_THRESH_DEFAULT(0), - .rx_drop_en = 0, - }; - - dev_info->default_txconf = (struct rte_eth_txconf) { - .tx_thresh = { - .pthresh = FM10K_DEFAULT_TX_PTHRESH, - .hthresh = FM10K_DEFAULT_TX_HTHRESH, - .wthresh = FM10K_DEFAULT_TX_WTHRESH, - }, - .tx_free_thresh = FM10K_TX_FREE_THRESH_DEFAULT(0), - .tx_rs_thresh = FM10K_TX_RS_THRESH_DEFAULT(0), - .txq_flags = FM10K_SIMPLE_TX_FLAG, - }; - - dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { - .nb_max = FM10K_MAX_RX_DESC, - .nb_min = FM10K_MIN_RX_DESC, - .nb_align = FM10K_MULT_RX_DESC, - }; - - dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { - .nb_max = FM10K_MAX_TX_DESC, - .nb_min = FM10K_MIN_TX_DESC, - .nb_align = FM10K_MULT_TX_DESC, - }; -} - -static int -fm10k_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) -{ - s32 result; - uint16_t mac_num = 0; - uint32_t vid_idx, vid_bit, mac_index; - struct fm10k_hw *hw; - struct fm10k_macvlan_filter_info *macvlan; - struct rte_eth_dev_data *data = dev->data; - - hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - - if (macvlan->nb_queue_pools > 0) { /* VMDQ mode */ - PMD_INIT_LOG(ERR, "Cannot change VLAN filter in VMDQ mode"); - return (-EINVAL); - } - - if (vlan_id > ETH_VLAN_ID_MAX) { - PMD_INIT_LOG(ERR, "Invalid vlan_id: must be < 4096"); - return (-EINVAL); - } - - vid_idx = FM10K_VFTA_IDX(vlan_id); - vid_bit = FM10K_VFTA_BIT(vlan_id); - /* this VLAN ID is already in the VLAN filter table, return SUCCESS */ - if (on && (macvlan->vfta[vid_idx] & vid_bit)) - return 0; - /* this VLAN ID is NOT in the VLAN filter table, cannot remove */ - if (!on && !(macvlan->vfta[vid_idx] & vid_bit)) { - PMD_INIT_LOG(ERR, "Invalid vlan_id: not existing " - "in the VLAN filter table"); - return (-EINVAL); - } - - fm10k_mbx_lock(hw); - result = fm10k_update_vlan(hw, vlan_id, 0, on); - fm10k_mbx_unlock(hw); - if (result != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "VLAN update failed: %d", result); - return (-EIO); - } - - for (mac_index = 0; (mac_index < FM10K_MAX_MACADDR_NUM) && - (result == FM10K_SUCCESS); mac_index++) { - if (is_zero_ether_addr(&data->mac_addrs[mac_index])) - continue; - if (mac_num > macvlan->mac_num - 1) { - PMD_INIT_LOG(ERR, "MAC address number " - "not match"); - break; - } - fm10k_mbx_lock(hw); - result = fm10k_update_uc_addr(hw, hw->mac.dglort_map, - data->mac_addrs[mac_index].addr_bytes, - vlan_id, on, 0); - fm10k_mbx_unlock(hw); - mac_num++; - } - if (result != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "MAC address update failed: %d", result); - return (-EIO); - } - - if (on) { - macvlan->vlan_num++; - macvlan->vfta[vid_idx] |= vid_bit; - } else { - macvlan->vlan_num--; - macvlan->vfta[vid_idx] &= ~vid_bit; - } - return 0; -} - -static void -fm10k_vlan_offload_set(__rte_unused struct rte_eth_dev *dev, int mask) -{ - if (mask & ETH_VLAN_STRIP_MASK) { - if (!dev->data->dev_conf.rxmode.hw_vlan_strip) - PMD_INIT_LOG(ERR, "VLAN stripping is " - "always on in fm10k"); - } - - if (mask & ETH_VLAN_EXTEND_MASK) { - if (dev->data->dev_conf.rxmode.hw_vlan_extend) - PMD_INIT_LOG(ERR, "VLAN QinQ is not " - "supported in fm10k"); - } - - if (mask & ETH_VLAN_FILTER_MASK) { - if (!dev->data->dev_conf.rxmode.hw_vlan_filter) - PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k"); - } -} - -/* Add/Remove a MAC address, and update filters to main VSI */ -static void fm10k_MAC_filter_set_main_vsi(struct rte_eth_dev *dev, - const u8 *mac, bool add, uint32_t pool) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct fm10k_macvlan_filter_info *macvlan; - uint32_t i, j, k; - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - - if (pool != MAIN_VSI_POOL_NUMBER) { - PMD_DRV_LOG(ERR, "VMDQ not enabled, can't set " - "mac to pool %u", pool); - return; - } - for (i = 0, j = 0; j < FM10K_VFTA_SIZE; j++) { - if (!macvlan->vfta[j]) - continue; - for (k = 0; k < FM10K_UINT32_BIT_SIZE; k++) { - if (!(macvlan->vfta[j] & (1 << k))) - continue; - if (i + 1 > macvlan->vlan_num) { - PMD_INIT_LOG(ERR, "vlan number not match"); - return; - } - fm10k_mbx_lock(hw); - fm10k_update_uc_addr(hw, hw->mac.dglort_map, mac, - j * FM10K_UINT32_BIT_SIZE + k, add, 0); - fm10k_mbx_unlock(hw); - i++; - } - } -} - -/* Add/Remove a MAC address, and update filters to VMDQ */ -static void fm10k_MAC_filter_set_vmdq(struct rte_eth_dev *dev, - const u8 *mac, bool add, uint32_t pool) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct fm10k_macvlan_filter_info *macvlan; - struct rte_eth_vmdq_rx_conf *vmdq_conf; - uint32_t i; - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - vmdq_conf = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; - - if (pool > macvlan->nb_queue_pools) { - PMD_DRV_LOG(ERR, "Pool number %u invalid." - " Max pool is %u", - pool, macvlan->nb_queue_pools); - return; - } - for (i = 0; i < vmdq_conf->nb_pool_maps; i++) { - if (!(vmdq_conf->pool_map[i].pools & (1UL << pool))) - continue; - fm10k_mbx_lock(hw); - fm10k_update_uc_addr(hw, hw->mac.dglort_map + pool, mac, - vmdq_conf->pool_map[i].vlan_id, add, 0); - fm10k_mbx_unlock(hw); - } -} - -/* Add/Remove a MAC address, and update filters */ -static void fm10k_MAC_filter_set(struct rte_eth_dev *dev, - const u8 *mac, bool add, uint32_t pool) -{ - struct fm10k_macvlan_filter_info *macvlan; - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - - if (macvlan->nb_queue_pools > 0) /* VMDQ mode */ - fm10k_MAC_filter_set_vmdq(dev, mac, add, pool); - else - fm10k_MAC_filter_set_main_vsi(dev, mac, add, pool); - - if (add) - macvlan->mac_num++; - else - macvlan->mac_num--; -} - -/* Add a MAC address, and update filters */ -static void -fm10k_macaddr_add(struct rte_eth_dev *dev, - struct ether_addr *mac_addr, - uint32_t index, - uint32_t pool) -{ - struct fm10k_macvlan_filter_info *macvlan; - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - fm10k_MAC_filter_set(dev, mac_addr->addr_bytes, TRUE, pool); - macvlan->mac_vmdq_id[index] = pool; -} - -/* Remove a MAC address, and update filters */ -static void -fm10k_macaddr_remove(struct rte_eth_dev *dev, uint32_t index) -{ - struct rte_eth_dev_data *data = dev->data; - struct fm10k_macvlan_filter_info *macvlan; - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - fm10k_MAC_filter_set(dev, data->mac_addrs[index].addr_bytes, - FALSE, macvlan->mac_vmdq_id[index]); - macvlan->mac_vmdq_id[index] = 0; -} - -static inline int -check_nb_desc(uint16_t min, uint16_t max, uint16_t mult, uint16_t request) -{ - if ((request < min) || (request > max) || ((request % mult) != 0)) - return -1; - else - return 0; -} - - -static inline int -check_thresh(uint16_t min, uint16_t max, uint16_t div, uint16_t request) -{ - if ((request < min) || (request > max) || ((div % request) != 0)) - return -1; - else - return 0; -} - -static inline int -handle_rxconf(struct fm10k_rx_queue *q, const struct rte_eth_rxconf *conf) -{ - uint16_t rx_free_thresh; - - if (conf->rx_free_thresh == 0) - rx_free_thresh = FM10K_RX_FREE_THRESH_DEFAULT(q); - else - rx_free_thresh = conf->rx_free_thresh; - - /* make sure the requested threshold satisfies the constraints */ - if (check_thresh(FM10K_RX_FREE_THRESH_MIN(q), - FM10K_RX_FREE_THRESH_MAX(q), - FM10K_RX_FREE_THRESH_DIV(q), - rx_free_thresh)) { - PMD_INIT_LOG(ERR, "rx_free_thresh (%u) must be " - "less than or equal to %u, " - "greater than or equal to %u, " - "and a divisor of %u", - rx_free_thresh, FM10K_RX_FREE_THRESH_MAX(q), - FM10K_RX_FREE_THRESH_MIN(q), - FM10K_RX_FREE_THRESH_DIV(q)); - return (-EINVAL); - } - - q->alloc_thresh = rx_free_thresh; - q->drop_en = conf->rx_drop_en; - q->rx_deferred_start = conf->rx_deferred_start; - - return 0; -} - -/* - * Hardware requires specific alignment for Rx packet buffers. At - * least one of the following two conditions must be satisfied. - * 1. Address is 512B aligned - * 2. Address is 8B aligned and buffer does not cross 4K boundary. - * - * As such, the driver may need to adjust the DMA address within the - * buffer by up to 512B. - * - * return 1 if the element size is valid, otherwise return 0. - */ -static int -mempool_element_size_valid(struct rte_mempool *mp) -{ - uint32_t min_size; - - /* elt_size includes mbuf header and headroom */ - min_size = mp->elt_size - sizeof(struct rte_mbuf) - - RTE_PKTMBUF_HEADROOM; - - /* account for up to 512B of alignment */ - min_size -= FM10K_RX_DATABUF_ALIGN; - - /* sanity check for overflow */ - if (min_size > mp->elt_size) - return 0; - - /* size is valid */ - return 1; -} - -static int -fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, - uint16_t nb_desc, unsigned int socket_id, - const struct rte_eth_rxconf *conf, struct rte_mempool *mp) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct fm10k_dev_info *dev_info = FM10K_DEV_PRIVATE_TO_INFO(dev); - struct fm10k_rx_queue *q; - const struct rte_memzone *mz; - - PMD_INIT_FUNC_TRACE(); - - /* make sure the mempool element size can account for alignment. */ - if (!mempool_element_size_valid(mp)) { - PMD_INIT_LOG(ERR, "Error : Mempool element size is too small"); - return (-EINVAL); - } - - /* make sure a valid number of descriptors have been requested */ - if (check_nb_desc(FM10K_MIN_RX_DESC, FM10K_MAX_RX_DESC, - FM10K_MULT_RX_DESC, nb_desc)) { - PMD_INIT_LOG(ERR, "Number of Rx descriptors (%u) must be " - "less than or equal to %"PRIu32", " - "greater than or equal to %u, " - "and a multiple of %u", - nb_desc, (uint32_t)FM10K_MAX_RX_DESC, FM10K_MIN_RX_DESC, - FM10K_MULT_RX_DESC); - return (-EINVAL); - } - - /* - * if this queue existed already, free the associated memory. The - * queue cannot be reused in case we need to allocate memory on - * different socket than was previously used. - */ - if (dev->data->rx_queues[queue_id] != NULL) { - rx_queue_free(dev->data->rx_queues[queue_id]); - dev->data->rx_queues[queue_id] = NULL; - } - - /* allocate memory for the queue structure */ - q = rte_zmalloc_socket("fm10k", sizeof(*q), RTE_CACHE_LINE_SIZE, - socket_id); - if (q == NULL) { - PMD_INIT_LOG(ERR, "Cannot allocate queue structure"); - return (-ENOMEM); - } - - /* setup queue */ - q->mp = mp; - q->nb_desc = nb_desc; - q->nb_fake_desc = FM10K_MULT_RX_DESC; - q->port_id = dev->data->port_id; - q->queue_id = queue_id; - q->tail_ptr = (volatile uint32_t *) - &((uint32_t *)hw->hw_addr)[FM10K_RDT(queue_id)]; - if (handle_rxconf(q, conf)) - return (-EINVAL); - - /* allocate memory for the software ring */ - q->sw_ring = rte_zmalloc_socket("fm10k sw ring", - (nb_desc + q->nb_fake_desc) * sizeof(struct rte_mbuf *), - RTE_CACHE_LINE_SIZE, socket_id); - if (q->sw_ring == NULL) { - PMD_INIT_LOG(ERR, "Cannot allocate software ring"); - rte_free(q); - return (-ENOMEM); - } - - /* - * allocate memory for the hardware descriptor ring. A memzone large - * enough to hold the maximum ring size is requested to allow for - * resizing in later calls to the queue setup function. - */ - mz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_id, - FM10K_MAX_RX_RING_SZ, FM10K_ALIGN_RX_DESC, - socket_id); - if (mz == NULL) { - PMD_INIT_LOG(ERR, "Cannot allocate hardware ring"); - rte_free(q->sw_ring); - rte_free(q); - return (-ENOMEM); - } - q->hw_ring = mz->addr; - q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr); - - /* Check if number of descs satisfied Vector requirement */ - if (!rte_is_power_of_2(nb_desc)) { - PMD_INIT_LOG(DEBUG, "queue[%d] doesn't meet Vector Rx " - "preconditions - canceling the feature for " - "the whole port[%d]", - q->queue_id, q->port_id); - dev_info->rx_vec_allowed = false; - } else - fm10k_rxq_vec_setup(q); - - dev->data->rx_queues[queue_id] = q; - return 0; -} - -static void -fm10k_rx_queue_release(void *queue) -{ - PMD_INIT_FUNC_TRACE(); - - rx_queue_free(queue); -} - -static inline int -handle_txconf(struct fm10k_tx_queue *q, const struct rte_eth_txconf *conf) -{ - uint16_t tx_free_thresh; - uint16_t tx_rs_thresh; - - /* constraint MACROs require that tx_free_thresh is configured - * before tx_rs_thresh */ - if (conf->tx_free_thresh == 0) - tx_free_thresh = FM10K_TX_FREE_THRESH_DEFAULT(q); - else - tx_free_thresh = conf->tx_free_thresh; - - /* make sure the requested threshold satisfies the constraints */ - if (check_thresh(FM10K_TX_FREE_THRESH_MIN(q), - FM10K_TX_FREE_THRESH_MAX(q), - FM10K_TX_FREE_THRESH_DIV(q), - tx_free_thresh)) { - PMD_INIT_LOG(ERR, "tx_free_thresh (%u) must be " - "less than or equal to %u, " - "greater than or equal to %u, " - "and a divisor of %u", - tx_free_thresh, FM10K_TX_FREE_THRESH_MAX(q), - FM10K_TX_FREE_THRESH_MIN(q), - FM10K_TX_FREE_THRESH_DIV(q)); - return (-EINVAL); - } - - q->free_thresh = tx_free_thresh; - - if (conf->tx_rs_thresh == 0) - tx_rs_thresh = FM10K_TX_RS_THRESH_DEFAULT(q); - else - tx_rs_thresh = conf->tx_rs_thresh; - - q->tx_deferred_start = conf->tx_deferred_start; - - /* make sure the requested threshold satisfies the constraints */ - if (check_thresh(FM10K_TX_RS_THRESH_MIN(q), - FM10K_TX_RS_THRESH_MAX(q), - FM10K_TX_RS_THRESH_DIV(q), - tx_rs_thresh)) { - PMD_INIT_LOG(ERR, "tx_rs_thresh (%u) must be " - "less than or equal to %u, " - "greater than or equal to %u, " - "and a divisor of %u", - tx_rs_thresh, FM10K_TX_RS_THRESH_MAX(q), - FM10K_TX_RS_THRESH_MIN(q), - FM10K_TX_RS_THRESH_DIV(q)); - return (-EINVAL); - } - - q->rs_thresh = tx_rs_thresh; - - return 0; -} - -static int -fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, - uint16_t nb_desc, unsigned int socket_id, - const struct rte_eth_txconf *conf) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct fm10k_tx_queue *q; - const struct rte_memzone *mz; - - PMD_INIT_FUNC_TRACE(); - - /* make sure a valid number of descriptors have been requested */ - if (check_nb_desc(FM10K_MIN_TX_DESC, FM10K_MAX_TX_DESC, - FM10K_MULT_TX_DESC, nb_desc)) { - PMD_INIT_LOG(ERR, "Number of Tx descriptors (%u) must be " - "less than or equal to %"PRIu32", " - "greater than or equal to %u, " - "and a multiple of %u", - nb_desc, (uint32_t)FM10K_MAX_TX_DESC, FM10K_MIN_TX_DESC, - FM10K_MULT_TX_DESC); - return (-EINVAL); - } - - /* - * if this queue existed already, free the associated memory. The - * queue cannot be reused in case we need to allocate memory on - * different socket than was previously used. - */ - if (dev->data->tx_queues[queue_id] != NULL) { - struct fm10k_tx_queue *txq = dev->data->tx_queues[queue_id]; - - tx_queue_free(txq); - dev->data->tx_queues[queue_id] = NULL; - } - - /* allocate memory for the queue structure */ - q = rte_zmalloc_socket("fm10k", sizeof(*q), RTE_CACHE_LINE_SIZE, - socket_id); - if (q == NULL) { - PMD_INIT_LOG(ERR, "Cannot allocate queue structure"); - return (-ENOMEM); - } - - /* setup queue */ - q->nb_desc = nb_desc; - q->port_id = dev->data->port_id; - q->queue_id = queue_id; - q->txq_flags = conf->txq_flags; - q->ops = &def_txq_ops; - q->tail_ptr = (volatile uint32_t *) - &((uint32_t *)hw->hw_addr)[FM10K_TDT(queue_id)]; - if (handle_txconf(q, conf)) - return (-EINVAL); - - /* allocate memory for the software ring */ - q->sw_ring = rte_zmalloc_socket("fm10k sw ring", - nb_desc * sizeof(struct rte_mbuf *), - RTE_CACHE_LINE_SIZE, socket_id); - if (q->sw_ring == NULL) { - PMD_INIT_LOG(ERR, "Cannot allocate software ring"); - rte_free(q); - return (-ENOMEM); - } - - /* - * allocate memory for the hardware descriptor ring. A memzone large - * enough to hold the maximum ring size is requested to allow for - * resizing in later calls to the queue setup function. - */ - mz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_id, - FM10K_MAX_TX_RING_SZ, FM10K_ALIGN_TX_DESC, - socket_id); - if (mz == NULL) { - PMD_INIT_LOG(ERR, "Cannot allocate hardware ring"); - rte_free(q->sw_ring); - rte_free(q); - return (-ENOMEM); - } - q->hw_ring = mz->addr; - q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr); - - /* - * allocate memory for the RS bit tracker. Enough slots to hold the - * descriptor index for each RS bit needing to be set are required. - */ - q->rs_tracker.list = rte_zmalloc_socket("fm10k rs tracker", - ((nb_desc + 1) / q->rs_thresh) * - sizeof(uint16_t), - RTE_CACHE_LINE_SIZE, socket_id); - if (q->rs_tracker.list == NULL) { - PMD_INIT_LOG(ERR, "Cannot allocate RS bit tracker"); - rte_free(q->sw_ring); - rte_free(q); - return (-ENOMEM); - } - - dev->data->tx_queues[queue_id] = q; - return 0; -} - -static void -fm10k_tx_queue_release(void *queue) -{ - struct fm10k_tx_queue *q = queue; - PMD_INIT_FUNC_TRACE(); - - tx_queue_free(q); -} - -static int -fm10k_reta_update(struct rte_eth_dev *dev, - struct rte_eth_rss_reta_entry64 *reta_conf, - uint16_t reta_size) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint16_t i, j, idx, shift; - uint8_t mask; - uint32_t reta; - - PMD_INIT_FUNC_TRACE(); - - if (reta_size > FM10K_MAX_RSS_INDICES) { - PMD_INIT_LOG(ERR, "The size of hash lookup table configured " - "(%d) doesn't match the number hardware can supported " - "(%d)", reta_size, FM10K_MAX_RSS_INDICES); - return -EINVAL; - } - - /* - * Update Redirection Table RETA[n], n=0..31. The redirection table has - * 128-entries in 32 registers - */ - for (i = 0; i < FM10K_MAX_RSS_INDICES; i += CHARS_PER_UINT32) { - idx = i / RTE_RETA_GROUP_SIZE; - shift = i % RTE_RETA_GROUP_SIZE; - mask = (uint8_t)((reta_conf[idx].mask >> shift) & - BIT_MASK_PER_UINT32); - if (mask == 0) - continue; - - reta = 0; - if (mask != BIT_MASK_PER_UINT32) - reta = FM10K_READ_REG(hw, FM10K_RETA(0, i >> 2)); - - for (j = 0; j < CHARS_PER_UINT32; j++) { - if (mask & (0x1 << j)) { - if (mask != 0xF) - reta &= ~(UINT8_MAX << CHAR_BIT * j); - reta |= reta_conf[idx].reta[shift + j] << - (CHAR_BIT * j); - } - } - FM10K_WRITE_REG(hw, FM10K_RETA(0, i >> 2), reta); - } - - return 0; -} - -static int -fm10k_reta_query(struct rte_eth_dev *dev, - struct rte_eth_rss_reta_entry64 *reta_conf, - uint16_t reta_size) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint16_t i, j, idx, shift; - uint8_t mask; - uint32_t reta; - - PMD_INIT_FUNC_TRACE(); - - if (reta_size < FM10K_MAX_RSS_INDICES) { - PMD_INIT_LOG(ERR, "The size of hash lookup table configured " - "(%d) doesn't match the number hardware can supported " - "(%d)", reta_size, FM10K_MAX_RSS_INDICES); - return -EINVAL; - } - - /* - * Read Redirection Table RETA[n], n=0..31. The redirection table has - * 128-entries in 32 registers - */ - for (i = 0; i < FM10K_MAX_RSS_INDICES; i += CHARS_PER_UINT32) { - idx = i / RTE_RETA_GROUP_SIZE; - shift = i % RTE_RETA_GROUP_SIZE; - mask = (uint8_t)((reta_conf[idx].mask >> shift) & - BIT_MASK_PER_UINT32); - if (mask == 0) - continue; - - reta = FM10K_READ_REG(hw, FM10K_RETA(0, i >> 2)); - for (j = 0; j < CHARS_PER_UINT32; j++) { - if (mask & (0x1 << j)) - reta_conf[idx].reta[shift + j] = ((reta >> - CHAR_BIT * j) & UINT8_MAX); - } - } - - return 0; -} - -static int -fm10k_rss_hash_update(struct rte_eth_dev *dev, - struct rte_eth_rss_conf *rss_conf) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t *key = (uint32_t *)rss_conf->rss_key; - uint32_t mrqc; - uint64_t hf = rss_conf->rss_hf; - int i; - - PMD_INIT_FUNC_TRACE(); - - if (rss_conf->rss_key_len < FM10K_RSSRK_SIZE * - FM10K_RSSRK_ENTRIES_PER_REG) - return -EINVAL; - - if (hf == 0) - return -EINVAL; - - mrqc = 0; - mrqc |= (hf & ETH_RSS_IPV4) ? FM10K_MRQC_IPV4 : 0; - mrqc |= (hf & ETH_RSS_IPV6) ? FM10K_MRQC_IPV6 : 0; - mrqc |= (hf & ETH_RSS_IPV6_EX) ? FM10K_MRQC_IPV6 : 0; - mrqc |= (hf & ETH_RSS_NONFRAG_IPV4_TCP) ? FM10K_MRQC_TCP_IPV4 : 0; - mrqc |= (hf & ETH_RSS_NONFRAG_IPV6_TCP) ? FM10K_MRQC_TCP_IPV6 : 0; - mrqc |= (hf & ETH_RSS_IPV6_TCP_EX) ? FM10K_MRQC_TCP_IPV6 : 0; - mrqc |= (hf & ETH_RSS_NONFRAG_IPV4_UDP) ? FM10K_MRQC_UDP_IPV4 : 0; - mrqc |= (hf & ETH_RSS_NONFRAG_IPV6_UDP) ? FM10K_MRQC_UDP_IPV6 : 0; - mrqc |= (hf & ETH_RSS_IPV6_UDP_EX) ? FM10K_MRQC_UDP_IPV6 : 0; - - /* If the mapping doesn't fit any supported, return */ - if (mrqc == 0) - return -EINVAL; - - if (key != NULL) - for (i = 0; i < FM10K_RSSRK_SIZE; ++i) - FM10K_WRITE_REG(hw, FM10K_RSSRK(0, i), key[i]); - - FM10K_WRITE_REG(hw, FM10K_MRQC(0), mrqc); - - return 0; -} - -static int -fm10k_rss_hash_conf_get(struct rte_eth_dev *dev, - struct rte_eth_rss_conf *rss_conf) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t *key = (uint32_t *)rss_conf->rss_key; - uint32_t mrqc; - uint64_t hf; - int i; - - PMD_INIT_FUNC_TRACE(); - - if (rss_conf->rss_key_len < FM10K_RSSRK_SIZE * - FM10K_RSSRK_ENTRIES_PER_REG) - return -EINVAL; - - if (key != NULL) - for (i = 0; i < FM10K_RSSRK_SIZE; ++i) - key[i] = FM10K_READ_REG(hw, FM10K_RSSRK(0, i)); - - mrqc = FM10K_READ_REG(hw, FM10K_MRQC(0)); - hf = 0; - hf |= (mrqc & FM10K_MRQC_IPV4) ? ETH_RSS_IPV4 : 0; - hf |= (mrqc & FM10K_MRQC_IPV6) ? ETH_RSS_IPV6 : 0; - hf |= (mrqc & FM10K_MRQC_IPV6) ? ETH_RSS_IPV6_EX : 0; - hf |= (mrqc & FM10K_MRQC_TCP_IPV4) ? ETH_RSS_NONFRAG_IPV4_TCP : 0; - hf |= (mrqc & FM10K_MRQC_TCP_IPV6) ? ETH_RSS_NONFRAG_IPV6_TCP : 0; - hf |= (mrqc & FM10K_MRQC_TCP_IPV6) ? ETH_RSS_IPV6_TCP_EX : 0; - hf |= (mrqc & FM10K_MRQC_UDP_IPV4) ? ETH_RSS_NONFRAG_IPV4_UDP : 0; - hf |= (mrqc & FM10K_MRQC_UDP_IPV6) ? ETH_RSS_NONFRAG_IPV6_UDP : 0; - hf |= (mrqc & FM10K_MRQC_UDP_IPV6) ? ETH_RSS_IPV6_UDP_EX : 0; - - rss_conf->rss_hf = hf; - - return 0; -} - -static void -fm10k_dev_enable_intr_pf(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t int_map = FM10K_INT_MAP_IMMEDIATE; - - /* Bind all local non-queue interrupt to vector 0 */ - int_map |= 0; - - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_Mailbox), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_PCIeFault), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SwitchUpDown), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SwitchEvent), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SRAM), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_VFLR), int_map); - - /* Enable misc causes */ - FM10K_WRITE_REG(hw, FM10K_EIMR, FM10K_EIMR_ENABLE(PCA_FAULT) | - FM10K_EIMR_ENABLE(THI_FAULT) | - FM10K_EIMR_ENABLE(FUM_FAULT) | - FM10K_EIMR_ENABLE(MAILBOX) | - FM10K_EIMR_ENABLE(SWITCHREADY) | - FM10K_EIMR_ENABLE(SWITCHNOTREADY) | - FM10K_EIMR_ENABLE(SRAMERROR) | - FM10K_EIMR_ENABLE(VFLR)); - - /* Enable ITR 0 */ - FM10K_WRITE_REG(hw, FM10K_ITR(0), FM10K_ITR_AUTOMASK | - FM10K_ITR_MASK_CLEAR); - FM10K_WRITE_FLUSH(hw); -} - -static void -fm10k_dev_disable_intr_pf(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t int_map = FM10K_INT_MAP_DISABLE; - - int_map |= 0; - - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_Mailbox), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_PCIeFault), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SwitchUpDown), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SwitchEvent), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SRAM), int_map); - FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_VFLR), int_map); - - /* Disable misc causes */ - FM10K_WRITE_REG(hw, FM10K_EIMR, FM10K_EIMR_DISABLE(PCA_FAULT) | - FM10K_EIMR_DISABLE(THI_FAULT) | - FM10K_EIMR_DISABLE(FUM_FAULT) | - FM10K_EIMR_DISABLE(MAILBOX) | - FM10K_EIMR_DISABLE(SWITCHREADY) | - FM10K_EIMR_DISABLE(SWITCHNOTREADY) | - FM10K_EIMR_DISABLE(SRAMERROR) | - FM10K_EIMR_DISABLE(VFLR)); - - /* Disable ITR 0 */ - FM10K_WRITE_REG(hw, FM10K_ITR(0), FM10K_ITR_MASK_SET); - FM10K_WRITE_FLUSH(hw); -} - -static void -fm10k_dev_enable_intr_vf(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t int_map = FM10K_INT_MAP_IMMEDIATE; - - /* Bind all local non-queue interrupt to vector 0 */ - int_map |= 0; - - /* Only INT 0 available, other 15 are reserved. */ - FM10K_WRITE_REG(hw, FM10K_VFINT_MAP, int_map); - - /* Enable ITR 0 */ - FM10K_WRITE_REG(hw, FM10K_VFITR(0), FM10K_ITR_AUTOMASK | - FM10K_ITR_MASK_CLEAR); - FM10K_WRITE_FLUSH(hw); -} - -static void -fm10k_dev_disable_intr_vf(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t int_map = FM10K_INT_MAP_DISABLE; - - int_map |= 0; - - /* Only INT 0 available, other 15 are reserved. */ - FM10K_WRITE_REG(hw, FM10K_VFINT_MAP, int_map); - - /* Disable ITR 0 */ - FM10K_WRITE_REG(hw, FM10K_VFITR(0), FM10K_ITR_MASK_SET); - FM10K_WRITE_FLUSH(hw); -} - -static int -fm10k_dev_handle_fault(struct fm10k_hw *hw, uint32_t eicr) -{ - struct fm10k_fault fault; - int err; - const char *estr = "Unknown error"; - - /* Process PCA fault */ - if (eicr & FM10K_EICR_PCA_FAULT) { - err = fm10k_get_fault(hw, FM10K_PCA_FAULT, &fault); - if (err) - goto error; - switch (fault.type) { - case PCA_NO_FAULT: - estr = "PCA_NO_FAULT"; break; - case PCA_UNMAPPED_ADDR: - estr = "PCA_UNMAPPED_ADDR"; break; - case PCA_BAD_QACCESS_PF: - estr = "PCA_BAD_QACCESS_PF"; break; - case PCA_BAD_QACCESS_VF: - estr = "PCA_BAD_QACCESS_VF"; break; - case PCA_MALICIOUS_REQ: - estr = "PCA_MALICIOUS_REQ"; break; - case PCA_POISONED_TLP: - estr = "PCA_POISONED_TLP"; break; - case PCA_TLP_ABORT: - estr = "PCA_TLP_ABORT"; break; - default: - goto error; - } - PMD_INIT_LOG(ERR, "%s: %s(%d) Addr:0x%"PRIx64" Spec: 0x%x", - estr, fault.func ? "VF" : "PF", fault.func, - fault.address, fault.specinfo); - } - - /* Process THI fault */ - if (eicr & FM10K_EICR_THI_FAULT) { - err = fm10k_get_fault(hw, FM10K_THI_FAULT, &fault); - if (err) - goto error; - switch (fault.type) { - case THI_NO_FAULT: - estr = "THI_NO_FAULT"; break; - case THI_MAL_DIS_Q_FAULT: - estr = "THI_MAL_DIS_Q_FAULT"; break; - default: - goto error; - } - PMD_INIT_LOG(ERR, "%s: %s(%d) Addr:0x%"PRIx64" Spec: 0x%x", - estr, fault.func ? "VF" : "PF", fault.func, - fault.address, fault.specinfo); - } - - /* Process FUM fault */ - if (eicr & FM10K_EICR_FUM_FAULT) { - err = fm10k_get_fault(hw, FM10K_FUM_FAULT, &fault); - if (err) - goto error; - switch (fault.type) { - case FUM_NO_FAULT: - estr = "FUM_NO_FAULT"; break; - case FUM_UNMAPPED_ADDR: - estr = "FUM_UNMAPPED_ADDR"; break; - case FUM_POISONED_TLP: - estr = "FUM_POISONED_TLP"; break; - case FUM_BAD_VF_QACCESS: - estr = "FUM_BAD_VF_QACCESS"; break; - case FUM_ADD_DECODE_ERR: - estr = "FUM_ADD_DECODE_ERR"; break; - case FUM_RO_ERROR: - estr = "FUM_RO_ERROR"; break; - case FUM_QPRC_CRC_ERROR: - estr = "FUM_QPRC_CRC_ERROR"; break; - case FUM_CSR_TIMEOUT: - estr = "FUM_CSR_TIMEOUT"; break; - case FUM_INVALID_TYPE: - estr = "FUM_INVALID_TYPE"; break; - case FUM_INVALID_LENGTH: - estr = "FUM_INVALID_LENGTH"; break; - case FUM_INVALID_BE: - estr = "FUM_INVALID_BE"; break; - case FUM_INVALID_ALIGN: - estr = "FUM_INVALID_ALIGN"; break; - default: - goto error; - } - PMD_INIT_LOG(ERR, "%s: %s(%d) Addr:0x%"PRIx64" Spec: 0x%x", - estr, fault.func ? "VF" : "PF", fault.func, - fault.address, fault.specinfo); - } - - return 0; -error: - PMD_INIT_LOG(ERR, "Failed to handle fault event."); - return err; -} - -/** - * PF interrupt handler triggered by NIC for handling specific interrupt. - * - * @param handle - * Pointer to interrupt handle. - * @param param - * The address of parameter (struct rte_eth_dev *) regsitered before. - * - * @return - * void - */ -static void -fm10k_dev_interrupt_handler_pf( - __rte_unused struct rte_intr_handle *handle, - void *param) -{ - struct rte_eth_dev *dev = (struct rte_eth_dev *)param; - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t cause, status; - - if (hw->mac.type != fm10k_mac_pf) - return; - - cause = FM10K_READ_REG(hw, FM10K_EICR); - - /* Handle PCI fault cases */ - if (cause & FM10K_EICR_FAULT_MASK) { - PMD_INIT_LOG(ERR, "INT: find fault!"); - fm10k_dev_handle_fault(hw, cause); - } - - /* Handle switch up/down */ - if (cause & FM10K_EICR_SWITCHNOTREADY) - PMD_INIT_LOG(ERR, "INT: Switch is not ready"); - - if (cause & FM10K_EICR_SWITCHREADY) - PMD_INIT_LOG(INFO, "INT: Switch is ready"); - - /* Handle mailbox message */ - fm10k_mbx_lock(hw); - hw->mbx.ops.process(hw, &hw->mbx); - fm10k_mbx_unlock(hw); - - /* Handle SRAM error */ - if (cause & FM10K_EICR_SRAMERROR) { - PMD_INIT_LOG(ERR, "INT: SRAM error on PEP"); - - status = FM10K_READ_REG(hw, FM10K_SRAM_IP); - /* Write to clear pending bits */ - FM10K_WRITE_REG(hw, FM10K_SRAM_IP, status); - - /* Todo: print out error message after shared code updates */ - } - - /* Clear these 3 events if having any */ - cause &= FM10K_EICR_SWITCHNOTREADY | FM10K_EICR_MAILBOX | - FM10K_EICR_SWITCHREADY; - if (cause) - FM10K_WRITE_REG(hw, FM10K_EICR, cause); - - /* Re-enable interrupt from device side */ - FM10K_WRITE_REG(hw, FM10K_ITR(0), FM10K_ITR_AUTOMASK | - FM10K_ITR_MASK_CLEAR); - /* Re-enable interrupt from host side */ - rte_intr_enable(&(dev->pci_dev->intr_handle)); -} - -/** - * VF interrupt handler triggered by NIC for handling specific interrupt. - * - * @param handle - * Pointer to interrupt handle. - * @param param - * The address of parameter (struct rte_eth_dev *) regsitered before. - * - * @return - * void - */ -static void -fm10k_dev_interrupt_handler_vf( - __rte_unused struct rte_intr_handle *handle, - void *param) -{ - struct rte_eth_dev *dev = (struct rte_eth_dev *)param; - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - - if (hw->mac.type != fm10k_mac_vf) - return; - - /* Handle mailbox message if lock is acquired */ - fm10k_mbx_lock(hw); - hw->mbx.ops.process(hw, &hw->mbx); - fm10k_mbx_unlock(hw); - - /* Re-enable interrupt from device side */ - FM10K_WRITE_REG(hw, FM10K_VFITR(0), FM10K_ITR_AUTOMASK | - FM10K_ITR_MASK_CLEAR); - /* Re-enable interrupt from host side */ - rte_intr_enable(&(dev->pci_dev->intr_handle)); -} - -/* Mailbox message handler in VF */ -static const struct fm10k_msg_data fm10k_msgdata_vf[] = { - FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), - FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf), - FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf), - FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), -}; - -/* Mailbox message handler in PF */ -static const struct fm10k_msg_data fm10k_msgdata_pf[] = { - FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), - FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), - FM10K_PF_MSG_LPORT_MAP_HANDLER(fm10k_msg_lport_map_pf), - FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf), - FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf), - FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_msg_update_pvid_pf), - FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), -}; - -static int -fm10k_setup_mbx_service(struct fm10k_hw *hw) -{ - int err; - - /* Initialize mailbox lock */ - fm10k_mbx_initlock(hw); - - /* Replace default message handler with new ones */ - if (hw->mac.type == fm10k_mac_pf) - err = hw->mbx.ops.register_handlers(&hw->mbx, fm10k_msgdata_pf); - else - err = hw->mbx.ops.register_handlers(&hw->mbx, fm10k_msgdata_vf); - - if (err) { - PMD_INIT_LOG(ERR, "Failed to register mailbox handler.err:%d", - err); - return err; - } - /* Connect to SM for PF device or PF for VF device */ - return hw->mbx.ops.connect(hw, &hw->mbx); -} - -static void -fm10k_close_mbx_service(struct fm10k_hw *hw) -{ - /* Disconnect from SM for PF device or PF for VF device */ - hw->mbx.ops.disconnect(hw, &hw->mbx); -} - -static const struct eth_dev_ops fm10k_eth_dev_ops = { - .dev_configure = fm10k_dev_configure, - .dev_start = fm10k_dev_start, - .dev_stop = fm10k_dev_stop, - .dev_close = fm10k_dev_close, - .promiscuous_enable = fm10k_dev_promiscuous_enable, - .promiscuous_disable = fm10k_dev_promiscuous_disable, - .allmulticast_enable = fm10k_dev_allmulticast_enable, - .allmulticast_disable = fm10k_dev_allmulticast_disable, - .stats_get = fm10k_stats_get, - .xstats_get = fm10k_xstats_get, - .stats_reset = fm10k_stats_reset, - .xstats_reset = fm10k_stats_reset, - .link_update = fm10k_link_update, - .dev_infos_get = fm10k_dev_infos_get, - .vlan_filter_set = fm10k_vlan_filter_set, - .vlan_offload_set = fm10k_vlan_offload_set, - .mac_addr_add = fm10k_macaddr_add, - .mac_addr_remove = fm10k_macaddr_remove, - .rx_queue_start = fm10k_dev_rx_queue_start, - .rx_queue_stop = fm10k_dev_rx_queue_stop, - .tx_queue_start = fm10k_dev_tx_queue_start, - .tx_queue_stop = fm10k_dev_tx_queue_stop, - .rx_queue_setup = fm10k_rx_queue_setup, - .rx_queue_release = fm10k_rx_queue_release, - .tx_queue_setup = fm10k_tx_queue_setup, - .tx_queue_release = fm10k_tx_queue_release, - .reta_update = fm10k_reta_update, - .reta_query = fm10k_reta_query, - .rss_hash_update = fm10k_rss_hash_update, - .rss_hash_conf_get = fm10k_rss_hash_conf_get, -}; - -static void __attribute__((cold)) -fm10k_set_tx_function(struct rte_eth_dev *dev) -{ - struct fm10k_tx_queue *txq; - int i; - int use_sse = 1; - - for (i = 0; i < dev->data->nb_tx_queues; i++) { - txq = dev->data->tx_queues[i]; - /* Check if Vector Tx is satisfied */ - if (fm10k_tx_vec_condition_check(txq)) { - use_sse = 0; - break; - } - } - - if (use_sse) { - PMD_INIT_LOG(DEBUG, "Use vector Tx func"); - for (i = 0; i < dev->data->nb_tx_queues; i++) { - txq = dev->data->tx_queues[i]; - fm10k_txq_vec_setup(txq); - } - dev->tx_pkt_burst = fm10k_xmit_pkts_vec; - } else { - dev->tx_pkt_burst = fm10k_xmit_pkts; - PMD_INIT_LOG(DEBUG, "Use regular Tx func"); - } -} - -static void __attribute__((cold)) -fm10k_set_rx_function(struct rte_eth_dev *dev) -{ - struct fm10k_dev_info *dev_info = FM10K_DEV_PRIVATE_TO_INFO(dev); - uint16_t i, rx_using_sse; - - /* In order to allow Vector Rx there are a few configuration - * conditions to be met. - */ - if (!fm10k_rx_vec_condition_check(dev) && dev_info->rx_vec_allowed) { - if (dev->data->scattered_rx) - dev->rx_pkt_burst = fm10k_recv_scattered_pkts_vec; - else - dev->rx_pkt_burst = fm10k_recv_pkts_vec; - } else if (dev->data->scattered_rx) - dev->rx_pkt_burst = fm10k_recv_scattered_pkts; - else - dev->rx_pkt_burst = fm10k_recv_pkts; - - rx_using_sse = - (dev->rx_pkt_burst == fm10k_recv_scattered_pkts_vec || - dev->rx_pkt_burst == fm10k_recv_pkts_vec); - - if (rx_using_sse) - PMD_INIT_LOG(DEBUG, "Use vector Rx func"); - else - PMD_INIT_LOG(DEBUG, "Use regular Rx func"); - - for (i = 0; i < dev->data->nb_rx_queues; i++) { - struct fm10k_rx_queue *rxq = dev->data->rx_queues[i]; - - rxq->rx_using_sse = rx_using_sse; - } -} - -static void -fm10k_params_init(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct fm10k_dev_info *info = FM10K_DEV_PRIVATE_TO_INFO(dev); - - /* Inialize bus info. Normally we would call fm10k_get_bus_info(), but - * there is no way to get link status without reading BAR4. Until this - * works, assume we have maximum bandwidth. - * @todo - fix bus info - */ - hw->bus_caps.speed = fm10k_bus_speed_8000; - hw->bus_caps.width = fm10k_bus_width_pcie_x8; - hw->bus_caps.payload = fm10k_bus_payload_512; - hw->bus.speed = fm10k_bus_speed_8000; - hw->bus.width = fm10k_bus_width_pcie_x8; - hw->bus.payload = fm10k_bus_payload_256; - - info->rx_vec_allowed = true; -} - -static int -eth_fm10k_dev_init(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int diag; - struct fm10k_macvlan_filter_info *macvlan; - - PMD_INIT_FUNC_TRACE(); - - dev->dev_ops = &fm10k_eth_dev_ops; - dev->rx_pkt_burst = &fm10k_recv_pkts; - dev->tx_pkt_burst = &fm10k_xmit_pkts; - - /* only initialize in the primary process */ - if (rte_eal_process_type() != RTE_PROC_PRIMARY) - return 0; - - rte_eth_copy_pci_info(dev, dev->pci_dev); - - macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); - memset(macvlan, 0, sizeof(*macvlan)); - /* Vendor and Device ID need to be set before init of shared code */ - memset(hw, 0, sizeof(*hw)); - hw->device_id = dev->pci_dev->id.device_id; - hw->vendor_id = dev->pci_dev->id.vendor_id; - hw->subsystem_device_id = dev->pci_dev->id.subsystem_device_id; - hw->subsystem_vendor_id = dev->pci_dev->id.subsystem_vendor_id; - hw->revision_id = 0; - hw->hw_addr = (void *)dev->pci_dev->mem_resource[0].addr; - if (hw->hw_addr == NULL) { - PMD_INIT_LOG(ERR, "Bad mem resource." - " Try to blacklist unused devices."); - return -EIO; - } - - /* Store fm10k_adapter pointer */ - hw->back = dev->data->dev_private; - - /* Initialize the shared code */ - diag = fm10k_init_shared_code(hw); - if (diag != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "Shared code init failed: %d", diag); - return -EIO; - } - - /* Initialize parameters */ - fm10k_params_init(dev); - - /* Initialize the hw */ - diag = fm10k_init_hw(hw); - if (diag != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "Hardware init failed: %d", diag); - return -EIO; - } - - /* Initialize MAC address(es) */ - dev->data->mac_addrs = rte_zmalloc("fm10k", - ETHER_ADDR_LEN * FM10K_MAX_MACADDR_NUM, 0); - if (dev->data->mac_addrs == NULL) { - PMD_INIT_LOG(ERR, "Cannot allocate memory for MAC addresses"); - return -ENOMEM; - } - - diag = fm10k_read_mac_addr(hw); - - ether_addr_copy((const struct ether_addr *)hw->mac.addr, - &dev->data->mac_addrs[0]); - - if (diag != FM10K_SUCCESS || - !is_valid_assigned_ether_addr(dev->data->mac_addrs)) { - - /* Generate a random addr */ - eth_random_addr(hw->mac.addr); - memcpy(hw->mac.perm_addr, hw->mac.addr, ETH_ALEN); - ether_addr_copy((const struct ether_addr *)hw->mac.addr, - &dev->data->mac_addrs[0]); - } - - /* Reset the hw statistics */ - fm10k_stats_reset(dev); - - /* Reset the hw */ - diag = fm10k_reset_hw(hw); - if (diag != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "Hardware reset failed: %d", diag); - return -EIO; - } - - /* Setup mailbox service */ - diag = fm10k_setup_mbx_service(hw); - if (diag != FM10K_SUCCESS) { - PMD_INIT_LOG(ERR, "Failed to setup mailbox: %d", diag); - return -EIO; - } - - /*PF/VF has different interrupt handling mechanism */ - if (hw->mac.type == fm10k_mac_pf) { - /* register callback func to eal lib */ - rte_intr_callback_register(&(dev->pci_dev->intr_handle), - fm10k_dev_interrupt_handler_pf, (void *)dev); - - /* enable MISC interrupt */ - fm10k_dev_enable_intr_pf(dev); - } else { /* VF */ - rte_intr_callback_register(&(dev->pci_dev->intr_handle), - fm10k_dev_interrupt_handler_vf, (void *)dev); - - fm10k_dev_enable_intr_vf(dev); - } - - /* Enable uio intr after callback registered */ - rte_intr_enable(&(dev->pci_dev->intr_handle)); - - hw->mac.ops.update_int_moderator(hw); - - /* Make sure Switch Manager is ready before going forward. */ - if (hw->mac.type == fm10k_mac_pf) { - int switch_ready = 0; - int i; - - for (i = 0; i < MAX_QUERY_SWITCH_STATE_TIMES; i++) { - fm10k_mbx_lock(hw); - hw->mac.ops.get_host_state(hw, &switch_ready); - fm10k_mbx_unlock(hw); - if (switch_ready) - break; - /* Delay some time to acquire async LPORT_MAP info. */ - rte_delay_us(WAIT_SWITCH_MSG_US); - } - - if (switch_ready == 0) { - PMD_INIT_LOG(ERR, "switch is not ready"); - return -1; - } - } - - /* - * Below function will trigger operations on mailbox, acquire lock to - * avoid race condition from interrupt handler. Operations on mailbox - * FIFO will trigger interrupt to PF/SM, in which interrupt handler - * will handle and generate an interrupt to our side. Then, FIFO in - * mailbox will be touched. - */ - fm10k_mbx_lock(hw); - /* Enable port first */ - hw->mac.ops.update_lport_state(hw, hw->mac.dglort_map, 1, 1); - - /* Set unicast mode by default. App can change to other mode in other - * API func. - */ - hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, - FM10K_XCAST_MODE_NONE); - - fm10k_mbx_unlock(hw); - - /* Add default mac address */ - fm10k_MAC_filter_set(dev, hw->mac.addr, true, - MAIN_VSI_POOL_NUMBER); - - return 0; -} - -static int -eth_fm10k_dev_uninit(struct rte_eth_dev *dev) -{ - struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - - PMD_INIT_FUNC_TRACE(); - - /* only uninitialize in the primary process */ - if (rte_eal_process_type() != RTE_PROC_PRIMARY) - return 0; - - /* safe to close dev here */ - fm10k_dev_close(dev); - - dev->dev_ops = NULL; - dev->rx_pkt_burst = NULL; - dev->tx_pkt_burst = NULL; - - /* disable uio/vfio intr */ - rte_intr_disable(&(dev->pci_dev->intr_handle)); - - /*PF/VF has different interrupt handling mechanism */ - if (hw->mac.type == fm10k_mac_pf) { - /* disable interrupt */ - fm10k_dev_disable_intr_pf(dev); - - /* unregister callback func to eal lib */ - rte_intr_callback_unregister(&(dev->pci_dev->intr_handle), - fm10k_dev_interrupt_handler_pf, (void *)dev); - } else { - /* disable interrupt */ - fm10k_dev_disable_intr_vf(dev); - - rte_intr_callback_unregister(&(dev->pci_dev->intr_handle), - fm10k_dev_interrupt_handler_vf, (void *)dev); - } - - /* free mac memory */ - if (dev->data->mac_addrs) { - rte_free(dev->data->mac_addrs); - dev->data->mac_addrs = NULL; - } - - memset(hw, 0, sizeof(*hw)); - - return 0; -} - -/* - * The set of PCI devices this driver supports. This driver will enable both PF - * and SRIOV-VF devices. - */ -static const struct rte_pci_id pci_id_fm10k_map[] = { -#define RTE_PCI_DEV_ID_DECL_FM10K(vend, dev) { RTE_PCI_DEVICE(vend, dev) }, -#define RTE_PCI_DEV_ID_DECL_FM10KVF(vend, dev) { RTE_PCI_DEVICE(vend, dev) }, -#include "rte_pci_dev_ids.h" - { .vendor_id = 0, /* sentinel */ }, -}; - -static struct eth_driver rte_pmd_fm10k = { - .pci_drv = { - .name = "rte_pmd_fm10k", - .id_table = pci_id_fm10k_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE, - }, - .eth_dev_init = eth_fm10k_dev_init, - .eth_dev_uninit = eth_fm10k_dev_uninit, - .dev_private_size = sizeof(struct fm10k_adapter), -}; - -/* - * Driver initialization routine. - * Invoked once at EAL init time. - * Register itself as the [Poll Mode] Driver of PCI FM10K devices. - */ -static int -rte_pmd_fm10k_init(__rte_unused const char *name, - __rte_unused const char *params) -{ - PMD_INIT_FUNC_TRACE(); - rte_eth_driver_register(&rte_pmd_fm10k); - return 0; -} - -static struct rte_driver rte_fm10k_driver = { - .type = PMD_PDEV, - .init = rte_pmd_fm10k_init, -}; - -PMD_REGISTER_DRIVER(rte_fm10k_driver); |