X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fena%2Fena_ethdev.c;h=dfe68279fa7bc1b79f491259ddf5e97b734bb1e9;hb=05b405d581486651305551a9f7295f40388d95db;hp=f6d0a75819d23d511e14abd7047983523f709a9e;hpb=c0006061fbe8df61a1caed0d578a0b416ab2166a;p=dpdk.git diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c index f6d0a75819..dfe68279fa 100644 --- a/drivers/net/ena/ena_ethdev.c +++ b/drivers/net/ena/ena_ethdev.c @@ -5,8 +5,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -27,8 +27,8 @@ #include #define DRV_MODULE_VER_MAJOR 2 -#define DRV_MODULE_VER_MINOR 0 -#define DRV_MODULE_VER_SUBMINOR 3 +#define DRV_MODULE_VER_MINOR 3 +#define DRV_MODULE_VER_SUBMINOR 0 #define ENA_IO_TXQ_IDX(q) (2 * (q)) #define ENA_IO_RXQ_IDX(q) (2 * (q) + 1) @@ -47,10 +47,12 @@ #define ENA_HASH_KEY_SIZE 40 #define ETH_GSTRING_LEN 32 -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define ARRAY_SIZE(x) RTE_DIM(x) #define ENA_MIN_RING_DESC 128 +#define ENA_PTYPE_HAS_HASH (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP) + enum ethtool_stringset { ETH_SS_TEST = 0, ETH_SS_STATS, @@ -72,6 +74,9 @@ struct ena_stats { #define ENA_STAT_TX_ENTRY(stat) \ ENA_STAT_ENTRY(stat, tx) +#define ENA_STAT_ENI_ENTRY(stat) \ + ENA_STAT_ENTRY(stat, eni) + #define ENA_STAT_GLOBAL_ENTRY(stat) \ ENA_STAT_ENTRY(stat, dev) @@ -82,7 +87,7 @@ struct ena_stats { * Each rte_memzone should have unique name. * To satisfy it, count number of allocation and add it to name. */ -rte_atomic32_t ena_alloc_cnt; +rte_atomic64_t ena_alloc_cnt; static const struct ena_stats ena_stats_global_strings[] = { ENA_STAT_GLOBAL_ENTRY(wd_expired), @@ -91,6 +96,14 @@ static const struct ena_stats ena_stats_global_strings[] = { ENA_STAT_GLOBAL_ENTRY(tx_drops), }; +static const struct ena_stats ena_stats_eni_strings[] = { + ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded), + ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded), + ENA_STAT_ENI_ENTRY(pps_allowance_exceeded), + ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded), + ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded), +}; + static const struct ena_stats ena_stats_tx_strings[] = { ENA_STAT_TX_ENTRY(cnt), ENA_STAT_TX_ENTRY(bytes), @@ -114,6 +127,7 @@ static const struct ena_stats ena_stats_rx_strings[] = { }; #define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings) +#define ENA_STATS_ARRAY_ENI ARRAY_SIZE(ena_stats_eni_strings) #define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) #define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) @@ -128,8 +142,8 @@ static const struct ena_stats ena_stats_rx_strings[] = { /** Vendor ID used by Amazon devices */ #define PCI_VENDOR_ID_AMAZON 0x1D0F /** Amazon devices */ -#define PCI_DEVICE_ID_ENA_VF 0xEC20 -#define PCI_DEVICE_ID_ENA_LLQ_VF 0xEC21 +#define PCI_DEVICE_ID_ENA_VF 0xEC20 +#define PCI_DEVICE_ID_ENA_VF_RSERV0 0xEC21 #define ENA_TX_OFFLOAD_MASK (\ PKT_TX_L4_MASK | \ @@ -141,34 +155,26 @@ static const struct ena_stats ena_stats_rx_strings[] = { #define ENA_TX_OFFLOAD_NOTSUP_MASK \ (PKT_TX_OFFLOAD_MASK ^ ENA_TX_OFFLOAD_MASK) -int ena_logtype_init; -int ena_logtype_driver; - -#ifdef RTE_LIBRTE_ENA_DEBUG_RX -int ena_logtype_rx; -#endif -#ifdef RTE_LIBRTE_ENA_DEBUG_TX -int ena_logtype_tx; -#endif -#ifdef RTE_LIBRTE_ENA_DEBUG_TX_FREE -int ena_logtype_tx_free; -#endif -#ifdef RTE_LIBRTE_ENA_COM_DEBUG -int ena_logtype_com; -#endif - static const struct rte_pci_id pci_id_ena_map[] = { { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF) }, - { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_LLQ_VF) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF_RSERV0) }, { .device_id = 0 }, }; static struct ena_aenq_handlers aenq_handlers; static int ena_device_init(struct ena_com_dev *ena_dev, + struct rte_pci_device *pdev, struct ena_com_dev_get_features_ctx *get_feat_ctx, bool *wd_state); static int ena_dev_configure(struct rte_eth_dev *dev); +static void ena_tx_map_mbuf(struct ena_ring *tx_ring, + struct ena_tx_buffer *tx_info, + struct rte_mbuf *mbuf, + void **push_header, + uint16_t *header_len); +static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf); +static void ena_tx_cleanup(struct ena_ring *tx_ring); static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); static uint16_t eth_ena_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, @@ -188,13 +194,15 @@ static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, uint8_t offset); static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); +static int ena_add_single_rx_desc(struct ena_com_io_sq *io_sq, + struct rte_mbuf *mbuf, uint16_t id); static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count); static void ena_init_rings(struct ena_adapter *adapter, bool disable_meta_caching); static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int ena_start(struct rte_eth_dev *dev); -static void ena_stop(struct rte_eth_dev *dev); -static void ena_close(struct rte_eth_dev *dev); +static int ena_stop(struct rte_eth_dev *dev); +static int ena_close(struct rte_eth_dev *dev); static int ena_dev_reset(struct rte_eth_dev *dev); static int ena_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static void ena_rx_queue_release_all(struct rte_eth_dev *dev); @@ -240,6 +248,7 @@ static int ena_process_bool_devarg(const char *key, void *opaque); static int ena_parse_devargs(struct ena_adapter *adapter, struct rte_devargs *devargs); +static int ena_copy_eni_stats(struct ena_adapter *adapter); static const struct eth_dev_ops ena_dev_ops = { .dev_configure = ena_dev_configure, @@ -290,21 +299,28 @@ static inline void ena_rx_mbuf_prepare(struct rte_mbuf *mbuf, else if (ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_UDP) packet_type |= RTE_PTYPE_L4_UDP; - if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV4) + if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV4) { packet_type |= RTE_PTYPE_L3_IPV4; - else if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV6) + if (unlikely(ena_rx_ctx->l3_csum_err)) + ol_flags |= PKT_RX_IP_CKSUM_BAD; + else + ol_flags |= PKT_RX_IP_CKSUM_GOOD; + } else if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV6) { packet_type |= RTE_PTYPE_L3_IPV6; + } - if (!ena_rx_ctx->l4_csum_checked) + if (!ena_rx_ctx->l4_csum_checked || ena_rx_ctx->frag) ol_flags |= PKT_RX_L4_CKSUM_UNKNOWN; else - if (unlikely(ena_rx_ctx->l4_csum_err) && !ena_rx_ctx->frag) + if (unlikely(ena_rx_ctx->l4_csum_err)) ol_flags |= PKT_RX_L4_CKSUM_BAD; else - ol_flags |= PKT_RX_L4_CKSUM_UNKNOWN; + ol_flags |= PKT_RX_L4_CKSUM_GOOD; - if (unlikely(ena_rx_ctx->l3_csum_err)) - ol_flags |= PKT_RX_IP_CKSUM_BAD; + if (likely((packet_type & ENA_PTYPE_HAS_HASH) && !ena_rx_ctx->frag)) { + ol_flags |= PKT_RX_RSS_HASH; + mbuf->hash.rss = ena_rx_ctx->hash; + } mbuf->ol_flags = ol_flags; mbuf->packet_type = packet_type; @@ -372,20 +388,6 @@ static inline void ena_tx_mbuf_prepare(struct rte_mbuf *mbuf, } } -static inline int validate_rx_req_id(struct ena_ring *rx_ring, uint16_t req_id) -{ - if (likely(req_id < rx_ring->ring_size)) - return 0; - - PMD_DRV_LOG(ERR, "Invalid rx req_id: %hu\n", req_id); - - rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID; - rx_ring->adapter->trigger_reset = true; - ++rx_ring->rx_stats.bad_req_id; - - return -EFAULT; -} - static int validate_tx_req_id(struct ena_ring *tx_ring, u16 req_id) { struct ena_tx_buffer *tx_info = NULL; @@ -456,11 +458,11 @@ err: } /* This function calculates the number of xstats based on the current config */ -static unsigned int ena_xstats_calc_num(struct rte_eth_dev *dev) +static unsigned int ena_xstats_calc_num(struct rte_eth_dev_data *data) { - return ENA_STATS_ARRAY_GLOBAL + - (dev->data->nb_tx_queues * ENA_STATS_ARRAY_TX) + - (dev->data->nb_rx_queues * ENA_STATS_ARRAY_RX); + return ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENI + + (data->nb_tx_queues * ENA_STATS_ARRAY_TX) + + (data->nb_rx_queues * ENA_STATS_ARRAY_RX); } static void ena_config_debug_area(struct ena_adapter *adapter) @@ -468,7 +470,7 @@ static void ena_config_debug_area(struct ena_adapter *adapter) u32 debug_area_size; int rc, ss_count; - ss_count = ena_xstats_calc_num(adapter->rte_dev); + ss_count = ena_xstats_calc_num(adapter->edev_data); /* allocate 32 bytes for each string and 64bit for the value */ debug_area_size = ss_count * ETH_GSTRING_LEN + sizeof(u64) * ss_count; @@ -494,14 +496,18 @@ err: ena_com_delete_debug_area(&adapter->ena_dev); } -static void ena_close(struct rte_eth_dev *dev) +static int ena_close(struct rte_eth_dev *dev) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; struct ena_adapter *adapter = dev->data->dev_private; + int ret = 0; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; if (adapter->state == ENA_ADAPTER_STATE_RUNNING) - ena_stop(dev); + ret = ena_stop(dev); adapter->state = ENA_ADAPTER_STATE_CLOSED; ena_rx_queue_release_all(dev); @@ -513,13 +519,15 @@ static void ena_close(struct rte_eth_dev *dev) rte_intr_disable(intr_handle); rte_intr_callback_unregister(intr_handle, ena_interrupt_handler_rte, - adapter); + dev); /* * MAC is not allocated dynamically. Setting NULL should prevent from * release of the resource in the rte_eth_dev_release_port(). */ dev->data->mac_addrs = NULL; + + return ret; } static int @@ -527,6 +535,12 @@ ena_dev_reset(struct rte_eth_dev *dev) { int rc = 0; + /* Cannot release memory in secondary process */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + PMD_DRV_LOG(WARNING, "dev_reset not supported in secondary.\n"); + return -EPERM; + } + ena_destroy_device(dev); rc = eth_ena_dev_init(dev); if (rc) @@ -577,14 +591,16 @@ static int ena_rss_reta_update(struct rte_eth_dev *dev, } } + rte_spinlock_lock(&adapter->admin_lock); rc = ena_com_indirect_table_set(ena_dev); + rte_spinlock_unlock(&adapter->admin_lock); if (unlikely(rc && rc != ENA_COM_UNSUPPORTED)) { PMD_DRV_LOG(ERR, "Cannot flush the indirect table\n"); return rc; } PMD_DRV_LOG(DEBUG, "%s(): RSS configured %d entries for port %d\n", - __func__, reta_size, adapter->rte_dev->data->port_id); + __func__, reta_size, dev->data->port_id); return 0; } @@ -606,7 +622,9 @@ static int ena_rss_reta_query(struct rte_eth_dev *dev, (reta_size > RTE_RETA_GROUP_SIZE && ((reta_conf + 1) == NULL))) return -EINVAL; + rte_spinlock_lock(&adapter->admin_lock); rc = ena_com_indirect_table_get(ena_dev, indirect_table); + rte_spinlock_unlock(&adapter->admin_lock); if (unlikely(rc && rc != ENA_COM_UNSUPPORTED)) { PMD_DRV_LOG(ERR, "cannot get indirect table\n"); return -ENOTSUP; @@ -626,7 +644,7 @@ static int ena_rss_reta_query(struct rte_eth_dev *dev, static int ena_rss_init_default(struct ena_adapter *adapter) { struct ena_com_dev *ena_dev = &adapter->ena_dev; - uint16_t nb_rx_queues = adapter->rte_dev->data->nb_rx_queues; + uint16_t nb_rx_queues = adapter->edev_data->nb_rx_queues; int rc, i; u32 val; @@ -665,7 +683,7 @@ static int ena_rss_init_default(struct ena_adapter *adapter) goto err_fill_indir; } PMD_DRV_LOG(DEBUG, "RSS configured for port %d\n", - adapter->rte_dev->data->port_id); + adapter->edev_data->port_id); return 0; @@ -763,8 +781,10 @@ static void ena_tx_queue_release_bufs(struct ena_ring *ring) for (i = 0; i < ring->ring_size; ++i) { struct ena_tx_buffer *tx_buf = &ring->tx_buffer_info[i]; - if (tx_buf->mbuf) + if (tx_buf->mbuf) { rte_pktmbuf_free(tx_buf->mbuf); + tx_buf->mbuf = NULL; + } } } @@ -834,10 +854,10 @@ static uint32_t ena_get_mtu_conf(struct ena_adapter *adapter) { uint32_t max_frame_len = adapter->max_mtu; - if (adapter->rte_eth_dev_data->dev_conf.rxmode.offloads & + if (adapter->edev_data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) max_frame_len = - adapter->rte_eth_dev_data->dev_conf.rxmode.max_rx_pkt_len; + adapter->edev_data->dev_conf.rxmode.max_rx_pkt_len; return max_frame_len; } @@ -961,7 +981,10 @@ static int ena_stats_get(struct rte_eth_dev *dev, return -ENOTSUP; memset(&ena_stats, 0, sizeof(ena_stats)); + + rte_spinlock_lock(&adapter->admin_lock); rc = ena_com_get_dev_basic_stats(ena_dev, &ena_stats); + rte_spinlock_unlock(&adapter->admin_lock); if (unlikely(rc)) { PMD_DRV_LOG(ERR, "Could not retrieve statistics from ENA\n"); return rc; @@ -1042,6 +1065,12 @@ static int ena_start(struct rte_eth_dev *dev) uint64_t ticks; int rc = 0; + /* Cannot allocate memory in secondary process */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + PMD_DRV_LOG(WARNING, "dev_start not supported in secondary.\n"); + return -EPERM; + } + rc = ena_check_valid_conf(adapter); if (rc) return rc; @@ -1054,8 +1083,8 @@ static int ena_start(struct rte_eth_dev *dev) if (rc) goto err_start_tx; - if (adapter->rte_dev->data->dev_conf.rxmode.mq_mode & - ETH_MQ_RX_RSS_FLAG && adapter->rte_dev->data->nb_rx_queues > 0) { + if (adapter->edev_data->dev_conf.rxmode.mq_mode & + ETH_MQ_RX_RSS_FLAG && adapter->edev_data->nb_rx_queues > 0) { rc = ena_rss_init_default(adapter); if (rc) goto err_rss_init; @@ -1068,7 +1097,7 @@ static int ena_start(struct rte_eth_dev *dev) ticks = rte_get_timer_hz(); rte_timer_reset(&adapter->timer_wd, ticks, PERIODICAL, rte_lcore_id(), - ena_timer_wd_callback, adapter); + ena_timer_wd_callback, dev); ++adapter->dev_stats.dev_start; adapter->state = ENA_ADAPTER_STATE_RUNNING; @@ -1082,12 +1111,18 @@ err_start_tx: return rc; } -static void ena_stop(struct rte_eth_dev *dev) +static int ena_stop(struct rte_eth_dev *dev) { struct ena_adapter *adapter = dev->data->dev_private; struct ena_com_dev *ena_dev = &adapter->ena_dev; int rc; + /* Cannot free memory in secondary process */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + PMD_DRV_LOG(WARNING, "dev_stop not supported in secondary.\n"); + return -EPERM; + } + rte_timer_stop_sync(&adapter->timer_wd); ena_queue_stop_all(dev, ENA_RING_TYPE_TX); ena_queue_stop_all(dev, ENA_RING_TYPE_RX); @@ -1100,6 +1135,9 @@ static void ena_stop(struct rte_eth_dev *dev) ++adapter->dev_stats.dev_stop; adapter->state = ENA_ADAPTER_STATE_STOPPED; + dev->data->dev_started = 0; + + return 0; } static int ena_create_io_queue(struct ena_ring *ring) @@ -1222,6 +1260,10 @@ static int ena_queue_start(struct ena_ring *ring) PMD_INIT_LOG(ERR, "Failed to populate rx ring !"); return ENA_COM_FAULT; } + /* Flush per-core RX buffers pools cache as they can be used on other + * cores as well. + */ + rte_mempool_cache_flush(NULL, ring->mb_pool); return 0; } @@ -1259,15 +1301,13 @@ static int ena_tx_queue_setup(struct rte_eth_dev *dev, return -EINVAL; } - if (nb_desc == RTE_ETH_DEV_FALLBACK_TX_RINGSIZE) - nb_desc = adapter->max_tx_ring_size; - txq->port_id = dev->data->port_id; txq->next_to_clean = 0; txq->next_to_use = 0; txq->ring_size = nb_desc; txq->size_mask = nb_desc - 1; txq->numa_socket_id = socket_id; + txq->pkts_without_db = false; txq->tx_buffer_info = rte_zmalloc("txq->tx_buffer_info", sizeof(struct ena_tx_buffer) * @@ -1332,9 +1372,6 @@ static int ena_rx_queue_setup(struct rte_eth_dev *dev, return ENA_COM_FAULT; } - if (nb_desc == RTE_ETH_DEV_FALLBACK_RX_RINGSIZE) - nb_desc = adapter->max_rx_ring_size; - if (!rte_is_power_of_2(nb_desc)) { PMD_DRV_LOG(ERR, "Unsupported size of RX queue: %d is not a power of 2.\n", @@ -1407,6 +1444,24 @@ static int ena_rx_queue_setup(struct rte_eth_dev *dev, return 0; } +static int ena_add_single_rx_desc(struct ena_com_io_sq *io_sq, + struct rte_mbuf *mbuf, uint16_t id) +{ + struct ena_com_buf ebuf; + int rc; + + /* prepare physical address for DMA transaction */ + ebuf.paddr = mbuf->buf_iova + RTE_PKTMBUF_HEADROOM; + ebuf.len = mbuf->buf_len - RTE_PKTMBUF_HEADROOM; + + /* pass resource to device */ + rc = ena_com_add_single_rx_desc(io_sq, &ebuf, id); + if (unlikely(rc != 0)) + PMD_DRV_LOG(WARNING, "failed adding rx desc\n"); + + return rc; +} + static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count) { unsigned int i; @@ -1424,7 +1479,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count) "bad ring state\n"); /* get resources for incoming packets */ - rc = rte_mempool_get_bulk(rxq->mb_pool, (void **)mbufs, count); + rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, count); if (unlikely(rc < 0)) { rte_atomic64_inc(&rxq->adapter->drv_stats->rx_nombuf); ++rxq->rx_stats.mbuf_alloc_fail; @@ -1434,29 +1489,18 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count) for (i = 0; i < count; i++) { struct rte_mbuf *mbuf = mbufs[i]; - struct ena_com_buf ebuf; struct ena_rx_buffer *rx_info; if (likely((i + 4) < count)) rte_prefetch0(mbufs[i + 4]); req_id = rxq->empty_rx_reqs[next_to_use]; - rc = validate_rx_req_id(rxq, req_id); - if (unlikely(rc)) - break; - rx_info = &rxq->rx_buffer_info[req_id]; - /* prepare physical address for DMA transaction */ - ebuf.paddr = mbuf->buf_iova + RTE_PKTMBUF_HEADROOM; - ebuf.len = mbuf->buf_len - RTE_PKTMBUF_HEADROOM; - /* pass resource to device */ - rc = ena_com_add_single_rx_desc(rxq->ena_com_io_sq, - &ebuf, req_id); - if (unlikely(rc)) { - PMD_DRV_LOG(WARNING, "failed adding rx desc\n"); + rc = ena_add_single_rx_desc(rxq->ena_com_io_sq, mbuf, req_id); + if (unlikely(rc != 0)) break; - } + rx_info->mbuf = mbuf; next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, rxq->size_mask); } @@ -1464,8 +1508,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count) if (unlikely(i < count)) { PMD_DRV_LOG(WARNING, "refilled rx qid %d with only %d " "buffers (from %d)\n", rxq->id, i, count); - rte_mempool_put_bulk(rxq->mb_pool, (void **)(&mbufs[i]), - count - i); + rte_pktmbuf_free_bulk(&mbufs[i], count - i); ++rxq->rx_stats.refill_partial; } @@ -1481,6 +1524,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count) } static int ena_device_init(struct ena_com_dev *ena_dev, + struct rte_pci_device *pdev, struct ena_com_dev_get_features_ctx *get_feat_ctx, bool *wd_state) { @@ -1498,9 +1542,7 @@ static int ena_device_init(struct ena_com_dev *ena_dev, /* The PCIe configuration space revision id indicate if mmio reg * read is disabled. */ - readless_supported = - !(((struct rte_pci_device *)ena_dev->dmadev)->id.class_id - & ENA_MMIO_DISABLE_REG_READ); + readless_supported = !(pdev->id.class_id & ENA_MMIO_DISABLE_REG_READ); ena_com_set_mmio_read_mode(ena_dev, readless_supported); /* reset device */ @@ -1571,12 +1613,13 @@ err_mmio_read_less: static void ena_interrupt_handler_rte(void *cb_arg) { - struct ena_adapter *adapter = cb_arg; + struct rte_eth_dev *dev = cb_arg; + struct ena_adapter *adapter = dev->data->dev_private; struct ena_com_dev *ena_dev = &adapter->ena_dev; ena_com_admin_q_comp_intr_handler(ena_dev); if (likely(adapter->state != ENA_ADAPTER_STATE_CLOSED)) - ena_com_aenq_intr_handler(ena_dev, adapter); + ena_com_aenq_intr_handler(ena_dev, dev); } static void check_for_missing_keep_alive(struct ena_adapter *adapter) @@ -1609,15 +1652,15 @@ static void check_for_admin_com_state(struct ena_adapter *adapter) static void ena_timer_wd_callback(__rte_unused struct rte_timer *timer, void *arg) { - struct ena_adapter *adapter = arg; - struct rte_eth_dev *dev = adapter->rte_dev; + struct rte_eth_dev *dev = arg; + struct ena_adapter *adapter = dev->data->dev_private; check_for_missing_keep_alive(adapter); check_for_admin_com_state(adapter); if (unlikely(adapter->trigger_reset)) { PMD_DRV_LOG(ERR, "Trigger reset is on\n"); - _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, + rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, NULL); } } @@ -1736,7 +1779,7 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) int rc; static int adapters_found; bool disable_meta_caching; - bool wd_state; + bool wd_state = false; eth_dev->dev_ops = &ena_dev_ops; eth_dev->rx_pkt_burst = ð_ena_recv_pkts; @@ -1746,14 +1789,14 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; + eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; + memset(adapter, 0, sizeof(struct ena_adapter)); ena_dev = &adapter->ena_dev; - adapter->rte_eth_dev_data = eth_dev->data; - adapter->rte_dev = eth_dev; + adapter->edev_data = eth_dev->data; pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); - adapter->pdev = pci_dev; PMD_INIT_LOG(INFO, "Initializing %x:%x:%x.%d", pci_dev->addr.domain, @@ -1773,7 +1816,8 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) } ena_dev->reg_bar = adapter->regs; - ena_dev->dmadev = adapter->pdev; + /* This is a dummy pointer for ena_com functions. */ + ena_dev->dmadev = adapter; adapter->id_number = adapters_found; @@ -1787,7 +1831,7 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) } /* device specific initialization routine */ - rc = ena_device_init(ena_dev, &get_feat_ctx, &wd_state); + rc = ena_device_init(ena_dev, pci_dev, &get_feat_ctx, &wd_state); if (rc) { PMD_INIT_LOG(CRIT, "Failed to init ENA device"); goto err; @@ -1857,12 +1901,6 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) get_feat_ctx.dev_attr.mac_addr, (struct rte_ether_addr *)adapter->mac_addr); - /* - * Pass the information to the rte_eth_dev_close() that it should also - * release the private port resources. - */ - eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; - adapter->drv_stats = rte_zmalloc("adapter stats", sizeof(*adapter->drv_stats), RTE_CACHE_LINE_SIZE); @@ -1872,9 +1910,11 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) goto err_delete_debug_area; } + rte_spinlock_init(&adapter->admin_lock); + rte_intr_callback_register(intr_handle, ena_interrupt_handler_rte, - adapter); + eth_dev); rte_intr_enable(intr_handle); ena_com_set_admin_polling_mode(ena_dev, false); ena_com_admin_aenq_enable(ena_dev); @@ -1930,11 +1970,6 @@ static int eth_ena_dev_uninit(struct rte_eth_dev *eth_dev) ena_destroy_device(eth_dev); - eth_dev->dev_ops = NULL; - eth_dev->rx_pkt_burst = NULL; - eth_dev->tx_pkt_burst = NULL; - eth_dev->tx_pkt_prepare = NULL; - return 0; } @@ -1944,6 +1979,9 @@ static int ena_dev_configure(struct rte_eth_dev *dev) adapter->state = ENA_ADAPTER_STATE_CONFIG; + if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) + dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH; + adapter->tx_selected_offloads = dev->data->dev_conf.txmode.offloads; adapter->rx_selected_offloads = dev->data->dev_conf.rxmode.offloads; return 0; @@ -2020,6 +2058,7 @@ static int ena_infos_get(struct rte_eth_dev *dev, /* Inform framework about available features */ dev_info->rx_offload_capa = rx_feat; + dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_RSS_HASH; dev_info->rx_queue_offload_capa = rx_feat; dev_info->tx_offload_capa = tx_feat; dev_info->tx_queue_offload_capa = tx_feat; @@ -2052,6 +2091,9 @@ static int ena_infos_get(struct rte_eth_dev *dev, dev_info->tx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, adapter->max_tx_sgl_size); + dev_info->default_rxportconf.ring_size = ENA_DEFAULT_RING_SIZE; + dev_info->default_txportconf.ring_size = ENA_DEFAULT_RING_SIZE; + return 0; } @@ -2072,6 +2114,7 @@ static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, struct rte_mbuf *mbuf; struct rte_mbuf *mbuf_head; struct ena_rx_buffer *rx_info; + int rc; uint16_t ntc, len, req_id, buf = 0; if (unlikely(descs == 0)) @@ -2081,8 +2124,6 @@ static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, len = ena_bufs[buf].len; req_id = ena_bufs[buf].req_id; - if (unlikely(validate_rx_req_id(rx_ring, req_id))) - return NULL; rx_info = &rx_ring->rx_buffer_info[req_id]; @@ -2106,21 +2147,48 @@ static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, ++buf; len = ena_bufs[buf].len; req_id = ena_bufs[buf].req_id; - if (unlikely(validate_rx_req_id(rx_ring, req_id))) { - rte_mbuf_raw_free(mbuf_head); - return NULL; - } rx_info = &rx_ring->rx_buffer_info[req_id]; RTE_ASSERT(rx_info->mbuf != NULL); - /* Create an mbuf chain. */ - mbuf->next = rx_info->mbuf; - mbuf = mbuf->next; + if (unlikely(len == 0)) { + /* + * Some devices can pass descriptor with the length 0. + * To avoid confusion, the PMD is simply putting the + * descriptor back, as it was never used. We'll avoid + * mbuf allocation that way. + */ + rc = ena_add_single_rx_desc(rx_ring->ena_com_io_sq, + rx_info->mbuf, req_id); + if (unlikely(rc != 0)) { + /* Free the mbuf in case of an error. */ + rte_mbuf_raw_free(rx_info->mbuf); + } else { + /* + * If there was no error, just exit the loop as + * 0 length descriptor is always the last one. + */ + break; + } + } else { + /* Create an mbuf chain. */ + mbuf->next = rx_info->mbuf; + mbuf = mbuf->next; - ena_init_rx_mbuf(mbuf, len); - mbuf_head->pkt_len += len; + ena_init_rx_mbuf(mbuf, len); + mbuf_head->pkt_len += len; + } + /* + * Mark the descriptor as depleted and perform necessary + * cleanup. + * This code will execute in two cases: + * 1. Descriptor len was greater than 0 - normal situation. + * 2. Descriptor len was 0 and we failed to add the descriptor + * to the device. In that situation, we should try to add + * the mbuf again in the populate routine and mark the + * descriptor as used up by the device. + */ rx_info->mbuf = NULL; rx_ring->empty_rx_reqs[ntc] = req_id; ntc = ENA_IDX_NEXT_MASKED(ntc, rx_ring->size_mask); @@ -2166,10 +2234,16 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, &ena_rx_ctx); if (unlikely(rc)) { PMD_DRV_LOG(ERR, "ena_com_rx_pkt error %d\n", rc); - rx_ring->adapter->reset_reason = - ENA_REGS_RESET_TOO_MANY_RX_DESCS; + if (rc == ENA_COM_NO_SPACE) { + ++rx_ring->rx_stats.bad_desc_num; + rx_ring->adapter->reset_reason = + ENA_REGS_RESET_TOO_MANY_RX_DESCS; + } else { + ++rx_ring->rx_stats.bad_req_id; + rx_ring->adapter->reset_reason = + ENA_REGS_RESET_INV_RX_REQ_ID; + } rx_ring->adapter->trigger_reset = true; - ++rx_ring->rx_stats.bad_desc_num; return 0; } @@ -2197,8 +2271,6 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, ++rx_ring->rx_stats.bad_csum; } - mbuf->hash.rss = ena_rx_ctx.hash; - rx_pkts[completed] = mbuf; rx_ring->rx_stats.bytes += mbuf->pkt_len; } @@ -2313,8 +2385,8 @@ static void ena_update_hints(struct ena_adapter *adapter, } } -static int ena_check_and_linearize_mbuf(struct ena_ring *tx_ring, - struct rte_mbuf *mbuf) +static int ena_check_space_and_linearize_mbuf(struct ena_ring *tx_ring, + struct rte_mbuf *mbuf) { struct ena_com_dev *ena_dev; int num_segments, header_len, rc; @@ -2324,13 +2396,21 @@ static int ena_check_and_linearize_mbuf(struct ena_ring *tx_ring, header_len = mbuf->data_len; if (likely(num_segments < tx_ring->sgl_size)) - return 0; + goto checkspace; if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV && (num_segments == tx_ring->sgl_size) && (header_len < tx_ring->tx_max_header_size)) - return 0; + goto checkspace; + /* Checking for space for 2 additional metadata descriptors due to + * possible header split and metadata descriptor. Linearization will + * be needed so we reduce the segments number from num_segments to 1 + */ + if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq, 3)) { + PMD_DRV_LOG(DEBUG, "Not enough space in the tx queue\n"); + return ENA_COM_NO_MEM; + } ++tx_ring->tx_stats.linearize; rc = rte_pktmbuf_linearize(mbuf); if (unlikely(rc)) { @@ -2340,201 +2420,266 @@ static int ena_check_and_linearize_mbuf(struct ena_ring *tx_ring, return rc; } - return rc; + return 0; + +checkspace: + /* Checking for space for 2 additional metadata descriptors due to + * possible header split and metadata descriptor + */ + if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq, + num_segments + 2)) { + PMD_DRV_LOG(DEBUG, "Not enough space in the tx queue\n"); + return ENA_COM_NO_MEM; + } + + return 0; } -static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, - uint16_t nb_pkts) +static void ena_tx_map_mbuf(struct ena_ring *tx_ring, + struct ena_tx_buffer *tx_info, + struct rte_mbuf *mbuf, + void **push_header, + uint16_t *header_len) { - struct ena_ring *tx_ring = (struct ena_ring *)(tx_queue); - uint16_t next_to_use = tx_ring->next_to_use; - uint16_t next_to_clean = tx_ring->next_to_clean; - struct rte_mbuf *mbuf; - uint16_t seg_len; - unsigned int cleanup_budget; - struct ena_com_tx_ctx ena_tx_ctx; - struct ena_tx_buffer *tx_info; - struct ena_com_buf *ebuf; - uint16_t rc, req_id, total_tx_descs = 0; - uint16_t sent_idx = 0; - uint16_t push_len = 0; - uint16_t delta = 0; - int nb_hw_desc; - uint32_t total_length; + struct ena_com_buf *ena_buf; + uint16_t delta, seg_len, push_len; - /* Check adapter state */ - if (unlikely(tx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) { - PMD_DRV_LOG(ALERT, - "Trying to xmit pkts while device is NOT running\n"); - return 0; - } + delta = 0; + seg_len = mbuf->data_len; - nb_pkts = RTE_MIN(ena_com_free_q_entries(tx_ring->ena_com_io_sq), - nb_pkts); + tx_info->mbuf = mbuf; + ena_buf = tx_info->bufs; - for (sent_idx = 0; sent_idx < nb_pkts; sent_idx++) { - mbuf = tx_pkts[sent_idx]; - total_length = 0; + if (tx_ring->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { + /* + * Tx header might be (and will be in most cases) smaller than + * tx_max_header_size. But it's not an issue to send more data + * to the device, than actually needed if the mbuf size is + * greater than tx_max_header_size. + */ + push_len = RTE_MIN(mbuf->pkt_len, tx_ring->tx_max_header_size); + *header_len = push_len; - rc = ena_check_and_linearize_mbuf(tx_ring, mbuf); - if (unlikely(rc)) - break; + if (likely(push_len <= seg_len)) { + /* If the push header is in the single segment, then + * just point it to the 1st mbuf data. + */ + *push_header = rte_pktmbuf_mtod(mbuf, uint8_t *); + } else { + /* If the push header lays in the several segments, copy + * it to the intermediate buffer. + */ + rte_pktmbuf_read(mbuf, 0, push_len, + tx_ring->push_buf_intermediate_buf); + *push_header = tx_ring->push_buf_intermediate_buf; + delta = push_len - seg_len; + } + } else { + *push_header = NULL; + *header_len = 0; + push_len = 0; + } - req_id = tx_ring->empty_tx_reqs[next_to_use]; - tx_info = &tx_ring->tx_buffer_info[req_id]; - tx_info->mbuf = mbuf; - tx_info->num_of_bufs = 0; - ebuf = tx_info->bufs; + /* Process first segment taking into consideration pushed header */ + if (seg_len > push_len) { + ena_buf->paddr = mbuf->buf_iova + + mbuf->data_off + + push_len; + ena_buf->len = seg_len - push_len; + ena_buf++; + tx_info->num_of_bufs++; + } - /* Prepare TX context */ - memset(&ena_tx_ctx, 0x0, sizeof(struct ena_com_tx_ctx)); - memset(&ena_tx_ctx.ena_meta, 0x0, - sizeof(struct ena_com_tx_meta)); - ena_tx_ctx.ena_bufs = ebuf; - ena_tx_ctx.req_id = req_id; + while ((mbuf = mbuf->next) != NULL) { + seg_len = mbuf->data_len; + + /* Skip mbufs if whole data is pushed as a header */ + if (unlikely(delta > seg_len)) { + delta -= seg_len; + continue; + } + + ena_buf->paddr = mbuf->buf_iova + mbuf->data_off + delta; + ena_buf->len = seg_len - delta; + ena_buf++; + tx_info->num_of_bufs++; delta = 0; - seg_len = mbuf->data_len; + } +} + +static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf) +{ + struct ena_tx_buffer *tx_info; + struct ena_com_tx_ctx ena_tx_ctx = { { 0 } }; + uint16_t next_to_use; + uint16_t header_len; + uint16_t req_id; + void *push_header; + int nb_hw_desc; + int rc; - if (tx_ring->tx_mem_queue_type == - ENA_ADMIN_PLACEMENT_POLICY_DEV) { - push_len = RTE_MIN(mbuf->pkt_len, - tx_ring->tx_max_header_size); - ena_tx_ctx.header_len = push_len; + rc = ena_check_space_and_linearize_mbuf(tx_ring, mbuf); + if (unlikely(rc)) + return rc; - if (likely(push_len <= seg_len)) { - /* If the push header is in the single segment, - * then just point it to the 1st mbuf data. - */ - ena_tx_ctx.push_header = - rte_pktmbuf_mtod(mbuf, uint8_t *); - } else { - /* If the push header lays in the several - * segments, copy it to the intermediate buffer. - */ - rte_pktmbuf_read(mbuf, 0, push_len, - tx_ring->push_buf_intermediate_buf); - ena_tx_ctx.push_header = - tx_ring->push_buf_intermediate_buf; - delta = push_len - seg_len; - } - } /* there's no else as we take advantage of memset zeroing */ + next_to_use = tx_ring->next_to_use; - /* Set TX offloads flags, if applicable */ - ena_tx_mbuf_prepare(mbuf, &ena_tx_ctx, tx_ring->offloads, - tx_ring->disable_meta_caching); + req_id = tx_ring->empty_tx_reqs[next_to_use]; + tx_info = &tx_ring->tx_buffer_info[req_id]; + tx_info->num_of_bufs = 0; - rte_prefetch0(tx_pkts[ENA_IDX_ADD_MASKED( - sent_idx, 4, tx_ring->size_mask)]); + ena_tx_map_mbuf(tx_ring, tx_info, mbuf, &push_header, &header_len); - /* Process first segment taking into - * consideration pushed header - */ - if (seg_len > push_len) { - ebuf->paddr = mbuf->buf_iova + - mbuf->data_off + - push_len; - ebuf->len = seg_len - push_len; - ebuf++; - tx_info->num_of_bufs++; - } - total_length += mbuf->data_len; + ena_tx_ctx.ena_bufs = tx_info->bufs; + ena_tx_ctx.push_header = push_header; + ena_tx_ctx.num_bufs = tx_info->num_of_bufs; + ena_tx_ctx.req_id = req_id; + ena_tx_ctx.header_len = header_len; - while ((mbuf = mbuf->next) != NULL) { - seg_len = mbuf->data_len; + /* Set Tx offloads flags, if applicable */ + ena_tx_mbuf_prepare(mbuf, &ena_tx_ctx, tx_ring->offloads, + tx_ring->disable_meta_caching); - /* Skip mbufs if whole data is pushed as a header */ - if (unlikely(delta > seg_len)) { - delta -= seg_len; - continue; - } + if (unlikely(ena_com_is_doorbell_needed(tx_ring->ena_com_io_sq, + &ena_tx_ctx))) { + PMD_DRV_LOG(DEBUG, + "llq tx max burst size of queue %d achieved, writing doorbell to send burst\n", + tx_ring->id); + ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); + tx_ring->tx_stats.doorbells++; + tx_ring->pkts_without_db = false; + } - ebuf->paddr = mbuf->buf_iova + mbuf->data_off + delta; - ebuf->len = seg_len - delta; - total_length += ebuf->len; - ebuf++; - tx_info->num_of_bufs++; + /* prepare the packet's descriptors to dma engine */ + rc = ena_com_prepare_tx(tx_ring->ena_com_io_sq, &ena_tx_ctx, + &nb_hw_desc); + if (unlikely(rc)) { + ++tx_ring->tx_stats.prepare_ctx_err; + return rc; + } - delta = 0; - } + tx_info->tx_descs = nb_hw_desc; - ena_tx_ctx.num_bufs = tx_info->num_of_bufs; + tx_ring->tx_stats.cnt++; + tx_ring->tx_stats.bytes += mbuf->pkt_len; - if (ena_com_is_doorbell_needed(tx_ring->ena_com_io_sq, - &ena_tx_ctx)) { - PMD_DRV_LOG(DEBUG, "llq tx max burst size of queue %d" - " achieved, writing doorbell to send burst\n", - tx_ring->id); - ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); - } + tx_ring->next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, + tx_ring->size_mask); - /* prepare the packet's descriptors to dma engine */ - rc = ena_com_prepare_tx(tx_ring->ena_com_io_sq, - &ena_tx_ctx, &nb_hw_desc); - if (unlikely(rc)) { - ++tx_ring->tx_stats.prepare_ctx_err; - break; - } - tx_info->tx_descs = nb_hw_desc; + return 0; +} - next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, - tx_ring->size_mask); - tx_ring->tx_stats.cnt++; - tx_ring->tx_stats.bytes += total_length; - } - tx_ring->tx_stats.available_desc = - ena_com_free_q_entries(tx_ring->ena_com_io_sq); +static void ena_tx_cleanup(struct ena_ring *tx_ring) +{ + unsigned int cleanup_budget; + unsigned int total_tx_descs = 0; + uint16_t next_to_clean = tx_ring->next_to_clean; - /* If there are ready packets to be xmitted... */ - if (sent_idx > 0) { - /* ...let HW do its best :-) */ - ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); - tx_ring->tx_stats.doorbells++; - tx_ring->next_to_use = next_to_use; - } + cleanup_budget = RTE_MIN(tx_ring->ring_size / ENA_REFILL_THRESH_DIVIDER, + (unsigned int)ENA_REFILL_THRESH_PACKET); - /* Clear complete packets */ - while (ena_com_tx_comp_req_id_get(tx_ring->ena_com_io_cq, &req_id) >= 0) { - rc = validate_tx_req_id(tx_ring, req_id); - if (rc) + while (likely(total_tx_descs < cleanup_budget)) { + struct rte_mbuf *mbuf; + struct ena_tx_buffer *tx_info; + uint16_t req_id; + + if (ena_com_tx_comp_req_id_get(tx_ring->ena_com_io_cq, &req_id) != 0) + break; + + if (unlikely(validate_tx_req_id(tx_ring, req_id) != 0)) break; /* Get Tx info & store how many descs were processed */ tx_info = &tx_ring->tx_buffer_info[req_id]; - total_tx_descs += tx_info->tx_descs; - /* Free whole mbuf chain */ mbuf = tx_info->mbuf; rte_pktmbuf_free(mbuf); + tx_info->mbuf = NULL; + tx_ring->empty_tx_reqs[next_to_clean] = req_id; + + total_tx_descs += tx_info->tx_descs; /* Put back descriptor to the ring for reuse */ - tx_ring->empty_tx_reqs[next_to_clean] = req_id; next_to_clean = ENA_IDX_NEXT_MASKED(next_to_clean, tx_ring->size_mask); - cleanup_budget = - RTE_MIN(tx_ring->ring_size / ENA_REFILL_THRESH_DIVIDER, - (unsigned int)ENA_REFILL_THRESH_PACKET); - - /* If too many descs to clean, leave it for another run */ - if (unlikely(total_tx_descs > cleanup_budget)) - break; } - tx_ring->tx_stats.available_desc = - ena_com_free_q_entries(tx_ring->ena_com_io_sq); - if (total_tx_descs > 0) { + if (likely(total_tx_descs > 0)) { /* acknowledge completion of sent packets */ tx_ring->next_to_clean = next_to_clean; ena_com_comp_ack(tx_ring->ena_com_io_sq, total_tx_descs); ena_com_update_dev_comp_head(tx_ring->ena_com_io_cq); } +} + +static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts) +{ + struct ena_ring *tx_ring = (struct ena_ring *)(tx_queue); + uint16_t sent_idx = 0; + + /* Check adapter state */ + if (unlikely(tx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) { + PMD_DRV_LOG(ALERT, + "Trying to xmit pkts while device is NOT running\n"); + return 0; + } + + for (sent_idx = 0; sent_idx < nb_pkts; sent_idx++) { + if (ena_xmit_mbuf(tx_ring, tx_pkts[sent_idx])) + break; + tx_ring->pkts_without_db = true; + rte_prefetch0(tx_pkts[ENA_IDX_ADD_MASKED(sent_idx, 4, + tx_ring->size_mask)]); + } + + tx_ring->tx_stats.available_desc = + ena_com_free_q_entries(tx_ring->ena_com_io_sq); + /* If there are ready packets to be xmitted... */ + if (likely(tx_ring->pkts_without_db)) { + /* ...let HW do its best :-) */ + ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); + tx_ring->tx_stats.doorbells++; + tx_ring->pkts_without_db = false; + } + + ena_tx_cleanup(tx_ring); + + tx_ring->tx_stats.available_desc = + ena_com_free_q_entries(tx_ring->ena_com_io_sq); tx_ring->tx_stats.tx_poll++; return sent_idx; } +int ena_copy_eni_stats(struct ena_adapter *adapter) +{ + struct ena_admin_eni_stats admin_eni_stats; + int rc; + + rte_spinlock_lock(&adapter->admin_lock); + rc = ena_com_get_eni_stats(&adapter->ena_dev, &admin_eni_stats); + rte_spinlock_unlock(&adapter->admin_lock); + if (rc != 0) { + if (rc == ENA_COM_UNSUPPORTED) { + PMD_DRV_LOG(DEBUG, + "Retrieving ENI metrics is not supported.\n"); + } else { + PMD_DRV_LOG(WARNING, + "Failed to get ENI metrics: %d\n", rc); + } + return rc; + } + + rte_memcpy(&adapter->eni_stats, &admin_eni_stats, + sizeof(struct ena_stats_eni)); + + return 0; +} + /** * DPDK callback to retrieve names of extended device statistics * @@ -2552,7 +2697,7 @@ static int ena_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned int n) { - unsigned int xstats_count = ena_xstats_calc_num(dev); + unsigned int xstats_count = ena_xstats_calc_num(dev->data); unsigned int stat, i, count = 0; if (n < xstats_count || !xstats_names) @@ -2562,6 +2707,10 @@ static int ena_xstats_get_names(struct rte_eth_dev *dev, strcpy(xstats_names[count].name, ena_stats_global_strings[stat].name); + for (stat = 0; stat < ENA_STATS_ARRAY_ENI; stat++, count++) + strcpy(xstats_names[count].name, + ena_stats_eni_strings[stat].name); + for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) for (i = 0; i < dev->data->nb_rx_queues; i++, count++) snprintf(xstats_names[count].name, @@ -2597,7 +2746,7 @@ static int ena_xstats_get(struct rte_eth_dev *dev, unsigned int n) { struct ena_adapter *adapter = dev->data->dev_private; - unsigned int xstats_count = ena_xstats_calc_num(dev); + unsigned int xstats_count = ena_xstats_calc_num(dev->data); unsigned int stat, i, count = 0; int stat_offset; void *stats_begin; @@ -2609,7 +2758,7 @@ static int ena_xstats_get(struct rte_eth_dev *dev, return 0; for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) { - stat_offset = ena_stats_rx_strings[stat].stat_offset; + stat_offset = ena_stats_global_strings[stat].stat_offset; stats_begin = &adapter->dev_stats; xstats[count].id = count; @@ -2617,6 +2766,19 @@ static int ena_xstats_get(struct rte_eth_dev *dev, ((char *)stats_begin + stat_offset)); } + /* Even if the function below fails, we should copy previous (or initial + * values) to keep structure of rte_eth_xstat consistent. + */ + ena_copy_eni_stats(adapter); + for (stat = 0; stat < ENA_STATS_ARRAY_ENI; stat++, count++) { + stat_offset = ena_stats_eni_strings[stat].stat_offset; + stats_begin = &adapter->eni_stats; + + xstats[count].id = count; + xstats[count].value = *((uint64_t *) + ((char *)stats_begin + stat_offset)); + } + for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) { for (i = 0; i < dev->data->nb_rx_queues; i++, count++) { stat_offset = ena_stats_rx_strings[stat].stat_offset; @@ -2653,6 +2815,8 @@ static int ena_xstats_get_by_id(struct rte_eth_dev *dev, unsigned int i; int qid; int valid = 0; + bool was_eni_copied = false; + for (i = 0; i < n; ++i) { id = ids[i]; /* Check if id belongs to global statistics */ @@ -2662,8 +2826,24 @@ static int ena_xstats_get_by_id(struct rte_eth_dev *dev, continue; } - /* Check if id belongs to rx queue statistics */ + /* Check if id belongs to ENI statistics */ id -= ENA_STATS_ARRAY_GLOBAL; + if (id < ENA_STATS_ARRAY_ENI) { + /* Avoid reading ENI stats multiple times in a single + * function call, as it requires communication with the + * admin queue. + */ + if (!was_eni_copied) { + was_eni_copied = true; + ena_copy_eni_stats(adapter); + } + values[i] = *((uint64_t *)&adapter->eni_stats + id); + ++valid; + continue; + } + + /* Check if id belongs to rx queue statistics */ + id -= ENA_STATS_ARRAY_ENI; rx_entries = ENA_STATS_ARRAY_RX * dev->data->nb_rx_queues; if (id < rx_entries) { qid = id % dev->data->nb_rx_queues; @@ -2709,7 +2889,7 @@ static int ena_process_bool_devarg(const char *key, } /* Now, assign it to the proper adapter field. */ - if (strcmp(key, ENA_DEVARG_LARGE_LLQ_HDR)) + if (strcmp(key, ENA_DEVARG_LARGE_LLQ_HDR) == 0) adapter->use_large_llq_hdr = bool_value; return 0; @@ -2720,6 +2900,7 @@ static int ena_parse_devargs(struct ena_adapter *adapter, { static const char * const allowed_args[] = { ENA_DEVARG_LARGE_LLQ_HDR, + NULL, }; struct rte_kvargs *kvlist; int rc; @@ -2769,40 +2950,20 @@ RTE_PMD_REGISTER_PCI(net_ena, rte_ena_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_ena, pci_id_ena_map); RTE_PMD_REGISTER_KMOD_DEP(net_ena, "* igb_uio | uio_pci_generic | vfio-pci"); RTE_PMD_REGISTER_PARAM_STRING(net_ena, ENA_DEVARG_LARGE_LLQ_HDR "=<0|1>"); - -RTE_INIT(ena_init_log) -{ - ena_logtype_init = rte_log_register("pmd.net.ena.init"); - if (ena_logtype_init >= 0) - rte_log_set_level(ena_logtype_init, RTE_LOG_NOTICE); - ena_logtype_driver = rte_log_register("pmd.net.ena.driver"); - if (ena_logtype_driver >= 0) - rte_log_set_level(ena_logtype_driver, RTE_LOG_NOTICE); - +RTE_LOG_REGISTER_SUFFIX(ena_logtype_init, init, NOTICE); +RTE_LOG_REGISTER_SUFFIX(ena_logtype_driver, driver, NOTICE); #ifdef RTE_LIBRTE_ENA_DEBUG_RX - ena_logtype_rx = rte_log_register("pmd.net.ena.rx"); - if (ena_logtype_rx >= 0) - rte_log_set_level(ena_logtype_rx, RTE_LOG_NOTICE); +RTE_LOG_REGISTER_SUFFIX(ena_logtype_rx, rx, NOTICE); #endif - #ifdef RTE_LIBRTE_ENA_DEBUG_TX - ena_logtype_tx = rte_log_register("pmd.net.ena.tx"); - if (ena_logtype_tx >= 0) - rte_log_set_level(ena_logtype_tx, RTE_LOG_NOTICE); +RTE_LOG_REGISTER_SUFFIX(ena_logtype_tx, tx, NOTICE); #endif - #ifdef RTE_LIBRTE_ENA_DEBUG_TX_FREE - ena_logtype_tx_free = rte_log_register("pmd.net.ena.tx_free"); - if (ena_logtype_tx_free >= 0) - rte_log_set_level(ena_logtype_tx_free, RTE_LOG_NOTICE); +RTE_LOG_REGISTER_SUFFIX(ena_logtype_tx_free, tx_free, NOTICE); #endif - #ifdef RTE_LIBRTE_ENA_COM_DEBUG - ena_logtype_com = rte_log_register("pmd.net.ena.com"); - if (ena_logtype_com >= 0) - rte_log_set_level(ena_logtype_com, RTE_LOG_NOTICE); +RTE_LOG_REGISTER_SUFFIX(ena_logtype_com, com, NOTICE); #endif -} /****************************************************************************** ******************************** AENQ Handlers ******************************* @@ -2810,26 +2971,25 @@ RTE_INIT(ena_init_log) static void ena_update_on_link_change(void *adapter_data, struct ena_admin_aenq_entry *aenq_e) { - struct rte_eth_dev *eth_dev; - struct ena_adapter *adapter; + struct rte_eth_dev *eth_dev = adapter_data; + struct ena_adapter *adapter = eth_dev->data->dev_private; struct ena_admin_aenq_link_change_desc *aenq_link_desc; uint32_t status; - adapter = adapter_data; aenq_link_desc = (struct ena_admin_aenq_link_change_desc *)aenq_e; - eth_dev = adapter->rte_dev; status = get_ena_admin_aenq_link_change_desc_link_status(aenq_link_desc); adapter->link_status = status; ena_link_update(eth_dev, 0); - _rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL); + rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL); } -static void ena_notification(void *data, +static void ena_notification(void *adapter_data, struct ena_admin_aenq_entry *aenq_e) { - struct ena_adapter *adapter = data; + struct rte_eth_dev *eth_dev = adapter_data; + struct ena_adapter *adapter = eth_dev->data->dev_private; struct ena_admin_ena_hw_hints *hints; if (aenq_e->aenq_common_desc.group != ENA_ADMIN_NOTIFICATION) @@ -2837,7 +2997,7 @@ static void ena_notification(void *data, aenq_e->aenq_common_desc.group, ENA_ADMIN_NOTIFICATION); - switch (aenq_e->aenq_common_desc.syndrom) { + switch (aenq_e->aenq_common_desc.syndrome) { case ENA_ADMIN_UPDATE_HINTS: hints = (struct ena_admin_ena_hw_hints *) (&aenq_e->inline_data_w4); @@ -2845,14 +3005,15 @@ static void ena_notification(void *data, break; default: PMD_DRV_LOG(ERR, "Invalid aenq notification link state %d\n", - aenq_e->aenq_common_desc.syndrom); + aenq_e->aenq_common_desc.syndrome); } } static void ena_keep_alive(void *adapter_data, __rte_unused struct ena_admin_aenq_entry *aenq_e) { - struct ena_adapter *adapter = adapter_data; + struct rte_eth_dev *eth_dev = adapter_data; + struct ena_adapter *adapter = eth_dev->data->dev_private; struct ena_admin_aenq_keep_alive_desc *desc; uint64_t rx_drops; uint64_t tx_drops;