1702928afSMaciej Bielski /* SPDX-License-Identifier: BSD-3-Clause 238364c26SMichal Krawczyk * Copyright (c) 2015-2020 Amazon.com, Inc. or its affiliates. 31173fca2SJan Medala * All rights reserved. 41173fca2SJan Medala */ 51173fca2SJan Medala 66723c0fcSBruce Richardson #include <rte_string_fns.h> 71173fca2SJan Medala #include <rte_errno.h> 8372c1af5SJan Medala #include <rte_version.h> 9b3fc5a1aSKonstantin Ananyev #include <rte_net.h> 108a7a73f2SMichal Krawczyk #include <rte_kvargs.h> 111173fca2SJan Medala 121173fca2SJan Medala #include "ena_ethdev.h" 131173fca2SJan Medala #include "ena_logs.h" 141173fca2SJan Medala #include "ena_platform.h" 151173fca2SJan Medala #include "ena_com.h" 161173fca2SJan Medala #include "ena_eth_com.h" 171173fca2SJan Medala 181173fca2SJan Medala #include <ena_common_defs.h> 191173fca2SJan Medala #include <ena_regs_defs.h> 201173fca2SJan Medala #include <ena_admin_defs.h> 211173fca2SJan Medala #include <ena_eth_io_defs.h> 221173fca2SJan Medala 23419c3e3eSMichal Krawczyk #define DRV_MODULE_VER_MAJOR 2 24ba94dad4SMichal Krawczyk #define DRV_MODULE_VER_MINOR 5 251b48c60dSMichal Krawczyk #define DRV_MODULE_VER_SUBMINOR 0 26372c1af5SJan Medala 271173fca2SJan Medala #define __MERGE_64B_H_L(h, l) (((uint64_t)h << 32) | l) 281173fca2SJan Medala 291173fca2SJan Medala #define GET_L4_HDR_LEN(mbuf) \ 30f41b5156SOlivier Matz ((rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, \ 311173fca2SJan Medala mbuf->l3_len + mbuf->l2_len)->data_off) >> 4) 321173fca2SJan Medala 33372c1af5SJan Medala #define ETH_GSTRING_LEN 32 34372c1af5SJan Medala 35a3c9a11aSAndrew Boyer #define ARRAY_SIZE(x) RTE_DIM(x) 36372c1af5SJan Medala 3792680dc2SRafal Kozik #define ENA_MIN_RING_DESC 128 3892680dc2SRafal Kozik 39b418f0d2SMichal Krawczyk #define ENA_PTYPE_HAS_HASH (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP) 40b418f0d2SMichal Krawczyk 41372c1af5SJan Medala enum ethtool_stringset { 42372c1af5SJan Medala ETH_SS_TEST = 0, 43372c1af5SJan Medala ETH_SS_STATS, 44372c1af5SJan Medala }; 45372c1af5SJan Medala 46372c1af5SJan Medala struct ena_stats { 47372c1af5SJan Medala char name[ETH_GSTRING_LEN]; 48372c1af5SJan Medala int stat_offset; 49372c1af5SJan Medala }; 50372c1af5SJan Medala 51372c1af5SJan Medala #define ENA_STAT_ENTRY(stat, stat_type) { \ 52372c1af5SJan Medala .name = #stat, \ 53372c1af5SJan Medala .stat_offset = offsetof(struct ena_stats_##stat_type, stat) \ 54372c1af5SJan Medala } 55372c1af5SJan Medala 56372c1af5SJan Medala #define ENA_STAT_RX_ENTRY(stat) \ 57372c1af5SJan Medala ENA_STAT_ENTRY(stat, rx) 58372c1af5SJan Medala 59372c1af5SJan Medala #define ENA_STAT_TX_ENTRY(stat) \ 60372c1af5SJan Medala ENA_STAT_ENTRY(stat, tx) 61372c1af5SJan Medala 6245718adaSMichal Krawczyk #define ENA_STAT_ENI_ENTRY(stat) \ 6345718adaSMichal Krawczyk ENA_STAT_ENTRY(stat, eni) 6445718adaSMichal Krawczyk 65372c1af5SJan Medala #define ENA_STAT_GLOBAL_ENTRY(stat) \ 66372c1af5SJan Medala ENA_STAT_ENTRY(stat, dev) 67372c1af5SJan Medala 688a7a73f2SMichal Krawczyk /* Device arguments */ 698a7a73f2SMichal Krawczyk #define ENA_DEVARG_LARGE_LLQ_HDR "large_llq_hdr" 708a7a73f2SMichal Krawczyk 713adcba9aSMichal Krawczyk /* 723adcba9aSMichal Krawczyk * Each rte_memzone should have unique name. 733adcba9aSMichal Krawczyk * To satisfy it, count number of allocation and add it to name. 743adcba9aSMichal Krawczyk */ 757c0a233eSAmit Bernstein rte_atomic64_t ena_alloc_cnt; 763adcba9aSMichal Krawczyk 77372c1af5SJan Medala static const struct ena_stats ena_stats_global_strings[] = { 78372c1af5SJan Medala ENA_STAT_GLOBAL_ENTRY(wd_expired), 797830e905SSolganik Alexander ENA_STAT_GLOBAL_ENTRY(dev_start), 807830e905SSolganik Alexander ENA_STAT_GLOBAL_ENTRY(dev_stop), 81e1e73e32SMichal Krawczyk ENA_STAT_GLOBAL_ENTRY(tx_drops), 82372c1af5SJan Medala }; 83372c1af5SJan Medala 8445718adaSMichal Krawczyk static const struct ena_stats ena_stats_eni_strings[] = { 8545718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded), 8645718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded), 8745718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(pps_allowance_exceeded), 8845718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded), 8945718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded), 9045718adaSMichal Krawczyk }; 9145718adaSMichal Krawczyk 92372c1af5SJan Medala static const struct ena_stats ena_stats_tx_strings[] = { 93372c1af5SJan Medala ENA_STAT_TX_ENTRY(cnt), 94372c1af5SJan Medala ENA_STAT_TX_ENTRY(bytes), 957830e905SSolganik Alexander ENA_STAT_TX_ENTRY(prepare_ctx_err), 96372c1af5SJan Medala ENA_STAT_TX_ENTRY(linearize), 97372c1af5SJan Medala ENA_STAT_TX_ENTRY(linearize_failed), 98372c1af5SJan Medala ENA_STAT_TX_ENTRY(tx_poll), 99372c1af5SJan Medala ENA_STAT_TX_ENTRY(doorbells), 100372c1af5SJan Medala ENA_STAT_TX_ENTRY(bad_req_id), 1017830e905SSolganik Alexander ENA_STAT_TX_ENTRY(available_desc), 102f93e20e5SMichal Krawczyk ENA_STAT_TX_ENTRY(missed_tx), 103372c1af5SJan Medala }; 104372c1af5SJan Medala 105372c1af5SJan Medala static const struct ena_stats ena_stats_rx_strings[] = { 106372c1af5SJan Medala ENA_STAT_RX_ENTRY(cnt), 107372c1af5SJan Medala ENA_STAT_RX_ENTRY(bytes), 1087830e905SSolganik Alexander ENA_STAT_RX_ENTRY(refill_partial), 109372c1af5SJan Medala ENA_STAT_RX_ENTRY(bad_csum), 1107830e905SSolganik Alexander ENA_STAT_RX_ENTRY(mbuf_alloc_fail), 111372c1af5SJan Medala ENA_STAT_RX_ENTRY(bad_desc_num), 1127830e905SSolganik Alexander ENA_STAT_RX_ENTRY(bad_req_id), 113372c1af5SJan Medala }; 114372c1af5SJan Medala 115372c1af5SJan Medala #define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings) 11645718adaSMichal Krawczyk #define ENA_STATS_ARRAY_ENI ARRAY_SIZE(ena_stats_eni_strings) 117372c1af5SJan Medala #define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) 118372c1af5SJan Medala #define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) 1191173fca2SJan Medala 120295968d1SFerruh Yigit #define QUEUE_OFFLOADS (RTE_ETH_TX_OFFLOAD_TCP_CKSUM |\ 121295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_UDP_CKSUM |\ 122295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |\ 123295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_TCP_TSO) 124*daa02b5cSOlivier Matz #define MBUF_OFFLOADS (RTE_MBUF_F_TX_L4_MASK |\ 125*daa02b5cSOlivier Matz RTE_MBUF_F_TX_IP_CKSUM |\ 126*daa02b5cSOlivier Matz RTE_MBUF_F_TX_TCP_SEG) 12756b8b9b7SRafal Kozik 1281173fca2SJan Medala /** Vendor ID used by Amazon devices */ 1291173fca2SJan Medala #define PCI_VENDOR_ID_AMAZON 0x1D0F 1301173fca2SJan Medala /** Amazon devices */ 1311173fca2SJan Medala #define PCI_DEVICE_ID_ENA_VF 0xEC20 132f7138b91SMichal Krawczyk #define PCI_DEVICE_ID_ENA_VF_RSERV0 0xEC21 1331173fca2SJan Medala 134*daa02b5cSOlivier Matz #define ENA_TX_OFFLOAD_MASK (RTE_MBUF_F_TX_L4_MASK | \ 135*daa02b5cSOlivier Matz RTE_MBUF_F_TX_IPV6 | \ 136*daa02b5cSOlivier Matz RTE_MBUF_F_TX_IPV4 | \ 137*daa02b5cSOlivier Matz RTE_MBUF_F_TX_IP_CKSUM | \ 138*daa02b5cSOlivier Matz RTE_MBUF_F_TX_TCP_SEG) 139b3fc5a1aSKonstantin Ananyev 140b3fc5a1aSKonstantin Ananyev #define ENA_TX_OFFLOAD_NOTSUP_MASK \ 141*daa02b5cSOlivier Matz (RTE_MBUF_F_TX_OFFLOAD_MASK ^ ENA_TX_OFFLOAD_MASK) 142b3fc5a1aSKonstantin Ananyev 143e8c838fdSMichal Krawczyk /** HW specific offloads capabilities. */ 144e8c838fdSMichal Krawczyk /* IPv4 checksum offload. */ 145e8c838fdSMichal Krawczyk #define ENA_L3_IPV4_CSUM 0x0001 146e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv4 packets. */ 147e8c838fdSMichal Krawczyk #define ENA_L4_IPV4_CSUM 0x0002 148e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv4 packets with pseudo header checksum. */ 149e8c838fdSMichal Krawczyk #define ENA_L4_IPV4_CSUM_PARTIAL 0x0004 150e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv6 packets. */ 151e8c838fdSMichal Krawczyk #define ENA_L4_IPV6_CSUM 0x0008 152e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv6 packets with pseudo header checksum. */ 153e8c838fdSMichal Krawczyk #define ENA_L4_IPV6_CSUM_PARTIAL 0x0010 154e8c838fdSMichal Krawczyk /* TSO support for IPv4 packets. */ 155e8c838fdSMichal Krawczyk #define ENA_IPV4_TSO 0x0020 156e8c838fdSMichal Krawczyk 157e8c838fdSMichal Krawczyk /* Device supports setting RSS hash. */ 158e8c838fdSMichal Krawczyk #define ENA_RX_RSS_HASH 0x0040 159e8c838fdSMichal Krawczyk 16028a1fd4fSFerruh Yigit static const struct rte_pci_id pci_id_ena_map[] = { 161cb990571SDavid Marchand { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF) }, 162f7138b91SMichal Krawczyk { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF_RSERV0) }, 1631173fca2SJan Medala { .device_id = 0 }, 1641173fca2SJan Medala }; 1651173fca2SJan Medala 166ca148440SMichal Krawczyk static struct ena_aenq_handlers aenq_handlers; 1673adcba9aSMichal Krawczyk 1681173fca2SJan Medala static int ena_device_init(struct ena_com_dev *ena_dev, 169aab58857SStanislaw Kardach struct rte_pci_device *pdev, 170e859d2b8SRafal Kozik struct ena_com_dev_get_features_ctx *get_feat_ctx, 171e859d2b8SRafal Kozik bool *wd_state); 1721173fca2SJan Medala static int ena_dev_configure(struct rte_eth_dev *dev); 17336278b82SMichal Krawczyk static void ena_tx_map_mbuf(struct ena_ring *tx_ring, 17436278b82SMichal Krawczyk struct ena_tx_buffer *tx_info, 17536278b82SMichal Krawczyk struct rte_mbuf *mbuf, 17636278b82SMichal Krawczyk void **push_header, 17736278b82SMichal Krawczyk uint16_t *header_len); 17836278b82SMichal Krawczyk static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf); 17936278b82SMichal Krawczyk static void ena_tx_cleanup(struct ena_ring *tx_ring); 1801173fca2SJan Medala static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 1811173fca2SJan Medala uint16_t nb_pkts); 182b3fc5a1aSKonstantin Ananyev static uint16_t eth_ena_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 183b3fc5a1aSKonstantin Ananyev uint16_t nb_pkts); 1841173fca2SJan Medala static int ena_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 1851173fca2SJan Medala uint16_t nb_desc, unsigned int socket_id, 1861173fca2SJan Medala const struct rte_eth_txconf *tx_conf); 1871173fca2SJan Medala static int ena_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 1881173fca2SJan Medala uint16_t nb_desc, unsigned int socket_id, 1891173fca2SJan Medala const struct rte_eth_rxconf *rx_conf, 1901173fca2SJan Medala struct rte_mempool *mp); 1911be097dcSMichal Krawczyk static inline void ena_init_rx_mbuf(struct rte_mbuf *mbuf, uint16_t len); 1921be097dcSMichal Krawczyk static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, 1931be097dcSMichal Krawczyk struct ena_com_rx_buf_info *ena_bufs, 1941be097dcSMichal Krawczyk uint32_t descs, 1951be097dcSMichal Krawczyk uint16_t *next_to_clean, 1961be097dcSMichal Krawczyk uint8_t offset); 1971173fca2SJan Medala static uint16_t eth_ena_recv_pkts(void *rx_queue, 1981173fca2SJan Medala struct rte_mbuf **rx_pkts, uint16_t nb_pkts); 19983fd97b2SMichal Krawczyk static int ena_add_single_rx_desc(struct ena_com_io_sq *io_sq, 20083fd97b2SMichal Krawczyk struct rte_mbuf *mbuf, uint16_t id); 2011173fca2SJan Medala static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count); 20233dde075SMichal Krawczyk static void ena_init_rings(struct ena_adapter *adapter, 20333dde075SMichal Krawczyk bool disable_meta_caching); 2041173fca2SJan Medala static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); 2051173fca2SJan Medala static int ena_start(struct rte_eth_dev *dev); 20662024eb8SIvan Ilchenko static int ena_stop(struct rte_eth_dev *dev); 207b142387bSThomas Monjalon static int ena_close(struct rte_eth_dev *dev); 2082081d5e2SMichal Krawczyk static int ena_dev_reset(struct rte_eth_dev *dev); 209d5b0924bSMatan Azrad static int ena_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); 2101173fca2SJan Medala static void ena_rx_queue_release_all(struct rte_eth_dev *dev); 2111173fca2SJan Medala static void ena_tx_queue_release_all(struct rte_eth_dev *dev); 2127483341aSXueming Li static void ena_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 2137483341aSXueming Li static void ena_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 2141173fca2SJan Medala static void ena_rx_queue_release_bufs(struct ena_ring *ring); 2151173fca2SJan Medala static void ena_tx_queue_release_bufs(struct ena_ring *ring); 2161173fca2SJan Medala static int ena_link_update(struct rte_eth_dev *dev, 217dd2c630aSFerruh Yigit int wait_to_complete); 2186986cdc4SMichal Krawczyk static int ena_create_io_queue(struct rte_eth_dev *dev, struct ena_ring *ring); 21926e5543dSRafal Kozik static void ena_queue_stop(struct ena_ring *ring); 22026e5543dSRafal Kozik static void ena_queue_stop_all(struct rte_eth_dev *dev, 22126e5543dSRafal Kozik enum ena_ring_type ring_type); 2226986cdc4SMichal Krawczyk static int ena_queue_start(struct rte_eth_dev *dev, struct ena_ring *ring); 22326e5543dSRafal Kozik static int ena_queue_start_all(struct rte_eth_dev *dev, 2241173fca2SJan Medala enum ena_ring_type ring_type); 2251173fca2SJan Medala static void ena_stats_restart(struct rte_eth_dev *dev); 2263a822d79SMichal Krawczyk static uint64_t ena_get_rx_port_offloads(struct ena_adapter *adapter); 2273a822d79SMichal Krawczyk static uint64_t ena_get_tx_port_offloads(struct ena_adapter *adapter); 2283a822d79SMichal Krawczyk static uint64_t ena_get_rx_queue_offloads(struct ena_adapter *adapter); 2293a822d79SMichal Krawczyk static uint64_t ena_get_tx_queue_offloads(struct ena_adapter *adapter); 230bdad90d1SIvan Ilchenko static int ena_infos_get(struct rte_eth_dev *dev, 2311173fca2SJan Medala struct rte_eth_dev_info *dev_info); 23215773e06SMichal Krawczyk static void ena_interrupt_handler_rte(void *cb_arg); 233d9b8b106SMichal Krawczyk static void ena_timer_wd_callback(struct rte_timer *timer, void *arg); 234e457bc70SRafal Kozik static void ena_destroy_device(struct rte_eth_dev *eth_dev); 235e457bc70SRafal Kozik static int eth_ena_dev_init(struct rte_eth_dev *eth_dev); 2367830e905SSolganik Alexander static int ena_xstats_get_names(struct rte_eth_dev *dev, 2377830e905SSolganik Alexander struct rte_eth_xstat_name *xstats_names, 2387830e905SSolganik Alexander unsigned int n); 2397830e905SSolganik Alexander static int ena_xstats_get(struct rte_eth_dev *dev, 2407830e905SSolganik Alexander struct rte_eth_xstat *stats, 2417830e905SSolganik Alexander unsigned int n); 2427830e905SSolganik Alexander static int ena_xstats_get_by_id(struct rte_eth_dev *dev, 2437830e905SSolganik Alexander const uint64_t *ids, 2447830e905SSolganik Alexander uint64_t *values, 2457830e905SSolganik Alexander unsigned int n); 2468a7a73f2SMichal Krawczyk static int ena_process_bool_devarg(const char *key, 2478a7a73f2SMichal Krawczyk const char *value, 2488a7a73f2SMichal Krawczyk void *opaque); 2498a7a73f2SMichal Krawczyk static int ena_parse_devargs(struct ena_adapter *adapter, 2508a7a73f2SMichal Krawczyk struct rte_devargs *devargs); 25145718adaSMichal Krawczyk static int ena_copy_eni_stats(struct ena_adapter *adapter); 2526986cdc4SMichal Krawczyk static int ena_setup_rx_intr(struct rte_eth_dev *dev); 2536986cdc4SMichal Krawczyk static int ena_rx_queue_intr_enable(struct rte_eth_dev *dev, 2546986cdc4SMichal Krawczyk uint16_t queue_id); 2556986cdc4SMichal Krawczyk static int ena_rx_queue_intr_disable(struct rte_eth_dev *dev, 2566986cdc4SMichal Krawczyk uint16_t queue_id); 2571173fca2SJan Medala 258103ab18cSFerruh Yigit static const struct eth_dev_ops ena_dev_ops = { 2591173fca2SJan Medala .dev_configure = ena_dev_configure, 2601173fca2SJan Medala .dev_infos_get = ena_infos_get, 2611173fca2SJan Medala .rx_queue_setup = ena_rx_queue_setup, 2621173fca2SJan Medala .tx_queue_setup = ena_tx_queue_setup, 2631173fca2SJan Medala .dev_start = ena_start, 264eb0ef49dSMichal Krawczyk .dev_stop = ena_stop, 2651173fca2SJan Medala .link_update = ena_link_update, 2661173fca2SJan Medala .stats_get = ena_stats_get, 2677830e905SSolganik Alexander .xstats_get_names = ena_xstats_get_names, 2687830e905SSolganik Alexander .xstats_get = ena_xstats_get, 2697830e905SSolganik Alexander .xstats_get_by_id = ena_xstats_get_by_id, 2701173fca2SJan Medala .mtu_set = ena_mtu_set, 2711173fca2SJan Medala .rx_queue_release = ena_rx_queue_release, 2721173fca2SJan Medala .tx_queue_release = ena_tx_queue_release, 2731173fca2SJan Medala .dev_close = ena_close, 2742081d5e2SMichal Krawczyk .dev_reset = ena_dev_reset, 2751173fca2SJan Medala .reta_update = ena_rss_reta_update, 2761173fca2SJan Medala .reta_query = ena_rss_reta_query, 2776986cdc4SMichal Krawczyk .rx_queue_intr_enable = ena_rx_queue_intr_enable, 2786986cdc4SMichal Krawczyk .rx_queue_intr_disable = ena_rx_queue_intr_disable, 27934d5e97eSMichal Krawczyk .rss_hash_update = ena_rss_hash_update, 28034d5e97eSMichal Krawczyk .rss_hash_conf_get = ena_rss_hash_conf_get, 2811173fca2SJan Medala }; 2821173fca2SJan Medala 2831173fca2SJan Medala static inline void ena_rx_mbuf_prepare(struct rte_mbuf *mbuf, 28434d5e97eSMichal Krawczyk struct ena_com_rx_ctx *ena_rx_ctx, 28534d5e97eSMichal Krawczyk bool fill_hash) 2861173fca2SJan Medala { 2871173fca2SJan Medala uint64_t ol_flags = 0; 288fd617795SRafal Kozik uint32_t packet_type = 0; 2891173fca2SJan Medala 2901173fca2SJan Medala if (ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_TCP) 291fd617795SRafal Kozik packet_type |= RTE_PTYPE_L4_TCP; 2921173fca2SJan Medala else if (ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_UDP) 293fd617795SRafal Kozik packet_type |= RTE_PTYPE_L4_UDP; 2941173fca2SJan Medala 295856edce2SMichal Krawczyk if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV4) { 296fd617795SRafal Kozik packet_type |= RTE_PTYPE_L3_IPV4; 2971173fca2SJan Medala if (unlikely(ena_rx_ctx->l3_csum_err)) 298*daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; 299856edce2SMichal Krawczyk else 300*daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD; 301856edce2SMichal Krawczyk } else if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV6) { 302856edce2SMichal Krawczyk packet_type |= RTE_PTYPE_L3_IPV6; 303856edce2SMichal Krawczyk } 304856edce2SMichal Krawczyk 305856edce2SMichal Krawczyk if (!ena_rx_ctx->l4_csum_checked || ena_rx_ctx->frag) 306*daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN; 307856edce2SMichal Krawczyk else 308856edce2SMichal Krawczyk if (unlikely(ena_rx_ctx->l4_csum_err)) 309*daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; 310856edce2SMichal Krawczyk else 311*daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; 3121173fca2SJan Medala 31334d5e97eSMichal Krawczyk if (fill_hash && 31434d5e97eSMichal Krawczyk likely((packet_type & ENA_PTYPE_HAS_HASH) && !ena_rx_ctx->frag)) { 315*daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_RSS_HASH; 316b418f0d2SMichal Krawczyk mbuf->hash.rss = ena_rx_ctx->hash; 317b418f0d2SMichal Krawczyk } 318b418f0d2SMichal Krawczyk 3191173fca2SJan Medala mbuf->ol_flags = ol_flags; 320fd617795SRafal Kozik mbuf->packet_type = packet_type; 3211173fca2SJan Medala } 3221173fca2SJan Medala 3231173fca2SJan Medala static inline void ena_tx_mbuf_prepare(struct rte_mbuf *mbuf, 32456b8b9b7SRafal Kozik struct ena_com_tx_ctx *ena_tx_ctx, 32533dde075SMichal Krawczyk uint64_t queue_offloads, 32633dde075SMichal Krawczyk bool disable_meta_caching) 3271173fca2SJan Medala { 3281173fca2SJan Medala struct ena_com_tx_meta *ena_meta = &ena_tx_ctx->ena_meta; 3291173fca2SJan Medala 33056b8b9b7SRafal Kozik if ((mbuf->ol_flags & MBUF_OFFLOADS) && 33156b8b9b7SRafal Kozik (queue_offloads & QUEUE_OFFLOADS)) { 3321173fca2SJan Medala /* check if TSO is required */ 333*daa02b5cSOlivier Matz if ((mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) && 334295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO)) { 3351173fca2SJan Medala ena_tx_ctx->tso_enable = true; 3361173fca2SJan Medala 3371173fca2SJan Medala ena_meta->l4_hdr_len = GET_L4_HDR_LEN(mbuf); 3381173fca2SJan Medala } 3391173fca2SJan Medala 3401173fca2SJan Medala /* check if L3 checksum is needed */ 341*daa02b5cSOlivier Matz if ((mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) && 342295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) 3431173fca2SJan Medala ena_tx_ctx->l3_csum_enable = true; 3441173fca2SJan Medala 345*daa02b5cSOlivier Matz if (mbuf->ol_flags & RTE_MBUF_F_TX_IPV6) { 3461173fca2SJan Medala ena_tx_ctx->l3_proto = ENA_ETH_IO_L3_PROTO_IPV6; 3471173fca2SJan Medala } else { 3481173fca2SJan Medala ena_tx_ctx->l3_proto = ENA_ETH_IO_L3_PROTO_IPV4; 3491173fca2SJan Medala 3501173fca2SJan Medala /* set don't fragment (DF) flag */ 3511173fca2SJan Medala if (mbuf->packet_type & 3521173fca2SJan Medala (RTE_PTYPE_L4_NONFRAG 3531173fca2SJan Medala | RTE_PTYPE_INNER_L4_NONFRAG)) 3541173fca2SJan Medala ena_tx_ctx->df = true; 3551173fca2SJan Medala } 3561173fca2SJan Medala 3571173fca2SJan Medala /* check if L4 checksum is needed */ 358*daa02b5cSOlivier Matz if (((mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK) == RTE_MBUF_F_TX_TCP_CKSUM) && 359295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) { 3601173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_TCP; 3611173fca2SJan Medala ena_tx_ctx->l4_csum_enable = true; 362*daa02b5cSOlivier Matz } else if (((mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK) == 363*daa02b5cSOlivier Matz RTE_MBUF_F_TX_UDP_CKSUM) && 364295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM)) { 3651173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_UDP; 3661173fca2SJan Medala ena_tx_ctx->l4_csum_enable = true; 36756b8b9b7SRafal Kozik } else { 3681173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_UNKNOWN; 3691173fca2SJan Medala ena_tx_ctx->l4_csum_enable = false; 3701173fca2SJan Medala } 3711173fca2SJan Medala 3721173fca2SJan Medala ena_meta->mss = mbuf->tso_segsz; 3731173fca2SJan Medala ena_meta->l3_hdr_len = mbuf->l3_len; 3741173fca2SJan Medala ena_meta->l3_hdr_offset = mbuf->l2_len; 3751173fca2SJan Medala 3761173fca2SJan Medala ena_tx_ctx->meta_valid = true; 37733dde075SMichal Krawczyk } else if (disable_meta_caching) { 37833dde075SMichal Krawczyk memset(ena_meta, 0, sizeof(*ena_meta)); 37933dde075SMichal Krawczyk ena_tx_ctx->meta_valid = true; 3801173fca2SJan Medala } else { 3811173fca2SJan Medala ena_tx_ctx->meta_valid = false; 3821173fca2SJan Medala } 3831173fca2SJan Medala } 3841173fca2SJan Medala 385f7d82d24SRafal Kozik static int validate_tx_req_id(struct ena_ring *tx_ring, u16 req_id) 386f7d82d24SRafal Kozik { 387f7d82d24SRafal Kozik struct ena_tx_buffer *tx_info = NULL; 388f7d82d24SRafal Kozik 389f7d82d24SRafal Kozik if (likely(req_id < tx_ring->ring_size)) { 390f7d82d24SRafal Kozik tx_info = &tx_ring->tx_buffer_info[req_id]; 391f7d82d24SRafal Kozik if (likely(tx_info->mbuf)) 392f7d82d24SRafal Kozik return 0; 393f7d82d24SRafal Kozik } 394f7d82d24SRafal Kozik 395f7d82d24SRafal Kozik if (tx_info) 3960a001d69SMichal Krawczyk PMD_TX_LOG(ERR, "tx_info doesn't have valid mbuf\n"); 397f7d82d24SRafal Kozik else 3980a001d69SMichal Krawczyk PMD_TX_LOG(ERR, "Invalid req_id: %hu\n", req_id); 399f7d82d24SRafal Kozik 400f7d82d24SRafal Kozik /* Trigger device reset */ 4017830e905SSolganik Alexander ++tx_ring->tx_stats.bad_req_id; 402f7d82d24SRafal Kozik tx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_TX_REQ_ID; 403f7d82d24SRafal Kozik tx_ring->adapter->trigger_reset = true; 404f7d82d24SRafal Kozik return -EFAULT; 405f7d82d24SRafal Kozik } 406f7d82d24SRafal Kozik 407372c1af5SJan Medala static void ena_config_host_info(struct ena_com_dev *ena_dev) 408372c1af5SJan Medala { 409372c1af5SJan Medala struct ena_admin_host_info *host_info; 410372c1af5SJan Medala int rc; 411372c1af5SJan Medala 412372c1af5SJan Medala /* Allocate only the host info */ 413372c1af5SJan Medala rc = ena_com_allocate_host_info(ena_dev); 414372c1af5SJan Medala if (rc) { 4156f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Cannot allocate host info\n"); 416372c1af5SJan Medala return; 417372c1af5SJan Medala } 418372c1af5SJan Medala 419372c1af5SJan Medala host_info = ena_dev->host_attr.host_info; 420372c1af5SJan Medala 421372c1af5SJan Medala host_info->os_type = ENA_ADMIN_OS_DPDK; 422372c1af5SJan Medala host_info->kernel_ver = RTE_VERSION; 4236723c0fcSBruce Richardson strlcpy((char *)host_info->kernel_ver_str, rte_version(), 4246723c0fcSBruce Richardson sizeof(host_info->kernel_ver_str)); 425372c1af5SJan Medala host_info->os_dist = RTE_VERSION; 4266723c0fcSBruce Richardson strlcpy((char *)host_info->os_dist_str, rte_version(), 4276723c0fcSBruce Richardson sizeof(host_info->os_dist_str)); 428372c1af5SJan Medala host_info->driver_version = 429372c1af5SJan Medala (DRV_MODULE_VER_MAJOR) | 430372c1af5SJan Medala (DRV_MODULE_VER_MINOR << ENA_ADMIN_HOST_INFO_MINOR_SHIFT) | 431c4144557SJan Medala (DRV_MODULE_VER_SUBMINOR << 432c4144557SJan Medala ENA_ADMIN_HOST_INFO_SUB_MINOR_SHIFT); 433b9302eb9SRafal Kozik host_info->num_cpus = rte_lcore_count(); 434372c1af5SJan Medala 4357b3a3c4bSMaciej Bielski host_info->driver_supported_features = 43634d5e97eSMichal Krawczyk ENA_ADMIN_HOST_INFO_RX_OFFSET_MASK | 43734d5e97eSMichal Krawczyk ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK; 4387b3a3c4bSMaciej Bielski 439372c1af5SJan Medala rc = ena_com_set_host_attributes(ena_dev); 440372c1af5SJan Medala if (rc) { 441241da076SRafal Kozik if (rc == -ENA_COM_UNSUPPORTED) 4426f1c9df9SStephen Hemminger PMD_DRV_LOG(WARNING, "Cannot set host attributes\n"); 443241da076SRafal Kozik else 4446f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Cannot set host attributes\n"); 445241da076SRafal Kozik 446372c1af5SJan Medala goto err; 447372c1af5SJan Medala } 448372c1af5SJan Medala 449372c1af5SJan Medala return; 450372c1af5SJan Medala 451372c1af5SJan Medala err: 452372c1af5SJan Medala ena_com_delete_host_info(ena_dev); 453372c1af5SJan Medala } 454372c1af5SJan Medala 4557830e905SSolganik Alexander /* This function calculates the number of xstats based on the current config */ 456aab58857SStanislaw Kardach static unsigned int ena_xstats_calc_num(struct rte_eth_dev_data *data) 457372c1af5SJan Medala { 45845718adaSMichal Krawczyk return ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENI + 459aab58857SStanislaw Kardach (data->nb_tx_queues * ENA_STATS_ARRAY_TX) + 460aab58857SStanislaw Kardach (data->nb_rx_queues * ENA_STATS_ARRAY_RX); 461372c1af5SJan Medala } 462372c1af5SJan Medala 463372c1af5SJan Medala static void ena_config_debug_area(struct ena_adapter *adapter) 464372c1af5SJan Medala { 465372c1af5SJan Medala u32 debug_area_size; 466372c1af5SJan Medala int rc, ss_count; 467372c1af5SJan Medala 468aab58857SStanislaw Kardach ss_count = ena_xstats_calc_num(adapter->edev_data); 469372c1af5SJan Medala 470372c1af5SJan Medala /* allocate 32 bytes for each string and 64bit for the value */ 471372c1af5SJan Medala debug_area_size = ss_count * ETH_GSTRING_LEN + sizeof(u64) * ss_count; 472372c1af5SJan Medala 473372c1af5SJan Medala rc = ena_com_allocate_debug_area(&adapter->ena_dev, debug_area_size); 474372c1af5SJan Medala if (rc) { 4756f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Cannot allocate debug area\n"); 476372c1af5SJan Medala return; 477372c1af5SJan Medala } 478372c1af5SJan Medala 479372c1af5SJan Medala rc = ena_com_set_host_attributes(&adapter->ena_dev); 480372c1af5SJan Medala if (rc) { 481241da076SRafal Kozik if (rc == -ENA_COM_UNSUPPORTED) 4826f1c9df9SStephen Hemminger PMD_DRV_LOG(WARNING, "Cannot set host attributes\n"); 483241da076SRafal Kozik else 4846f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Cannot set host attributes\n"); 485241da076SRafal Kozik 486372c1af5SJan Medala goto err; 487372c1af5SJan Medala } 488372c1af5SJan Medala 489372c1af5SJan Medala return; 490372c1af5SJan Medala err: 491372c1af5SJan Medala ena_com_delete_debug_area(&adapter->ena_dev); 492372c1af5SJan Medala } 493372c1af5SJan Medala 494b142387bSThomas Monjalon static int ena_close(struct rte_eth_dev *dev) 4951173fca2SJan Medala { 4964d7877fdSMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 4974d7877fdSMichal Krawczyk struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; 498890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 49962024eb8SIvan Ilchenko int ret = 0; 5001173fca2SJan Medala 50130410493SThomas Monjalon if (rte_eal_process_type() != RTE_PROC_PRIMARY) 50230410493SThomas Monjalon return 0; 50330410493SThomas Monjalon 504df238f84SMichal Krawczyk if (adapter->state == ENA_ADAPTER_STATE_RUNNING) 50562024eb8SIvan Ilchenko ret = ena_stop(dev); 506eb0ef49dSMichal Krawczyk adapter->state = ENA_ADAPTER_STATE_CLOSED; 50715773e06SMichal Krawczyk 5081173fca2SJan Medala ena_rx_queue_release_all(dev); 5091173fca2SJan Medala ena_tx_queue_release_all(dev); 5104d7877fdSMichal Krawczyk 5114d7877fdSMichal Krawczyk rte_free(adapter->drv_stats); 5124d7877fdSMichal Krawczyk adapter->drv_stats = NULL; 5134d7877fdSMichal Krawczyk 5144d7877fdSMichal Krawczyk rte_intr_disable(intr_handle); 5154d7877fdSMichal Krawczyk rte_intr_callback_unregister(intr_handle, 5164d7877fdSMichal Krawczyk ena_interrupt_handler_rte, 517aab58857SStanislaw Kardach dev); 5184d7877fdSMichal Krawczyk 5194d7877fdSMichal Krawczyk /* 5204d7877fdSMichal Krawczyk * MAC is not allocated dynamically. Setting NULL should prevent from 5214d7877fdSMichal Krawczyk * release of the resource in the rte_eth_dev_release_port(). 5224d7877fdSMichal Krawczyk */ 5234d7877fdSMichal Krawczyk dev->data->mac_addrs = NULL; 524b142387bSThomas Monjalon 52562024eb8SIvan Ilchenko return ret; 5261173fca2SJan Medala } 5271173fca2SJan Medala 5282081d5e2SMichal Krawczyk static int 5292081d5e2SMichal Krawczyk ena_dev_reset(struct rte_eth_dev *dev) 5302081d5e2SMichal Krawczyk { 531e457bc70SRafal Kozik int rc = 0; 5322081d5e2SMichal Krawczyk 53339ecdd3dSStanislaw Kardach /* Cannot release memory in secondary process */ 53439ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 53539ecdd3dSStanislaw Kardach PMD_DRV_LOG(WARNING, "dev_reset not supported in secondary.\n"); 53639ecdd3dSStanislaw Kardach return -EPERM; 53739ecdd3dSStanislaw Kardach } 53839ecdd3dSStanislaw Kardach 539e457bc70SRafal Kozik ena_destroy_device(dev); 540e457bc70SRafal Kozik rc = eth_ena_dev_init(dev); 541241da076SRafal Kozik if (rc) 542617898d1SMichal Krawczyk PMD_INIT_LOG(CRIT, "Cannot initialize device\n"); 543e457bc70SRafal Kozik 5442081d5e2SMichal Krawczyk return rc; 5452081d5e2SMichal Krawczyk } 5462081d5e2SMichal Krawczyk 5471173fca2SJan Medala static void ena_rx_queue_release_all(struct rte_eth_dev *dev) 5481173fca2SJan Medala { 5491173fca2SJan Medala int nb_queues = dev->data->nb_rx_queues; 5501173fca2SJan Medala int i; 5511173fca2SJan Medala 5521173fca2SJan Medala for (i = 0; i < nb_queues; i++) 5537483341aSXueming Li ena_rx_queue_release(dev, i); 5541173fca2SJan Medala } 5551173fca2SJan Medala 5561173fca2SJan Medala static void ena_tx_queue_release_all(struct rte_eth_dev *dev) 5571173fca2SJan Medala { 5581173fca2SJan Medala int nb_queues = dev->data->nb_tx_queues; 5591173fca2SJan Medala int i; 5601173fca2SJan Medala 5611173fca2SJan Medala for (i = 0; i < nb_queues; i++) 5627483341aSXueming Li ena_tx_queue_release(dev, i); 5631173fca2SJan Medala } 5641173fca2SJan Medala 5657483341aSXueming Li static void ena_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 5661173fca2SJan Medala { 5677483341aSXueming Li struct ena_ring *ring = dev->data->rx_queues[qid]; 5681173fca2SJan Medala 5691173fca2SJan Medala /* Free ring resources */ 5701173fca2SJan Medala if (ring->rx_buffer_info) 5711173fca2SJan Medala rte_free(ring->rx_buffer_info); 5721173fca2SJan Medala ring->rx_buffer_info = NULL; 5731173fca2SJan Medala 57479405ee1SRafal Kozik if (ring->rx_refill_buffer) 57579405ee1SRafal Kozik rte_free(ring->rx_refill_buffer); 57679405ee1SRafal Kozik ring->rx_refill_buffer = NULL; 57779405ee1SRafal Kozik 578c2034976SMichal Krawczyk if (ring->empty_rx_reqs) 579c2034976SMichal Krawczyk rte_free(ring->empty_rx_reqs); 580c2034976SMichal Krawczyk ring->empty_rx_reqs = NULL; 581c2034976SMichal Krawczyk 5821173fca2SJan Medala ring->configured = 0; 5831173fca2SJan Medala 584617898d1SMichal Krawczyk PMD_DRV_LOG(NOTICE, "Rx queue %d:%d released\n", 5851173fca2SJan Medala ring->port_id, ring->id); 5861173fca2SJan Medala } 5871173fca2SJan Medala 5887483341aSXueming Li static void ena_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 5891173fca2SJan Medala { 5907483341aSXueming Li struct ena_ring *ring = dev->data->tx_queues[qid]; 5911173fca2SJan Medala 5921173fca2SJan Medala /* Free ring resources */ 5932fca2a98SMichal Krawczyk if (ring->push_buf_intermediate_buf) 5942fca2a98SMichal Krawczyk rte_free(ring->push_buf_intermediate_buf); 5952fca2a98SMichal Krawczyk 5961173fca2SJan Medala if (ring->tx_buffer_info) 5971173fca2SJan Medala rte_free(ring->tx_buffer_info); 5981173fca2SJan Medala 5991173fca2SJan Medala if (ring->empty_tx_reqs) 6001173fca2SJan Medala rte_free(ring->empty_tx_reqs); 6011173fca2SJan Medala 6021173fca2SJan Medala ring->empty_tx_reqs = NULL; 6031173fca2SJan Medala ring->tx_buffer_info = NULL; 6042fca2a98SMichal Krawczyk ring->push_buf_intermediate_buf = NULL; 6051173fca2SJan Medala 6061173fca2SJan Medala ring->configured = 0; 6071173fca2SJan Medala 608617898d1SMichal Krawczyk PMD_DRV_LOG(NOTICE, "Tx queue %d:%d released\n", 6091173fca2SJan Medala ring->port_id, ring->id); 6101173fca2SJan Medala } 6111173fca2SJan Medala 6121173fca2SJan Medala static void ena_rx_queue_release_bufs(struct ena_ring *ring) 6131173fca2SJan Medala { 614709b1dcbSRafal Kozik unsigned int i; 6151173fca2SJan Medala 6161be097dcSMichal Krawczyk for (i = 0; i < ring->ring_size; ++i) { 6171be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info = &ring->rx_buffer_info[i]; 6181be097dcSMichal Krawczyk if (rx_info->mbuf) { 6191be097dcSMichal Krawczyk rte_mbuf_raw_free(rx_info->mbuf); 6201be097dcSMichal Krawczyk rx_info->mbuf = NULL; 6211be097dcSMichal Krawczyk } 6221173fca2SJan Medala } 6231173fca2SJan Medala } 6241173fca2SJan Medala 6251173fca2SJan Medala static void ena_tx_queue_release_bufs(struct ena_ring *ring) 6261173fca2SJan Medala { 627207a514cSMichal Krawczyk unsigned int i; 6281173fca2SJan Medala 629207a514cSMichal Krawczyk for (i = 0; i < ring->ring_size; ++i) { 630207a514cSMichal Krawczyk struct ena_tx_buffer *tx_buf = &ring->tx_buffer_info[i]; 6311173fca2SJan Medala 6323c8bc29fSDavid Harton if (tx_buf->mbuf) { 6331173fca2SJan Medala rte_pktmbuf_free(tx_buf->mbuf); 6343c8bc29fSDavid Harton tx_buf->mbuf = NULL; 6353c8bc29fSDavid Harton } 6361173fca2SJan Medala } 6371173fca2SJan Medala } 6381173fca2SJan Medala 6391173fca2SJan Medala static int ena_link_update(struct rte_eth_dev *dev, 6401173fca2SJan Medala __rte_unused int wait_to_complete) 6411173fca2SJan Medala { 6421173fca2SJan Medala struct rte_eth_link *link = &dev->data->dev_link; 643890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 644ca148440SMichal Krawczyk 645295968d1SFerruh Yigit link->link_status = adapter->link_status ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN; 646295968d1SFerruh Yigit link->link_speed = RTE_ETH_SPEED_NUM_NONE; 647295968d1SFerruh Yigit link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 6481173fca2SJan Medala 6491173fca2SJan Medala return 0; 6501173fca2SJan Medala } 6511173fca2SJan Medala 65226e5543dSRafal Kozik static int ena_queue_start_all(struct rte_eth_dev *dev, 6531173fca2SJan Medala enum ena_ring_type ring_type) 6541173fca2SJan Medala { 655890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 6561173fca2SJan Medala struct ena_ring *queues = NULL; 65753b61841SMichal Krawczyk int nb_queues; 6581173fca2SJan Medala int i = 0; 6591173fca2SJan Medala int rc = 0; 6601173fca2SJan Medala 66153b61841SMichal Krawczyk if (ring_type == ENA_RING_TYPE_RX) { 66253b61841SMichal Krawczyk queues = adapter->rx_ring; 66353b61841SMichal Krawczyk nb_queues = dev->data->nb_rx_queues; 66453b61841SMichal Krawczyk } else { 66553b61841SMichal Krawczyk queues = adapter->tx_ring; 66653b61841SMichal Krawczyk nb_queues = dev->data->nb_tx_queues; 66753b61841SMichal Krawczyk } 66853b61841SMichal Krawczyk for (i = 0; i < nb_queues; i++) { 6691173fca2SJan Medala if (queues[i].configured) { 6701173fca2SJan Medala if (ring_type == ENA_RING_TYPE_RX) { 6711173fca2SJan Medala ena_assert_msg( 6721173fca2SJan Medala dev->data->rx_queues[i] == &queues[i], 673617898d1SMichal Krawczyk "Inconsistent state of Rx queues\n"); 6741173fca2SJan Medala } else { 6751173fca2SJan Medala ena_assert_msg( 6761173fca2SJan Medala dev->data->tx_queues[i] == &queues[i], 677617898d1SMichal Krawczyk "Inconsistent state of Tx queues\n"); 6781173fca2SJan Medala } 6791173fca2SJan Medala 6806986cdc4SMichal Krawczyk rc = ena_queue_start(dev, &queues[i]); 6811173fca2SJan Medala 6821173fca2SJan Medala if (rc) { 6831173fca2SJan Medala PMD_INIT_LOG(ERR, 684617898d1SMichal Krawczyk "Failed to start queue[%d] of type(%d)\n", 6851173fca2SJan Medala i, ring_type); 68626e5543dSRafal Kozik goto err; 6871173fca2SJan Medala } 6881173fca2SJan Medala } 6891173fca2SJan Medala } 6901173fca2SJan Medala 6911173fca2SJan Medala return 0; 69226e5543dSRafal Kozik 69326e5543dSRafal Kozik err: 69426e5543dSRafal Kozik while (i--) 69526e5543dSRafal Kozik if (queues[i].configured) 69626e5543dSRafal Kozik ena_queue_stop(&queues[i]); 69726e5543dSRafal Kozik 69826e5543dSRafal Kozik return rc; 6991173fca2SJan Medala } 7001173fca2SJan Medala 7011173fca2SJan Medala static int ena_check_valid_conf(struct ena_adapter *adapter) 7021173fca2SJan Medala { 7031bb4a528SFerruh Yigit uint32_t mtu = adapter->edev_data->mtu; 7041173fca2SJan Medala 7051bb4a528SFerruh Yigit if (mtu > adapter->max_mtu || mtu < ENA_MIN_MTU) { 706617898d1SMichal Krawczyk PMD_INIT_LOG(ERR, 707617898d1SMichal Krawczyk "Unsupported MTU of %d. Max MTU: %d, min MTU: %d\n", 7081bb4a528SFerruh Yigit mtu, adapter->max_mtu, ENA_MIN_MTU); 709241da076SRafal Kozik return ENA_COM_UNSUPPORTED; 7101173fca2SJan Medala } 7111173fca2SJan Medala 7121173fca2SJan Medala return 0; 7131173fca2SJan Medala } 7141173fca2SJan Medala 7151173fca2SJan Medala static int 7168a7a73f2SMichal Krawczyk ena_calc_io_queue_size(struct ena_calc_queue_size_ctx *ctx, 7178a7a73f2SMichal Krawczyk bool use_large_llq_hdr) 7181173fca2SJan Medala { 7192fca2a98SMichal Krawczyk struct ena_admin_feature_llq_desc *llq = &ctx->get_feat_ctx->llq; 7202fca2a98SMichal Krawczyk struct ena_com_dev *ena_dev = ctx->ena_dev; 7215920d930SMichal Krawczyk uint32_t max_tx_queue_size; 7225920d930SMichal Krawczyk uint32_t max_rx_queue_size; 7231173fca2SJan Medala 7242fca2a98SMichal Krawczyk if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) { 725ea93d37eSRafal Kozik struct ena_admin_queue_ext_feature_fields *max_queue_ext = 726ea93d37eSRafal Kozik &ctx->get_feat_ctx->max_queue_ext.max_queue_ext; 7275920d930SMichal Krawczyk max_rx_queue_size = RTE_MIN(max_queue_ext->max_rx_cq_depth, 728ea93d37eSRafal Kozik max_queue_ext->max_rx_sq_depth); 7295920d930SMichal Krawczyk max_tx_queue_size = max_queue_ext->max_tx_cq_depth; 7302fca2a98SMichal Krawczyk 7312fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == 7322fca2a98SMichal Krawczyk ENA_ADMIN_PLACEMENT_POLICY_DEV) { 7335920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 7342fca2a98SMichal Krawczyk llq->max_llq_depth); 7352fca2a98SMichal Krawczyk } else { 7365920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 737ea93d37eSRafal Kozik max_queue_ext->max_tx_sq_depth); 7382fca2a98SMichal Krawczyk } 7392fca2a98SMichal Krawczyk 740ea93d37eSRafal Kozik ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 741ea93d37eSRafal Kozik max_queue_ext->max_per_packet_rx_descs); 742ea93d37eSRafal Kozik ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 743ea93d37eSRafal Kozik max_queue_ext->max_per_packet_tx_descs); 744ea93d37eSRafal Kozik } else { 745ea93d37eSRafal Kozik struct ena_admin_queue_feature_desc *max_queues = 746ea93d37eSRafal Kozik &ctx->get_feat_ctx->max_queues; 7475920d930SMichal Krawczyk max_rx_queue_size = RTE_MIN(max_queues->max_cq_depth, 748ea93d37eSRafal Kozik max_queues->max_sq_depth); 7495920d930SMichal Krawczyk max_tx_queue_size = max_queues->max_cq_depth; 7502fca2a98SMichal Krawczyk 7512fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == 7522fca2a98SMichal Krawczyk ENA_ADMIN_PLACEMENT_POLICY_DEV) { 7535920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 7542fca2a98SMichal Krawczyk llq->max_llq_depth); 7552fca2a98SMichal Krawczyk } else { 7565920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 7572fca2a98SMichal Krawczyk max_queues->max_sq_depth); 7582fca2a98SMichal Krawczyk } 7592fca2a98SMichal Krawczyk 760ea93d37eSRafal Kozik ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 761ea93d37eSRafal Kozik max_queues->max_packet_rx_descs); 7625920d930SMichal Krawczyk ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 7635920d930SMichal Krawczyk max_queues->max_packet_tx_descs); 764ea93d37eSRafal Kozik } 7651173fca2SJan Medala 766ea93d37eSRafal Kozik /* Round down to the nearest power of 2 */ 7675920d930SMichal Krawczyk max_rx_queue_size = rte_align32prevpow2(max_rx_queue_size); 7685920d930SMichal Krawczyk max_tx_queue_size = rte_align32prevpow2(max_tx_queue_size); 7691173fca2SJan Medala 7708a7a73f2SMichal Krawczyk if (use_large_llq_hdr) { 7718a7a73f2SMichal Krawczyk if ((llq->entry_size_ctrl_supported & 7728a7a73f2SMichal Krawczyk ENA_ADMIN_LIST_ENTRY_SIZE_256B) && 7738a7a73f2SMichal Krawczyk (ena_dev->tx_mem_queue_type == 7748a7a73f2SMichal Krawczyk ENA_ADMIN_PLACEMENT_POLICY_DEV)) { 7758a7a73f2SMichal Krawczyk max_tx_queue_size /= 2; 7768a7a73f2SMichal Krawczyk PMD_INIT_LOG(INFO, 777617898d1SMichal Krawczyk "Forcing large headers and decreasing maximum Tx queue size to %d\n", 7788a7a73f2SMichal Krawczyk max_tx_queue_size); 7798a7a73f2SMichal Krawczyk } else { 7808a7a73f2SMichal Krawczyk PMD_INIT_LOG(ERR, 7818a7a73f2SMichal Krawczyk "Forcing large headers failed: LLQ is disabled or device does not support large headers\n"); 7828a7a73f2SMichal Krawczyk } 7838a7a73f2SMichal Krawczyk } 7848a7a73f2SMichal Krawczyk 7855920d930SMichal Krawczyk if (unlikely(max_rx_queue_size == 0 || max_tx_queue_size == 0)) { 786617898d1SMichal Krawczyk PMD_INIT_LOG(ERR, "Invalid queue size\n"); 7871173fca2SJan Medala return -EFAULT; 7881173fca2SJan Medala } 7891173fca2SJan Medala 7905920d930SMichal Krawczyk ctx->max_tx_queue_size = max_tx_queue_size; 7915920d930SMichal Krawczyk ctx->max_rx_queue_size = max_rx_queue_size; 7922061fe41SRafal Kozik 793ea93d37eSRafal Kozik return 0; 7941173fca2SJan Medala } 7951173fca2SJan Medala 7961173fca2SJan Medala static void ena_stats_restart(struct rte_eth_dev *dev) 7971173fca2SJan Medala { 798890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 7991173fca2SJan Medala 8001173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->ierrors); 8011173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->oerrors); 8021173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->rx_nombuf); 803e1e73e32SMichal Krawczyk adapter->drv_stats->rx_drops = 0; 8041173fca2SJan Medala } 8051173fca2SJan Medala 806d5b0924bSMatan Azrad static int ena_stats_get(struct rte_eth_dev *dev, 8071173fca2SJan Medala struct rte_eth_stats *stats) 8081173fca2SJan Medala { 8091173fca2SJan Medala struct ena_admin_basic_stats ena_stats; 810890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 8111173fca2SJan Medala struct ena_com_dev *ena_dev = &adapter->ena_dev; 8121173fca2SJan Medala int rc; 81345b6d861SMichal Krawczyk int i; 81445b6d861SMichal Krawczyk int max_rings_stats; 8151173fca2SJan Medala 8161173fca2SJan Medala if (rte_eal_process_type() != RTE_PROC_PRIMARY) 817d5b0924bSMatan Azrad return -ENOTSUP; 8181173fca2SJan Medala 8191173fca2SJan Medala memset(&ena_stats, 0, sizeof(ena_stats)); 8201343c415SMichal Krawczyk 8211343c415SMichal Krawczyk rte_spinlock_lock(&adapter->admin_lock); 8221173fca2SJan Medala rc = ena_com_get_dev_basic_stats(ena_dev, &ena_stats); 8231343c415SMichal Krawczyk rte_spinlock_unlock(&adapter->admin_lock); 8241173fca2SJan Medala if (unlikely(rc)) { 8256f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Could not retrieve statistics from ENA\n"); 826d5b0924bSMatan Azrad return rc; 8271173fca2SJan Medala } 8281173fca2SJan Medala 8291173fca2SJan Medala /* Set of basic statistics from ENA */ 8301173fca2SJan Medala stats->ipackets = __MERGE_64B_H_L(ena_stats.rx_pkts_high, 8311173fca2SJan Medala ena_stats.rx_pkts_low); 8321173fca2SJan Medala stats->opackets = __MERGE_64B_H_L(ena_stats.tx_pkts_high, 8331173fca2SJan Medala ena_stats.tx_pkts_low); 8341173fca2SJan Medala stats->ibytes = __MERGE_64B_H_L(ena_stats.rx_bytes_high, 8351173fca2SJan Medala ena_stats.rx_bytes_low); 8361173fca2SJan Medala stats->obytes = __MERGE_64B_H_L(ena_stats.tx_bytes_high, 8371173fca2SJan Medala ena_stats.tx_bytes_low); 8381173fca2SJan Medala 8391173fca2SJan Medala /* Driver related stats */ 840e1e73e32SMichal Krawczyk stats->imissed = adapter->drv_stats->rx_drops; 8411173fca2SJan Medala stats->ierrors = rte_atomic64_read(&adapter->drv_stats->ierrors); 8421173fca2SJan Medala stats->oerrors = rte_atomic64_read(&adapter->drv_stats->oerrors); 8431173fca2SJan Medala stats->rx_nombuf = rte_atomic64_read(&adapter->drv_stats->rx_nombuf); 84445b6d861SMichal Krawczyk 84545b6d861SMichal Krawczyk max_rings_stats = RTE_MIN(dev->data->nb_rx_queues, 84645b6d861SMichal Krawczyk RTE_ETHDEV_QUEUE_STAT_CNTRS); 84745b6d861SMichal Krawczyk for (i = 0; i < max_rings_stats; ++i) { 84845b6d861SMichal Krawczyk struct ena_stats_rx *rx_stats = &adapter->rx_ring[i].rx_stats; 84945b6d861SMichal Krawczyk 85045b6d861SMichal Krawczyk stats->q_ibytes[i] = rx_stats->bytes; 85145b6d861SMichal Krawczyk stats->q_ipackets[i] = rx_stats->cnt; 85245b6d861SMichal Krawczyk stats->q_errors[i] = rx_stats->bad_desc_num + 85345b6d861SMichal Krawczyk rx_stats->bad_req_id; 85445b6d861SMichal Krawczyk } 85545b6d861SMichal Krawczyk 85645b6d861SMichal Krawczyk max_rings_stats = RTE_MIN(dev->data->nb_tx_queues, 85745b6d861SMichal Krawczyk RTE_ETHDEV_QUEUE_STAT_CNTRS); 85845b6d861SMichal Krawczyk for (i = 0; i < max_rings_stats; ++i) { 85945b6d861SMichal Krawczyk struct ena_stats_tx *tx_stats = &adapter->tx_ring[i].tx_stats; 86045b6d861SMichal Krawczyk 86145b6d861SMichal Krawczyk stats->q_obytes[i] = tx_stats->bytes; 86245b6d861SMichal Krawczyk stats->q_opackets[i] = tx_stats->cnt; 86345b6d861SMichal Krawczyk } 86445b6d861SMichal Krawczyk 865d5b0924bSMatan Azrad return 0; 8661173fca2SJan Medala } 8671173fca2SJan Medala 8681173fca2SJan Medala static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) 8691173fca2SJan Medala { 8701173fca2SJan Medala struct ena_adapter *adapter; 8711173fca2SJan Medala struct ena_com_dev *ena_dev; 8721173fca2SJan Medala int rc = 0; 8731173fca2SJan Medala 874498c687aSRafal Kozik ena_assert_msg(dev->data != NULL, "Uninitialized device\n"); 875498c687aSRafal Kozik ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device\n"); 876890728ffSStephen Hemminger adapter = dev->data->dev_private; 8771173fca2SJan Medala 8781173fca2SJan Medala ena_dev = &adapter->ena_dev; 879498c687aSRafal Kozik ena_assert_msg(ena_dev != NULL, "Uninitialized device\n"); 8801173fca2SJan Medala 8811bb4a528SFerruh Yigit if (mtu > adapter->max_mtu || mtu < ENA_MIN_MTU) { 8826f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 883617898d1SMichal Krawczyk "Invalid MTU setting. New MTU: %d, max MTU: %d, min MTU: %d\n", 8841bb4a528SFerruh Yigit mtu, adapter->max_mtu, ENA_MIN_MTU); 885241da076SRafal Kozik return -EINVAL; 8861173fca2SJan Medala } 8871173fca2SJan Medala 8881173fca2SJan Medala rc = ena_com_set_dev_mtu(ena_dev, mtu); 8891173fca2SJan Medala if (rc) 8906f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Could not set MTU: %d\n", mtu); 8911173fca2SJan Medala else 892617898d1SMichal Krawczyk PMD_DRV_LOG(NOTICE, "MTU set to: %d\n", mtu); 8931173fca2SJan Medala 8941173fca2SJan Medala return rc; 8951173fca2SJan Medala } 8961173fca2SJan Medala 8971173fca2SJan Medala static int ena_start(struct rte_eth_dev *dev) 8981173fca2SJan Medala { 899890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 900d9b8b106SMichal Krawczyk uint64_t ticks; 9011173fca2SJan Medala int rc = 0; 9021173fca2SJan Medala 90339ecdd3dSStanislaw Kardach /* Cannot allocate memory in secondary process */ 90439ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 90539ecdd3dSStanislaw Kardach PMD_DRV_LOG(WARNING, "dev_start not supported in secondary.\n"); 90639ecdd3dSStanislaw Kardach return -EPERM; 90739ecdd3dSStanislaw Kardach } 90839ecdd3dSStanislaw Kardach 9091173fca2SJan Medala rc = ena_check_valid_conf(adapter); 9101173fca2SJan Medala if (rc) 9111173fca2SJan Medala return rc; 9121173fca2SJan Medala 9136986cdc4SMichal Krawczyk rc = ena_setup_rx_intr(dev); 9146986cdc4SMichal Krawczyk if (rc) 9156986cdc4SMichal Krawczyk return rc; 9166986cdc4SMichal Krawczyk 91726e5543dSRafal Kozik rc = ena_queue_start_all(dev, ENA_RING_TYPE_RX); 9181173fca2SJan Medala if (rc) 9191173fca2SJan Medala return rc; 9201173fca2SJan Medala 92126e5543dSRafal Kozik rc = ena_queue_start_all(dev, ENA_RING_TYPE_TX); 9221173fca2SJan Medala if (rc) 92326e5543dSRafal Kozik goto err_start_tx; 9241173fca2SJan Medala 925295968d1SFerruh Yigit if (adapter->edev_data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) { 92634d5e97eSMichal Krawczyk rc = ena_rss_configure(adapter); 9271173fca2SJan Medala if (rc) 92826e5543dSRafal Kozik goto err_rss_init; 9291173fca2SJan Medala } 9301173fca2SJan Medala 9311173fca2SJan Medala ena_stats_restart(dev); 9321173fca2SJan Medala 933d9b8b106SMichal Krawczyk adapter->timestamp_wd = rte_get_timer_cycles(); 934d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = ENA_DEVICE_KALIVE_TIMEOUT; 935d9b8b106SMichal Krawczyk 936d9b8b106SMichal Krawczyk ticks = rte_get_timer_hz(); 937d9b8b106SMichal Krawczyk rte_timer_reset(&adapter->timer_wd, ticks, PERIODICAL, rte_lcore_id(), 938aab58857SStanislaw Kardach ena_timer_wd_callback, dev); 939d9b8b106SMichal Krawczyk 9407830e905SSolganik Alexander ++adapter->dev_stats.dev_start; 9411173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_RUNNING; 9421173fca2SJan Medala 9431173fca2SJan Medala return 0; 94426e5543dSRafal Kozik 94526e5543dSRafal Kozik err_rss_init: 94626e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_TX); 94726e5543dSRafal Kozik err_start_tx: 94826e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_RX); 94926e5543dSRafal Kozik return rc; 9501173fca2SJan Medala } 9511173fca2SJan Medala 95262024eb8SIvan Ilchenko static int ena_stop(struct rte_eth_dev *dev) 953eb0ef49dSMichal Krawczyk { 954890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 955e457bc70SRafal Kozik struct ena_com_dev *ena_dev = &adapter->ena_dev; 9566986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 9576986cdc4SMichal Krawczyk struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; 958e457bc70SRafal Kozik int rc; 959eb0ef49dSMichal Krawczyk 96039ecdd3dSStanislaw Kardach /* Cannot free memory in secondary process */ 96139ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 96239ecdd3dSStanislaw Kardach PMD_DRV_LOG(WARNING, "dev_stop not supported in secondary.\n"); 96339ecdd3dSStanislaw Kardach return -EPERM; 96439ecdd3dSStanislaw Kardach } 96539ecdd3dSStanislaw Kardach 966d9b8b106SMichal Krawczyk rte_timer_stop_sync(&adapter->timer_wd); 96726e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_TX); 96826e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_RX); 969d9b8b106SMichal Krawczyk 970e457bc70SRafal Kozik if (adapter->trigger_reset) { 971e457bc70SRafal Kozik rc = ena_com_dev_reset(ena_dev, adapter->reset_reason); 972e457bc70SRafal Kozik if (rc) 973617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Device reset failed, rc: %d\n", rc); 974e457bc70SRafal Kozik } 975e457bc70SRafal Kozik 9766986cdc4SMichal Krawczyk rte_intr_disable(intr_handle); 9776986cdc4SMichal Krawczyk 9786986cdc4SMichal Krawczyk rte_intr_efd_disable(intr_handle); 9796986cdc4SMichal Krawczyk if (intr_handle->intr_vec != NULL) { 9806986cdc4SMichal Krawczyk rte_free(intr_handle->intr_vec); 9816986cdc4SMichal Krawczyk intr_handle->intr_vec = NULL; 9826986cdc4SMichal Krawczyk } 9836986cdc4SMichal Krawczyk 9846986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 9856986cdc4SMichal Krawczyk 9867830e905SSolganik Alexander ++adapter->dev_stats.dev_stop; 987eb0ef49dSMichal Krawczyk adapter->state = ENA_ADAPTER_STATE_STOPPED; 988b8f5d2aeSThomas Monjalon dev->data->dev_started = 0; 98962024eb8SIvan Ilchenko 99062024eb8SIvan Ilchenko return 0; 991eb0ef49dSMichal Krawczyk } 992eb0ef49dSMichal Krawczyk 9936986cdc4SMichal Krawczyk static int ena_create_io_queue(struct rte_eth_dev *dev, struct ena_ring *ring) 994df238f84SMichal Krawczyk { 9956986cdc4SMichal Krawczyk struct ena_adapter *adapter = ring->adapter; 9966986cdc4SMichal Krawczyk struct ena_com_dev *ena_dev = &adapter->ena_dev; 9976986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 9986986cdc4SMichal Krawczyk struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; 999df238f84SMichal Krawczyk struct ena_com_create_io_ctx ctx = 1000df238f84SMichal Krawczyk /* policy set to _HOST just to satisfy icc compiler */ 1001df238f84SMichal Krawczyk { ENA_ADMIN_PLACEMENT_POLICY_HOST, 1002df238f84SMichal Krawczyk 0, 0, 0, 0, 0 }; 1003df238f84SMichal Krawczyk uint16_t ena_qid; 1004778677dcSRafal Kozik unsigned int i; 1005df238f84SMichal Krawczyk int rc; 1006df238f84SMichal Krawczyk 10076986cdc4SMichal Krawczyk ctx.msix_vector = -1; 1008df238f84SMichal Krawczyk if (ring->type == ENA_RING_TYPE_TX) { 1009df238f84SMichal Krawczyk ena_qid = ENA_IO_TXQ_IDX(ring->id); 1010df238f84SMichal Krawczyk ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_TX; 1011df238f84SMichal Krawczyk ctx.mem_queue_type = ena_dev->tx_mem_queue_type; 1012778677dcSRafal Kozik for (i = 0; i < ring->ring_size; i++) 1013778677dcSRafal Kozik ring->empty_tx_reqs[i] = i; 1014df238f84SMichal Krawczyk } else { 1015df238f84SMichal Krawczyk ena_qid = ENA_IO_RXQ_IDX(ring->id); 1016df238f84SMichal Krawczyk ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_RX; 10176986cdc4SMichal Krawczyk if (rte_intr_dp_is_en(intr_handle)) 10186986cdc4SMichal Krawczyk ctx.msix_vector = intr_handle->intr_vec[ring->id]; 1019778677dcSRafal Kozik for (i = 0; i < ring->ring_size; i++) 1020778677dcSRafal Kozik ring->empty_rx_reqs[i] = i; 1021df238f84SMichal Krawczyk } 1022badc3a6aSMichal Krawczyk ctx.queue_size = ring->ring_size; 1023df238f84SMichal Krawczyk ctx.qid = ena_qid; 10244217cb0bSMichal Krawczyk ctx.numa_node = ring->numa_socket_id; 1025df238f84SMichal Krawczyk 1026df238f84SMichal Krawczyk rc = ena_com_create_io_queue(ena_dev, &ctx); 1027df238f84SMichal Krawczyk if (rc) { 10286f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1029617898d1SMichal Krawczyk "Failed to create IO queue[%d] (qid:%d), rc: %d\n", 1030df238f84SMichal Krawczyk ring->id, ena_qid, rc); 1031df238f84SMichal Krawczyk return rc; 1032df238f84SMichal Krawczyk } 1033df238f84SMichal Krawczyk 1034df238f84SMichal Krawczyk rc = ena_com_get_io_handlers(ena_dev, ena_qid, 1035df238f84SMichal Krawczyk &ring->ena_com_io_sq, 1036df238f84SMichal Krawczyk &ring->ena_com_io_cq); 1037df238f84SMichal Krawczyk if (rc) { 10386f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1039617898d1SMichal Krawczyk "Failed to get IO queue[%d] handlers, rc: %d\n", 1040df238f84SMichal Krawczyk ring->id, rc); 1041df238f84SMichal Krawczyk ena_com_destroy_io_queue(ena_dev, ena_qid); 1042df238f84SMichal Krawczyk return rc; 1043df238f84SMichal Krawczyk } 1044df238f84SMichal Krawczyk 1045df238f84SMichal Krawczyk if (ring->type == ENA_RING_TYPE_TX) 1046df238f84SMichal Krawczyk ena_com_update_numa_node(ring->ena_com_io_cq, ctx.numa_node); 1047df238f84SMichal Krawczyk 10486986cdc4SMichal Krawczyk /* Start with Rx interrupts being masked. */ 10496986cdc4SMichal Krawczyk if (ring->type == ENA_RING_TYPE_RX && rte_intr_dp_is_en(intr_handle)) 10506986cdc4SMichal Krawczyk ena_rx_queue_intr_disable(dev, ring->id); 10516986cdc4SMichal Krawczyk 1052df238f84SMichal Krawczyk return 0; 1053df238f84SMichal Krawczyk } 1054df238f84SMichal Krawczyk 105526e5543dSRafal Kozik static void ena_queue_stop(struct ena_ring *ring) 1056df238f84SMichal Krawczyk { 105726e5543dSRafal Kozik struct ena_com_dev *ena_dev = &ring->adapter->ena_dev; 1058df238f84SMichal Krawczyk 105926e5543dSRafal Kozik if (ring->type == ENA_RING_TYPE_RX) { 106026e5543dSRafal Kozik ena_com_destroy_io_queue(ena_dev, ENA_IO_RXQ_IDX(ring->id)); 106126e5543dSRafal Kozik ena_rx_queue_release_bufs(ring); 106226e5543dSRafal Kozik } else { 106326e5543dSRafal Kozik ena_com_destroy_io_queue(ena_dev, ENA_IO_TXQ_IDX(ring->id)); 106426e5543dSRafal Kozik ena_tx_queue_release_bufs(ring); 1065df238f84SMichal Krawczyk } 1066df238f84SMichal Krawczyk } 1067df238f84SMichal Krawczyk 106826e5543dSRafal Kozik static void ena_queue_stop_all(struct rte_eth_dev *dev, 106926e5543dSRafal Kozik enum ena_ring_type ring_type) 107026e5543dSRafal Kozik { 1071890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 107226e5543dSRafal Kozik struct ena_ring *queues = NULL; 107326e5543dSRafal Kozik uint16_t nb_queues, i; 107426e5543dSRafal Kozik 107526e5543dSRafal Kozik if (ring_type == ENA_RING_TYPE_RX) { 107626e5543dSRafal Kozik queues = adapter->rx_ring; 107726e5543dSRafal Kozik nb_queues = dev->data->nb_rx_queues; 107826e5543dSRafal Kozik } else { 107926e5543dSRafal Kozik queues = adapter->tx_ring; 108026e5543dSRafal Kozik nb_queues = dev->data->nb_tx_queues; 108126e5543dSRafal Kozik } 108226e5543dSRafal Kozik 108326e5543dSRafal Kozik for (i = 0; i < nb_queues; ++i) 108426e5543dSRafal Kozik if (queues[i].configured) 108526e5543dSRafal Kozik ena_queue_stop(&queues[i]); 108626e5543dSRafal Kozik } 108726e5543dSRafal Kozik 10886986cdc4SMichal Krawczyk static int ena_queue_start(struct rte_eth_dev *dev, struct ena_ring *ring) 10891173fca2SJan Medala { 1090a467e8f3SMichal Krawczyk int rc, bufs_num; 10911173fca2SJan Medala 10921173fca2SJan Medala ena_assert_msg(ring->configured == 1, 109326e5543dSRafal Kozik "Trying to start unconfigured queue\n"); 10941173fca2SJan Medala 10956986cdc4SMichal Krawczyk rc = ena_create_io_queue(dev, ring); 1096df238f84SMichal Krawczyk if (rc) { 1097617898d1SMichal Krawczyk PMD_INIT_LOG(ERR, "Failed to create IO queue\n"); 1098df238f84SMichal Krawczyk return rc; 1099df238f84SMichal Krawczyk } 1100df238f84SMichal Krawczyk 11011173fca2SJan Medala ring->next_to_clean = 0; 11021173fca2SJan Medala ring->next_to_use = 0; 11031173fca2SJan Medala 11047830e905SSolganik Alexander if (ring->type == ENA_RING_TYPE_TX) { 11057830e905SSolganik Alexander ring->tx_stats.available_desc = 1106b2b02edeSMichal Krawczyk ena_com_free_q_entries(ring->ena_com_io_sq); 11071173fca2SJan Medala return 0; 11087830e905SSolganik Alexander } 11091173fca2SJan Medala 1110a467e8f3SMichal Krawczyk bufs_num = ring->ring_size - 1; 1111a467e8f3SMichal Krawczyk rc = ena_populate_rx_queue(ring, bufs_num); 1112a467e8f3SMichal Krawczyk if (rc != bufs_num) { 111326e5543dSRafal Kozik ena_com_destroy_io_queue(&ring->adapter->ena_dev, 111426e5543dSRafal Kozik ENA_IO_RXQ_IDX(ring->id)); 1115617898d1SMichal Krawczyk PMD_INIT_LOG(ERR, "Failed to populate Rx ring\n"); 1116241da076SRafal Kozik return ENA_COM_FAULT; 11171173fca2SJan Medala } 11184387e81cSIdo Segev /* Flush per-core RX buffers pools cache as they can be used on other 11194387e81cSIdo Segev * cores as well. 11204387e81cSIdo Segev */ 11214387e81cSIdo Segev rte_mempool_cache_flush(NULL, ring->mb_pool); 11221173fca2SJan Medala 11231173fca2SJan Medala return 0; 11241173fca2SJan Medala } 11251173fca2SJan Medala 11261173fca2SJan Medala static int ena_tx_queue_setup(struct rte_eth_dev *dev, 11271173fca2SJan Medala uint16_t queue_idx, 11281173fca2SJan Medala uint16_t nb_desc, 11294217cb0bSMichal Krawczyk unsigned int socket_id, 113056b8b9b7SRafal Kozik const struct rte_eth_txconf *tx_conf) 11311173fca2SJan Medala { 11321173fca2SJan Medala struct ena_ring *txq = NULL; 1133890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 11341173fca2SJan Medala unsigned int i; 1135005064e5SMichal Krawczyk uint16_t dyn_thresh; 11361173fca2SJan Medala 11371173fca2SJan Medala txq = &adapter->tx_ring[queue_idx]; 11381173fca2SJan Medala 11391173fca2SJan Medala if (txq->configured) { 11406f1c9df9SStephen Hemminger PMD_DRV_LOG(CRIT, 1141617898d1SMichal Krawczyk "API violation. Queue[%d] is already configured\n", 11421173fca2SJan Medala queue_idx); 1143241da076SRafal Kozik return ENA_COM_FAULT; 11441173fca2SJan Medala } 11451173fca2SJan Medala 11461daff526SJakub Palider if (!rte_is_power_of_2(nb_desc)) { 11476f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1148617898d1SMichal Krawczyk "Unsupported size of Tx queue: %d is not a power of 2.\n", 11491daff526SJakub Palider nb_desc); 11501daff526SJakub Palider return -EINVAL; 11511daff526SJakub Palider } 11521daff526SJakub Palider 11535920d930SMichal Krawczyk if (nb_desc > adapter->max_tx_ring_size) { 11546f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1155617898d1SMichal Krawczyk "Unsupported size of Tx queue (max size: %d)\n", 11565920d930SMichal Krawczyk adapter->max_tx_ring_size); 11571173fca2SJan Medala return -EINVAL; 11581173fca2SJan Medala } 11591173fca2SJan Medala 11601173fca2SJan Medala txq->port_id = dev->data->port_id; 11611173fca2SJan Medala txq->next_to_clean = 0; 11621173fca2SJan Medala txq->next_to_use = 0; 11631173fca2SJan Medala txq->ring_size = nb_desc; 1164c0006061SMichal Krawczyk txq->size_mask = nb_desc - 1; 11654217cb0bSMichal Krawczyk txq->numa_socket_id = socket_id; 11661d973d8fSIgor Chauskin txq->pkts_without_db = false; 1167f93e20e5SMichal Krawczyk txq->last_cleanup_ticks = 0; 11681173fca2SJan Medala 116908180833SMichal Krawczyk txq->tx_buffer_info = rte_zmalloc_socket("txq->tx_buffer_info", 117008180833SMichal Krawczyk sizeof(struct ena_tx_buffer) * txq->ring_size, 117108180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 117208180833SMichal Krawczyk socket_id); 11731173fca2SJan Medala if (!txq->tx_buffer_info) { 1174617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1175617898d1SMichal Krawczyk "Failed to allocate memory for Tx buffer info\n"); 1176df238f84SMichal Krawczyk return -ENOMEM; 11771173fca2SJan Medala } 11781173fca2SJan Medala 117908180833SMichal Krawczyk txq->empty_tx_reqs = rte_zmalloc_socket("txq->empty_tx_reqs", 118008180833SMichal Krawczyk sizeof(uint16_t) * txq->ring_size, 118108180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 118208180833SMichal Krawczyk socket_id); 11831173fca2SJan Medala if (!txq->empty_tx_reqs) { 1184617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1185617898d1SMichal Krawczyk "Failed to allocate memory for empty Tx requests\n"); 1186df238f84SMichal Krawczyk rte_free(txq->tx_buffer_info); 1187df238f84SMichal Krawczyk return -ENOMEM; 11881173fca2SJan Medala } 1189241da076SRafal Kozik 11902fca2a98SMichal Krawczyk txq->push_buf_intermediate_buf = 119108180833SMichal Krawczyk rte_zmalloc_socket("txq->push_buf_intermediate_buf", 11922fca2a98SMichal Krawczyk txq->tx_max_header_size, 119308180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 119408180833SMichal Krawczyk socket_id); 11952fca2a98SMichal Krawczyk if (!txq->push_buf_intermediate_buf) { 1196617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to alloc push buffer for LLQ\n"); 11972fca2a98SMichal Krawczyk rte_free(txq->tx_buffer_info); 11982fca2a98SMichal Krawczyk rte_free(txq->empty_tx_reqs); 11992fca2a98SMichal Krawczyk return -ENOMEM; 12002fca2a98SMichal Krawczyk } 12012fca2a98SMichal Krawczyk 12021173fca2SJan Medala for (i = 0; i < txq->ring_size; i++) 12031173fca2SJan Medala txq->empty_tx_reqs[i] = i; 12041173fca2SJan Medala 1205005064e5SMichal Krawczyk txq->offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads; 1206005064e5SMichal Krawczyk 1207005064e5SMichal Krawczyk /* Check if caller provided the Tx cleanup threshold value. */ 1208005064e5SMichal Krawczyk if (tx_conf->tx_free_thresh != 0) { 1209005064e5SMichal Krawczyk txq->tx_free_thresh = tx_conf->tx_free_thresh; 1210005064e5SMichal Krawczyk } else { 1211005064e5SMichal Krawczyk dyn_thresh = txq->ring_size - 1212005064e5SMichal Krawczyk txq->ring_size / ENA_REFILL_THRESH_DIVIDER; 1213005064e5SMichal Krawczyk txq->tx_free_thresh = RTE_MAX(dyn_thresh, 1214005064e5SMichal Krawczyk txq->ring_size - ENA_REFILL_THRESH_PACKET); 12152081d5e2SMichal Krawczyk } 1216005064e5SMichal Krawczyk 1217f93e20e5SMichal Krawczyk txq->missing_tx_completion_threshold = 1218f93e20e5SMichal Krawczyk RTE_MIN(txq->ring_size / 2, ENA_DEFAULT_MISSING_COMP); 1219f93e20e5SMichal Krawczyk 12201173fca2SJan Medala /* Store pointer to this queue in upper layer */ 12211173fca2SJan Medala txq->configured = 1; 12221173fca2SJan Medala dev->data->tx_queues[queue_idx] = txq; 1223241da076SRafal Kozik 1224241da076SRafal Kozik return 0; 12251173fca2SJan Medala } 12261173fca2SJan Medala 12271173fca2SJan Medala static int ena_rx_queue_setup(struct rte_eth_dev *dev, 12281173fca2SJan Medala uint16_t queue_idx, 12291173fca2SJan Medala uint16_t nb_desc, 12304217cb0bSMichal Krawczyk unsigned int socket_id, 123134d5e97eSMichal Krawczyk const struct rte_eth_rxconf *rx_conf, 12321173fca2SJan Medala struct rte_mempool *mp) 12331173fca2SJan Medala { 1234890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 12351173fca2SJan Medala struct ena_ring *rxq = NULL; 123638364c26SMichal Krawczyk size_t buffer_size; 1237df238f84SMichal Krawczyk int i; 1238005064e5SMichal Krawczyk uint16_t dyn_thresh; 12391173fca2SJan Medala 12401173fca2SJan Medala rxq = &adapter->rx_ring[queue_idx]; 12411173fca2SJan Medala if (rxq->configured) { 12426f1c9df9SStephen Hemminger PMD_DRV_LOG(CRIT, 1243617898d1SMichal Krawczyk "API violation. Queue[%d] is already configured\n", 12441173fca2SJan Medala queue_idx); 1245241da076SRafal Kozik return ENA_COM_FAULT; 12461173fca2SJan Medala } 12471173fca2SJan Medala 12481daff526SJakub Palider if (!rte_is_power_of_2(nb_desc)) { 12496f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1250617898d1SMichal Krawczyk "Unsupported size of Rx queue: %d is not a power of 2.\n", 12511daff526SJakub Palider nb_desc); 12521daff526SJakub Palider return -EINVAL; 12531daff526SJakub Palider } 12541daff526SJakub Palider 12555920d930SMichal Krawczyk if (nb_desc > adapter->max_rx_ring_size) { 12566f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1257617898d1SMichal Krawczyk "Unsupported size of Rx queue (max size: %d)\n", 12585920d930SMichal Krawczyk adapter->max_rx_ring_size); 12591173fca2SJan Medala return -EINVAL; 12601173fca2SJan Medala } 12611173fca2SJan Medala 126238364c26SMichal Krawczyk /* ENA isn't supporting buffers smaller than 1400 bytes */ 126338364c26SMichal Krawczyk buffer_size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM; 126438364c26SMichal Krawczyk if (buffer_size < ENA_RX_BUF_MIN_SIZE) { 126538364c26SMichal Krawczyk PMD_DRV_LOG(ERR, 1266617898d1SMichal Krawczyk "Unsupported size of Rx buffer: %zu (min size: %d)\n", 126738364c26SMichal Krawczyk buffer_size, ENA_RX_BUF_MIN_SIZE); 126838364c26SMichal Krawczyk return -EINVAL; 126938364c26SMichal Krawczyk } 127038364c26SMichal Krawczyk 12711173fca2SJan Medala rxq->port_id = dev->data->port_id; 12721173fca2SJan Medala rxq->next_to_clean = 0; 12731173fca2SJan Medala rxq->next_to_use = 0; 12741173fca2SJan Medala rxq->ring_size = nb_desc; 1275c0006061SMichal Krawczyk rxq->size_mask = nb_desc - 1; 12764217cb0bSMichal Krawczyk rxq->numa_socket_id = socket_id; 12771173fca2SJan Medala rxq->mb_pool = mp; 12781173fca2SJan Medala 127908180833SMichal Krawczyk rxq->rx_buffer_info = rte_zmalloc_socket("rxq->buffer_info", 12801be097dcSMichal Krawczyk sizeof(struct ena_rx_buffer) * nb_desc, 128108180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 128208180833SMichal Krawczyk socket_id); 12831173fca2SJan Medala if (!rxq->rx_buffer_info) { 1284617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1285617898d1SMichal Krawczyk "Failed to allocate memory for Rx buffer info\n"); 12861173fca2SJan Medala return -ENOMEM; 12871173fca2SJan Medala } 12881173fca2SJan Medala 128908180833SMichal Krawczyk rxq->rx_refill_buffer = rte_zmalloc_socket("rxq->rx_refill_buffer", 129079405ee1SRafal Kozik sizeof(struct rte_mbuf *) * nb_desc, 129108180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 129208180833SMichal Krawczyk socket_id); 129379405ee1SRafal Kozik if (!rxq->rx_refill_buffer) { 1294617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1295617898d1SMichal Krawczyk "Failed to allocate memory for Rx refill buffer\n"); 129679405ee1SRafal Kozik rte_free(rxq->rx_buffer_info); 129779405ee1SRafal Kozik rxq->rx_buffer_info = NULL; 129879405ee1SRafal Kozik return -ENOMEM; 129979405ee1SRafal Kozik } 130079405ee1SRafal Kozik 130108180833SMichal Krawczyk rxq->empty_rx_reqs = rte_zmalloc_socket("rxq->empty_rx_reqs", 1302c2034976SMichal Krawczyk sizeof(uint16_t) * nb_desc, 130308180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 130408180833SMichal Krawczyk socket_id); 1305c2034976SMichal Krawczyk if (!rxq->empty_rx_reqs) { 1306617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1307617898d1SMichal Krawczyk "Failed to allocate memory for empty Rx requests\n"); 1308c2034976SMichal Krawczyk rte_free(rxq->rx_buffer_info); 1309c2034976SMichal Krawczyk rxq->rx_buffer_info = NULL; 131079405ee1SRafal Kozik rte_free(rxq->rx_refill_buffer); 131179405ee1SRafal Kozik rxq->rx_refill_buffer = NULL; 1312c2034976SMichal Krawczyk return -ENOMEM; 1313c2034976SMichal Krawczyk } 1314c2034976SMichal Krawczyk 1315c2034976SMichal Krawczyk for (i = 0; i < nb_desc; i++) 1316eccbe2ffSRafal Kozik rxq->empty_rx_reqs[i] = i; 1317c2034976SMichal Krawczyk 131834d5e97eSMichal Krawczyk rxq->offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads; 131934d5e97eSMichal Krawczyk 1320005064e5SMichal Krawczyk if (rx_conf->rx_free_thresh != 0) { 1321005064e5SMichal Krawczyk rxq->rx_free_thresh = rx_conf->rx_free_thresh; 1322005064e5SMichal Krawczyk } else { 1323005064e5SMichal Krawczyk dyn_thresh = rxq->ring_size / ENA_REFILL_THRESH_DIVIDER; 1324005064e5SMichal Krawczyk rxq->rx_free_thresh = RTE_MIN(dyn_thresh, 1325005064e5SMichal Krawczyk (uint16_t)(ENA_REFILL_THRESH_PACKET)); 1326005064e5SMichal Krawczyk } 1327005064e5SMichal Krawczyk 13281173fca2SJan Medala /* Store pointer to this queue in upper layer */ 13291173fca2SJan Medala rxq->configured = 1; 13301173fca2SJan Medala dev->data->rx_queues[queue_idx] = rxq; 13311173fca2SJan Medala 1332df238f84SMichal Krawczyk return 0; 13331173fca2SJan Medala } 13341173fca2SJan Medala 133583fd97b2SMichal Krawczyk static int ena_add_single_rx_desc(struct ena_com_io_sq *io_sq, 133683fd97b2SMichal Krawczyk struct rte_mbuf *mbuf, uint16_t id) 133783fd97b2SMichal Krawczyk { 133883fd97b2SMichal Krawczyk struct ena_com_buf ebuf; 133983fd97b2SMichal Krawczyk int rc; 134083fd97b2SMichal Krawczyk 134183fd97b2SMichal Krawczyk /* prepare physical address for DMA transaction */ 134283fd97b2SMichal Krawczyk ebuf.paddr = mbuf->buf_iova + RTE_PKTMBUF_HEADROOM; 134383fd97b2SMichal Krawczyk ebuf.len = mbuf->buf_len - RTE_PKTMBUF_HEADROOM; 134483fd97b2SMichal Krawczyk 134583fd97b2SMichal Krawczyk /* pass resource to device */ 134683fd97b2SMichal Krawczyk rc = ena_com_add_single_rx_desc(io_sq, &ebuf, id); 134783fd97b2SMichal Krawczyk if (unlikely(rc != 0)) 13480a001d69SMichal Krawczyk PMD_RX_LOG(WARNING, "Failed adding Rx desc\n"); 134983fd97b2SMichal Krawczyk 135083fd97b2SMichal Krawczyk return rc; 135183fd97b2SMichal Krawczyk } 135283fd97b2SMichal Krawczyk 13531173fca2SJan Medala static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count) 13541173fca2SJan Medala { 13551173fca2SJan Medala unsigned int i; 13561173fca2SJan Medala int rc; 13571daff526SJakub Palider uint16_t next_to_use = rxq->next_to_use; 13580a001d69SMichal Krawczyk uint16_t req_id; 13590a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 13600a001d69SMichal Krawczyk uint16_t in_use; 13610a001d69SMichal Krawczyk #endif 136279405ee1SRafal Kozik struct rte_mbuf **mbufs = rxq->rx_refill_buffer; 13631173fca2SJan Medala 13641173fca2SJan Medala if (unlikely(!count)) 13651173fca2SJan Medala return 0; 13661173fca2SJan Medala 13670a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 1368c0006061SMichal Krawczyk in_use = rxq->ring_size - 1 - 1369c0006061SMichal Krawczyk ena_com_free_q_entries(rxq->ena_com_io_sq); 13700a001d69SMichal Krawczyk if (unlikely((in_use + count) >= rxq->ring_size)) 13710a001d69SMichal Krawczyk PMD_RX_LOG(ERR, "Bad Rx ring state\n"); 13720a001d69SMichal Krawczyk #endif 13731173fca2SJan Medala 13741173fca2SJan Medala /* get resources for incoming packets */ 13753c8bc29fSDavid Harton rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, count); 13761173fca2SJan Medala if (unlikely(rc < 0)) { 13771173fca2SJan Medala rte_atomic64_inc(&rxq->adapter->drv_stats->rx_nombuf); 13787830e905SSolganik Alexander ++rxq->rx_stats.mbuf_alloc_fail; 1379617898d1SMichal Krawczyk PMD_RX_LOG(DEBUG, "There are not enough free buffers\n"); 13801173fca2SJan Medala return 0; 13811173fca2SJan Medala } 13821173fca2SJan Medala 13831173fca2SJan Medala for (i = 0; i < count; i++) { 138479405ee1SRafal Kozik struct rte_mbuf *mbuf = mbufs[i]; 13851be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info; 13861173fca2SJan Medala 138779405ee1SRafal Kozik if (likely((i + 4) < count)) 138879405ee1SRafal Kozik rte_prefetch0(mbufs[i + 4]); 1389c2034976SMichal Krawczyk 1390c0006061SMichal Krawczyk req_id = rxq->empty_rx_reqs[next_to_use]; 13911be097dcSMichal Krawczyk rx_info = &rxq->rx_buffer_info[req_id]; 1392241da076SRafal Kozik 139383fd97b2SMichal Krawczyk rc = ena_add_single_rx_desc(rxq->ena_com_io_sq, mbuf, req_id); 139483fd97b2SMichal Krawczyk if (unlikely(rc != 0)) 13951173fca2SJan Medala break; 139683fd97b2SMichal Krawczyk 13971be097dcSMichal Krawczyk rx_info->mbuf = mbuf; 1398c0006061SMichal Krawczyk next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, rxq->size_mask); 13991173fca2SJan Medala } 14001173fca2SJan Medala 140179405ee1SRafal Kozik if (unlikely(i < count)) { 14020a001d69SMichal Krawczyk PMD_RX_LOG(WARNING, 1403617898d1SMichal Krawczyk "Refilled Rx queue[%d] with only %d/%d buffers\n", 1404617898d1SMichal Krawczyk rxq->id, i, count); 14053c8bc29fSDavid Harton rte_pktmbuf_free_bulk(&mbufs[i], count - i); 14067830e905SSolganik Alexander ++rxq->rx_stats.refill_partial; 140779405ee1SRafal Kozik } 1408241da076SRafal Kozik 14095e02e19eSJan Medala /* When we submitted free recources to device... */ 14103d19e1abSRafal Kozik if (likely(i > 0)) { 141138faa87eSMichal Krawczyk /* ...let HW know that it can fill buffers with data. */ 14121173fca2SJan Medala ena_com_write_sq_doorbell(rxq->ena_com_io_sq); 14131173fca2SJan Medala 14145e02e19eSJan Medala rxq->next_to_use = next_to_use; 14155e02e19eSJan Medala } 14165e02e19eSJan Medala 14171173fca2SJan Medala return i; 14181173fca2SJan Medala } 14191173fca2SJan Medala 14201173fca2SJan Medala static int ena_device_init(struct ena_com_dev *ena_dev, 1421aab58857SStanislaw Kardach struct rte_pci_device *pdev, 1422e859d2b8SRafal Kozik struct ena_com_dev_get_features_ctx *get_feat_ctx, 1423e859d2b8SRafal Kozik bool *wd_state) 14241173fca2SJan Medala { 1425ca148440SMichal Krawczyk uint32_t aenq_groups; 14261173fca2SJan Medala int rc; 1427c4144557SJan Medala bool readless_supported; 14281173fca2SJan Medala 14291173fca2SJan Medala /* Initialize mmio registers */ 14301173fca2SJan Medala rc = ena_com_mmio_reg_read_request_init(ena_dev); 14311173fca2SJan Medala if (rc) { 1432617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to init MMIO read less\n"); 14331173fca2SJan Medala return rc; 14341173fca2SJan Medala } 14351173fca2SJan Medala 1436c4144557SJan Medala /* The PCIe configuration space revision id indicate if mmio reg 1437c4144557SJan Medala * read is disabled. 1438c4144557SJan Medala */ 1439aab58857SStanislaw Kardach readless_supported = !(pdev->id.class_id & ENA_MMIO_DISABLE_REG_READ); 1440c4144557SJan Medala ena_com_set_mmio_read_mode(ena_dev, readless_supported); 1441c4144557SJan Medala 14421173fca2SJan Medala /* reset device */ 14433adcba9aSMichal Krawczyk rc = ena_com_dev_reset(ena_dev, ENA_REGS_RESET_NORMAL); 14441173fca2SJan Medala if (rc) { 1445617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Cannot reset device\n"); 14461173fca2SJan Medala goto err_mmio_read_less; 14471173fca2SJan Medala } 14481173fca2SJan Medala 14491173fca2SJan Medala /* check FW version */ 14501173fca2SJan Medala rc = ena_com_validate_version(ena_dev); 14511173fca2SJan Medala if (rc) { 1452617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Device version is too low\n"); 14531173fca2SJan Medala goto err_mmio_read_less; 14541173fca2SJan Medala } 14551173fca2SJan Medala 14561173fca2SJan Medala ena_dev->dma_addr_bits = ena_com_get_dma_width(ena_dev); 14571173fca2SJan Medala 14581173fca2SJan Medala /* ENA device administration layer init */ 1459b68309beSRafal Kozik rc = ena_com_admin_init(ena_dev, &aenq_handlers); 14601173fca2SJan Medala if (rc) { 14616f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1462617898d1SMichal Krawczyk "Cannot initialize ENA admin queue\n"); 14631173fca2SJan Medala goto err_mmio_read_less; 14641173fca2SJan Medala } 14651173fca2SJan Medala 14661173fca2SJan Medala /* To enable the msix interrupts the driver needs to know the number 14671173fca2SJan Medala * of queues. So the driver uses polling mode to retrieve this 14681173fca2SJan Medala * information. 14691173fca2SJan Medala */ 14701173fca2SJan Medala ena_com_set_admin_polling_mode(ena_dev, true); 14711173fca2SJan Medala 1472201ff2e5SJakub Palider ena_config_host_info(ena_dev); 1473201ff2e5SJakub Palider 14741173fca2SJan Medala /* Get Device Attributes and features */ 14751173fca2SJan Medala rc = ena_com_get_dev_attr_feat(ena_dev, get_feat_ctx); 14761173fca2SJan Medala if (rc) { 14776f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1478617898d1SMichal Krawczyk "Cannot get attribute for ENA device, rc: %d\n", rc); 14791173fca2SJan Medala goto err_admin_init; 14801173fca2SJan Medala } 14811173fca2SJan Medala 1482f01f060cSRafal Kozik aenq_groups = BIT(ENA_ADMIN_LINK_CHANGE) | 1483d9b8b106SMichal Krawczyk BIT(ENA_ADMIN_NOTIFICATION) | 1484983cce2dSRafal Kozik BIT(ENA_ADMIN_KEEP_ALIVE) | 1485983cce2dSRafal Kozik BIT(ENA_ADMIN_FATAL_ERROR) | 1486983cce2dSRafal Kozik BIT(ENA_ADMIN_WARNING); 1487ca148440SMichal Krawczyk 1488ca148440SMichal Krawczyk aenq_groups &= get_feat_ctx->aenq.supported_groups; 1489ca148440SMichal Krawczyk rc = ena_com_set_aenq_config(ena_dev, aenq_groups); 1490ca148440SMichal Krawczyk if (rc) { 1491617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Cannot configure AENQ groups, rc: %d\n", rc); 1492ca148440SMichal Krawczyk goto err_admin_init; 1493ca148440SMichal Krawczyk } 1494ca148440SMichal Krawczyk 1495e859d2b8SRafal Kozik *wd_state = !!(aenq_groups & BIT(ENA_ADMIN_KEEP_ALIVE)); 1496e859d2b8SRafal Kozik 14971173fca2SJan Medala return 0; 14981173fca2SJan Medala 14991173fca2SJan Medala err_admin_init: 15001173fca2SJan Medala ena_com_admin_destroy(ena_dev); 15011173fca2SJan Medala 15021173fca2SJan Medala err_mmio_read_less: 15031173fca2SJan Medala ena_com_mmio_reg_read_request_destroy(ena_dev); 15041173fca2SJan Medala 15051173fca2SJan Medala return rc; 15061173fca2SJan Medala } 15071173fca2SJan Medala 1508ca148440SMichal Krawczyk static void ena_interrupt_handler_rte(void *cb_arg) 150915773e06SMichal Krawczyk { 1510aab58857SStanislaw Kardach struct rte_eth_dev *dev = cb_arg; 1511aab58857SStanislaw Kardach struct ena_adapter *adapter = dev->data->dev_private; 151215773e06SMichal Krawczyk struct ena_com_dev *ena_dev = &adapter->ena_dev; 151315773e06SMichal Krawczyk 151415773e06SMichal Krawczyk ena_com_admin_q_comp_intr_handler(ena_dev); 15153d19e1abSRafal Kozik if (likely(adapter->state != ENA_ADAPTER_STATE_CLOSED)) 1516aab58857SStanislaw Kardach ena_com_aenq_intr_handler(ena_dev, dev); 151715773e06SMichal Krawczyk } 151815773e06SMichal Krawczyk 15195efb9fc7SMichal Krawczyk static void check_for_missing_keep_alive(struct ena_adapter *adapter) 15205efb9fc7SMichal Krawczyk { 1521e859d2b8SRafal Kozik if (!adapter->wd_state) 1522e859d2b8SRafal Kozik return; 1523e859d2b8SRafal Kozik 15245efb9fc7SMichal Krawczyk if (adapter->keep_alive_timeout == ENA_HW_HINTS_NO_TIMEOUT) 15255efb9fc7SMichal Krawczyk return; 15265efb9fc7SMichal Krawczyk 15275efb9fc7SMichal Krawczyk if (unlikely((rte_get_timer_cycles() - adapter->timestamp_wd) >= 15285efb9fc7SMichal Krawczyk adapter->keep_alive_timeout)) { 15296f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Keep alive timeout\n"); 15305efb9fc7SMichal Krawczyk adapter->reset_reason = ENA_REGS_RESET_KEEP_ALIVE_TO; 15315efb9fc7SMichal Krawczyk adapter->trigger_reset = true; 15327830e905SSolganik Alexander ++adapter->dev_stats.wd_expired; 15335efb9fc7SMichal Krawczyk } 15345efb9fc7SMichal Krawczyk } 15355efb9fc7SMichal Krawczyk 15365efb9fc7SMichal Krawczyk /* Check if admin queue is enabled */ 15375efb9fc7SMichal Krawczyk static void check_for_admin_com_state(struct ena_adapter *adapter) 15385efb9fc7SMichal Krawczyk { 15395efb9fc7SMichal Krawczyk if (unlikely(!ena_com_get_admin_running_state(&adapter->ena_dev))) { 1540617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "ENA admin queue is not in running state\n"); 15415efb9fc7SMichal Krawczyk adapter->reset_reason = ENA_REGS_RESET_ADMIN_TO; 15425efb9fc7SMichal Krawczyk adapter->trigger_reset = true; 15435efb9fc7SMichal Krawczyk } 15445efb9fc7SMichal Krawczyk } 15455efb9fc7SMichal Krawczyk 1546f93e20e5SMichal Krawczyk static int check_for_tx_completion_in_queue(struct ena_adapter *adapter, 1547f93e20e5SMichal Krawczyk struct ena_ring *tx_ring) 1548f93e20e5SMichal Krawczyk { 1549f93e20e5SMichal Krawczyk struct ena_tx_buffer *tx_buf; 1550f93e20e5SMichal Krawczyk uint64_t timestamp; 1551f93e20e5SMichal Krawczyk uint64_t completion_delay; 1552f93e20e5SMichal Krawczyk uint32_t missed_tx = 0; 1553f93e20e5SMichal Krawczyk unsigned int i; 1554f93e20e5SMichal Krawczyk int rc = 0; 1555f93e20e5SMichal Krawczyk 1556f93e20e5SMichal Krawczyk for (i = 0; i < tx_ring->ring_size; ++i) { 1557f93e20e5SMichal Krawczyk tx_buf = &tx_ring->tx_buffer_info[i]; 1558f93e20e5SMichal Krawczyk timestamp = tx_buf->timestamp; 1559f93e20e5SMichal Krawczyk 1560f93e20e5SMichal Krawczyk if (timestamp == 0) 1561f93e20e5SMichal Krawczyk continue; 1562f93e20e5SMichal Krawczyk 1563f93e20e5SMichal Krawczyk completion_delay = rte_get_timer_cycles() - timestamp; 1564f93e20e5SMichal Krawczyk if (completion_delay > adapter->missing_tx_completion_to) { 1565f93e20e5SMichal Krawczyk if (unlikely(!tx_buf->print_once)) { 1566f93e20e5SMichal Krawczyk PMD_TX_LOG(WARNING, 1567f93e20e5SMichal Krawczyk "Found a Tx that wasn't completed on time, qid %d, index %d. " 1568f93e20e5SMichal Krawczyk "Missing Tx outstanding for %" PRIu64 " msecs.\n", 1569f93e20e5SMichal Krawczyk tx_ring->id, i, completion_delay / 1570f93e20e5SMichal Krawczyk rte_get_timer_hz() * 1000); 1571f93e20e5SMichal Krawczyk tx_buf->print_once = true; 1572f93e20e5SMichal Krawczyk } 1573f93e20e5SMichal Krawczyk ++missed_tx; 1574f93e20e5SMichal Krawczyk } 1575f93e20e5SMichal Krawczyk } 1576f93e20e5SMichal Krawczyk 1577f93e20e5SMichal Krawczyk if (unlikely(missed_tx > tx_ring->missing_tx_completion_threshold)) { 1578f93e20e5SMichal Krawczyk PMD_DRV_LOG(ERR, 1579f93e20e5SMichal Krawczyk "The number of lost Tx completions is above the threshold (%d > %d). " 1580f93e20e5SMichal Krawczyk "Trigger the device reset.\n", 1581f93e20e5SMichal Krawczyk missed_tx, 1582f93e20e5SMichal Krawczyk tx_ring->missing_tx_completion_threshold); 1583f93e20e5SMichal Krawczyk adapter->reset_reason = ENA_REGS_RESET_MISS_TX_CMPL; 1584f93e20e5SMichal Krawczyk adapter->trigger_reset = true; 1585f93e20e5SMichal Krawczyk rc = -EIO; 1586f93e20e5SMichal Krawczyk } 1587f93e20e5SMichal Krawczyk 1588f93e20e5SMichal Krawczyk tx_ring->tx_stats.missed_tx += missed_tx; 1589f93e20e5SMichal Krawczyk 1590f93e20e5SMichal Krawczyk return rc; 1591f93e20e5SMichal Krawczyk } 1592f93e20e5SMichal Krawczyk 1593f93e20e5SMichal Krawczyk static void check_for_tx_completions(struct ena_adapter *adapter) 1594f93e20e5SMichal Krawczyk { 1595f93e20e5SMichal Krawczyk struct ena_ring *tx_ring; 1596f93e20e5SMichal Krawczyk uint64_t tx_cleanup_delay; 1597f93e20e5SMichal Krawczyk size_t qid; 1598f93e20e5SMichal Krawczyk int budget; 1599f93e20e5SMichal Krawczyk uint16_t nb_tx_queues = adapter->edev_data->nb_tx_queues; 1600f93e20e5SMichal Krawczyk 1601f93e20e5SMichal Krawczyk if (adapter->missing_tx_completion_to == ENA_HW_HINTS_NO_TIMEOUT) 1602f93e20e5SMichal Krawczyk return; 1603f93e20e5SMichal Krawczyk 1604f93e20e5SMichal Krawczyk nb_tx_queues = adapter->edev_data->nb_tx_queues; 1605f93e20e5SMichal Krawczyk budget = adapter->missing_tx_completion_budget; 1606f93e20e5SMichal Krawczyk 1607f93e20e5SMichal Krawczyk qid = adapter->last_tx_comp_qid; 1608f93e20e5SMichal Krawczyk while (budget-- > 0) { 1609f93e20e5SMichal Krawczyk tx_ring = &adapter->tx_ring[qid]; 1610f93e20e5SMichal Krawczyk 1611f93e20e5SMichal Krawczyk /* Tx cleanup is called only by the burst function and can be 1612f93e20e5SMichal Krawczyk * called dynamically by the application. Also cleanup is 1613f93e20e5SMichal Krawczyk * limited by the threshold. To avoid false detection of the 1614f93e20e5SMichal Krawczyk * missing HW Tx completion, get the delay since last cleanup 1615f93e20e5SMichal Krawczyk * function was called. 1616f93e20e5SMichal Krawczyk */ 1617f93e20e5SMichal Krawczyk tx_cleanup_delay = rte_get_timer_cycles() - 1618f93e20e5SMichal Krawczyk tx_ring->last_cleanup_ticks; 1619f93e20e5SMichal Krawczyk if (tx_cleanup_delay < adapter->tx_cleanup_stall_delay) 1620f93e20e5SMichal Krawczyk check_for_tx_completion_in_queue(adapter, tx_ring); 1621f93e20e5SMichal Krawczyk qid = (qid + 1) % nb_tx_queues; 1622f93e20e5SMichal Krawczyk } 1623f93e20e5SMichal Krawczyk 1624f93e20e5SMichal Krawczyk adapter->last_tx_comp_qid = qid; 1625f93e20e5SMichal Krawczyk } 1626f93e20e5SMichal Krawczyk 1627d9b8b106SMichal Krawczyk static void ena_timer_wd_callback(__rte_unused struct rte_timer *timer, 1628d9b8b106SMichal Krawczyk void *arg) 1629d9b8b106SMichal Krawczyk { 1630aab58857SStanislaw Kardach struct rte_eth_dev *dev = arg; 1631aab58857SStanislaw Kardach struct ena_adapter *adapter = dev->data->dev_private; 1632d9b8b106SMichal Krawczyk 16335efb9fc7SMichal Krawczyk check_for_missing_keep_alive(adapter); 16345efb9fc7SMichal Krawczyk check_for_admin_com_state(adapter); 1635f93e20e5SMichal Krawczyk check_for_tx_completions(adapter); 1636d9b8b106SMichal Krawczyk 16375efb9fc7SMichal Krawczyk if (unlikely(adapter->trigger_reset)) { 16386f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Trigger reset is on\n"); 16395723fbedSFerruh Yigit rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, 1640d9b8b106SMichal Krawczyk NULL); 1641d9b8b106SMichal Krawczyk } 1642d9b8b106SMichal Krawczyk } 1643d9b8b106SMichal Krawczyk 16442fca2a98SMichal Krawczyk static inline void 16458a7a73f2SMichal Krawczyk set_default_llq_configurations(struct ena_llq_configurations *llq_config, 16468a7a73f2SMichal Krawczyk struct ena_admin_feature_llq_desc *llq, 16478a7a73f2SMichal Krawczyk bool use_large_llq_hdr) 16482fca2a98SMichal Krawczyk { 16492fca2a98SMichal Krawczyk llq_config->llq_header_location = ENA_ADMIN_INLINE_HEADER; 16502fca2a98SMichal Krawczyk llq_config->llq_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY; 16512fca2a98SMichal Krawczyk llq_config->llq_num_decs_before_header = 16522fca2a98SMichal Krawczyk ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2; 16538a7a73f2SMichal Krawczyk 16548a7a73f2SMichal Krawczyk if (use_large_llq_hdr && 16558a7a73f2SMichal Krawczyk (llq->entry_size_ctrl_supported & ENA_ADMIN_LIST_ENTRY_SIZE_256B)) { 16568a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size = 16578a7a73f2SMichal Krawczyk ENA_ADMIN_LIST_ENTRY_SIZE_256B; 16588a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size_value = 256; 16598a7a73f2SMichal Krawczyk } else { 16608a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size = 16618a7a73f2SMichal Krawczyk ENA_ADMIN_LIST_ENTRY_SIZE_128B; 16622fca2a98SMichal Krawczyk llq_config->llq_ring_entry_size_value = 128; 16632fca2a98SMichal Krawczyk } 16648a7a73f2SMichal Krawczyk } 16652fca2a98SMichal Krawczyk 16662fca2a98SMichal Krawczyk static int 16672fca2a98SMichal Krawczyk ena_set_queues_placement_policy(struct ena_adapter *adapter, 16682fca2a98SMichal Krawczyk struct ena_com_dev *ena_dev, 16692fca2a98SMichal Krawczyk struct ena_admin_feature_llq_desc *llq, 16702fca2a98SMichal Krawczyk struct ena_llq_configurations *llq_default_configurations) 16712fca2a98SMichal Krawczyk { 16722fca2a98SMichal Krawczyk int rc; 16732fca2a98SMichal Krawczyk u32 llq_feature_mask; 16742fca2a98SMichal Krawczyk 16752fca2a98SMichal Krawczyk llq_feature_mask = 1 << ENA_ADMIN_LLQ; 16762fca2a98SMichal Krawczyk if (!(ena_dev->supported_features & llq_feature_mask)) { 16776f1c9df9SStephen Hemminger PMD_DRV_LOG(INFO, 16782fca2a98SMichal Krawczyk "LLQ is not supported. Fallback to host mode policy.\n"); 16792fca2a98SMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 16802fca2a98SMichal Krawczyk return 0; 16812fca2a98SMichal Krawczyk } 16822fca2a98SMichal Krawczyk 16832fca2a98SMichal Krawczyk rc = ena_com_config_dev_mode(ena_dev, llq, llq_default_configurations); 16842fca2a98SMichal Krawczyk if (unlikely(rc)) { 1685617898d1SMichal Krawczyk PMD_INIT_LOG(WARNING, 1686617898d1SMichal Krawczyk "Failed to config dev mode. Fallback to host mode policy.\n"); 16872fca2a98SMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 16882fca2a98SMichal Krawczyk return 0; 16892fca2a98SMichal Krawczyk } 16902fca2a98SMichal Krawczyk 16912fca2a98SMichal Krawczyk /* Nothing to config, exit */ 16922fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) 16932fca2a98SMichal Krawczyk return 0; 16942fca2a98SMichal Krawczyk 16952fca2a98SMichal Krawczyk if (!adapter->dev_mem_base) { 1696617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1697617898d1SMichal Krawczyk "Unable to access LLQ BAR resource. Fallback to host mode policy.\n"); 16982fca2a98SMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 16992fca2a98SMichal Krawczyk return 0; 17002fca2a98SMichal Krawczyk } 17012fca2a98SMichal Krawczyk 17022fca2a98SMichal Krawczyk ena_dev->mem_bar = adapter->dev_mem_base; 17032fca2a98SMichal Krawczyk 17042fca2a98SMichal Krawczyk return 0; 17052fca2a98SMichal Krawczyk } 17062fca2a98SMichal Krawczyk 17075920d930SMichal Krawczyk static uint32_t ena_calc_max_io_queue_num(struct ena_com_dev *ena_dev, 170801bd6877SRafal Kozik struct ena_com_dev_get_features_ctx *get_feat_ctx) 170901bd6877SRafal Kozik { 17105920d930SMichal Krawczyk uint32_t io_tx_sq_num, io_tx_cq_num, io_rx_num, max_num_io_queues; 171101bd6877SRafal Kozik 1712ea93d37eSRafal Kozik /* Regular queues capabilities */ 1713ea93d37eSRafal Kozik if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) { 1714ea93d37eSRafal Kozik struct ena_admin_queue_ext_feature_fields *max_queue_ext = 1715ea93d37eSRafal Kozik &get_feat_ctx->max_queue_ext.max_queue_ext; 17162fca2a98SMichal Krawczyk io_rx_num = RTE_MIN(max_queue_ext->max_rx_sq_num, 17172fca2a98SMichal Krawczyk max_queue_ext->max_rx_cq_num); 17182fca2a98SMichal Krawczyk io_tx_sq_num = max_queue_ext->max_tx_sq_num; 17192fca2a98SMichal Krawczyk io_tx_cq_num = max_queue_ext->max_tx_cq_num; 1720ea93d37eSRafal Kozik } else { 1721ea93d37eSRafal Kozik struct ena_admin_queue_feature_desc *max_queues = 1722ea93d37eSRafal Kozik &get_feat_ctx->max_queues; 17232fca2a98SMichal Krawczyk io_tx_sq_num = max_queues->max_sq_num; 17242fca2a98SMichal Krawczyk io_tx_cq_num = max_queues->max_cq_num; 17252fca2a98SMichal Krawczyk io_rx_num = RTE_MIN(io_tx_sq_num, io_tx_cq_num); 1726ea93d37eSRafal Kozik } 172701bd6877SRafal Kozik 17282fca2a98SMichal Krawczyk /* In case of LLQ use the llq number in the get feature cmd */ 17292fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) 17302fca2a98SMichal Krawczyk io_tx_sq_num = get_feat_ctx->llq.max_llq_num; 17312fca2a98SMichal Krawczyk 17325920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(ENA_MAX_NUM_IO_QUEUES, io_rx_num); 17335920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(max_num_io_queues, io_tx_sq_num); 17345920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(max_num_io_queues, io_tx_cq_num); 173501bd6877SRafal Kozik 17365920d930SMichal Krawczyk if (unlikely(max_num_io_queues == 0)) { 1737617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Number of IO queues cannot not be 0\n"); 173801bd6877SRafal Kozik return -EFAULT; 173901bd6877SRafal Kozik } 174001bd6877SRafal Kozik 17415920d930SMichal Krawczyk return max_num_io_queues; 174201bd6877SRafal Kozik } 174301bd6877SRafal Kozik 1744e8c838fdSMichal Krawczyk static void 1745e8c838fdSMichal Krawczyk ena_set_offloads(struct ena_offloads *offloads, 1746e8c838fdSMichal Krawczyk struct ena_admin_feature_offload_desc *offload_desc) 1747e8c838fdSMichal Krawczyk { 1748e8c838fdSMichal Krawczyk if (offload_desc->tx & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TSO_IPV4_MASK) 1749e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_IPV4_TSO; 1750e8c838fdSMichal Krawczyk 1751e8c838fdSMichal Krawczyk /* Tx IPv4 checksum offloads */ 1752e8c838fdSMichal Krawczyk if (offload_desc->tx & 1753e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L3_CSUM_IPV4_MASK) 1754e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L3_IPV4_CSUM; 1755e8c838fdSMichal Krawczyk if (offload_desc->tx & 1756e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_FULL_MASK) 1757e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV4_CSUM; 1758e8c838fdSMichal Krawczyk if (offload_desc->tx & 1759e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_PART_MASK) 1760e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV4_CSUM_PARTIAL; 1761e8c838fdSMichal Krawczyk 1762e8c838fdSMichal Krawczyk /* Tx IPv6 checksum offloads */ 1763e8c838fdSMichal Krawczyk if (offload_desc->tx & 1764e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_FULL_MASK) 1765e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV6_CSUM; 1766e8c838fdSMichal Krawczyk if (offload_desc->tx & 1767e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_PART_MASK) 1768e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV6_CSUM_PARTIAL; 1769e8c838fdSMichal Krawczyk 1770e8c838fdSMichal Krawczyk /* Rx IPv4 checksum offloads */ 1771e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 1772e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L3_CSUM_IPV4_MASK) 1773e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L3_IPV4_CSUM; 1774e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 1775e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV4_CSUM_MASK) 1776e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L4_IPV4_CSUM; 1777e8c838fdSMichal Krawczyk 1778e8c838fdSMichal Krawczyk /* Rx IPv6 checksum offloads */ 1779e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 1780e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV6_CSUM_MASK) 1781e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L4_IPV6_CSUM; 1782e8c838fdSMichal Krawczyk 1783e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 1784e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_HASH_MASK) 1785e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_RX_RSS_HASH; 1786e8c838fdSMichal Krawczyk } 1787e8c838fdSMichal Krawczyk 17881173fca2SJan Medala static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) 17891173fca2SJan Medala { 1790ea93d37eSRafal Kozik struct ena_calc_queue_size_ctx calc_queue_ctx = { 0 }; 17911173fca2SJan Medala struct rte_pci_device *pci_dev; 1792eb0ef49dSMichal Krawczyk struct rte_intr_handle *intr_handle; 1793890728ffSStephen Hemminger struct ena_adapter *adapter = eth_dev->data->dev_private; 17941173fca2SJan Medala struct ena_com_dev *ena_dev = &adapter->ena_dev; 17951173fca2SJan Medala struct ena_com_dev_get_features_ctx get_feat_ctx; 17962fca2a98SMichal Krawczyk struct ena_llq_configurations llq_config; 17972fca2a98SMichal Krawczyk const char *queue_type_str; 17985920d930SMichal Krawczyk uint32_t max_num_io_queues; 1799ea93d37eSRafal Kozik int rc; 18001173fca2SJan Medala static int adapters_found; 180133dde075SMichal Krawczyk bool disable_meta_caching; 18025f267cb0SFerruh Yigit bool wd_state = false; 18031173fca2SJan Medala 18041173fca2SJan Medala eth_dev->dev_ops = &ena_dev_ops; 18051173fca2SJan Medala eth_dev->rx_pkt_burst = ð_ena_recv_pkts; 18061173fca2SJan Medala eth_dev->tx_pkt_burst = ð_ena_xmit_pkts; 1807b3fc5a1aSKonstantin Ananyev eth_dev->tx_pkt_prepare = ð_ena_prep_pkts; 18081173fca2SJan Medala 18091173fca2SJan Medala if (rte_eal_process_type() != RTE_PROC_PRIMARY) 18101173fca2SJan Medala return 0; 18111173fca2SJan Medala 1812f30e69b4SFerruh Yigit eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 1813f30e69b4SFerruh Yigit 1814fd976890SMichal Krawczyk memset(adapter, 0, sizeof(struct ena_adapter)); 1815fd976890SMichal Krawczyk ena_dev = &adapter->ena_dev; 1816fd976890SMichal Krawczyk 1817aab58857SStanislaw Kardach adapter->edev_data = eth_dev->data; 1818fd976890SMichal Krawczyk 1819c0802544SFerruh Yigit pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 18201173fca2SJan Medala 1821617898d1SMichal Krawczyk PMD_INIT_LOG(INFO, "Initializing %x:%x:%x.%d\n", 18221173fca2SJan Medala pci_dev->addr.domain, 18231173fca2SJan Medala pci_dev->addr.bus, 18241173fca2SJan Medala pci_dev->addr.devid, 18251173fca2SJan Medala pci_dev->addr.function); 18261173fca2SJan Medala 1827eb0ef49dSMichal Krawczyk intr_handle = &pci_dev->intr_handle; 1828eb0ef49dSMichal Krawczyk 18291173fca2SJan Medala adapter->regs = pci_dev->mem_resource[ENA_REGS_BAR].addr; 18301173fca2SJan Medala adapter->dev_mem_base = pci_dev->mem_resource[ENA_MEM_BAR].addr; 18311173fca2SJan Medala 18321d339597SRafal Kozik if (!adapter->regs) { 1833617898d1SMichal Krawczyk PMD_INIT_LOG(CRIT, "Failed to access registers BAR(%d)\n", 18341173fca2SJan Medala ENA_REGS_BAR); 18351d339597SRafal Kozik return -ENXIO; 18361d339597SRafal Kozik } 18371173fca2SJan Medala 18381173fca2SJan Medala ena_dev->reg_bar = adapter->regs; 1839aab58857SStanislaw Kardach /* This is a dummy pointer for ena_com functions. */ 1840aab58857SStanislaw Kardach ena_dev->dmadev = adapter; 18411173fca2SJan Medala 18421173fca2SJan Medala adapter->id_number = adapters_found; 18431173fca2SJan Medala 18441173fca2SJan Medala snprintf(adapter->name, ENA_NAME_MAX_LEN, "ena_%d", 18451173fca2SJan Medala adapter->id_number); 18461173fca2SJan Medala 18478a7a73f2SMichal Krawczyk rc = ena_parse_devargs(adapter, pci_dev->device.devargs); 18488a7a73f2SMichal Krawczyk if (rc != 0) { 18498a7a73f2SMichal Krawczyk PMD_INIT_LOG(CRIT, "Failed to parse devargs\n"); 18508a7a73f2SMichal Krawczyk goto err; 18518a7a73f2SMichal Krawczyk } 18528a7a73f2SMichal Krawczyk 18531173fca2SJan Medala /* device specific initialization routine */ 1854aab58857SStanislaw Kardach rc = ena_device_init(ena_dev, pci_dev, &get_feat_ctx, &wd_state); 18551173fca2SJan Medala if (rc) { 1856617898d1SMichal Krawczyk PMD_INIT_LOG(CRIT, "Failed to init ENA device\n"); 1857241da076SRafal Kozik goto err; 18581173fca2SJan Medala } 1859e859d2b8SRafal Kozik adapter->wd_state = wd_state; 18601173fca2SJan Medala 18618a7a73f2SMichal Krawczyk set_default_llq_configurations(&llq_config, &get_feat_ctx.llq, 18628a7a73f2SMichal Krawczyk adapter->use_large_llq_hdr); 18632fca2a98SMichal Krawczyk rc = ena_set_queues_placement_policy(adapter, ena_dev, 18642fca2a98SMichal Krawczyk &get_feat_ctx.llq, &llq_config); 18652fca2a98SMichal Krawczyk if (unlikely(rc)) { 1866617898d1SMichal Krawczyk PMD_INIT_LOG(CRIT, "Failed to set placement policy\n"); 18672fca2a98SMichal Krawczyk return rc; 18682fca2a98SMichal Krawczyk } 18692fca2a98SMichal Krawczyk 18702fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) 18712fca2a98SMichal Krawczyk queue_type_str = "Regular"; 18722fca2a98SMichal Krawczyk else 18732fca2a98SMichal Krawczyk queue_type_str = "Low latency"; 18746f1c9df9SStephen Hemminger PMD_DRV_LOG(INFO, "Placement policy: %s\n", queue_type_str); 1875ea93d37eSRafal Kozik 1876ea93d37eSRafal Kozik calc_queue_ctx.ena_dev = ena_dev; 1877ea93d37eSRafal Kozik calc_queue_ctx.get_feat_ctx = &get_feat_ctx; 18781173fca2SJan Medala 18795920d930SMichal Krawczyk max_num_io_queues = ena_calc_max_io_queue_num(ena_dev, &get_feat_ctx); 18808a7a73f2SMichal Krawczyk rc = ena_calc_io_queue_size(&calc_queue_ctx, 18818a7a73f2SMichal Krawczyk adapter->use_large_llq_hdr); 18825920d930SMichal Krawczyk if (unlikely((rc != 0) || (max_num_io_queues == 0))) { 1883241da076SRafal Kozik rc = -EFAULT; 1884241da076SRafal Kozik goto err_device_destroy; 1885241da076SRafal Kozik } 18861173fca2SJan Medala 18875920d930SMichal Krawczyk adapter->max_tx_ring_size = calc_queue_ctx.max_tx_queue_size; 18885920d930SMichal Krawczyk adapter->max_rx_ring_size = calc_queue_ctx.max_rx_queue_size; 1889ea93d37eSRafal Kozik adapter->max_tx_sgl_size = calc_queue_ctx.max_tx_sgl_size; 1890ea93d37eSRafal Kozik adapter->max_rx_sgl_size = calc_queue_ctx.max_rx_sgl_size; 18915920d930SMichal Krawczyk adapter->max_num_io_queues = max_num_io_queues; 18922061fe41SRafal Kozik 189333dde075SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 189433dde075SMichal Krawczyk disable_meta_caching = 189533dde075SMichal Krawczyk !!(get_feat_ctx.llq.accel_mode.u.get.supported_flags & 189633dde075SMichal Krawczyk BIT(ENA_ADMIN_DISABLE_META_CACHING)); 189733dde075SMichal Krawczyk } else { 189833dde075SMichal Krawczyk disable_meta_caching = false; 189933dde075SMichal Krawczyk } 190033dde075SMichal Krawczyk 19011173fca2SJan Medala /* prepare ring structures */ 190233dde075SMichal Krawczyk ena_init_rings(adapter, disable_meta_caching); 19031173fca2SJan Medala 1904372c1af5SJan Medala ena_config_debug_area(adapter); 1905372c1af5SJan Medala 19061173fca2SJan Medala /* Set max MTU for this device */ 19071173fca2SJan Medala adapter->max_mtu = get_feat_ctx.dev_attr.max_mtu; 19081173fca2SJan Medala 1909e8c838fdSMichal Krawczyk ena_set_offloads(&adapter->offloads, &get_feat_ctx.offload); 191083277a7cSJakub Palider 19111173fca2SJan Medala /* Copy MAC address and point DPDK to it */ 19126d13ea8eSOlivier Matz eth_dev->data->mac_addrs = (struct rte_ether_addr *)adapter->mac_addr; 1913538da7a1SOlivier Matz rte_ether_addr_copy((struct rte_ether_addr *) 1914538da7a1SOlivier Matz get_feat_ctx.dev_attr.mac_addr, 19156d13ea8eSOlivier Matz (struct rte_ether_addr *)adapter->mac_addr); 19161173fca2SJan Medala 191734d5e97eSMichal Krawczyk rc = ena_com_rss_init(ena_dev, ENA_RX_RSS_TABLE_LOG_SIZE); 191834d5e97eSMichal Krawczyk if (unlikely(rc != 0)) { 191934d5e97eSMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to initialize RSS in ENA device\n"); 192034d5e97eSMichal Krawczyk goto err_delete_debug_area; 192134d5e97eSMichal Krawczyk } 192234d5e97eSMichal Krawczyk 19231173fca2SJan Medala adapter->drv_stats = rte_zmalloc("adapter stats", 19241173fca2SJan Medala sizeof(*adapter->drv_stats), 19251173fca2SJan Medala RTE_CACHE_LINE_SIZE); 19261173fca2SJan Medala if (!adapter->drv_stats) { 1927617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1928617898d1SMichal Krawczyk "Failed to allocate memory for adapter statistics\n"); 1929241da076SRafal Kozik rc = -ENOMEM; 193034d5e97eSMichal Krawczyk goto err_rss_destroy; 19311173fca2SJan Medala } 19321173fca2SJan Medala 19331343c415SMichal Krawczyk rte_spinlock_init(&adapter->admin_lock); 19341343c415SMichal Krawczyk 1935eb0ef49dSMichal Krawczyk rte_intr_callback_register(intr_handle, 1936eb0ef49dSMichal Krawczyk ena_interrupt_handler_rte, 1937aab58857SStanislaw Kardach eth_dev); 1938eb0ef49dSMichal Krawczyk rte_intr_enable(intr_handle); 1939eb0ef49dSMichal Krawczyk ena_com_set_admin_polling_mode(ena_dev, false); 1940ca148440SMichal Krawczyk ena_com_admin_aenq_enable(ena_dev); 1941eb0ef49dSMichal Krawczyk 1942d9b8b106SMichal Krawczyk if (adapters_found == 0) 1943d9b8b106SMichal Krawczyk rte_timer_subsystem_init(); 1944d9b8b106SMichal Krawczyk rte_timer_init(&adapter->timer_wd); 1945d9b8b106SMichal Krawczyk 19461173fca2SJan Medala adapters_found++; 19471173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_INIT; 19481173fca2SJan Medala 19491173fca2SJan Medala return 0; 1950241da076SRafal Kozik 195134d5e97eSMichal Krawczyk err_rss_destroy: 195234d5e97eSMichal Krawczyk ena_com_rss_destroy(ena_dev); 1953241da076SRafal Kozik err_delete_debug_area: 1954241da076SRafal Kozik ena_com_delete_debug_area(ena_dev); 1955241da076SRafal Kozik 1956241da076SRafal Kozik err_device_destroy: 1957241da076SRafal Kozik ena_com_delete_host_info(ena_dev); 1958241da076SRafal Kozik ena_com_admin_destroy(ena_dev); 1959241da076SRafal Kozik 1960241da076SRafal Kozik err: 1961241da076SRafal Kozik return rc; 19621173fca2SJan Medala } 19631173fca2SJan Medala 1964e457bc70SRafal Kozik static void ena_destroy_device(struct rte_eth_dev *eth_dev) 1965eb0ef49dSMichal Krawczyk { 1966890728ffSStephen Hemminger struct ena_adapter *adapter = eth_dev->data->dev_private; 1967e457bc70SRafal Kozik struct ena_com_dev *ena_dev = &adapter->ena_dev; 1968eb0ef49dSMichal Krawczyk 1969e457bc70SRafal Kozik if (adapter->state == ENA_ADAPTER_STATE_FREE) 1970e457bc70SRafal Kozik return; 1971e457bc70SRafal Kozik 1972e457bc70SRafal Kozik ena_com_set_admin_running_state(ena_dev, false); 1973eb0ef49dSMichal Krawczyk 1974eb0ef49dSMichal Krawczyk if (adapter->state != ENA_ADAPTER_STATE_CLOSED) 1975eb0ef49dSMichal Krawczyk ena_close(eth_dev); 1976eb0ef49dSMichal Krawczyk 197734d5e97eSMichal Krawczyk ena_com_rss_destroy(ena_dev); 197834d5e97eSMichal Krawczyk 1979e457bc70SRafal Kozik ena_com_delete_debug_area(ena_dev); 1980e457bc70SRafal Kozik ena_com_delete_host_info(ena_dev); 1981e457bc70SRafal Kozik 1982e457bc70SRafal Kozik ena_com_abort_admin_commands(ena_dev); 1983e457bc70SRafal Kozik ena_com_wait_for_abort_completion(ena_dev); 1984e457bc70SRafal Kozik ena_com_admin_destroy(ena_dev); 1985e457bc70SRafal Kozik ena_com_mmio_reg_read_request_destroy(ena_dev); 1986e457bc70SRafal Kozik 1987e457bc70SRafal Kozik adapter->state = ENA_ADAPTER_STATE_FREE; 1988e457bc70SRafal Kozik } 1989e457bc70SRafal Kozik 1990e457bc70SRafal Kozik static int eth_ena_dev_uninit(struct rte_eth_dev *eth_dev) 1991e457bc70SRafal Kozik { 1992e457bc70SRafal Kozik if (rte_eal_process_type() != RTE_PROC_PRIMARY) 1993e457bc70SRafal Kozik return 0; 1994e457bc70SRafal Kozik 1995e457bc70SRafal Kozik ena_destroy_device(eth_dev); 1996e457bc70SRafal Kozik 1997eb0ef49dSMichal Krawczyk return 0; 1998eb0ef49dSMichal Krawczyk } 1999eb0ef49dSMichal Krawczyk 20001173fca2SJan Medala static int ena_dev_configure(struct rte_eth_dev *dev) 20011173fca2SJan Medala { 2002890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 20037369f88fSRafal Kozik 20041173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_CONFIG; 20051173fca2SJan Medala 2006295968d1SFerruh Yigit if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) 2007295968d1SFerruh Yigit dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 2008295968d1SFerruh Yigit dev->data->dev_conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 2009b418f0d2SMichal Krawczyk 2010e2a6d08bSMichal Krawczyk /* Scattered Rx cannot be turned off in the HW, so this capability must 2011e2a6d08bSMichal Krawczyk * be forced. 2012e2a6d08bSMichal Krawczyk */ 2013e2a6d08bSMichal Krawczyk dev->data->scattered_rx = 1; 2014e2a6d08bSMichal Krawczyk 2015f93e20e5SMichal Krawczyk adapter->last_tx_comp_qid = 0; 2016f93e20e5SMichal Krawczyk 2017f93e20e5SMichal Krawczyk adapter->missing_tx_completion_budget = 2018f93e20e5SMichal Krawczyk RTE_MIN(ENA_MONITORED_TX_QUEUES, dev->data->nb_tx_queues); 2019f93e20e5SMichal Krawczyk 2020f93e20e5SMichal Krawczyk adapter->missing_tx_completion_to = ENA_TX_TIMEOUT; 2021f93e20e5SMichal Krawczyk /* To avoid detection of the spurious Tx completion timeout due to 2022f93e20e5SMichal Krawczyk * application not calling the Tx cleanup function, set timeout for the 2023f93e20e5SMichal Krawczyk * Tx queue which should be half of the missing completion timeout for a 2024f93e20e5SMichal Krawczyk * safety. If there will be a lot of missing Tx completions in the 2025f93e20e5SMichal Krawczyk * queue, they will be detected sooner or later. 2026f93e20e5SMichal Krawczyk */ 2027f93e20e5SMichal Krawczyk adapter->tx_cleanup_stall_delay = adapter->missing_tx_completion_to / 2; 2028f93e20e5SMichal Krawczyk 2029a4996bd8SWei Dai adapter->tx_selected_offloads = dev->data->dev_conf.txmode.offloads; 2030a4996bd8SWei Dai adapter->rx_selected_offloads = dev->data->dev_conf.rxmode.offloads; 2031e2a6d08bSMichal Krawczyk 20321173fca2SJan Medala return 0; 20331173fca2SJan Medala } 20341173fca2SJan Medala 203533dde075SMichal Krawczyk static void ena_init_rings(struct ena_adapter *adapter, 203633dde075SMichal Krawczyk bool disable_meta_caching) 20371173fca2SJan Medala { 20385920d930SMichal Krawczyk size_t i; 20391173fca2SJan Medala 20405920d930SMichal Krawczyk for (i = 0; i < adapter->max_num_io_queues; i++) { 20411173fca2SJan Medala struct ena_ring *ring = &adapter->tx_ring[i]; 20421173fca2SJan Medala 20431173fca2SJan Medala ring->configured = 0; 20441173fca2SJan Medala ring->type = ENA_RING_TYPE_TX; 20451173fca2SJan Medala ring->adapter = adapter; 20461173fca2SJan Medala ring->id = i; 20471173fca2SJan Medala ring->tx_mem_queue_type = adapter->ena_dev.tx_mem_queue_type; 20481173fca2SJan Medala ring->tx_max_header_size = adapter->ena_dev.tx_max_header_size; 20492061fe41SRafal Kozik ring->sgl_size = adapter->max_tx_sgl_size; 205033dde075SMichal Krawczyk ring->disable_meta_caching = disable_meta_caching; 20511173fca2SJan Medala } 20521173fca2SJan Medala 20535920d930SMichal Krawczyk for (i = 0; i < adapter->max_num_io_queues; i++) { 20541173fca2SJan Medala struct ena_ring *ring = &adapter->rx_ring[i]; 20551173fca2SJan Medala 20561173fca2SJan Medala ring->configured = 0; 20571173fca2SJan Medala ring->type = ENA_RING_TYPE_RX; 20581173fca2SJan Medala ring->adapter = adapter; 20591173fca2SJan Medala ring->id = i; 2060ea93d37eSRafal Kozik ring->sgl_size = adapter->max_rx_sgl_size; 20611173fca2SJan Medala } 20621173fca2SJan Medala } 20631173fca2SJan Medala 20643a822d79SMichal Krawczyk static uint64_t ena_get_rx_port_offloads(struct ena_adapter *adapter) 20653a822d79SMichal Krawczyk { 20663a822d79SMichal Krawczyk uint64_t port_offloads = 0; 20673a822d79SMichal Krawczyk 20683a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & ENA_L3_IPV4_CSUM) 2069295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM; 20703a822d79SMichal Krawczyk 20713a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & 20723a822d79SMichal Krawczyk (ENA_L4_IPV4_CSUM | ENA_L4_IPV6_CSUM)) 20733a822d79SMichal Krawczyk port_offloads |= 2074295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM; 20753a822d79SMichal Krawczyk 20763a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & ENA_RX_RSS_HASH) 2077295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 20783a822d79SMichal Krawczyk 2079295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_SCATTER; 2080e2a6d08bSMichal Krawczyk 20813a822d79SMichal Krawczyk return port_offloads; 20823a822d79SMichal Krawczyk } 20833a822d79SMichal Krawczyk 20843a822d79SMichal Krawczyk static uint64_t ena_get_tx_port_offloads(struct ena_adapter *adapter) 20853a822d79SMichal Krawczyk { 20863a822d79SMichal Krawczyk uint64_t port_offloads = 0; 20873a822d79SMichal Krawczyk 20883a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & ENA_IPV4_TSO) 2089295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO; 20903a822d79SMichal Krawczyk 20913a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & ENA_L3_IPV4_CSUM) 2092295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM; 20933a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & 20943a822d79SMichal Krawczyk (ENA_L4_IPV4_CSUM_PARTIAL | ENA_L4_IPV4_CSUM | 20953a822d79SMichal Krawczyk ENA_L4_IPV6_CSUM | ENA_L4_IPV6_CSUM_PARTIAL)) 20963a822d79SMichal Krawczyk port_offloads |= 2097295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_UDP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_CKSUM; 20983a822d79SMichal Krawczyk 2099295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 21003a822d79SMichal Krawczyk 21013a822d79SMichal Krawczyk return port_offloads; 21023a822d79SMichal Krawczyk } 21033a822d79SMichal Krawczyk 21043a822d79SMichal Krawczyk static uint64_t ena_get_rx_queue_offloads(struct ena_adapter *adapter) 21053a822d79SMichal Krawczyk { 21063a822d79SMichal Krawczyk RTE_SET_USED(adapter); 21073a822d79SMichal Krawczyk 21083a822d79SMichal Krawczyk return 0; 21093a822d79SMichal Krawczyk } 21103a822d79SMichal Krawczyk 21113a822d79SMichal Krawczyk static uint64_t ena_get_tx_queue_offloads(struct ena_adapter *adapter) 21123a822d79SMichal Krawczyk { 21133a822d79SMichal Krawczyk RTE_SET_USED(adapter); 21143a822d79SMichal Krawczyk 21153a822d79SMichal Krawczyk return 0; 21163a822d79SMichal Krawczyk } 21173a822d79SMichal Krawczyk 2118bdad90d1SIvan Ilchenko static int ena_infos_get(struct rte_eth_dev *dev, 21191173fca2SJan Medala struct rte_eth_dev_info *dev_info) 21201173fca2SJan Medala { 21211173fca2SJan Medala struct ena_adapter *adapter; 21221173fca2SJan Medala struct ena_com_dev *ena_dev; 21231173fca2SJan Medala 2124498c687aSRafal Kozik ena_assert_msg(dev->data != NULL, "Uninitialized device\n"); 2125498c687aSRafal Kozik ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device\n"); 2126890728ffSStephen Hemminger adapter = dev->data->dev_private; 21271173fca2SJan Medala 21281173fca2SJan Medala ena_dev = &adapter->ena_dev; 2129498c687aSRafal Kozik ena_assert_msg(ena_dev != NULL, "Uninitialized device\n"); 21301173fca2SJan Medala 2131e274f573SMarc Sune dev_info->speed_capa = 2132295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_1G | 2133295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_2_5G | 2134295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_5G | 2135295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_10G | 2136295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_25G | 2137295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_40G | 2138295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_50G | 2139295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_100G; 2140e274f573SMarc Sune 21411173fca2SJan Medala /* Inform framework about available features */ 21423a822d79SMichal Krawczyk dev_info->rx_offload_capa = ena_get_rx_port_offloads(adapter); 21433a822d79SMichal Krawczyk dev_info->tx_offload_capa = ena_get_tx_port_offloads(adapter); 21443a822d79SMichal Krawczyk dev_info->rx_queue_offload_capa = ena_get_rx_queue_offloads(adapter); 21453a822d79SMichal Krawczyk dev_info->tx_queue_offload_capa = ena_get_tx_queue_offloads(adapter); 21461173fca2SJan Medala 214734d5e97eSMichal Krawczyk dev_info->flow_type_rss_offloads = ENA_ALL_RSS_HF; 214834d5e97eSMichal Krawczyk dev_info->hash_key_size = ENA_HASH_KEY_SIZE; 2149b01ead20SRafal Kozik 21501173fca2SJan Medala dev_info->min_rx_bufsize = ENA_MIN_FRAME_LEN; 21511bb4a528SFerruh Yigit dev_info->max_rx_pktlen = adapter->max_mtu + RTE_ETHER_HDR_LEN + 21521bb4a528SFerruh Yigit RTE_ETHER_CRC_LEN; 21531bb4a528SFerruh Yigit dev_info->min_mtu = ENA_MIN_MTU; 21541bb4a528SFerruh Yigit dev_info->max_mtu = adapter->max_mtu; 21551173fca2SJan Medala dev_info->max_mac_addrs = 1; 21561173fca2SJan Medala 21575920d930SMichal Krawczyk dev_info->max_rx_queues = adapter->max_num_io_queues; 21585920d930SMichal Krawczyk dev_info->max_tx_queues = adapter->max_num_io_queues; 21591173fca2SJan Medala dev_info->reta_size = ENA_RX_RSS_TABLE_SIZE; 216056b8b9b7SRafal Kozik 21615920d930SMichal Krawczyk dev_info->rx_desc_lim.nb_max = adapter->max_rx_ring_size; 216292680dc2SRafal Kozik dev_info->rx_desc_lim.nb_min = ENA_MIN_RING_DESC; 2163ea93d37eSRafal Kozik dev_info->rx_desc_lim.nb_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2164ea93d37eSRafal Kozik adapter->max_rx_sgl_size); 2165ea93d37eSRafal Kozik dev_info->rx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2166ea93d37eSRafal Kozik adapter->max_rx_sgl_size); 216792680dc2SRafal Kozik 21685920d930SMichal Krawczyk dev_info->tx_desc_lim.nb_max = adapter->max_tx_ring_size; 216992680dc2SRafal Kozik dev_info->tx_desc_lim.nb_min = ENA_MIN_RING_DESC; 217092680dc2SRafal Kozik dev_info->tx_desc_lim.nb_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2171ea93d37eSRafal Kozik adapter->max_tx_sgl_size); 217292680dc2SRafal Kozik dev_info->tx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2173ea93d37eSRafal Kozik adapter->max_tx_sgl_size); 2174bdad90d1SIvan Ilchenko 217530a6c7efSStanislaw Kardach dev_info->default_rxportconf.ring_size = ENA_DEFAULT_RING_SIZE; 217630a6c7efSStanislaw Kardach dev_info->default_txportconf.ring_size = ENA_DEFAULT_RING_SIZE; 217730a6c7efSStanislaw Kardach 2178bdad90d1SIvan Ilchenko return 0; 21791173fca2SJan Medala } 21801173fca2SJan Medala 21811be097dcSMichal Krawczyk static inline void ena_init_rx_mbuf(struct rte_mbuf *mbuf, uint16_t len) 21821be097dcSMichal Krawczyk { 21831be097dcSMichal Krawczyk mbuf->data_len = len; 21841be097dcSMichal Krawczyk mbuf->data_off = RTE_PKTMBUF_HEADROOM; 21851be097dcSMichal Krawczyk mbuf->refcnt = 1; 21861be097dcSMichal Krawczyk mbuf->next = NULL; 21871be097dcSMichal Krawczyk } 21881be097dcSMichal Krawczyk 21891be097dcSMichal Krawczyk static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, 21901be097dcSMichal Krawczyk struct ena_com_rx_buf_info *ena_bufs, 21911be097dcSMichal Krawczyk uint32_t descs, 21921be097dcSMichal Krawczyk uint16_t *next_to_clean, 21931be097dcSMichal Krawczyk uint8_t offset) 21941be097dcSMichal Krawczyk { 21951be097dcSMichal Krawczyk struct rte_mbuf *mbuf; 21961be097dcSMichal Krawczyk struct rte_mbuf *mbuf_head; 21971be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info; 219883fd97b2SMichal Krawczyk int rc; 21991be097dcSMichal Krawczyk uint16_t ntc, len, req_id, buf = 0; 22001be097dcSMichal Krawczyk 22011be097dcSMichal Krawczyk if (unlikely(descs == 0)) 22021be097dcSMichal Krawczyk return NULL; 22031be097dcSMichal Krawczyk 22041be097dcSMichal Krawczyk ntc = *next_to_clean; 22051be097dcSMichal Krawczyk 22061be097dcSMichal Krawczyk len = ena_bufs[buf].len; 22071be097dcSMichal Krawczyk req_id = ena_bufs[buf].req_id; 22081be097dcSMichal Krawczyk 22091be097dcSMichal Krawczyk rx_info = &rx_ring->rx_buffer_info[req_id]; 22101be097dcSMichal Krawczyk 22111be097dcSMichal Krawczyk mbuf = rx_info->mbuf; 22121be097dcSMichal Krawczyk RTE_ASSERT(mbuf != NULL); 22131be097dcSMichal Krawczyk 22141be097dcSMichal Krawczyk ena_init_rx_mbuf(mbuf, len); 22151be097dcSMichal Krawczyk 22161be097dcSMichal Krawczyk /* Fill the mbuf head with the data specific for 1st segment. */ 22171be097dcSMichal Krawczyk mbuf_head = mbuf; 22181be097dcSMichal Krawczyk mbuf_head->nb_segs = descs; 22191be097dcSMichal Krawczyk mbuf_head->port = rx_ring->port_id; 22201be097dcSMichal Krawczyk mbuf_head->pkt_len = len; 22211be097dcSMichal Krawczyk mbuf_head->data_off += offset; 22221be097dcSMichal Krawczyk 22231be097dcSMichal Krawczyk rx_info->mbuf = NULL; 2224c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[ntc] = req_id; 2225c0006061SMichal Krawczyk ntc = ENA_IDX_NEXT_MASKED(ntc, rx_ring->size_mask); 22261be097dcSMichal Krawczyk 22271be097dcSMichal Krawczyk while (--descs) { 22281be097dcSMichal Krawczyk ++buf; 22291be097dcSMichal Krawczyk len = ena_bufs[buf].len; 22301be097dcSMichal Krawczyk req_id = ena_bufs[buf].req_id; 22311be097dcSMichal Krawczyk 22321be097dcSMichal Krawczyk rx_info = &rx_ring->rx_buffer_info[req_id]; 22331be097dcSMichal Krawczyk RTE_ASSERT(rx_info->mbuf != NULL); 22341be097dcSMichal Krawczyk 223583fd97b2SMichal Krawczyk if (unlikely(len == 0)) { 223683fd97b2SMichal Krawczyk /* 223783fd97b2SMichal Krawczyk * Some devices can pass descriptor with the length 0. 223883fd97b2SMichal Krawczyk * To avoid confusion, the PMD is simply putting the 223983fd97b2SMichal Krawczyk * descriptor back, as it was never used. We'll avoid 224083fd97b2SMichal Krawczyk * mbuf allocation that way. 224183fd97b2SMichal Krawczyk */ 224283fd97b2SMichal Krawczyk rc = ena_add_single_rx_desc(rx_ring->ena_com_io_sq, 224383fd97b2SMichal Krawczyk rx_info->mbuf, req_id); 224483fd97b2SMichal Krawczyk if (unlikely(rc != 0)) { 224583fd97b2SMichal Krawczyk /* Free the mbuf in case of an error. */ 224683fd97b2SMichal Krawczyk rte_mbuf_raw_free(rx_info->mbuf); 224783fd97b2SMichal Krawczyk } else { 224883fd97b2SMichal Krawczyk /* 224983fd97b2SMichal Krawczyk * If there was no error, just exit the loop as 225083fd97b2SMichal Krawczyk * 0 length descriptor is always the last one. 225183fd97b2SMichal Krawczyk */ 225283fd97b2SMichal Krawczyk break; 225383fd97b2SMichal Krawczyk } 225483fd97b2SMichal Krawczyk } else { 22551be097dcSMichal Krawczyk /* Create an mbuf chain. */ 22561be097dcSMichal Krawczyk mbuf->next = rx_info->mbuf; 22571be097dcSMichal Krawczyk mbuf = mbuf->next; 22581be097dcSMichal Krawczyk 22591be097dcSMichal Krawczyk ena_init_rx_mbuf(mbuf, len); 22601be097dcSMichal Krawczyk mbuf_head->pkt_len += len; 226183fd97b2SMichal Krawczyk } 22621be097dcSMichal Krawczyk 226383fd97b2SMichal Krawczyk /* 226483fd97b2SMichal Krawczyk * Mark the descriptor as depleted and perform necessary 226583fd97b2SMichal Krawczyk * cleanup. 226683fd97b2SMichal Krawczyk * This code will execute in two cases: 226783fd97b2SMichal Krawczyk * 1. Descriptor len was greater than 0 - normal situation. 226883fd97b2SMichal Krawczyk * 2. Descriptor len was 0 and we failed to add the descriptor 226983fd97b2SMichal Krawczyk * to the device. In that situation, we should try to add 227083fd97b2SMichal Krawczyk * the mbuf again in the populate routine and mark the 227183fd97b2SMichal Krawczyk * descriptor as used up by the device. 227283fd97b2SMichal Krawczyk */ 22731be097dcSMichal Krawczyk rx_info->mbuf = NULL; 2274c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[ntc] = req_id; 2275c0006061SMichal Krawczyk ntc = ENA_IDX_NEXT_MASKED(ntc, rx_ring->size_mask); 22761be097dcSMichal Krawczyk } 22771be097dcSMichal Krawczyk 22781be097dcSMichal Krawczyk *next_to_clean = ntc; 22791be097dcSMichal Krawczyk 22801be097dcSMichal Krawczyk return mbuf_head; 22811be097dcSMichal Krawczyk } 22821be097dcSMichal Krawczyk 22831173fca2SJan Medala static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, 22841173fca2SJan Medala uint16_t nb_pkts) 22851173fca2SJan Medala { 22861173fca2SJan Medala struct ena_ring *rx_ring = (struct ena_ring *)(rx_queue); 228777550607SMichal Krawczyk unsigned int free_queue_entries; 22881173fca2SJan Medala uint16_t next_to_clean = rx_ring->next_to_clean; 228974456796SMichal Krawczyk uint16_t descs_in_use; 22901be097dcSMichal Krawczyk struct rte_mbuf *mbuf; 22911be097dcSMichal Krawczyk uint16_t completed; 22921173fca2SJan Medala struct ena_com_rx_ctx ena_rx_ctx; 22931be097dcSMichal Krawczyk int i, rc = 0; 229434d5e97eSMichal Krawczyk bool fill_hash; 22951173fca2SJan Medala 22960a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 22971173fca2SJan Medala /* Check adapter state */ 22981173fca2SJan Medala if (unlikely(rx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) { 22990a001d69SMichal Krawczyk PMD_RX_LOG(ALERT, 23001173fca2SJan Medala "Trying to receive pkts while device is NOT running\n"); 23011173fca2SJan Medala return 0; 23021173fca2SJan Medala } 23030a001d69SMichal Krawczyk #endif 23041173fca2SJan Medala 2305295968d1SFerruh Yigit fill_hash = rx_ring->offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH; 230634d5e97eSMichal Krawczyk 2307c0006061SMichal Krawczyk descs_in_use = rx_ring->ring_size - 230874456796SMichal Krawczyk ena_com_free_q_entries(rx_ring->ena_com_io_sq) - 1; 230974456796SMichal Krawczyk nb_pkts = RTE_MIN(descs_in_use, nb_pkts); 23101173fca2SJan Medala 23111173fca2SJan Medala for (completed = 0; completed < nb_pkts; completed++) { 2312ea93d37eSRafal Kozik ena_rx_ctx.max_bufs = rx_ring->sgl_size; 23131173fca2SJan Medala ena_rx_ctx.ena_bufs = rx_ring->ena_bufs; 23141173fca2SJan Medala ena_rx_ctx.descs = 0; 23157b3a3c4bSMaciej Bielski ena_rx_ctx.pkt_offset = 0; 23161173fca2SJan Medala /* receive packet context */ 23171173fca2SJan Medala rc = ena_com_rx_pkt(rx_ring->ena_com_io_cq, 23181173fca2SJan Medala rx_ring->ena_com_io_sq, 23191173fca2SJan Medala &ena_rx_ctx); 23201173fca2SJan Medala if (unlikely(rc)) { 23210a001d69SMichal Krawczyk PMD_RX_LOG(ERR, 2322617898d1SMichal Krawczyk "Failed to get the packet from the device, rc: %d\n", 2323617898d1SMichal Krawczyk rc); 232405cffdcfSMichal Krawczyk if (rc == ENA_COM_NO_SPACE) { 232505cffdcfSMichal Krawczyk ++rx_ring->rx_stats.bad_desc_num; 23269b260dbfSRafal Kozik rx_ring->adapter->reset_reason = 23279b260dbfSRafal Kozik ENA_REGS_RESET_TOO_MANY_RX_DESCS; 232805cffdcfSMichal Krawczyk } else { 232905cffdcfSMichal Krawczyk ++rx_ring->rx_stats.bad_req_id; 233005cffdcfSMichal Krawczyk rx_ring->adapter->reset_reason = 233105cffdcfSMichal Krawczyk ENA_REGS_RESET_INV_RX_REQ_ID; 233205cffdcfSMichal Krawczyk } 2333241da076SRafal Kozik rx_ring->adapter->trigger_reset = true; 23341173fca2SJan Medala return 0; 23351173fca2SJan Medala } 23361173fca2SJan Medala 23371be097dcSMichal Krawczyk mbuf = ena_rx_mbuf(rx_ring, 23381be097dcSMichal Krawczyk ena_rx_ctx.ena_bufs, 23391be097dcSMichal Krawczyk ena_rx_ctx.descs, 23401be097dcSMichal Krawczyk &next_to_clean, 23411be097dcSMichal Krawczyk ena_rx_ctx.pkt_offset); 23421be097dcSMichal Krawczyk if (unlikely(mbuf == NULL)) { 23431be097dcSMichal Krawczyk for (i = 0; i < ena_rx_ctx.descs; ++i) { 2344c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[next_to_clean] = 23451be097dcSMichal Krawczyk rx_ring->ena_bufs[i].req_id; 2346c0006061SMichal Krawczyk next_to_clean = ENA_IDX_NEXT_MASKED( 2347c0006061SMichal Krawczyk next_to_clean, rx_ring->size_mask); 23481173fca2SJan Medala } 2349f00930d9SRafal Kozik break; 23501be097dcSMichal Krawczyk } 23511173fca2SJan Medala 23521173fca2SJan Medala /* fill mbuf attributes if any */ 235334d5e97eSMichal Krawczyk ena_rx_mbuf_prepare(mbuf, &ena_rx_ctx, fill_hash); 23547830e905SSolganik Alexander 23551be097dcSMichal Krawczyk if (unlikely(mbuf->ol_flags & 2356*daa02b5cSOlivier Matz (RTE_MBUF_F_RX_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD))) { 2357ef74b5f7SMichal Krawczyk rte_atomic64_inc(&rx_ring->adapter->drv_stats->ierrors); 23587830e905SSolganik Alexander ++rx_ring->rx_stats.bad_csum; 2359ef74b5f7SMichal Krawczyk } 23607830e905SSolganik Alexander 23611be097dcSMichal Krawczyk rx_pkts[completed] = mbuf; 23621be097dcSMichal Krawczyk rx_ring->rx_stats.bytes += mbuf->pkt_len; 23631173fca2SJan Medala } 23641173fca2SJan Medala 23651be097dcSMichal Krawczyk rx_ring->rx_stats.cnt += completed; 2366ec78af6bSMichal Krawczyk rx_ring->next_to_clean = next_to_clean; 2367ec78af6bSMichal Krawczyk 236877550607SMichal Krawczyk free_queue_entries = ena_com_free_q_entries(rx_ring->ena_com_io_sq); 236977550607SMichal Krawczyk 23701173fca2SJan Medala /* Burst refill to save doorbells, memory barriers, const interval */ 2371005064e5SMichal Krawczyk if (free_queue_entries >= rx_ring->rx_free_thresh) { 2372a45462c5SRafal Kozik ena_com_update_dev_comp_head(rx_ring->ena_com_io_cq); 237377550607SMichal Krawczyk ena_populate_rx_queue(rx_ring, free_queue_entries); 2374a45462c5SRafal Kozik } 23751173fca2SJan Medala 23761be097dcSMichal Krawczyk return completed; 23771173fca2SJan Medala } 23781173fca2SJan Medala 2379b3fc5a1aSKonstantin Ananyev static uint16_t 238083277a7cSJakub Palider eth_ena_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 2381b3fc5a1aSKonstantin Ananyev uint16_t nb_pkts) 2382b3fc5a1aSKonstantin Ananyev { 2383b3fc5a1aSKonstantin Ananyev int32_t ret; 2384b3fc5a1aSKonstantin Ananyev uint32_t i; 2385b3fc5a1aSKonstantin Ananyev struct rte_mbuf *m; 238683277a7cSJakub Palider struct ena_ring *tx_ring = (struct ena_ring *)(tx_queue); 2387e8c838fdSMichal Krawczyk struct ena_adapter *adapter = tx_ring->adapter; 2388a7c528e5SOlivier Matz struct rte_ipv4_hdr *ip_hdr; 2389b3fc5a1aSKonstantin Ananyev uint64_t ol_flags; 2390e8c838fdSMichal Krawczyk uint64_t l4_csum_flag; 2391e8c838fdSMichal Krawczyk uint64_t dev_offload_capa; 239283277a7cSJakub Palider uint16_t frag_field; 2393e8c838fdSMichal Krawczyk bool need_pseudo_csum; 239483277a7cSJakub Palider 2395e8c838fdSMichal Krawczyk dev_offload_capa = adapter->offloads.tx_offloads; 2396b3fc5a1aSKonstantin Ananyev for (i = 0; i != nb_pkts; i++) { 2397b3fc5a1aSKonstantin Ananyev m = tx_pkts[i]; 2398b3fc5a1aSKonstantin Ananyev ol_flags = m->ol_flags; 2399b3fc5a1aSKonstantin Ananyev 2400e8c838fdSMichal Krawczyk /* Check if any offload flag was set */ 2401e8c838fdSMichal Krawczyk if (ol_flags == 0) 2402bc5ef57dSMichal Krawczyk continue; 2403bc5ef57dSMichal Krawczyk 2404*daa02b5cSOlivier Matz l4_csum_flag = ol_flags & RTE_MBUF_F_TX_L4_MASK; 2405e8c838fdSMichal Krawczyk /* SCTP checksum offload is not supported by the ENA. */ 2406e8c838fdSMichal Krawczyk if ((ol_flags & ENA_TX_OFFLOAD_NOTSUP_MASK) || 2407*daa02b5cSOlivier Matz l4_csum_flag == RTE_MBUF_F_TX_SCTP_CKSUM) { 2408e8c838fdSMichal Krawczyk PMD_TX_LOG(DEBUG, 2409e8c838fdSMichal Krawczyk "mbuf[%" PRIu32 "] has unsupported offloads flags set: 0x%" PRIu64 "\n", 2410e8c838fdSMichal Krawczyk i, ol_flags); 2411baeed5f4SMichal Krawczyk rte_errno = ENOTSUP; 2412b3fc5a1aSKonstantin Ananyev return i; 2413b3fc5a1aSKonstantin Ananyev } 2414b3fc5a1aSKonstantin Ananyev 2415b3fc5a1aSKonstantin Ananyev #ifdef RTE_LIBRTE_ETHDEV_DEBUG 2416e8c838fdSMichal Krawczyk /* Check if requested offload is also enabled for the queue */ 2417*daa02b5cSOlivier Matz if ((ol_flags & RTE_MBUF_F_TX_IP_CKSUM && 2418295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) || 2419*daa02b5cSOlivier Matz (l4_csum_flag == RTE_MBUF_F_TX_TCP_CKSUM && 2420295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) || 2421*daa02b5cSOlivier Matz (l4_csum_flag == RTE_MBUF_F_TX_UDP_CKSUM && 2422295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM))) { 2423e8c838fdSMichal Krawczyk PMD_TX_LOG(DEBUG, 2424e8c838fdSMichal Krawczyk "mbuf[%" PRIu32 "]: requested offloads: %" PRIu16 " are not enabled for the queue[%u]\n", 2425e8c838fdSMichal Krawczyk i, m->nb_segs, tx_ring->id); 2426e8c838fdSMichal Krawczyk rte_errno = EINVAL; 2427e8c838fdSMichal Krawczyk return i; 2428e8c838fdSMichal Krawczyk } 2429e8c838fdSMichal Krawczyk 2430e8c838fdSMichal Krawczyk /* The caller is obligated to set l2 and l3 len if any cksum 2431e8c838fdSMichal Krawczyk * offload is enabled. 2432e8c838fdSMichal Krawczyk */ 2433*daa02b5cSOlivier Matz if (unlikely(ol_flags & (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_L4_MASK) && 2434e8c838fdSMichal Krawczyk (m->l2_len == 0 || m->l3_len == 0))) { 2435e8c838fdSMichal Krawczyk PMD_TX_LOG(DEBUG, 2436e8c838fdSMichal Krawczyk "mbuf[%" PRIu32 "]: l2_len or l3_len values are 0 while the offload was requested\n", 2437e8c838fdSMichal Krawczyk i); 2438e8c838fdSMichal Krawczyk rte_errno = EINVAL; 2439e8c838fdSMichal Krawczyk return i; 2440e8c838fdSMichal Krawczyk } 2441b3fc5a1aSKonstantin Ananyev ret = rte_validate_tx_offload(m); 2442b3fc5a1aSKonstantin Ananyev if (ret != 0) { 2443baeed5f4SMichal Krawczyk rte_errno = -ret; 2444b3fc5a1aSKonstantin Ananyev return i; 2445b3fc5a1aSKonstantin Ananyev } 2446b3fc5a1aSKonstantin Ananyev #endif 244783277a7cSJakub Palider 2448e8c838fdSMichal Krawczyk /* Verify HW support for requested offloads and determine if 2449e8c838fdSMichal Krawczyk * pseudo header checksum is needed. 245083277a7cSJakub Palider */ 2451e8c838fdSMichal Krawczyk need_pseudo_csum = false; 2452*daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_IPV4) { 2453*daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM && 2454e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L3_IPV4_CSUM)) { 2455e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2456e8c838fdSMichal Krawczyk return i; 2457e8c838fdSMichal Krawczyk } 245883277a7cSJakub Palider 2459*daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_TCP_SEG && 2460e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_IPV4_TSO)) { 2461e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2462e8c838fdSMichal Krawczyk return i; 2463e8c838fdSMichal Krawczyk } 2464e8c838fdSMichal Krawczyk 2465e8c838fdSMichal Krawczyk /* Check HW capabilities and if pseudo csum is needed 2466e8c838fdSMichal Krawczyk * for L4 offloads. 2467e8c838fdSMichal Krawczyk */ 2468*daa02b5cSOlivier Matz if (l4_csum_flag != RTE_MBUF_F_TX_L4_NO_CKSUM && 2469e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L4_IPV4_CSUM)) { 2470e8c838fdSMichal Krawczyk if (dev_offload_capa & 2471e8c838fdSMichal Krawczyk ENA_L4_IPV4_CSUM_PARTIAL) { 2472e8c838fdSMichal Krawczyk need_pseudo_csum = true; 2473e8c838fdSMichal Krawczyk } else { 2474e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2475e8c838fdSMichal Krawczyk return i; 2476e8c838fdSMichal Krawczyk } 2477e8c838fdSMichal Krawczyk } 2478e8c838fdSMichal Krawczyk 2479e8c838fdSMichal Krawczyk /* Parse the DF flag */ 2480e8c838fdSMichal Krawczyk ip_hdr = rte_pktmbuf_mtod_offset(m, 2481e8c838fdSMichal Krawczyk struct rte_ipv4_hdr *, m->l2_len); 2482e8c838fdSMichal Krawczyk frag_field = rte_be_to_cpu_16(ip_hdr->fragment_offset); 2483e8c838fdSMichal Krawczyk if (frag_field & RTE_IPV4_HDR_DF_FLAG) { 2484e8c838fdSMichal Krawczyk m->packet_type |= RTE_PTYPE_L4_NONFRAG; 2485*daa02b5cSOlivier Matz } else if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 2486e8c838fdSMichal Krawczyk /* In case we are supposed to TSO and have DF 2487e8c838fdSMichal Krawczyk * not set (DF=0) hardware must be provided with 2488e8c838fdSMichal Krawczyk * partial checksum. 2489e8c838fdSMichal Krawczyk */ 2490e8c838fdSMichal Krawczyk need_pseudo_csum = true; 2491e8c838fdSMichal Krawczyk } 2492*daa02b5cSOlivier Matz } else if (ol_flags & RTE_MBUF_F_TX_IPV6) { 2493e8c838fdSMichal Krawczyk /* There is no support for IPv6 TSO as for now. */ 2494*daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 2495e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2496e8c838fdSMichal Krawczyk return i; 2497e8c838fdSMichal Krawczyk } 2498e8c838fdSMichal Krawczyk 2499e8c838fdSMichal Krawczyk /* Check HW capabilities and if pseudo csum is needed */ 2500*daa02b5cSOlivier Matz if (l4_csum_flag != RTE_MBUF_F_TX_L4_NO_CKSUM && 2501e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L4_IPV6_CSUM)) { 2502e8c838fdSMichal Krawczyk if (dev_offload_capa & 2503e8c838fdSMichal Krawczyk ENA_L4_IPV6_CSUM_PARTIAL) { 2504e8c838fdSMichal Krawczyk need_pseudo_csum = true; 2505e8c838fdSMichal Krawczyk } else { 2506e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2507e8c838fdSMichal Krawczyk return i; 2508e8c838fdSMichal Krawczyk } 2509e8c838fdSMichal Krawczyk } 2510e8c838fdSMichal Krawczyk } 2511e8c838fdSMichal Krawczyk 2512e8c838fdSMichal Krawczyk if (need_pseudo_csum) { 2513e8c838fdSMichal Krawczyk ret = rte_net_intel_cksum_flags_prepare(m, ol_flags); 2514b3fc5a1aSKonstantin Ananyev if (ret != 0) { 2515baeed5f4SMichal Krawczyk rte_errno = -ret; 2516b3fc5a1aSKonstantin Ananyev return i; 2517b3fc5a1aSKonstantin Ananyev } 2518b3fc5a1aSKonstantin Ananyev } 2519e8c838fdSMichal Krawczyk } 2520b3fc5a1aSKonstantin Ananyev 2521b3fc5a1aSKonstantin Ananyev return i; 2522b3fc5a1aSKonstantin Ananyev } 2523b3fc5a1aSKonstantin Ananyev 2524f01f060cSRafal Kozik static void ena_update_hints(struct ena_adapter *adapter, 2525f01f060cSRafal Kozik struct ena_admin_ena_hw_hints *hints) 2526f01f060cSRafal Kozik { 2527f01f060cSRafal Kozik if (hints->admin_completion_tx_timeout) 2528f01f060cSRafal Kozik adapter->ena_dev.admin_queue.completion_timeout = 2529f01f060cSRafal Kozik hints->admin_completion_tx_timeout * 1000; 2530f01f060cSRafal Kozik 2531f01f060cSRafal Kozik if (hints->mmio_read_timeout) 2532f01f060cSRafal Kozik /* convert to usec */ 2533f01f060cSRafal Kozik adapter->ena_dev.mmio_read.reg_read_to = 2534f01f060cSRafal Kozik hints->mmio_read_timeout * 1000; 2535d9b8b106SMichal Krawczyk 2536f93e20e5SMichal Krawczyk if (hints->missing_tx_completion_timeout) { 2537f93e20e5SMichal Krawczyk if (hints->missing_tx_completion_timeout == 2538f93e20e5SMichal Krawczyk ENA_HW_HINTS_NO_TIMEOUT) { 2539f93e20e5SMichal Krawczyk adapter->missing_tx_completion_to = 2540f93e20e5SMichal Krawczyk ENA_HW_HINTS_NO_TIMEOUT; 2541f93e20e5SMichal Krawczyk } else { 2542f93e20e5SMichal Krawczyk /* Convert from msecs to ticks */ 2543f93e20e5SMichal Krawczyk adapter->missing_tx_completion_to = rte_get_timer_hz() * 2544f93e20e5SMichal Krawczyk hints->missing_tx_completion_timeout / 1000; 2545f93e20e5SMichal Krawczyk adapter->tx_cleanup_stall_delay = 2546f93e20e5SMichal Krawczyk adapter->missing_tx_completion_to / 2; 2547f93e20e5SMichal Krawczyk } 2548f93e20e5SMichal Krawczyk } 2549f93e20e5SMichal Krawczyk 2550d9b8b106SMichal Krawczyk if (hints->driver_watchdog_timeout) { 2551d9b8b106SMichal Krawczyk if (hints->driver_watchdog_timeout == ENA_HW_HINTS_NO_TIMEOUT) 2552d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = ENA_HW_HINTS_NO_TIMEOUT; 2553d9b8b106SMichal Krawczyk else 2554d9b8b106SMichal Krawczyk // Convert msecs to ticks 2555d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = 2556d9b8b106SMichal Krawczyk (hints->driver_watchdog_timeout * 2557d9b8b106SMichal Krawczyk rte_get_timer_hz()) / 1000; 2558d9b8b106SMichal Krawczyk } 2559f01f060cSRafal Kozik } 2560f01f060cSRafal Kozik 25618a90f3d8SIgor Chauskin static int ena_check_space_and_linearize_mbuf(struct ena_ring *tx_ring, 25622061fe41SRafal Kozik struct rte_mbuf *mbuf) 25632061fe41SRafal Kozik { 25642fca2a98SMichal Krawczyk struct ena_com_dev *ena_dev; 25652fca2a98SMichal Krawczyk int num_segments, header_len, rc; 25662061fe41SRafal Kozik 25672fca2a98SMichal Krawczyk ena_dev = &tx_ring->adapter->ena_dev; 25682061fe41SRafal Kozik num_segments = mbuf->nb_segs; 25692fca2a98SMichal Krawczyk header_len = mbuf->data_len; 25702061fe41SRafal Kozik 25712061fe41SRafal Kozik if (likely(num_segments < tx_ring->sgl_size)) 25728a90f3d8SIgor Chauskin goto checkspace; 25732061fe41SRafal Kozik 25742fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV && 25752fca2a98SMichal Krawczyk (num_segments == tx_ring->sgl_size) && 25762fca2a98SMichal Krawczyk (header_len < tx_ring->tx_max_header_size)) 25778a90f3d8SIgor Chauskin goto checkspace; 25782fca2a98SMichal Krawczyk 25798a90f3d8SIgor Chauskin /* Checking for space for 2 additional metadata descriptors due to 25808a90f3d8SIgor Chauskin * possible header split and metadata descriptor. Linearization will 25818a90f3d8SIgor Chauskin * be needed so we reduce the segments number from num_segments to 1 25828a90f3d8SIgor Chauskin */ 25838a90f3d8SIgor Chauskin if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq, 3)) { 25840a001d69SMichal Krawczyk PMD_TX_LOG(DEBUG, "Not enough space in the Tx queue\n"); 25858a90f3d8SIgor Chauskin return ENA_COM_NO_MEM; 25868a90f3d8SIgor Chauskin } 25877830e905SSolganik Alexander ++tx_ring->tx_stats.linearize; 25882061fe41SRafal Kozik rc = rte_pktmbuf_linearize(mbuf); 25897830e905SSolganik Alexander if (unlikely(rc)) { 25900a001d69SMichal Krawczyk PMD_TX_LOG(WARNING, "Mbuf linearize failed\n"); 25917830e905SSolganik Alexander rte_atomic64_inc(&tx_ring->adapter->drv_stats->ierrors); 25927830e905SSolganik Alexander ++tx_ring->tx_stats.linearize_failed; 25937830e905SSolganik Alexander return rc; 25947830e905SSolganik Alexander } 25952061fe41SRafal Kozik 25968a90f3d8SIgor Chauskin return 0; 25978a90f3d8SIgor Chauskin 25988a90f3d8SIgor Chauskin checkspace: 25998a90f3d8SIgor Chauskin /* Checking for space for 2 additional metadata descriptors due to 26008a90f3d8SIgor Chauskin * possible header split and metadata descriptor 26018a90f3d8SIgor Chauskin */ 26028a90f3d8SIgor Chauskin if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq, 26038a90f3d8SIgor Chauskin num_segments + 2)) { 26040a001d69SMichal Krawczyk PMD_TX_LOG(DEBUG, "Not enough space in the Tx queue\n"); 26058a90f3d8SIgor Chauskin return ENA_COM_NO_MEM; 26068a90f3d8SIgor Chauskin } 26078a90f3d8SIgor Chauskin 26088a90f3d8SIgor Chauskin return 0; 26092061fe41SRafal Kozik } 26102061fe41SRafal Kozik 261136278b82SMichal Krawczyk static void ena_tx_map_mbuf(struct ena_ring *tx_ring, 261236278b82SMichal Krawczyk struct ena_tx_buffer *tx_info, 261336278b82SMichal Krawczyk struct rte_mbuf *mbuf, 261436278b82SMichal Krawczyk void **push_header, 261536278b82SMichal Krawczyk uint16_t *header_len) 261636278b82SMichal Krawczyk { 261736278b82SMichal Krawczyk struct ena_com_buf *ena_buf; 261836278b82SMichal Krawczyk uint16_t delta, seg_len, push_len; 261936278b82SMichal Krawczyk 262036278b82SMichal Krawczyk delta = 0; 262136278b82SMichal Krawczyk seg_len = mbuf->data_len; 262236278b82SMichal Krawczyk 262336278b82SMichal Krawczyk tx_info->mbuf = mbuf; 262436278b82SMichal Krawczyk ena_buf = tx_info->bufs; 262536278b82SMichal Krawczyk 262636278b82SMichal Krawczyk if (tx_ring->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 262736278b82SMichal Krawczyk /* 262836278b82SMichal Krawczyk * Tx header might be (and will be in most cases) smaller than 262936278b82SMichal Krawczyk * tx_max_header_size. But it's not an issue to send more data 263036278b82SMichal Krawczyk * to the device, than actually needed if the mbuf size is 263136278b82SMichal Krawczyk * greater than tx_max_header_size. 263236278b82SMichal Krawczyk */ 263336278b82SMichal Krawczyk push_len = RTE_MIN(mbuf->pkt_len, tx_ring->tx_max_header_size); 263436278b82SMichal Krawczyk *header_len = push_len; 263536278b82SMichal Krawczyk 263636278b82SMichal Krawczyk if (likely(push_len <= seg_len)) { 263736278b82SMichal Krawczyk /* If the push header is in the single segment, then 263836278b82SMichal Krawczyk * just point it to the 1st mbuf data. 263936278b82SMichal Krawczyk */ 264036278b82SMichal Krawczyk *push_header = rte_pktmbuf_mtod(mbuf, uint8_t *); 264136278b82SMichal Krawczyk } else { 264236278b82SMichal Krawczyk /* If the push header lays in the several segments, copy 264336278b82SMichal Krawczyk * it to the intermediate buffer. 264436278b82SMichal Krawczyk */ 264536278b82SMichal Krawczyk rte_pktmbuf_read(mbuf, 0, push_len, 264636278b82SMichal Krawczyk tx_ring->push_buf_intermediate_buf); 264736278b82SMichal Krawczyk *push_header = tx_ring->push_buf_intermediate_buf; 264836278b82SMichal Krawczyk delta = push_len - seg_len; 264936278b82SMichal Krawczyk } 265036278b82SMichal Krawczyk } else { 265136278b82SMichal Krawczyk *push_header = NULL; 265236278b82SMichal Krawczyk *header_len = 0; 265336278b82SMichal Krawczyk push_len = 0; 265436278b82SMichal Krawczyk } 265536278b82SMichal Krawczyk 265636278b82SMichal Krawczyk /* Process first segment taking into consideration pushed header */ 265736278b82SMichal Krawczyk if (seg_len > push_len) { 265836278b82SMichal Krawczyk ena_buf->paddr = mbuf->buf_iova + 265936278b82SMichal Krawczyk mbuf->data_off + 266036278b82SMichal Krawczyk push_len; 266136278b82SMichal Krawczyk ena_buf->len = seg_len - push_len; 266236278b82SMichal Krawczyk ena_buf++; 266336278b82SMichal Krawczyk tx_info->num_of_bufs++; 266436278b82SMichal Krawczyk } 266536278b82SMichal Krawczyk 266636278b82SMichal Krawczyk while ((mbuf = mbuf->next) != NULL) { 266736278b82SMichal Krawczyk seg_len = mbuf->data_len; 266836278b82SMichal Krawczyk 266936278b82SMichal Krawczyk /* Skip mbufs if whole data is pushed as a header */ 267036278b82SMichal Krawczyk if (unlikely(delta > seg_len)) { 267136278b82SMichal Krawczyk delta -= seg_len; 267236278b82SMichal Krawczyk continue; 267336278b82SMichal Krawczyk } 267436278b82SMichal Krawczyk 267536278b82SMichal Krawczyk ena_buf->paddr = mbuf->buf_iova + mbuf->data_off + delta; 267636278b82SMichal Krawczyk ena_buf->len = seg_len - delta; 267736278b82SMichal Krawczyk ena_buf++; 267836278b82SMichal Krawczyk tx_info->num_of_bufs++; 267936278b82SMichal Krawczyk 268036278b82SMichal Krawczyk delta = 0; 268136278b82SMichal Krawczyk } 268236278b82SMichal Krawczyk } 268336278b82SMichal Krawczyk 268436278b82SMichal Krawczyk static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf) 268536278b82SMichal Krawczyk { 268636278b82SMichal Krawczyk struct ena_tx_buffer *tx_info; 268736278b82SMichal Krawczyk struct ena_com_tx_ctx ena_tx_ctx = { { 0 } }; 268836278b82SMichal Krawczyk uint16_t next_to_use; 268936278b82SMichal Krawczyk uint16_t header_len; 269036278b82SMichal Krawczyk uint16_t req_id; 269136278b82SMichal Krawczyk void *push_header; 269236278b82SMichal Krawczyk int nb_hw_desc; 269336278b82SMichal Krawczyk int rc; 269436278b82SMichal Krawczyk 26958a90f3d8SIgor Chauskin rc = ena_check_space_and_linearize_mbuf(tx_ring, mbuf); 269636278b82SMichal Krawczyk if (unlikely(rc)) 269736278b82SMichal Krawczyk return rc; 269836278b82SMichal Krawczyk 269936278b82SMichal Krawczyk next_to_use = tx_ring->next_to_use; 270036278b82SMichal Krawczyk 270136278b82SMichal Krawczyk req_id = tx_ring->empty_tx_reqs[next_to_use]; 270236278b82SMichal Krawczyk tx_info = &tx_ring->tx_buffer_info[req_id]; 270336278b82SMichal Krawczyk tx_info->num_of_bufs = 0; 270436278b82SMichal Krawczyk 270536278b82SMichal Krawczyk ena_tx_map_mbuf(tx_ring, tx_info, mbuf, &push_header, &header_len); 270636278b82SMichal Krawczyk 270736278b82SMichal Krawczyk ena_tx_ctx.ena_bufs = tx_info->bufs; 270836278b82SMichal Krawczyk ena_tx_ctx.push_header = push_header; 270936278b82SMichal Krawczyk ena_tx_ctx.num_bufs = tx_info->num_of_bufs; 271036278b82SMichal Krawczyk ena_tx_ctx.req_id = req_id; 271136278b82SMichal Krawczyk ena_tx_ctx.header_len = header_len; 271236278b82SMichal Krawczyk 271336278b82SMichal Krawczyk /* Set Tx offloads flags, if applicable */ 271436278b82SMichal Krawczyk ena_tx_mbuf_prepare(mbuf, &ena_tx_ctx, tx_ring->offloads, 271536278b82SMichal Krawczyk tx_ring->disable_meta_caching); 271636278b82SMichal Krawczyk 271736278b82SMichal Krawczyk if (unlikely(ena_com_is_doorbell_needed(tx_ring->ena_com_io_sq, 271836278b82SMichal Krawczyk &ena_tx_ctx))) { 27190a001d69SMichal Krawczyk PMD_TX_LOG(DEBUG, 2720617898d1SMichal Krawczyk "LLQ Tx max burst size of queue %d achieved, writing doorbell to send burst\n", 272136278b82SMichal Krawczyk tx_ring->id); 272236278b82SMichal Krawczyk ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); 27231f949ad9SAmit Bernstein tx_ring->tx_stats.doorbells++; 27241d973d8fSIgor Chauskin tx_ring->pkts_without_db = false; 272536278b82SMichal Krawczyk } 272636278b82SMichal Krawczyk 272736278b82SMichal Krawczyk /* prepare the packet's descriptors to dma engine */ 272836278b82SMichal Krawczyk rc = ena_com_prepare_tx(tx_ring->ena_com_io_sq, &ena_tx_ctx, 272936278b82SMichal Krawczyk &nb_hw_desc); 273036278b82SMichal Krawczyk if (unlikely(rc)) { 2731b57e1053SMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to prepare Tx buffers, rc: %d\n", rc); 273236278b82SMichal Krawczyk ++tx_ring->tx_stats.prepare_ctx_err; 2733b57e1053SMichal Krawczyk tx_ring->adapter->reset_reason = 2734b57e1053SMichal Krawczyk ENA_REGS_RESET_DRIVER_INVALID_STATE; 2735b57e1053SMichal Krawczyk tx_ring->adapter->trigger_reset = true; 273636278b82SMichal Krawczyk return rc; 273736278b82SMichal Krawczyk } 273836278b82SMichal Krawczyk 273936278b82SMichal Krawczyk tx_info->tx_descs = nb_hw_desc; 2740f93e20e5SMichal Krawczyk tx_info->timestamp = rte_get_timer_cycles(); 274136278b82SMichal Krawczyk 274236278b82SMichal Krawczyk tx_ring->tx_stats.cnt++; 274336278b82SMichal Krawczyk tx_ring->tx_stats.bytes += mbuf->pkt_len; 274436278b82SMichal Krawczyk 274536278b82SMichal Krawczyk tx_ring->next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, 274636278b82SMichal Krawczyk tx_ring->size_mask); 274736278b82SMichal Krawczyk 274836278b82SMichal Krawczyk return 0; 274936278b82SMichal Krawczyk } 275036278b82SMichal Krawczyk 275136278b82SMichal Krawczyk static void ena_tx_cleanup(struct ena_ring *tx_ring) 275236278b82SMichal Krawczyk { 275336278b82SMichal Krawczyk unsigned int total_tx_descs = 0; 2754005064e5SMichal Krawczyk uint16_t cleanup_budget; 275536278b82SMichal Krawczyk uint16_t next_to_clean = tx_ring->next_to_clean; 275636278b82SMichal Krawczyk 2757005064e5SMichal Krawczyk /* Attempt to release all Tx descriptors (ring_size - 1 -> size_mask) */ 2758005064e5SMichal Krawczyk cleanup_budget = tx_ring->size_mask; 275936278b82SMichal Krawczyk 276036278b82SMichal Krawczyk while (likely(total_tx_descs < cleanup_budget)) { 276136278b82SMichal Krawczyk struct rte_mbuf *mbuf; 276236278b82SMichal Krawczyk struct ena_tx_buffer *tx_info; 276336278b82SMichal Krawczyk uint16_t req_id; 276436278b82SMichal Krawczyk 276536278b82SMichal Krawczyk if (ena_com_tx_comp_req_id_get(tx_ring->ena_com_io_cq, &req_id) != 0) 276636278b82SMichal Krawczyk break; 276736278b82SMichal Krawczyk 276836278b82SMichal Krawczyk if (unlikely(validate_tx_req_id(tx_ring, req_id) != 0)) 276936278b82SMichal Krawczyk break; 277036278b82SMichal Krawczyk 277136278b82SMichal Krawczyk /* Get Tx info & store how many descs were processed */ 277236278b82SMichal Krawczyk tx_info = &tx_ring->tx_buffer_info[req_id]; 2773f93e20e5SMichal Krawczyk tx_info->timestamp = 0; 277436278b82SMichal Krawczyk 277536278b82SMichal Krawczyk mbuf = tx_info->mbuf; 277636278b82SMichal Krawczyk rte_pktmbuf_free(mbuf); 277736278b82SMichal Krawczyk 277836278b82SMichal Krawczyk tx_info->mbuf = NULL; 277936278b82SMichal Krawczyk tx_ring->empty_tx_reqs[next_to_clean] = req_id; 278036278b82SMichal Krawczyk 278136278b82SMichal Krawczyk total_tx_descs += tx_info->tx_descs; 278236278b82SMichal Krawczyk 278336278b82SMichal Krawczyk /* Put back descriptor to the ring for reuse */ 278436278b82SMichal Krawczyk next_to_clean = ENA_IDX_NEXT_MASKED(next_to_clean, 278536278b82SMichal Krawczyk tx_ring->size_mask); 278636278b82SMichal Krawczyk } 278736278b82SMichal Krawczyk 278836278b82SMichal Krawczyk if (likely(total_tx_descs > 0)) { 278936278b82SMichal Krawczyk /* acknowledge completion of sent packets */ 279036278b82SMichal Krawczyk tx_ring->next_to_clean = next_to_clean; 279136278b82SMichal Krawczyk ena_com_comp_ack(tx_ring->ena_com_io_sq, total_tx_descs); 279236278b82SMichal Krawczyk ena_com_update_dev_comp_head(tx_ring->ena_com_io_cq); 279336278b82SMichal Krawczyk } 2794f93e20e5SMichal Krawczyk 2795f93e20e5SMichal Krawczyk /* Notify completion handler that the cleanup was just called */ 2796f93e20e5SMichal Krawczyk tx_ring->last_cleanup_ticks = rte_get_timer_cycles(); 279736278b82SMichal Krawczyk } 279836278b82SMichal Krawczyk 27991173fca2SJan Medala static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 28001173fca2SJan Medala uint16_t nb_pkts) 28011173fca2SJan Medala { 28021173fca2SJan Medala struct ena_ring *tx_ring = (struct ena_ring *)(tx_queue); 2803005064e5SMichal Krawczyk int available_desc; 280474456796SMichal Krawczyk uint16_t sent_idx = 0; 28051173fca2SJan Medala 28060a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_TX 28071173fca2SJan Medala /* Check adapter state */ 28081173fca2SJan Medala if (unlikely(tx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) { 28090a001d69SMichal Krawczyk PMD_TX_LOG(ALERT, 28101173fca2SJan Medala "Trying to xmit pkts while device is NOT running\n"); 28111173fca2SJan Medala return 0; 28121173fca2SJan Medala } 28130a001d69SMichal Krawczyk #endif 28141173fca2SJan Medala 28151173fca2SJan Medala for (sent_idx = 0; sent_idx < nb_pkts; sent_idx++) { 281636278b82SMichal Krawczyk if (ena_xmit_mbuf(tx_ring, tx_pkts[sent_idx])) 28172061fe41SRafal Kozik break; 28181d973d8fSIgor Chauskin tx_ring->pkts_without_db = true; 281936278b82SMichal Krawczyk rte_prefetch0(tx_pkts[ENA_IDX_ADD_MASKED(sent_idx, 4, 282036278b82SMichal Krawczyk tx_ring->size_mask)]); 28212fca2a98SMichal Krawczyk } 28222fca2a98SMichal Krawczyk 2823005064e5SMichal Krawczyk available_desc = ena_com_free_q_entries(tx_ring->ena_com_io_sq); 2824005064e5SMichal Krawczyk tx_ring->tx_stats.available_desc = available_desc; 28251173fca2SJan Medala 28265e02e19eSJan Medala /* If there are ready packets to be xmitted... */ 28271d973d8fSIgor Chauskin if (likely(tx_ring->pkts_without_db)) { 28285e02e19eSJan Medala /* ...let HW do its best :-) */ 28291173fca2SJan Medala ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); 283045b6d861SMichal Krawczyk tx_ring->tx_stats.doorbells++; 28311d973d8fSIgor Chauskin tx_ring->pkts_without_db = false; 28325e02e19eSJan Medala } 28335e02e19eSJan Medala 2834005064e5SMichal Krawczyk if (available_desc < tx_ring->tx_free_thresh) 283536278b82SMichal Krawczyk ena_tx_cleanup(tx_ring); 2836f7d82d24SRafal Kozik 28377830e905SSolganik Alexander tx_ring->tx_stats.available_desc = 2838b2b02edeSMichal Krawczyk ena_com_free_q_entries(tx_ring->ena_com_io_sq); 28397830e905SSolganik Alexander tx_ring->tx_stats.tx_poll++; 28407830e905SSolganik Alexander 28411173fca2SJan Medala return sent_idx; 28421173fca2SJan Medala } 28431173fca2SJan Medala 284445718adaSMichal Krawczyk int ena_copy_eni_stats(struct ena_adapter *adapter) 284545718adaSMichal Krawczyk { 284645718adaSMichal Krawczyk struct ena_admin_eni_stats admin_eni_stats; 284745718adaSMichal Krawczyk int rc; 284845718adaSMichal Krawczyk 284945718adaSMichal Krawczyk rte_spinlock_lock(&adapter->admin_lock); 285045718adaSMichal Krawczyk rc = ena_com_get_eni_stats(&adapter->ena_dev, &admin_eni_stats); 285145718adaSMichal Krawczyk rte_spinlock_unlock(&adapter->admin_lock); 285245718adaSMichal Krawczyk if (rc != 0) { 285345718adaSMichal Krawczyk if (rc == ENA_COM_UNSUPPORTED) { 285445718adaSMichal Krawczyk PMD_DRV_LOG(DEBUG, 2855617898d1SMichal Krawczyk "Retrieving ENI metrics is not supported\n"); 285645718adaSMichal Krawczyk } else { 285745718adaSMichal Krawczyk PMD_DRV_LOG(WARNING, 2858617898d1SMichal Krawczyk "Failed to get ENI metrics, rc: %d\n", rc); 285945718adaSMichal Krawczyk } 286045718adaSMichal Krawczyk return rc; 286145718adaSMichal Krawczyk } 286245718adaSMichal Krawczyk 286345718adaSMichal Krawczyk rte_memcpy(&adapter->eni_stats, &admin_eni_stats, 286445718adaSMichal Krawczyk sizeof(struct ena_stats_eni)); 286545718adaSMichal Krawczyk 286645718adaSMichal Krawczyk return 0; 286745718adaSMichal Krawczyk } 286845718adaSMichal Krawczyk 28697830e905SSolganik Alexander /** 28707830e905SSolganik Alexander * DPDK callback to retrieve names of extended device statistics 28717830e905SSolganik Alexander * 28727830e905SSolganik Alexander * @param dev 28737830e905SSolganik Alexander * Pointer to Ethernet device structure. 28747830e905SSolganik Alexander * @param[out] xstats_names 28757830e905SSolganik Alexander * Buffer to insert names into. 28767830e905SSolganik Alexander * @param n 28777830e905SSolganik Alexander * Number of names. 28787830e905SSolganik Alexander * 28797830e905SSolganik Alexander * @return 28807830e905SSolganik Alexander * Number of xstats names. 28817830e905SSolganik Alexander */ 28827830e905SSolganik Alexander static int ena_xstats_get_names(struct rte_eth_dev *dev, 28837830e905SSolganik Alexander struct rte_eth_xstat_name *xstats_names, 28847830e905SSolganik Alexander unsigned int n) 28857830e905SSolganik Alexander { 2886aab58857SStanislaw Kardach unsigned int xstats_count = ena_xstats_calc_num(dev->data); 28877830e905SSolganik Alexander unsigned int stat, i, count = 0; 28887830e905SSolganik Alexander 28897830e905SSolganik Alexander if (n < xstats_count || !xstats_names) 28907830e905SSolganik Alexander return xstats_count; 28917830e905SSolganik Alexander 28927830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) 28937830e905SSolganik Alexander strcpy(xstats_names[count].name, 28947830e905SSolganik Alexander ena_stats_global_strings[stat].name); 28957830e905SSolganik Alexander 289645718adaSMichal Krawczyk for (stat = 0; stat < ENA_STATS_ARRAY_ENI; stat++, count++) 289745718adaSMichal Krawczyk strcpy(xstats_names[count].name, 289845718adaSMichal Krawczyk ena_stats_eni_strings[stat].name); 289945718adaSMichal Krawczyk 29007830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) 29017830e905SSolganik Alexander for (i = 0; i < dev->data->nb_rx_queues; i++, count++) 29027830e905SSolganik Alexander snprintf(xstats_names[count].name, 29037830e905SSolganik Alexander sizeof(xstats_names[count].name), 29047830e905SSolganik Alexander "rx_q%d_%s", i, 29057830e905SSolganik Alexander ena_stats_rx_strings[stat].name); 29067830e905SSolganik Alexander 29077830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_TX; stat++) 29087830e905SSolganik Alexander for (i = 0; i < dev->data->nb_tx_queues; i++, count++) 29097830e905SSolganik Alexander snprintf(xstats_names[count].name, 29107830e905SSolganik Alexander sizeof(xstats_names[count].name), 29117830e905SSolganik Alexander "tx_q%d_%s", i, 29127830e905SSolganik Alexander ena_stats_tx_strings[stat].name); 29137830e905SSolganik Alexander 29147830e905SSolganik Alexander return xstats_count; 29157830e905SSolganik Alexander } 29167830e905SSolganik Alexander 29177830e905SSolganik Alexander /** 29187830e905SSolganik Alexander * DPDK callback to get extended device statistics. 29197830e905SSolganik Alexander * 29207830e905SSolganik Alexander * @param dev 29217830e905SSolganik Alexander * Pointer to Ethernet device structure. 29227830e905SSolganik Alexander * @param[out] stats 29237830e905SSolganik Alexander * Stats table output buffer. 29247830e905SSolganik Alexander * @param n 29257830e905SSolganik Alexander * The size of the stats table. 29267830e905SSolganik Alexander * 29277830e905SSolganik Alexander * @return 29287830e905SSolganik Alexander * Number of xstats on success, negative on failure. 29297830e905SSolganik Alexander */ 29307830e905SSolganik Alexander static int ena_xstats_get(struct rte_eth_dev *dev, 29317830e905SSolganik Alexander struct rte_eth_xstat *xstats, 29327830e905SSolganik Alexander unsigned int n) 29337830e905SSolganik Alexander { 2934890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 2935aab58857SStanislaw Kardach unsigned int xstats_count = ena_xstats_calc_num(dev->data); 29367830e905SSolganik Alexander unsigned int stat, i, count = 0; 29377830e905SSolganik Alexander int stat_offset; 29387830e905SSolganik Alexander void *stats_begin; 29397830e905SSolganik Alexander 29407830e905SSolganik Alexander if (n < xstats_count) 29417830e905SSolganik Alexander return xstats_count; 29427830e905SSolganik Alexander 29437830e905SSolganik Alexander if (!xstats) 29447830e905SSolganik Alexander return 0; 29457830e905SSolganik Alexander 29467830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) { 2947493107fdSMichal Krawczyk stat_offset = ena_stats_global_strings[stat].stat_offset; 29487830e905SSolganik Alexander stats_begin = &adapter->dev_stats; 29497830e905SSolganik Alexander 29507830e905SSolganik Alexander xstats[count].id = count; 29517830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 29527830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 29537830e905SSolganik Alexander } 29547830e905SSolganik Alexander 295545718adaSMichal Krawczyk /* Even if the function below fails, we should copy previous (or initial 295645718adaSMichal Krawczyk * values) to keep structure of rte_eth_xstat consistent. 295745718adaSMichal Krawczyk */ 295845718adaSMichal Krawczyk ena_copy_eni_stats(adapter); 295945718adaSMichal Krawczyk for (stat = 0; stat < ENA_STATS_ARRAY_ENI; stat++, count++) { 296045718adaSMichal Krawczyk stat_offset = ena_stats_eni_strings[stat].stat_offset; 296145718adaSMichal Krawczyk stats_begin = &adapter->eni_stats; 296245718adaSMichal Krawczyk 296345718adaSMichal Krawczyk xstats[count].id = count; 296445718adaSMichal Krawczyk xstats[count].value = *((uint64_t *) 296545718adaSMichal Krawczyk ((char *)stats_begin + stat_offset)); 296645718adaSMichal Krawczyk } 296745718adaSMichal Krawczyk 29687830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) { 29697830e905SSolganik Alexander for (i = 0; i < dev->data->nb_rx_queues; i++, count++) { 29707830e905SSolganik Alexander stat_offset = ena_stats_rx_strings[stat].stat_offset; 29717830e905SSolganik Alexander stats_begin = &adapter->rx_ring[i].rx_stats; 29727830e905SSolganik Alexander 29737830e905SSolganik Alexander xstats[count].id = count; 29747830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 29757830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 29767830e905SSolganik Alexander } 29777830e905SSolganik Alexander } 29787830e905SSolganik Alexander 29797830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_TX; stat++) { 29807830e905SSolganik Alexander for (i = 0; i < dev->data->nb_tx_queues; i++, count++) { 29817830e905SSolganik Alexander stat_offset = ena_stats_tx_strings[stat].stat_offset; 29827830e905SSolganik Alexander stats_begin = &adapter->tx_ring[i].rx_stats; 29837830e905SSolganik Alexander 29847830e905SSolganik Alexander xstats[count].id = count; 29857830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 29867830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 29877830e905SSolganik Alexander } 29887830e905SSolganik Alexander } 29897830e905SSolganik Alexander 29907830e905SSolganik Alexander return count; 29917830e905SSolganik Alexander } 29927830e905SSolganik Alexander 29937830e905SSolganik Alexander static int ena_xstats_get_by_id(struct rte_eth_dev *dev, 29947830e905SSolganik Alexander const uint64_t *ids, 29957830e905SSolganik Alexander uint64_t *values, 29967830e905SSolganik Alexander unsigned int n) 29977830e905SSolganik Alexander { 2998890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 29997830e905SSolganik Alexander uint64_t id; 30007830e905SSolganik Alexander uint64_t rx_entries, tx_entries; 30017830e905SSolganik Alexander unsigned int i; 30027830e905SSolganik Alexander int qid; 30037830e905SSolganik Alexander int valid = 0; 300445718adaSMichal Krawczyk bool was_eni_copied = false; 300545718adaSMichal Krawczyk 30067830e905SSolganik Alexander for (i = 0; i < n; ++i) { 30077830e905SSolganik Alexander id = ids[i]; 30087830e905SSolganik Alexander /* Check if id belongs to global statistics */ 30097830e905SSolganik Alexander if (id < ENA_STATS_ARRAY_GLOBAL) { 30107830e905SSolganik Alexander values[i] = *((uint64_t *)&adapter->dev_stats + id); 30117830e905SSolganik Alexander ++valid; 30127830e905SSolganik Alexander continue; 30137830e905SSolganik Alexander } 30147830e905SSolganik Alexander 301545718adaSMichal Krawczyk /* Check if id belongs to ENI statistics */ 30167830e905SSolganik Alexander id -= ENA_STATS_ARRAY_GLOBAL; 301745718adaSMichal Krawczyk if (id < ENA_STATS_ARRAY_ENI) { 301845718adaSMichal Krawczyk /* Avoid reading ENI stats multiple times in a single 301945718adaSMichal Krawczyk * function call, as it requires communication with the 302045718adaSMichal Krawczyk * admin queue. 302145718adaSMichal Krawczyk */ 302245718adaSMichal Krawczyk if (!was_eni_copied) { 302345718adaSMichal Krawczyk was_eni_copied = true; 302445718adaSMichal Krawczyk ena_copy_eni_stats(adapter); 302545718adaSMichal Krawczyk } 302645718adaSMichal Krawczyk values[i] = *((uint64_t *)&adapter->eni_stats + id); 302745718adaSMichal Krawczyk ++valid; 302845718adaSMichal Krawczyk continue; 302945718adaSMichal Krawczyk } 303045718adaSMichal Krawczyk 303145718adaSMichal Krawczyk /* Check if id belongs to rx queue statistics */ 303245718adaSMichal Krawczyk id -= ENA_STATS_ARRAY_ENI; 30337830e905SSolganik Alexander rx_entries = ENA_STATS_ARRAY_RX * dev->data->nb_rx_queues; 30347830e905SSolganik Alexander if (id < rx_entries) { 30357830e905SSolganik Alexander qid = id % dev->data->nb_rx_queues; 30367830e905SSolganik Alexander id /= dev->data->nb_rx_queues; 30377830e905SSolganik Alexander values[i] = *((uint64_t *) 30387830e905SSolganik Alexander &adapter->rx_ring[qid].rx_stats + id); 30397830e905SSolganik Alexander ++valid; 30407830e905SSolganik Alexander continue; 30417830e905SSolganik Alexander } 30427830e905SSolganik Alexander /* Check if id belongs to rx queue statistics */ 30437830e905SSolganik Alexander id -= rx_entries; 30447830e905SSolganik Alexander tx_entries = ENA_STATS_ARRAY_TX * dev->data->nb_tx_queues; 30457830e905SSolganik Alexander if (id < tx_entries) { 30467830e905SSolganik Alexander qid = id % dev->data->nb_tx_queues; 30477830e905SSolganik Alexander id /= dev->data->nb_tx_queues; 30487830e905SSolganik Alexander values[i] = *((uint64_t *) 30497830e905SSolganik Alexander &adapter->tx_ring[qid].tx_stats + id); 30507830e905SSolganik Alexander ++valid; 30517830e905SSolganik Alexander continue; 30527830e905SSolganik Alexander } 30537830e905SSolganik Alexander } 30547830e905SSolganik Alexander 30557830e905SSolganik Alexander return valid; 30567830e905SSolganik Alexander } 30577830e905SSolganik Alexander 30588a7a73f2SMichal Krawczyk static int ena_process_bool_devarg(const char *key, 30598a7a73f2SMichal Krawczyk const char *value, 30608a7a73f2SMichal Krawczyk void *opaque) 30618a7a73f2SMichal Krawczyk { 30628a7a73f2SMichal Krawczyk struct ena_adapter *adapter = opaque; 30638a7a73f2SMichal Krawczyk bool bool_value; 30648a7a73f2SMichal Krawczyk 30658a7a73f2SMichal Krawczyk /* Parse the value. */ 30668a7a73f2SMichal Krawczyk if (strcmp(value, "1") == 0) { 30678a7a73f2SMichal Krawczyk bool_value = true; 30688a7a73f2SMichal Krawczyk } else if (strcmp(value, "0") == 0) { 30698a7a73f2SMichal Krawczyk bool_value = false; 30708a7a73f2SMichal Krawczyk } else { 30718a7a73f2SMichal Krawczyk PMD_INIT_LOG(ERR, 30728a7a73f2SMichal Krawczyk "Invalid value: '%s' for key '%s'. Accepted: '0' or '1'\n", 30738a7a73f2SMichal Krawczyk value, key); 30748a7a73f2SMichal Krawczyk return -EINVAL; 30758a7a73f2SMichal Krawczyk } 30768a7a73f2SMichal Krawczyk 30778a7a73f2SMichal Krawczyk /* Now, assign it to the proper adapter field. */ 30789b312ad3SIgor Chauskin if (strcmp(key, ENA_DEVARG_LARGE_LLQ_HDR) == 0) 30798a7a73f2SMichal Krawczyk adapter->use_large_llq_hdr = bool_value; 30808a7a73f2SMichal Krawczyk 30818a7a73f2SMichal Krawczyk return 0; 30828a7a73f2SMichal Krawczyk } 30838a7a73f2SMichal Krawczyk 30848a7a73f2SMichal Krawczyk static int ena_parse_devargs(struct ena_adapter *adapter, 30858a7a73f2SMichal Krawczyk struct rte_devargs *devargs) 30868a7a73f2SMichal Krawczyk { 30878a7a73f2SMichal Krawczyk static const char * const allowed_args[] = { 30888a7a73f2SMichal Krawczyk ENA_DEVARG_LARGE_LLQ_HDR, 30899f220a95SMichal Krawczyk NULL, 30908a7a73f2SMichal Krawczyk }; 30918a7a73f2SMichal Krawczyk struct rte_kvargs *kvlist; 30928a7a73f2SMichal Krawczyk int rc; 30938a7a73f2SMichal Krawczyk 30948a7a73f2SMichal Krawczyk if (devargs == NULL) 30958a7a73f2SMichal Krawczyk return 0; 30968a7a73f2SMichal Krawczyk 30978a7a73f2SMichal Krawczyk kvlist = rte_kvargs_parse(devargs->args, allowed_args); 30988a7a73f2SMichal Krawczyk if (kvlist == NULL) { 30998a7a73f2SMichal Krawczyk PMD_INIT_LOG(ERR, "Invalid device arguments: %s\n", 31008a7a73f2SMichal Krawczyk devargs->args); 31018a7a73f2SMichal Krawczyk return -EINVAL; 31028a7a73f2SMichal Krawczyk } 31038a7a73f2SMichal Krawczyk 31048a7a73f2SMichal Krawczyk rc = rte_kvargs_process(kvlist, ENA_DEVARG_LARGE_LLQ_HDR, 31058a7a73f2SMichal Krawczyk ena_process_bool_devarg, adapter); 31068a7a73f2SMichal Krawczyk 31078a7a73f2SMichal Krawczyk rte_kvargs_free(kvlist); 31088a7a73f2SMichal Krawczyk 31098a7a73f2SMichal Krawczyk return rc; 31108a7a73f2SMichal Krawczyk } 31118a7a73f2SMichal Krawczyk 31126986cdc4SMichal Krawczyk static int ena_setup_rx_intr(struct rte_eth_dev *dev) 31136986cdc4SMichal Krawczyk { 31146986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 31156986cdc4SMichal Krawczyk struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; 31166986cdc4SMichal Krawczyk int rc; 31176986cdc4SMichal Krawczyk uint16_t vectors_nb, i; 31186986cdc4SMichal Krawczyk bool rx_intr_requested = dev->data->dev_conf.intr_conf.rxq; 31196986cdc4SMichal Krawczyk 31206986cdc4SMichal Krawczyk if (!rx_intr_requested) 31216986cdc4SMichal Krawczyk return 0; 31226986cdc4SMichal Krawczyk 31236986cdc4SMichal Krawczyk if (!rte_intr_cap_multiple(intr_handle)) { 31246986cdc4SMichal Krawczyk PMD_DRV_LOG(ERR, 31256986cdc4SMichal Krawczyk "Rx interrupt requested, but it isn't supported by the PCI driver\n"); 31266986cdc4SMichal Krawczyk return -ENOTSUP; 31276986cdc4SMichal Krawczyk } 31286986cdc4SMichal Krawczyk 31296986cdc4SMichal Krawczyk /* Disable interrupt mapping before the configuration starts. */ 31306986cdc4SMichal Krawczyk rte_intr_disable(intr_handle); 31316986cdc4SMichal Krawczyk 31326986cdc4SMichal Krawczyk /* Verify if there are enough vectors available. */ 31336986cdc4SMichal Krawczyk vectors_nb = dev->data->nb_rx_queues; 31346986cdc4SMichal Krawczyk if (vectors_nb > RTE_MAX_RXTX_INTR_VEC_ID) { 31356986cdc4SMichal Krawczyk PMD_DRV_LOG(ERR, 31366986cdc4SMichal Krawczyk "Too many Rx interrupts requested, maximum number: %d\n", 31376986cdc4SMichal Krawczyk RTE_MAX_RXTX_INTR_VEC_ID); 31386986cdc4SMichal Krawczyk rc = -ENOTSUP; 31396986cdc4SMichal Krawczyk goto enable_intr; 31406986cdc4SMichal Krawczyk } 31416986cdc4SMichal Krawczyk 31426986cdc4SMichal Krawczyk intr_handle->intr_vec = rte_zmalloc("intr_vec", 31436986cdc4SMichal Krawczyk dev->data->nb_rx_queues * sizeof(*intr_handle->intr_vec), 0); 31446986cdc4SMichal Krawczyk if (intr_handle->intr_vec == NULL) { 31456986cdc4SMichal Krawczyk PMD_DRV_LOG(ERR, 31466986cdc4SMichal Krawczyk "Failed to allocate interrupt vector for %d queues\n", 31476986cdc4SMichal Krawczyk dev->data->nb_rx_queues); 31486986cdc4SMichal Krawczyk rc = -ENOMEM; 31496986cdc4SMichal Krawczyk goto enable_intr; 31506986cdc4SMichal Krawczyk } 31516986cdc4SMichal Krawczyk 31526986cdc4SMichal Krawczyk rc = rte_intr_efd_enable(intr_handle, vectors_nb); 31536986cdc4SMichal Krawczyk if (rc != 0) 31546986cdc4SMichal Krawczyk goto free_intr_vec; 31556986cdc4SMichal Krawczyk 31566986cdc4SMichal Krawczyk if (!rte_intr_allow_others(intr_handle)) { 31576986cdc4SMichal Krawczyk PMD_DRV_LOG(ERR, 31586986cdc4SMichal Krawczyk "Not enough interrupts available to use both ENA Admin and Rx interrupts\n"); 31596986cdc4SMichal Krawczyk goto disable_intr_efd; 31606986cdc4SMichal Krawczyk } 31616986cdc4SMichal Krawczyk 31626986cdc4SMichal Krawczyk for (i = 0; i < vectors_nb; ++i) 31636986cdc4SMichal Krawczyk intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + i; 31646986cdc4SMichal Krawczyk 31656986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 31666986cdc4SMichal Krawczyk return 0; 31676986cdc4SMichal Krawczyk 31686986cdc4SMichal Krawczyk disable_intr_efd: 31696986cdc4SMichal Krawczyk rte_intr_efd_disable(intr_handle); 31706986cdc4SMichal Krawczyk free_intr_vec: 31716986cdc4SMichal Krawczyk rte_free(intr_handle->intr_vec); 31726986cdc4SMichal Krawczyk intr_handle->intr_vec = NULL; 31736986cdc4SMichal Krawczyk enable_intr: 31746986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 31756986cdc4SMichal Krawczyk return rc; 31766986cdc4SMichal Krawczyk } 31776986cdc4SMichal Krawczyk 31786986cdc4SMichal Krawczyk static void ena_rx_queue_intr_set(struct rte_eth_dev *dev, 31796986cdc4SMichal Krawczyk uint16_t queue_id, 31806986cdc4SMichal Krawczyk bool unmask) 31816986cdc4SMichal Krawczyk { 31826986cdc4SMichal Krawczyk struct ena_adapter *adapter = dev->data->dev_private; 31836986cdc4SMichal Krawczyk struct ena_ring *rxq = &adapter->rx_ring[queue_id]; 31846986cdc4SMichal Krawczyk struct ena_eth_io_intr_reg intr_reg; 31856986cdc4SMichal Krawczyk 31866986cdc4SMichal Krawczyk ena_com_update_intr_reg(&intr_reg, 0, 0, unmask); 31876986cdc4SMichal Krawczyk ena_com_unmask_intr(rxq->ena_com_io_cq, &intr_reg); 31886986cdc4SMichal Krawczyk } 31896986cdc4SMichal Krawczyk 31906986cdc4SMichal Krawczyk static int ena_rx_queue_intr_enable(struct rte_eth_dev *dev, 31916986cdc4SMichal Krawczyk uint16_t queue_id) 31926986cdc4SMichal Krawczyk { 31936986cdc4SMichal Krawczyk ena_rx_queue_intr_set(dev, queue_id, true); 31946986cdc4SMichal Krawczyk 31956986cdc4SMichal Krawczyk return 0; 31966986cdc4SMichal Krawczyk } 31976986cdc4SMichal Krawczyk 31986986cdc4SMichal Krawczyk static int ena_rx_queue_intr_disable(struct rte_eth_dev *dev, 31996986cdc4SMichal Krawczyk uint16_t queue_id) 32006986cdc4SMichal Krawczyk { 32016986cdc4SMichal Krawczyk ena_rx_queue_intr_set(dev, queue_id, false); 32026986cdc4SMichal Krawczyk 32036986cdc4SMichal Krawczyk return 0; 32046986cdc4SMichal Krawczyk } 32056986cdc4SMichal Krawczyk 3206ca148440SMichal Krawczyk /********************************************************************* 3207ca148440SMichal Krawczyk * PMD configuration 3208ca148440SMichal Krawczyk *********************************************************************/ 3209fdf91e0fSJan Blunck static int eth_ena_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 3210fdf91e0fSJan Blunck struct rte_pci_device *pci_dev) 3211fdf91e0fSJan Blunck { 3212fdf91e0fSJan Blunck return rte_eth_dev_pci_generic_probe(pci_dev, 3213fdf91e0fSJan Blunck sizeof(struct ena_adapter), eth_ena_dev_init); 3214fdf91e0fSJan Blunck } 3215fdf91e0fSJan Blunck 3216fdf91e0fSJan Blunck static int eth_ena_pci_remove(struct rte_pci_device *pci_dev) 3217fdf91e0fSJan Blunck { 3218eb0ef49dSMichal Krawczyk return rte_eth_dev_pci_generic_remove(pci_dev, eth_ena_dev_uninit); 3219fdf91e0fSJan Blunck } 3220fdf91e0fSJan Blunck 3221fdf91e0fSJan Blunck static struct rte_pci_driver rte_ena_pmd = { 32221173fca2SJan Medala .id_table = pci_id_ena_map, 322305e0eee0SRafal Kozik .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | 322405e0eee0SRafal Kozik RTE_PCI_DRV_WC_ACTIVATE, 3225fdf91e0fSJan Blunck .probe = eth_ena_pci_probe, 3226fdf91e0fSJan Blunck .remove = eth_ena_pci_remove, 32271173fca2SJan Medala }; 32281173fca2SJan Medala 3229fdf91e0fSJan Blunck RTE_PMD_REGISTER_PCI(net_ena, rte_ena_pmd); 323001f19227SShreyansh Jain RTE_PMD_REGISTER_PCI_TABLE(net_ena, pci_id_ena_map); 323106e81dc9SDavid Marchand RTE_PMD_REGISTER_KMOD_DEP(net_ena, "* igb_uio | uio_pci_generic | vfio-pci"); 32328a7a73f2SMichal Krawczyk RTE_PMD_REGISTER_PARAM_STRING(net_ena, ENA_DEVARG_LARGE_LLQ_HDR "=<0|1>"); 3233eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(ena_logtype_init, init, NOTICE); 3234eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(ena_logtype_driver, driver, NOTICE); 32350a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 32360a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_rx, rx, DEBUG); 32376f1c9df9SStephen Hemminger #endif 32380a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_TX 32390a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_tx, tx, DEBUG); 32406f1c9df9SStephen Hemminger #endif 32410a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_com, com, WARNING); 32423adcba9aSMichal Krawczyk 32433adcba9aSMichal Krawczyk /****************************************************************************** 32443adcba9aSMichal Krawczyk ******************************** AENQ Handlers ******************************* 32453adcba9aSMichal Krawczyk *****************************************************************************/ 3246ca148440SMichal Krawczyk static void ena_update_on_link_change(void *adapter_data, 3247ca148440SMichal Krawczyk struct ena_admin_aenq_entry *aenq_e) 3248ca148440SMichal Krawczyk { 3249aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 3250aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 3251ca148440SMichal Krawczyk struct ena_admin_aenq_link_change_desc *aenq_link_desc; 3252ca148440SMichal Krawczyk uint32_t status; 3253ca148440SMichal Krawczyk 3254ca148440SMichal Krawczyk aenq_link_desc = (struct ena_admin_aenq_link_change_desc *)aenq_e; 3255ca148440SMichal Krawczyk 3256ca148440SMichal Krawczyk status = get_ena_admin_aenq_link_change_desc_link_status(aenq_link_desc); 3257ca148440SMichal Krawczyk adapter->link_status = status; 3258ca148440SMichal Krawczyk 3259ca148440SMichal Krawczyk ena_link_update(eth_dev, 0); 32605723fbedSFerruh Yigit rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL); 3261ca148440SMichal Krawczyk } 3262ca148440SMichal Krawczyk 3263aab58857SStanislaw Kardach static void ena_notification(void *adapter_data, 3264f01f060cSRafal Kozik struct ena_admin_aenq_entry *aenq_e) 3265f01f060cSRafal Kozik { 3266aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 3267aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 3268f01f060cSRafal Kozik struct ena_admin_ena_hw_hints *hints; 3269f01f060cSRafal Kozik 3270f01f060cSRafal Kozik if (aenq_e->aenq_common_desc.group != ENA_ADMIN_NOTIFICATION) 3271617898d1SMichal Krawczyk PMD_DRV_LOG(WARNING, "Invalid AENQ group: %x. Expected: %x\n", 3272f01f060cSRafal Kozik aenq_e->aenq_common_desc.group, 3273f01f060cSRafal Kozik ENA_ADMIN_NOTIFICATION); 3274f01f060cSRafal Kozik 3275b19f366cSMichal Krawczyk switch (aenq_e->aenq_common_desc.syndrome) { 3276f01f060cSRafal Kozik case ENA_ADMIN_UPDATE_HINTS: 3277f01f060cSRafal Kozik hints = (struct ena_admin_ena_hw_hints *) 3278f01f060cSRafal Kozik (&aenq_e->inline_data_w4); 3279f01f060cSRafal Kozik ena_update_hints(adapter, hints); 3280f01f060cSRafal Kozik break; 3281f01f060cSRafal Kozik default: 3282617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Invalid AENQ notification link state: %d\n", 3283b19f366cSMichal Krawczyk aenq_e->aenq_common_desc.syndrome); 3284f01f060cSRafal Kozik } 3285f01f060cSRafal Kozik } 3286f01f060cSRafal Kozik 3287d9b8b106SMichal Krawczyk static void ena_keep_alive(void *adapter_data, 3288d9b8b106SMichal Krawczyk __rte_unused struct ena_admin_aenq_entry *aenq_e) 3289d9b8b106SMichal Krawczyk { 3290aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 3291aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 329294c3e376SRafal Kozik struct ena_admin_aenq_keep_alive_desc *desc; 329394c3e376SRafal Kozik uint64_t rx_drops; 3294e1e73e32SMichal Krawczyk uint64_t tx_drops; 3295d9b8b106SMichal Krawczyk 3296d9b8b106SMichal Krawczyk adapter->timestamp_wd = rte_get_timer_cycles(); 329794c3e376SRafal Kozik 329894c3e376SRafal Kozik desc = (struct ena_admin_aenq_keep_alive_desc *)aenq_e; 329994c3e376SRafal Kozik rx_drops = ((uint64_t)desc->rx_drops_high << 32) | desc->rx_drops_low; 3300e1e73e32SMichal Krawczyk tx_drops = ((uint64_t)desc->tx_drops_high << 32) | desc->tx_drops_low; 3301e1e73e32SMichal Krawczyk 3302e1e73e32SMichal Krawczyk adapter->drv_stats->rx_drops = rx_drops; 3303e1e73e32SMichal Krawczyk adapter->dev_stats.tx_drops = tx_drops; 3304d9b8b106SMichal Krawczyk } 3305d9b8b106SMichal Krawczyk 33063adcba9aSMichal Krawczyk /** 33073adcba9aSMichal Krawczyk * This handler will called for unknown event group or unimplemented handlers 33083adcba9aSMichal Krawczyk **/ 33093adcba9aSMichal Krawczyk static void unimplemented_aenq_handler(__rte_unused void *data, 33103adcba9aSMichal Krawczyk __rte_unused struct ena_admin_aenq_entry *aenq_e) 33113adcba9aSMichal Krawczyk { 3312617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 3313617898d1SMichal Krawczyk "Unknown event was received or event with unimplemented handler\n"); 33143adcba9aSMichal Krawczyk } 33153adcba9aSMichal Krawczyk 3316ca148440SMichal Krawczyk static struct ena_aenq_handlers aenq_handlers = { 33173adcba9aSMichal Krawczyk .handlers = { 3318ca148440SMichal Krawczyk [ENA_ADMIN_LINK_CHANGE] = ena_update_on_link_change, 3319f01f060cSRafal Kozik [ENA_ADMIN_NOTIFICATION] = ena_notification, 3320d9b8b106SMichal Krawczyk [ENA_ADMIN_KEEP_ALIVE] = ena_keep_alive 33213adcba9aSMichal Krawczyk }, 33223adcba9aSMichal Krawczyk .unimplemented_handler = unimplemented_aenq_handler 33233adcba9aSMichal Krawczyk }; 3324