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 24dbbdeb8bSMichal Krawczyk #define DRV_MODULE_VER_MINOR 6 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 39c339f538SDawid Gorecki /* 40c339f538SDawid Gorecki * We should try to keep ENA_CLEANUP_BUF_SIZE lower than 41c339f538SDawid Gorecki * RTE_MEMPOOL_CACHE_MAX_SIZE, so we can fit this in mempool local cache. 42c339f538SDawid Gorecki */ 43c339f538SDawid Gorecki #define ENA_CLEANUP_BUF_SIZE 256 44c339f538SDawid Gorecki 45b418f0d2SMichal Krawczyk #define ENA_PTYPE_HAS_HASH (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP) 46b418f0d2SMichal Krawczyk 47372c1af5SJan Medala struct ena_stats { 48372c1af5SJan Medala char name[ETH_GSTRING_LEN]; 49372c1af5SJan Medala int stat_offset; 50372c1af5SJan Medala }; 51372c1af5SJan Medala 52372c1af5SJan Medala #define ENA_STAT_ENTRY(stat, stat_type) { \ 53372c1af5SJan Medala .name = #stat, \ 54372c1af5SJan Medala .stat_offset = offsetof(struct ena_stats_##stat_type, stat) \ 55372c1af5SJan Medala } 56372c1af5SJan Medala 57372c1af5SJan Medala #define ENA_STAT_RX_ENTRY(stat) \ 58372c1af5SJan Medala ENA_STAT_ENTRY(stat, rx) 59372c1af5SJan Medala 60372c1af5SJan Medala #define ENA_STAT_TX_ENTRY(stat) \ 61372c1af5SJan Medala ENA_STAT_ENTRY(stat, tx) 62372c1af5SJan Medala 6345718adaSMichal Krawczyk #define ENA_STAT_ENI_ENTRY(stat) \ 6445718adaSMichal Krawczyk ENA_STAT_ENTRY(stat, eni) 6545718adaSMichal Krawczyk 66372c1af5SJan Medala #define ENA_STAT_GLOBAL_ENTRY(stat) \ 67372c1af5SJan Medala ENA_STAT_ENTRY(stat, dev) 68372c1af5SJan Medala 698a7a73f2SMichal Krawczyk /* Device arguments */ 708a7a73f2SMichal Krawczyk #define ENA_DEVARG_LARGE_LLQ_HDR "large_llq_hdr" 71cc0c5d25SMichal Krawczyk /* Timeout in seconds after which a single uncompleted Tx packet should be 72cc0c5d25SMichal Krawczyk * considered as a missing. 73cc0c5d25SMichal Krawczyk */ 74cc0c5d25SMichal Krawczyk #define ENA_DEVARG_MISS_TXC_TO "miss_txc_to" 75*9944919eSMichal Krawczyk /* 76*9944919eSMichal Krawczyk * Controls whether LLQ should be used (if available). Enabled by default. 77*9944919eSMichal Krawczyk * NOTE: It's highly not recommended to disable the LLQ, as it may lead to a 78*9944919eSMichal Krawczyk * huge performance degradation on 6th generation AWS instances. 79*9944919eSMichal Krawczyk */ 80*9944919eSMichal Krawczyk #define ENA_DEVARG_ENABLE_LLQ "enable_llq" 818a7a73f2SMichal Krawczyk 823adcba9aSMichal Krawczyk /* 833adcba9aSMichal Krawczyk * Each rte_memzone should have unique name. 843adcba9aSMichal Krawczyk * To satisfy it, count number of allocation and add it to name. 853adcba9aSMichal Krawczyk */ 867c0a233eSAmit Bernstein rte_atomic64_t ena_alloc_cnt; 873adcba9aSMichal Krawczyk 88372c1af5SJan Medala static const struct ena_stats ena_stats_global_strings[] = { 89372c1af5SJan Medala ENA_STAT_GLOBAL_ENTRY(wd_expired), 907830e905SSolganik Alexander ENA_STAT_GLOBAL_ENTRY(dev_start), 917830e905SSolganik Alexander ENA_STAT_GLOBAL_ENTRY(dev_stop), 92e1e73e32SMichal Krawczyk ENA_STAT_GLOBAL_ENTRY(tx_drops), 93372c1af5SJan Medala }; 94372c1af5SJan Medala 9545718adaSMichal Krawczyk static const struct ena_stats ena_stats_eni_strings[] = { 9645718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded), 9745718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded), 9845718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(pps_allowance_exceeded), 9945718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded), 10045718adaSMichal Krawczyk ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded), 10145718adaSMichal Krawczyk }; 10245718adaSMichal Krawczyk 103372c1af5SJan Medala static const struct ena_stats ena_stats_tx_strings[] = { 104372c1af5SJan Medala ENA_STAT_TX_ENTRY(cnt), 105372c1af5SJan Medala ENA_STAT_TX_ENTRY(bytes), 1067830e905SSolganik Alexander ENA_STAT_TX_ENTRY(prepare_ctx_err), 107372c1af5SJan Medala ENA_STAT_TX_ENTRY(tx_poll), 108372c1af5SJan Medala ENA_STAT_TX_ENTRY(doorbells), 109372c1af5SJan Medala ENA_STAT_TX_ENTRY(bad_req_id), 1107830e905SSolganik Alexander ENA_STAT_TX_ENTRY(available_desc), 111f93e20e5SMichal Krawczyk ENA_STAT_TX_ENTRY(missed_tx), 112372c1af5SJan Medala }; 113372c1af5SJan Medala 114372c1af5SJan Medala static const struct ena_stats ena_stats_rx_strings[] = { 115372c1af5SJan Medala ENA_STAT_RX_ENTRY(cnt), 116372c1af5SJan Medala ENA_STAT_RX_ENTRY(bytes), 1177830e905SSolganik Alexander ENA_STAT_RX_ENTRY(refill_partial), 11884daba99SMichal Krawczyk ENA_STAT_RX_ENTRY(l3_csum_bad), 11984daba99SMichal Krawczyk ENA_STAT_RX_ENTRY(l4_csum_bad), 12084daba99SMichal Krawczyk ENA_STAT_RX_ENTRY(l4_csum_good), 1217830e905SSolganik Alexander ENA_STAT_RX_ENTRY(mbuf_alloc_fail), 122372c1af5SJan Medala ENA_STAT_RX_ENTRY(bad_desc_num), 1237830e905SSolganik Alexander ENA_STAT_RX_ENTRY(bad_req_id), 124372c1af5SJan Medala }; 125372c1af5SJan Medala 126372c1af5SJan Medala #define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings) 12745718adaSMichal Krawczyk #define ENA_STATS_ARRAY_ENI ARRAY_SIZE(ena_stats_eni_strings) 128372c1af5SJan Medala #define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) 129372c1af5SJan Medala #define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) 1301173fca2SJan Medala 131295968d1SFerruh Yigit #define QUEUE_OFFLOADS (RTE_ETH_TX_OFFLOAD_TCP_CKSUM |\ 132295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_UDP_CKSUM |\ 133295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |\ 134295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_TCP_TSO) 135daa02b5cSOlivier Matz #define MBUF_OFFLOADS (RTE_MBUF_F_TX_L4_MASK |\ 136daa02b5cSOlivier Matz RTE_MBUF_F_TX_IP_CKSUM |\ 137daa02b5cSOlivier Matz RTE_MBUF_F_TX_TCP_SEG) 13856b8b9b7SRafal Kozik 1391173fca2SJan Medala /** Vendor ID used by Amazon devices */ 1401173fca2SJan Medala #define PCI_VENDOR_ID_AMAZON 0x1D0F 1411173fca2SJan Medala /** Amazon devices */ 1421173fca2SJan Medala #define PCI_DEVICE_ID_ENA_VF 0xEC20 143f7138b91SMichal Krawczyk #define PCI_DEVICE_ID_ENA_VF_RSERV0 0xEC21 1441173fca2SJan Medala 145daa02b5cSOlivier Matz #define ENA_TX_OFFLOAD_MASK (RTE_MBUF_F_TX_L4_MASK | \ 146daa02b5cSOlivier Matz RTE_MBUF_F_TX_IPV6 | \ 147daa02b5cSOlivier Matz RTE_MBUF_F_TX_IPV4 | \ 148daa02b5cSOlivier Matz RTE_MBUF_F_TX_IP_CKSUM | \ 149daa02b5cSOlivier Matz RTE_MBUF_F_TX_TCP_SEG) 150b3fc5a1aSKonstantin Ananyev 151b3fc5a1aSKonstantin Ananyev #define ENA_TX_OFFLOAD_NOTSUP_MASK \ 152daa02b5cSOlivier Matz (RTE_MBUF_F_TX_OFFLOAD_MASK ^ ENA_TX_OFFLOAD_MASK) 153b3fc5a1aSKonstantin Ananyev 154e8c838fdSMichal Krawczyk /** HW specific offloads capabilities. */ 155e8c838fdSMichal Krawczyk /* IPv4 checksum offload. */ 156e8c838fdSMichal Krawczyk #define ENA_L3_IPV4_CSUM 0x0001 157e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv4 packets. */ 158e8c838fdSMichal Krawczyk #define ENA_L4_IPV4_CSUM 0x0002 159e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv4 packets with pseudo header checksum. */ 160e8c838fdSMichal Krawczyk #define ENA_L4_IPV4_CSUM_PARTIAL 0x0004 161e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv6 packets. */ 162e8c838fdSMichal Krawczyk #define ENA_L4_IPV6_CSUM 0x0008 163e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv6 packets with pseudo header checksum. */ 164e8c838fdSMichal Krawczyk #define ENA_L4_IPV6_CSUM_PARTIAL 0x0010 165e8c838fdSMichal Krawczyk /* TSO support for IPv4 packets. */ 166e8c838fdSMichal Krawczyk #define ENA_IPV4_TSO 0x0020 167e8c838fdSMichal Krawczyk 168e8c838fdSMichal Krawczyk /* Device supports setting RSS hash. */ 169e8c838fdSMichal Krawczyk #define ENA_RX_RSS_HASH 0x0040 170e8c838fdSMichal Krawczyk 17128a1fd4fSFerruh Yigit static const struct rte_pci_id pci_id_ena_map[] = { 172cb990571SDavid Marchand { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF) }, 173f7138b91SMichal Krawczyk { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF_RSERV0) }, 1741173fca2SJan Medala { .device_id = 0 }, 1751173fca2SJan Medala }; 1761173fca2SJan Medala 177ca148440SMichal Krawczyk static struct ena_aenq_handlers aenq_handlers; 1783adcba9aSMichal Krawczyk 179b9b05d6fSMichal Krawczyk static int ena_device_init(struct ena_adapter *adapter, 180aab58857SStanislaw Kardach struct rte_pci_device *pdev, 181b9b05d6fSMichal Krawczyk struct ena_com_dev_get_features_ctx *get_feat_ctx); 1821173fca2SJan Medala static int ena_dev_configure(struct rte_eth_dev *dev); 18336278b82SMichal Krawczyk static void ena_tx_map_mbuf(struct ena_ring *tx_ring, 18436278b82SMichal Krawczyk struct ena_tx_buffer *tx_info, 18536278b82SMichal Krawczyk struct rte_mbuf *mbuf, 18636278b82SMichal Krawczyk void **push_header, 18736278b82SMichal Krawczyk uint16_t *header_len); 18836278b82SMichal Krawczyk static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf); 189a52b317eSDawid Gorecki static int ena_tx_cleanup(void *txp, uint32_t free_pkt_cnt); 1901173fca2SJan Medala static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 1911173fca2SJan Medala uint16_t nb_pkts); 192b3fc5a1aSKonstantin Ananyev static uint16_t eth_ena_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 193b3fc5a1aSKonstantin Ananyev uint16_t nb_pkts); 1941173fca2SJan Medala static int ena_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 1951173fca2SJan Medala uint16_t nb_desc, unsigned int socket_id, 1961173fca2SJan Medala const struct rte_eth_txconf *tx_conf); 1971173fca2SJan Medala static int ena_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 1981173fca2SJan Medala uint16_t nb_desc, unsigned int socket_id, 1991173fca2SJan Medala const struct rte_eth_rxconf *rx_conf, 2001173fca2SJan Medala struct rte_mempool *mp); 2011be097dcSMichal Krawczyk static inline void ena_init_rx_mbuf(struct rte_mbuf *mbuf, uint16_t len); 2021be097dcSMichal Krawczyk static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, 2031be097dcSMichal Krawczyk struct ena_com_rx_buf_info *ena_bufs, 2041be097dcSMichal Krawczyk uint32_t descs, 2051be097dcSMichal Krawczyk uint16_t *next_to_clean, 2061be097dcSMichal Krawczyk uint8_t offset); 2071173fca2SJan Medala static uint16_t eth_ena_recv_pkts(void *rx_queue, 2081173fca2SJan Medala struct rte_mbuf **rx_pkts, uint16_t nb_pkts); 20983fd97b2SMichal Krawczyk static int ena_add_single_rx_desc(struct ena_com_io_sq *io_sq, 21083fd97b2SMichal Krawczyk struct rte_mbuf *mbuf, uint16_t id); 2111173fca2SJan Medala static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count); 21233dde075SMichal Krawczyk static void ena_init_rings(struct ena_adapter *adapter, 21333dde075SMichal Krawczyk bool disable_meta_caching); 2141173fca2SJan Medala static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); 2151173fca2SJan Medala static int ena_start(struct rte_eth_dev *dev); 21662024eb8SIvan Ilchenko static int ena_stop(struct rte_eth_dev *dev); 217b142387bSThomas Monjalon static int ena_close(struct rte_eth_dev *dev); 2182081d5e2SMichal Krawczyk static int ena_dev_reset(struct rte_eth_dev *dev); 219d5b0924bSMatan Azrad static int ena_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); 2201173fca2SJan Medala static void ena_rx_queue_release_all(struct rte_eth_dev *dev); 2211173fca2SJan Medala static void ena_tx_queue_release_all(struct rte_eth_dev *dev); 2227483341aSXueming Li static void ena_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 2237483341aSXueming Li static void ena_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 2241173fca2SJan Medala static void ena_rx_queue_release_bufs(struct ena_ring *ring); 2251173fca2SJan Medala static void ena_tx_queue_release_bufs(struct ena_ring *ring); 2261173fca2SJan Medala static int ena_link_update(struct rte_eth_dev *dev, 227dd2c630aSFerruh Yigit int wait_to_complete); 2286986cdc4SMichal Krawczyk static int ena_create_io_queue(struct rte_eth_dev *dev, struct ena_ring *ring); 22926e5543dSRafal Kozik static void ena_queue_stop(struct ena_ring *ring); 23026e5543dSRafal Kozik static void ena_queue_stop_all(struct rte_eth_dev *dev, 23126e5543dSRafal Kozik enum ena_ring_type ring_type); 2326986cdc4SMichal Krawczyk static int ena_queue_start(struct rte_eth_dev *dev, struct ena_ring *ring); 23326e5543dSRafal Kozik static int ena_queue_start_all(struct rte_eth_dev *dev, 2341173fca2SJan Medala enum ena_ring_type ring_type); 2351173fca2SJan Medala static void ena_stats_restart(struct rte_eth_dev *dev); 2363a822d79SMichal Krawczyk static uint64_t ena_get_rx_port_offloads(struct ena_adapter *adapter); 2373a822d79SMichal Krawczyk static uint64_t ena_get_tx_port_offloads(struct ena_adapter *adapter); 2383a822d79SMichal Krawczyk static uint64_t ena_get_rx_queue_offloads(struct ena_adapter *adapter); 2393a822d79SMichal Krawczyk static uint64_t ena_get_tx_queue_offloads(struct ena_adapter *adapter); 240bdad90d1SIvan Ilchenko static int ena_infos_get(struct rte_eth_dev *dev, 2411173fca2SJan Medala struct rte_eth_dev_info *dev_info); 24215773e06SMichal Krawczyk static void ena_interrupt_handler_rte(void *cb_arg); 243d9b8b106SMichal Krawczyk static void ena_timer_wd_callback(struct rte_timer *timer, void *arg); 244e457bc70SRafal Kozik static void ena_destroy_device(struct rte_eth_dev *eth_dev); 245e457bc70SRafal Kozik static int eth_ena_dev_init(struct rte_eth_dev *eth_dev); 2467830e905SSolganik Alexander static int ena_xstats_get_names(struct rte_eth_dev *dev, 2477830e905SSolganik Alexander struct rte_eth_xstat_name *xstats_names, 2487830e905SSolganik Alexander unsigned int n); 2493cec73faSMichal Krawczyk static int ena_xstats_get_names_by_id(struct rte_eth_dev *dev, 2503cec73faSMichal Krawczyk const uint64_t *ids, 2513cec73faSMichal Krawczyk struct rte_eth_xstat_name *xstats_names, 2523cec73faSMichal Krawczyk unsigned int size); 2537830e905SSolganik Alexander static int ena_xstats_get(struct rte_eth_dev *dev, 2547830e905SSolganik Alexander struct rte_eth_xstat *stats, 2557830e905SSolganik Alexander unsigned int n); 2567830e905SSolganik Alexander static int ena_xstats_get_by_id(struct rte_eth_dev *dev, 2577830e905SSolganik Alexander const uint64_t *ids, 2587830e905SSolganik Alexander uint64_t *values, 2597830e905SSolganik Alexander unsigned int n); 2608a7a73f2SMichal Krawczyk static int ena_process_bool_devarg(const char *key, 2618a7a73f2SMichal Krawczyk const char *value, 2628a7a73f2SMichal Krawczyk void *opaque); 2638a7a73f2SMichal Krawczyk static int ena_parse_devargs(struct ena_adapter *adapter, 2648a7a73f2SMichal Krawczyk struct rte_devargs *devargs); 265e3595539SStanislaw Kardach static int ena_copy_eni_stats(struct ena_adapter *adapter, 266e3595539SStanislaw Kardach struct ena_stats_eni *stats); 2676986cdc4SMichal Krawczyk static int ena_setup_rx_intr(struct rte_eth_dev *dev); 2686986cdc4SMichal Krawczyk static int ena_rx_queue_intr_enable(struct rte_eth_dev *dev, 2696986cdc4SMichal Krawczyk uint16_t queue_id); 2706986cdc4SMichal Krawczyk static int ena_rx_queue_intr_disable(struct rte_eth_dev *dev, 2716986cdc4SMichal Krawczyk uint16_t queue_id); 272b9b05d6fSMichal Krawczyk static int ena_configure_aenq(struct ena_adapter *adapter); 273e3595539SStanislaw Kardach static int ena_mp_primary_handle(const struct rte_mp_msg *mp_msg, 274e3595539SStanislaw Kardach const void *peer); 2751173fca2SJan Medala 276103ab18cSFerruh Yigit static const struct eth_dev_ops ena_dev_ops = { 2771173fca2SJan Medala .dev_configure = ena_dev_configure, 2781173fca2SJan Medala .dev_infos_get = ena_infos_get, 2791173fca2SJan Medala .rx_queue_setup = ena_rx_queue_setup, 2801173fca2SJan Medala .tx_queue_setup = ena_tx_queue_setup, 2811173fca2SJan Medala .dev_start = ena_start, 282eb0ef49dSMichal Krawczyk .dev_stop = ena_stop, 2831173fca2SJan Medala .link_update = ena_link_update, 2841173fca2SJan Medala .stats_get = ena_stats_get, 2857830e905SSolganik Alexander .xstats_get_names = ena_xstats_get_names, 2863cec73faSMichal Krawczyk .xstats_get_names_by_id = ena_xstats_get_names_by_id, 2877830e905SSolganik Alexander .xstats_get = ena_xstats_get, 2887830e905SSolganik Alexander .xstats_get_by_id = ena_xstats_get_by_id, 2891173fca2SJan Medala .mtu_set = ena_mtu_set, 2901173fca2SJan Medala .rx_queue_release = ena_rx_queue_release, 2911173fca2SJan Medala .tx_queue_release = ena_tx_queue_release, 2921173fca2SJan Medala .dev_close = ena_close, 2932081d5e2SMichal Krawczyk .dev_reset = ena_dev_reset, 2941173fca2SJan Medala .reta_update = ena_rss_reta_update, 2951173fca2SJan Medala .reta_query = ena_rss_reta_query, 2966986cdc4SMichal Krawczyk .rx_queue_intr_enable = ena_rx_queue_intr_enable, 2976986cdc4SMichal Krawczyk .rx_queue_intr_disable = ena_rx_queue_intr_disable, 29834d5e97eSMichal Krawczyk .rss_hash_update = ena_rss_hash_update, 29934d5e97eSMichal Krawczyk .rss_hash_conf_get = ena_rss_hash_conf_get, 300a52b317eSDawid Gorecki .tx_done_cleanup = ena_tx_cleanup, 3011173fca2SJan Medala }; 3021173fca2SJan Medala 303e3595539SStanislaw Kardach /********************************************************************* 304e3595539SStanislaw Kardach * Multi-Process communication bits 305e3595539SStanislaw Kardach *********************************************************************/ 306e3595539SStanislaw Kardach /* rte_mp IPC message name */ 307e3595539SStanislaw Kardach #define ENA_MP_NAME "net_ena_mp" 308e3595539SStanislaw Kardach /* Request timeout in seconds */ 309e3595539SStanislaw Kardach #define ENA_MP_REQ_TMO 5 310e3595539SStanislaw Kardach 311e3595539SStanislaw Kardach /** Proxy request type */ 312e3595539SStanislaw Kardach enum ena_mp_req { 313e3595539SStanislaw Kardach ENA_MP_DEV_STATS_GET, 314e3595539SStanislaw Kardach ENA_MP_ENI_STATS_GET, 315e3595539SStanislaw Kardach ENA_MP_MTU_SET, 316e3595539SStanislaw Kardach ENA_MP_IND_TBL_GET, 317e3595539SStanislaw Kardach ENA_MP_IND_TBL_SET 318e3595539SStanislaw Kardach }; 319e3595539SStanislaw Kardach 320e3595539SStanislaw Kardach /** Proxy message body. Shared between requests and responses. */ 321e3595539SStanislaw Kardach struct ena_mp_body { 322e3595539SStanislaw Kardach /* Message type */ 323e3595539SStanislaw Kardach enum ena_mp_req type; 324e3595539SStanislaw Kardach int port_id; 325e3595539SStanislaw Kardach /* Processing result. Set in replies. 0 if message succeeded, negative 326e3595539SStanislaw Kardach * error code otherwise. 327e3595539SStanislaw Kardach */ 328e3595539SStanislaw Kardach int result; 329e3595539SStanislaw Kardach union { 330e3595539SStanislaw Kardach int mtu; /* For ENA_MP_MTU_SET */ 331e3595539SStanislaw Kardach } args; 332e3595539SStanislaw Kardach }; 333e3595539SStanislaw Kardach 334e3595539SStanislaw Kardach /** 335e3595539SStanislaw Kardach * Initialize IPC message. 336e3595539SStanislaw Kardach * 337e3595539SStanislaw Kardach * @param[out] msg 338e3595539SStanislaw Kardach * Pointer to the message to initialize. 339e3595539SStanislaw Kardach * @param[in] type 340e3595539SStanislaw Kardach * Message type. 341e3595539SStanislaw Kardach * @param[in] port_id 342e3595539SStanislaw Kardach * Port ID of target device. 343e3595539SStanislaw Kardach * 344e3595539SStanislaw Kardach */ 345e3595539SStanislaw Kardach static void 346e3595539SStanislaw Kardach mp_msg_init(struct rte_mp_msg *msg, enum ena_mp_req type, int port_id) 347e3595539SStanislaw Kardach { 348e3595539SStanislaw Kardach struct ena_mp_body *body = (struct ena_mp_body *)&msg->param; 349e3595539SStanislaw Kardach 350e3595539SStanislaw Kardach memset(msg, 0, sizeof(*msg)); 351e3595539SStanislaw Kardach strlcpy(msg->name, ENA_MP_NAME, sizeof(msg->name)); 352e3595539SStanislaw Kardach msg->len_param = sizeof(*body); 353e3595539SStanislaw Kardach body->type = type; 354e3595539SStanislaw Kardach body->port_id = port_id; 355e3595539SStanislaw Kardach } 356e3595539SStanislaw Kardach 357e3595539SStanislaw Kardach /********************************************************************* 358e3595539SStanislaw Kardach * Multi-Process communication PMD API 359e3595539SStanislaw Kardach *********************************************************************/ 360e3595539SStanislaw Kardach /** 361e3595539SStanislaw Kardach * Define proxy request descriptor 362e3595539SStanislaw Kardach * 363e3595539SStanislaw Kardach * Used to define all structures and functions required for proxying a given 364e3595539SStanislaw Kardach * function to the primary process including the code to perform to prepare the 365e3595539SStanislaw Kardach * request and process the response. 366e3595539SStanislaw Kardach * 367e3595539SStanislaw Kardach * @param[in] f 368e3595539SStanislaw Kardach * Name of the function to proxy 369e3595539SStanislaw Kardach * @param[in] t 370e3595539SStanislaw Kardach * Message type to use 371e3595539SStanislaw Kardach * @param[in] prep 372e3595539SStanislaw Kardach * Body of a function to prepare the request in form of a statement 373e3595539SStanislaw Kardach * expression. It is passed all the original function arguments along with two 374e3595539SStanislaw Kardach * extra ones: 375e3595539SStanislaw Kardach * - struct ena_adapter *adapter - PMD data of the device calling the proxy. 376e3595539SStanislaw Kardach * - struct ena_mp_body *req - body of a request to prepare. 377e3595539SStanislaw Kardach * @param[in] proc 378e3595539SStanislaw Kardach * Body of a function to process the response in form of a statement 379e3595539SStanislaw Kardach * expression. It is passed all the original function arguments along with two 380e3595539SStanislaw Kardach * extra ones: 381e3595539SStanislaw Kardach * - struct ena_adapter *adapter - PMD data of the device calling the proxy. 382e3595539SStanislaw Kardach * - struct ena_mp_body *rsp - body of a response to process. 383e3595539SStanislaw Kardach * @param ... 384e3595539SStanislaw Kardach * Proxied function's arguments 385e3595539SStanislaw Kardach * 386e3595539SStanislaw Kardach * @note Inside prep and proc any parameters which aren't used should be marked 387e3595539SStanislaw Kardach * as such (with ENA_TOUCH or __rte_unused). 388e3595539SStanislaw Kardach */ 389e3595539SStanislaw Kardach #define ENA_PROXY_DESC(f, t, prep, proc, ...) \ 390e3595539SStanislaw Kardach static const enum ena_mp_req mp_type_ ## f = t; \ 391e3595539SStanislaw Kardach static const char *mp_name_ ## f = #t; \ 392e3595539SStanislaw Kardach static void mp_prep_ ## f(struct ena_adapter *adapter, \ 393e3595539SStanislaw Kardach struct ena_mp_body *req, \ 394e3595539SStanislaw Kardach __VA_ARGS__) \ 395e3595539SStanislaw Kardach { \ 396e3595539SStanislaw Kardach prep; \ 397e3595539SStanislaw Kardach } \ 398e3595539SStanislaw Kardach static void mp_proc_ ## f(struct ena_adapter *adapter, \ 399e3595539SStanislaw Kardach struct ena_mp_body *rsp, \ 400e3595539SStanislaw Kardach __VA_ARGS__) \ 401e3595539SStanislaw Kardach { \ 402e3595539SStanislaw Kardach proc; \ 403e3595539SStanislaw Kardach } 404e3595539SStanislaw Kardach 405e3595539SStanislaw Kardach /** 406e3595539SStanislaw Kardach * Proxy wrapper for calling primary functions in a secondary process. 407e3595539SStanislaw Kardach * 408e3595539SStanislaw Kardach * Depending on whether called in primary or secondary process, calls the 409e3595539SStanislaw Kardach * @p func directly or proxies the call to the primary process via rte_mp IPC. 410e3595539SStanislaw Kardach * This macro requires a proxy request descriptor to be defined for @p func 411e3595539SStanislaw Kardach * using ENA_PROXY_DESC() macro. 412e3595539SStanislaw Kardach * 413e3595539SStanislaw Kardach * @param[in/out] a 414e3595539SStanislaw Kardach * Device PMD data. Used for sending the message and sharing message results 415e3595539SStanislaw Kardach * between primary and secondary. 416e3595539SStanislaw Kardach * @param[in] f 417e3595539SStanislaw Kardach * Function to proxy. 418e3595539SStanislaw Kardach * @param ... 419e3595539SStanislaw Kardach * Arguments of @p func. 420e3595539SStanislaw Kardach * 421e3595539SStanislaw Kardach * @return 422e3595539SStanislaw Kardach * - 0: Processing succeeded and response handler was called. 423e3595539SStanislaw Kardach * - -EPERM: IPC is unavailable on this platform. This means only primary 424e3595539SStanislaw Kardach * process may call the proxied function. 425e3595539SStanislaw Kardach * - -EIO: IPC returned error on request send. Inspect rte_errno detailed 426e3595539SStanislaw Kardach * error code. 427e3595539SStanislaw Kardach * - Negative error code from the proxied function. 428e3595539SStanislaw Kardach * 429e3595539SStanislaw Kardach * @note This mechanism is geared towards control-path tasks. Avoid calling it 430e3595539SStanislaw Kardach * in fast-path unless unbound delays are allowed. This is due to the IPC 431e3595539SStanislaw Kardach * mechanism itself (socket based). 432e3595539SStanislaw Kardach * @note Due to IPC parameter size limitations the proxy logic shares call 433e3595539SStanislaw Kardach * results through the struct ena_adapter shared memory. This makes the 434e3595539SStanislaw Kardach * proxy mechanism strictly single-threaded. Therefore be sure to make all 435e3595539SStanislaw Kardach * calls to the same proxied function under the same lock. 436e3595539SStanislaw Kardach */ 437e3595539SStanislaw Kardach #define ENA_PROXY(a, f, ...) \ 438e3595539SStanislaw Kardach ({ \ 439e3595539SStanislaw Kardach struct ena_adapter *_a = (a); \ 440e3595539SStanislaw Kardach struct timespec ts = { .tv_sec = ENA_MP_REQ_TMO }; \ 441e3595539SStanislaw Kardach struct ena_mp_body *req, *rsp; \ 442e3595539SStanislaw Kardach struct rte_mp_reply mp_rep; \ 443e3595539SStanislaw Kardach struct rte_mp_msg mp_req; \ 444e3595539SStanislaw Kardach int ret; \ 445e3595539SStanislaw Kardach \ 446e3595539SStanislaw Kardach if (rte_eal_process_type() == RTE_PROC_PRIMARY) { \ 447e3595539SStanislaw Kardach ret = f(__VA_ARGS__); \ 448e3595539SStanislaw Kardach } else { \ 449e3595539SStanislaw Kardach /* Prepare and send request */ \ 450e3595539SStanislaw Kardach req = (struct ena_mp_body *)&mp_req.param; \ 451e3595539SStanislaw Kardach mp_msg_init(&mp_req, mp_type_ ## f, _a->edev_data->port_id); \ 452e3595539SStanislaw Kardach mp_prep_ ## f(_a, req, ## __VA_ARGS__); \ 453e3595539SStanislaw Kardach \ 454e3595539SStanislaw Kardach ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts); \ 455e3595539SStanislaw Kardach if (likely(!ret)) { \ 456e3595539SStanislaw Kardach RTE_ASSERT(mp_rep.nb_received == 1); \ 457e3595539SStanislaw Kardach rsp = (struct ena_mp_body *)&mp_rep.msgs[0].param; \ 458e3595539SStanislaw Kardach ret = rsp->result; \ 459e3595539SStanislaw Kardach if (ret == 0) { \ 460e3595539SStanislaw Kardach mp_proc_##f(_a, rsp, ## __VA_ARGS__); \ 461e3595539SStanislaw Kardach } else { \ 462e3595539SStanislaw Kardach PMD_DRV_LOG(ERR, \ 463e3595539SStanislaw Kardach "%s returned error: %d\n", \ 464e3595539SStanislaw Kardach mp_name_ ## f, rsp->result);\ 465e3595539SStanislaw Kardach } \ 466e3595539SStanislaw Kardach free(mp_rep.msgs); \ 467e3595539SStanislaw Kardach } else if (rte_errno == ENOTSUP) { \ 468e3595539SStanislaw Kardach PMD_DRV_LOG(ERR, \ 469e3595539SStanislaw Kardach "No IPC, can't proxy to primary\n");\ 470e3595539SStanislaw Kardach ret = -rte_errno; \ 471e3595539SStanislaw Kardach } else { \ 472e3595539SStanislaw Kardach PMD_DRV_LOG(ERR, "Request %s failed: %s\n", \ 473e3595539SStanislaw Kardach mp_name_ ## f, \ 474e3595539SStanislaw Kardach rte_strerror(rte_errno)); \ 475e3595539SStanislaw Kardach ret = -EIO; \ 476e3595539SStanislaw Kardach } \ 477e3595539SStanislaw Kardach } \ 478e3595539SStanislaw Kardach ret; \ 479e3595539SStanislaw Kardach }) 480e3595539SStanislaw Kardach 481e3595539SStanislaw Kardach /********************************************************************* 482e3595539SStanislaw Kardach * Multi-Process communication request descriptors 483e3595539SStanislaw Kardach *********************************************************************/ 484e3595539SStanislaw Kardach 485e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_get_dev_basic_stats, ENA_MP_DEV_STATS_GET, 486e3595539SStanislaw Kardach ({ 487e3595539SStanislaw Kardach ENA_TOUCH(adapter); 488e3595539SStanislaw Kardach ENA_TOUCH(req); 489e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 490e3595539SStanislaw Kardach ENA_TOUCH(stats); 491e3595539SStanislaw Kardach }), 492e3595539SStanislaw Kardach ({ 493e3595539SStanislaw Kardach ENA_TOUCH(rsp); 494e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 495e3595539SStanislaw Kardach if (stats != &adapter->basic_stats) 496e3595539SStanislaw Kardach rte_memcpy(stats, &adapter->basic_stats, sizeof(*stats)); 497e3595539SStanislaw Kardach }), 498e3595539SStanislaw Kardach struct ena_com_dev *ena_dev, struct ena_admin_basic_stats *stats); 499e3595539SStanislaw Kardach 500e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_get_eni_stats, ENA_MP_ENI_STATS_GET, 501e3595539SStanislaw Kardach ({ 502e3595539SStanislaw Kardach ENA_TOUCH(adapter); 503e3595539SStanislaw Kardach ENA_TOUCH(req); 504e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 505e3595539SStanislaw Kardach ENA_TOUCH(stats); 506e3595539SStanislaw Kardach }), 507e3595539SStanislaw Kardach ({ 508e3595539SStanislaw Kardach ENA_TOUCH(rsp); 509e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 510e3595539SStanislaw Kardach if (stats != (struct ena_admin_eni_stats *)&adapter->eni_stats) 511e3595539SStanislaw Kardach rte_memcpy(stats, &adapter->eni_stats, sizeof(*stats)); 512e3595539SStanislaw Kardach }), 513e3595539SStanislaw Kardach struct ena_com_dev *ena_dev, struct ena_admin_eni_stats *stats); 514e3595539SStanislaw Kardach 515e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_set_dev_mtu, ENA_MP_MTU_SET, 516e3595539SStanislaw Kardach ({ 517e3595539SStanislaw Kardach ENA_TOUCH(adapter); 518e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 519e3595539SStanislaw Kardach req->args.mtu = mtu; 520e3595539SStanislaw Kardach }), 521e3595539SStanislaw Kardach ({ 522e3595539SStanislaw Kardach ENA_TOUCH(adapter); 523e3595539SStanislaw Kardach ENA_TOUCH(rsp); 524e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 525e3595539SStanislaw Kardach ENA_TOUCH(mtu); 526e3595539SStanislaw Kardach }), 527e3595539SStanislaw Kardach struct ena_com_dev *ena_dev, int mtu); 528e3595539SStanislaw Kardach 529e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_indirect_table_set, ENA_MP_IND_TBL_SET, 530e3595539SStanislaw Kardach ({ 531e3595539SStanislaw Kardach ENA_TOUCH(adapter); 532e3595539SStanislaw Kardach ENA_TOUCH(req); 533e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 534e3595539SStanislaw Kardach }), 535e3595539SStanislaw Kardach ({ 536e3595539SStanislaw Kardach ENA_TOUCH(adapter); 537e3595539SStanislaw Kardach ENA_TOUCH(rsp); 538e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 539e3595539SStanislaw Kardach }), 540e3595539SStanislaw Kardach struct ena_com_dev *ena_dev); 541e3595539SStanislaw Kardach 542e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_indirect_table_get, ENA_MP_IND_TBL_GET, 543e3595539SStanislaw Kardach ({ 544e3595539SStanislaw Kardach ENA_TOUCH(adapter); 545e3595539SStanislaw Kardach ENA_TOUCH(req); 546e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 547e3595539SStanislaw Kardach ENA_TOUCH(ind_tbl); 548e3595539SStanislaw Kardach }), 549e3595539SStanislaw Kardach ({ 550e3595539SStanislaw Kardach ENA_TOUCH(rsp); 551e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 552e3595539SStanislaw Kardach if (ind_tbl != adapter->indirect_table) 553e3595539SStanislaw Kardach rte_memcpy(ind_tbl, adapter->indirect_table, 554e3595539SStanislaw Kardach sizeof(adapter->indirect_table)); 555e3595539SStanislaw Kardach }), 556e3595539SStanislaw Kardach struct ena_com_dev *ena_dev, u32 *ind_tbl); 557e3595539SStanislaw Kardach 5582bae75eaSDawid Gorecki static inline void ena_trigger_reset(struct ena_adapter *adapter, 5592bae75eaSDawid Gorecki enum ena_regs_reset_reason_types reason) 5602bae75eaSDawid Gorecki { 5612bae75eaSDawid Gorecki if (likely(!adapter->trigger_reset)) { 5622bae75eaSDawid Gorecki adapter->reset_reason = reason; 5632bae75eaSDawid Gorecki adapter->trigger_reset = true; 5642bae75eaSDawid Gorecki } 5652bae75eaSDawid Gorecki } 5662bae75eaSDawid Gorecki 56784daba99SMichal Krawczyk static inline void ena_rx_mbuf_prepare(struct ena_ring *rx_ring, 56884daba99SMichal Krawczyk struct rte_mbuf *mbuf, 56934d5e97eSMichal Krawczyk struct ena_com_rx_ctx *ena_rx_ctx, 57034d5e97eSMichal Krawczyk bool fill_hash) 5711173fca2SJan Medala { 57284daba99SMichal Krawczyk struct ena_stats_rx *rx_stats = &rx_ring->rx_stats; 5731173fca2SJan Medala uint64_t ol_flags = 0; 574fd617795SRafal Kozik uint32_t packet_type = 0; 5751173fca2SJan Medala 5761173fca2SJan Medala if (ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_TCP) 577fd617795SRafal Kozik packet_type |= RTE_PTYPE_L4_TCP; 5781173fca2SJan Medala else if (ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_UDP) 579fd617795SRafal Kozik packet_type |= RTE_PTYPE_L4_UDP; 5801173fca2SJan Medala 581856edce2SMichal Krawczyk if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV4) { 582fd617795SRafal Kozik packet_type |= RTE_PTYPE_L3_IPV4; 58384daba99SMichal Krawczyk if (unlikely(ena_rx_ctx->l3_csum_err)) { 58484daba99SMichal Krawczyk ++rx_stats->l3_csum_bad; 585daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; 58684daba99SMichal Krawczyk } else { 587daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD; 58884daba99SMichal Krawczyk } 589856edce2SMichal Krawczyk } else if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV6) { 590856edce2SMichal Krawczyk packet_type |= RTE_PTYPE_L3_IPV6; 591856edce2SMichal Krawczyk } 592856edce2SMichal Krawczyk 59384daba99SMichal Krawczyk if (!ena_rx_ctx->l4_csum_checked || ena_rx_ctx->frag) { 594daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN; 59584daba99SMichal Krawczyk } else { 59684daba99SMichal Krawczyk if (unlikely(ena_rx_ctx->l4_csum_err)) { 59784daba99SMichal Krawczyk ++rx_stats->l4_csum_bad; 598b2d2f1cfSMichal Krawczyk /* 599b2d2f1cfSMichal Krawczyk * For the L4 Rx checksum offload the HW may indicate 600b2d2f1cfSMichal Krawczyk * bad checksum although it's valid. Because of that, 601b2d2f1cfSMichal Krawczyk * we're setting the UNKNOWN flag to let the app 602b2d2f1cfSMichal Krawczyk * re-verify the checksum. 603b2d2f1cfSMichal Krawczyk */ 604b2d2f1cfSMichal Krawczyk ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN; 60584daba99SMichal Krawczyk } else { 60684daba99SMichal Krawczyk ++rx_stats->l4_csum_good; 607daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; 60884daba99SMichal Krawczyk } 60984daba99SMichal Krawczyk } 6101173fca2SJan Medala 61134d5e97eSMichal Krawczyk if (fill_hash && 61234d5e97eSMichal Krawczyk likely((packet_type & ENA_PTYPE_HAS_HASH) && !ena_rx_ctx->frag)) { 613daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_RSS_HASH; 614b418f0d2SMichal Krawczyk mbuf->hash.rss = ena_rx_ctx->hash; 615b418f0d2SMichal Krawczyk } 616b418f0d2SMichal Krawczyk 6171173fca2SJan Medala mbuf->ol_flags = ol_flags; 618fd617795SRafal Kozik mbuf->packet_type = packet_type; 6191173fca2SJan Medala } 6201173fca2SJan Medala 6211173fca2SJan Medala static inline void ena_tx_mbuf_prepare(struct rte_mbuf *mbuf, 62256b8b9b7SRafal Kozik struct ena_com_tx_ctx *ena_tx_ctx, 62333dde075SMichal Krawczyk uint64_t queue_offloads, 62433dde075SMichal Krawczyk bool disable_meta_caching) 6251173fca2SJan Medala { 6261173fca2SJan Medala struct ena_com_tx_meta *ena_meta = &ena_tx_ctx->ena_meta; 6271173fca2SJan Medala 62856b8b9b7SRafal Kozik if ((mbuf->ol_flags & MBUF_OFFLOADS) && 62956b8b9b7SRafal Kozik (queue_offloads & QUEUE_OFFLOADS)) { 6301173fca2SJan Medala /* check if TSO is required */ 631daa02b5cSOlivier Matz if ((mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) && 632295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO)) { 6331173fca2SJan Medala ena_tx_ctx->tso_enable = true; 6341173fca2SJan Medala 6351173fca2SJan Medala ena_meta->l4_hdr_len = GET_L4_HDR_LEN(mbuf); 6361173fca2SJan Medala } 6371173fca2SJan Medala 6381173fca2SJan Medala /* check if L3 checksum is needed */ 639daa02b5cSOlivier Matz if ((mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) && 640295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) 6411173fca2SJan Medala ena_tx_ctx->l3_csum_enable = true; 6421173fca2SJan Medala 643daa02b5cSOlivier Matz if (mbuf->ol_flags & RTE_MBUF_F_TX_IPV6) { 6441173fca2SJan Medala ena_tx_ctx->l3_proto = ENA_ETH_IO_L3_PROTO_IPV6; 645022fb61bSMichal Krawczyk /* For the IPv6 packets, DF always needs to be true. */ 646022fb61bSMichal Krawczyk ena_tx_ctx->df = 1; 6471173fca2SJan Medala } else { 6481173fca2SJan Medala ena_tx_ctx->l3_proto = ENA_ETH_IO_L3_PROTO_IPV4; 6491173fca2SJan Medala 6501173fca2SJan Medala /* set don't fragment (DF) flag */ 6511173fca2SJan Medala if (mbuf->packet_type & 6521173fca2SJan Medala (RTE_PTYPE_L4_NONFRAG 6531173fca2SJan Medala | RTE_PTYPE_INNER_L4_NONFRAG)) 654022fb61bSMichal Krawczyk ena_tx_ctx->df = 1; 6551173fca2SJan Medala } 6561173fca2SJan Medala 6571173fca2SJan Medala /* check if L4 checksum is needed */ 658daa02b5cSOlivier Matz if (((mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK) == RTE_MBUF_F_TX_TCP_CKSUM) && 659295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) { 6601173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_TCP; 6611173fca2SJan Medala ena_tx_ctx->l4_csum_enable = true; 662daa02b5cSOlivier Matz } else if (((mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK) == 663daa02b5cSOlivier Matz RTE_MBUF_F_TX_UDP_CKSUM) && 664295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM)) { 6651173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_UDP; 6661173fca2SJan Medala ena_tx_ctx->l4_csum_enable = true; 66756b8b9b7SRafal Kozik } else { 6681173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_UNKNOWN; 6691173fca2SJan Medala ena_tx_ctx->l4_csum_enable = false; 6701173fca2SJan Medala } 6711173fca2SJan Medala 6721173fca2SJan Medala ena_meta->mss = mbuf->tso_segsz; 6731173fca2SJan Medala ena_meta->l3_hdr_len = mbuf->l3_len; 6741173fca2SJan Medala ena_meta->l3_hdr_offset = mbuf->l2_len; 6751173fca2SJan Medala 6761173fca2SJan Medala ena_tx_ctx->meta_valid = true; 67733dde075SMichal Krawczyk } else if (disable_meta_caching) { 67833dde075SMichal Krawczyk memset(ena_meta, 0, sizeof(*ena_meta)); 67933dde075SMichal Krawczyk ena_tx_ctx->meta_valid = true; 6801173fca2SJan Medala } else { 6811173fca2SJan Medala ena_tx_ctx->meta_valid = false; 6821173fca2SJan Medala } 6831173fca2SJan Medala } 6841173fca2SJan Medala 685f7d82d24SRafal Kozik static int validate_tx_req_id(struct ena_ring *tx_ring, u16 req_id) 686f7d82d24SRafal Kozik { 687f7d82d24SRafal Kozik struct ena_tx_buffer *tx_info = NULL; 688f7d82d24SRafal Kozik 689f7d82d24SRafal Kozik if (likely(req_id < tx_ring->ring_size)) { 690f7d82d24SRafal Kozik tx_info = &tx_ring->tx_buffer_info[req_id]; 691f7d82d24SRafal Kozik if (likely(tx_info->mbuf)) 692f7d82d24SRafal Kozik return 0; 693f7d82d24SRafal Kozik } 694f7d82d24SRafal Kozik 695f7d82d24SRafal Kozik if (tx_info) 69677e764c7SDawid Gorecki PMD_TX_LOG(ERR, "tx_info doesn't have valid mbuf. queue %d:%d req_id %u\n", 69777e764c7SDawid Gorecki tx_ring->port_id, tx_ring->id, req_id); 698f7d82d24SRafal Kozik else 69977e764c7SDawid Gorecki PMD_TX_LOG(ERR, "Invalid req_id: %hu in queue %d:%d\n", 70077e764c7SDawid Gorecki req_id, tx_ring->port_id, tx_ring->id); 701f7d82d24SRafal Kozik 702f7d82d24SRafal Kozik /* Trigger device reset */ 7037830e905SSolganik Alexander ++tx_ring->tx_stats.bad_req_id; 7042bae75eaSDawid Gorecki ena_trigger_reset(tx_ring->adapter, ENA_REGS_RESET_INV_TX_REQ_ID); 705f7d82d24SRafal Kozik return -EFAULT; 706f7d82d24SRafal Kozik } 707f7d82d24SRafal Kozik 708372c1af5SJan Medala static void ena_config_host_info(struct ena_com_dev *ena_dev) 709372c1af5SJan Medala { 710372c1af5SJan Medala struct ena_admin_host_info *host_info; 711372c1af5SJan Medala int rc; 712372c1af5SJan Medala 713372c1af5SJan Medala /* Allocate only the host info */ 714372c1af5SJan Medala rc = ena_com_allocate_host_info(ena_dev); 715372c1af5SJan Medala if (rc) { 7166f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Cannot allocate host info\n"); 717372c1af5SJan Medala return; 718372c1af5SJan Medala } 719372c1af5SJan Medala 720372c1af5SJan Medala host_info = ena_dev->host_attr.host_info; 721372c1af5SJan Medala 722372c1af5SJan Medala host_info->os_type = ENA_ADMIN_OS_DPDK; 723372c1af5SJan Medala host_info->kernel_ver = RTE_VERSION; 7246723c0fcSBruce Richardson strlcpy((char *)host_info->kernel_ver_str, rte_version(), 7256723c0fcSBruce Richardson sizeof(host_info->kernel_ver_str)); 726372c1af5SJan Medala host_info->os_dist = RTE_VERSION; 7276723c0fcSBruce Richardson strlcpy((char *)host_info->os_dist_str, rte_version(), 7286723c0fcSBruce Richardson sizeof(host_info->os_dist_str)); 729372c1af5SJan Medala host_info->driver_version = 730372c1af5SJan Medala (DRV_MODULE_VER_MAJOR) | 731372c1af5SJan Medala (DRV_MODULE_VER_MINOR << ENA_ADMIN_HOST_INFO_MINOR_SHIFT) | 732c4144557SJan Medala (DRV_MODULE_VER_SUBMINOR << 733c4144557SJan Medala ENA_ADMIN_HOST_INFO_SUB_MINOR_SHIFT); 734b9302eb9SRafal Kozik host_info->num_cpus = rte_lcore_count(); 735372c1af5SJan Medala 7367b3a3c4bSMaciej Bielski host_info->driver_supported_features = 73734d5e97eSMichal Krawczyk ENA_ADMIN_HOST_INFO_RX_OFFSET_MASK | 73834d5e97eSMichal Krawczyk ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK; 7397b3a3c4bSMaciej Bielski 740372c1af5SJan Medala rc = ena_com_set_host_attributes(ena_dev); 741372c1af5SJan Medala if (rc) { 742241da076SRafal Kozik if (rc == -ENA_COM_UNSUPPORTED) 7436f1c9df9SStephen Hemminger PMD_DRV_LOG(WARNING, "Cannot set host attributes\n"); 744241da076SRafal Kozik else 7456f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Cannot set host attributes\n"); 746241da076SRafal Kozik 747372c1af5SJan Medala goto err; 748372c1af5SJan Medala } 749372c1af5SJan Medala 750372c1af5SJan Medala return; 751372c1af5SJan Medala 752372c1af5SJan Medala err: 753372c1af5SJan Medala ena_com_delete_host_info(ena_dev); 754372c1af5SJan Medala } 755372c1af5SJan Medala 7567830e905SSolganik Alexander /* This function calculates the number of xstats based on the current config */ 757aab58857SStanislaw Kardach static unsigned int ena_xstats_calc_num(struct rte_eth_dev_data *data) 758372c1af5SJan Medala { 75945718adaSMichal Krawczyk return ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENI + 760aab58857SStanislaw Kardach (data->nb_tx_queues * ENA_STATS_ARRAY_TX) + 761aab58857SStanislaw Kardach (data->nb_rx_queues * ENA_STATS_ARRAY_RX); 762372c1af5SJan Medala } 763372c1af5SJan Medala 764372c1af5SJan Medala static void ena_config_debug_area(struct ena_adapter *adapter) 765372c1af5SJan Medala { 766372c1af5SJan Medala u32 debug_area_size; 767372c1af5SJan Medala int rc, ss_count; 768372c1af5SJan Medala 769aab58857SStanislaw Kardach ss_count = ena_xstats_calc_num(adapter->edev_data); 770372c1af5SJan Medala 771372c1af5SJan Medala /* allocate 32 bytes for each string and 64bit for the value */ 772372c1af5SJan Medala debug_area_size = ss_count * ETH_GSTRING_LEN + sizeof(u64) * ss_count; 773372c1af5SJan Medala 774372c1af5SJan Medala rc = ena_com_allocate_debug_area(&adapter->ena_dev, debug_area_size); 775372c1af5SJan Medala if (rc) { 7766f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Cannot allocate debug area\n"); 777372c1af5SJan Medala return; 778372c1af5SJan Medala } 779372c1af5SJan Medala 780372c1af5SJan Medala rc = ena_com_set_host_attributes(&adapter->ena_dev); 781372c1af5SJan Medala if (rc) { 782241da076SRafal Kozik if (rc == -ENA_COM_UNSUPPORTED) 7836f1c9df9SStephen Hemminger PMD_DRV_LOG(WARNING, "Cannot set host attributes\n"); 784241da076SRafal Kozik else 7856f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Cannot set host attributes\n"); 786241da076SRafal Kozik 787372c1af5SJan Medala goto err; 788372c1af5SJan Medala } 789372c1af5SJan Medala 790372c1af5SJan Medala return; 791372c1af5SJan Medala err: 792372c1af5SJan Medala ena_com_delete_debug_area(&adapter->ena_dev); 793372c1af5SJan Medala } 794372c1af5SJan Medala 795b142387bSThomas Monjalon static int ena_close(struct rte_eth_dev *dev) 7961173fca2SJan Medala { 7974d7877fdSMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 798d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 799890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 80062024eb8SIvan Ilchenko int ret = 0; 8011173fca2SJan Medala 80230410493SThomas Monjalon if (rte_eal_process_type() != RTE_PROC_PRIMARY) 80330410493SThomas Monjalon return 0; 80430410493SThomas Monjalon 805df238f84SMichal Krawczyk if (adapter->state == ENA_ADAPTER_STATE_RUNNING) 80662024eb8SIvan Ilchenko ret = ena_stop(dev); 807eb0ef49dSMichal Krawczyk adapter->state = ENA_ADAPTER_STATE_CLOSED; 80815773e06SMichal Krawczyk 8091173fca2SJan Medala ena_rx_queue_release_all(dev); 8101173fca2SJan Medala ena_tx_queue_release_all(dev); 8114d7877fdSMichal Krawczyk 8124d7877fdSMichal Krawczyk rte_free(adapter->drv_stats); 8134d7877fdSMichal Krawczyk adapter->drv_stats = NULL; 8144d7877fdSMichal Krawczyk 8154d7877fdSMichal Krawczyk rte_intr_disable(intr_handle); 8164d7877fdSMichal Krawczyk rte_intr_callback_unregister(intr_handle, 8174d7877fdSMichal Krawczyk ena_interrupt_handler_rte, 818aab58857SStanislaw Kardach dev); 8194d7877fdSMichal Krawczyk 8204d7877fdSMichal Krawczyk /* 8214d7877fdSMichal Krawczyk * MAC is not allocated dynamically. Setting NULL should prevent from 8224d7877fdSMichal Krawczyk * release of the resource in the rte_eth_dev_release_port(). 8234d7877fdSMichal Krawczyk */ 8244d7877fdSMichal Krawczyk dev->data->mac_addrs = NULL; 825b142387bSThomas Monjalon 82662024eb8SIvan Ilchenko return ret; 8271173fca2SJan Medala } 8281173fca2SJan Medala 8292081d5e2SMichal Krawczyk static int 8302081d5e2SMichal Krawczyk ena_dev_reset(struct rte_eth_dev *dev) 8312081d5e2SMichal Krawczyk { 832e457bc70SRafal Kozik int rc = 0; 8332081d5e2SMichal Krawczyk 83439ecdd3dSStanislaw Kardach /* Cannot release memory in secondary process */ 83539ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 83639ecdd3dSStanislaw Kardach PMD_DRV_LOG(WARNING, "dev_reset not supported in secondary.\n"); 83739ecdd3dSStanislaw Kardach return -EPERM; 83839ecdd3dSStanislaw Kardach } 83939ecdd3dSStanislaw Kardach 840e457bc70SRafal Kozik ena_destroy_device(dev); 841e457bc70SRafal Kozik rc = eth_ena_dev_init(dev); 842241da076SRafal Kozik if (rc) 843617898d1SMichal Krawczyk PMD_INIT_LOG(CRIT, "Cannot initialize device\n"); 844e457bc70SRafal Kozik 8452081d5e2SMichal Krawczyk return rc; 8462081d5e2SMichal Krawczyk } 8472081d5e2SMichal Krawczyk 8481173fca2SJan Medala static void ena_rx_queue_release_all(struct rte_eth_dev *dev) 8491173fca2SJan Medala { 8501173fca2SJan Medala int nb_queues = dev->data->nb_rx_queues; 8511173fca2SJan Medala int i; 8521173fca2SJan Medala 8531173fca2SJan Medala for (i = 0; i < nb_queues; i++) 8547483341aSXueming Li ena_rx_queue_release(dev, i); 8551173fca2SJan Medala } 8561173fca2SJan Medala 8571173fca2SJan Medala static void ena_tx_queue_release_all(struct rte_eth_dev *dev) 8581173fca2SJan Medala { 8591173fca2SJan Medala int nb_queues = dev->data->nb_tx_queues; 8601173fca2SJan Medala int i; 8611173fca2SJan Medala 8621173fca2SJan Medala for (i = 0; i < nb_queues; i++) 8637483341aSXueming Li ena_tx_queue_release(dev, i); 8641173fca2SJan Medala } 8651173fca2SJan Medala 8667483341aSXueming Li static void ena_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 8671173fca2SJan Medala { 8687483341aSXueming Li struct ena_ring *ring = dev->data->rx_queues[qid]; 8691173fca2SJan Medala 8701173fca2SJan Medala /* Free ring resources */ 8711173fca2SJan Medala rte_free(ring->rx_buffer_info); 8721173fca2SJan Medala ring->rx_buffer_info = NULL; 8731173fca2SJan Medala 87479405ee1SRafal Kozik rte_free(ring->rx_refill_buffer); 87579405ee1SRafal Kozik ring->rx_refill_buffer = NULL; 87679405ee1SRafal Kozik 877c2034976SMichal Krawczyk rte_free(ring->empty_rx_reqs); 878c2034976SMichal Krawczyk ring->empty_rx_reqs = NULL; 879c2034976SMichal Krawczyk 8801173fca2SJan Medala ring->configured = 0; 8811173fca2SJan Medala 882617898d1SMichal Krawczyk PMD_DRV_LOG(NOTICE, "Rx queue %d:%d released\n", 8831173fca2SJan Medala ring->port_id, ring->id); 8841173fca2SJan Medala } 8851173fca2SJan Medala 8867483341aSXueming Li static void ena_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 8871173fca2SJan Medala { 8887483341aSXueming Li struct ena_ring *ring = dev->data->tx_queues[qid]; 8891173fca2SJan Medala 8901173fca2SJan Medala /* Free ring resources */ 8912fca2a98SMichal Krawczyk rte_free(ring->push_buf_intermediate_buf); 8922fca2a98SMichal Krawczyk 8931173fca2SJan Medala rte_free(ring->tx_buffer_info); 8941173fca2SJan Medala 8951173fca2SJan Medala rte_free(ring->empty_tx_reqs); 8961173fca2SJan Medala 8971173fca2SJan Medala ring->empty_tx_reqs = NULL; 8981173fca2SJan Medala ring->tx_buffer_info = NULL; 8992fca2a98SMichal Krawczyk ring->push_buf_intermediate_buf = NULL; 9001173fca2SJan Medala 9011173fca2SJan Medala ring->configured = 0; 9021173fca2SJan Medala 903617898d1SMichal Krawczyk PMD_DRV_LOG(NOTICE, "Tx queue %d:%d released\n", 9041173fca2SJan Medala ring->port_id, ring->id); 9051173fca2SJan Medala } 9061173fca2SJan Medala 9071173fca2SJan Medala static void ena_rx_queue_release_bufs(struct ena_ring *ring) 9081173fca2SJan Medala { 909709b1dcbSRafal Kozik unsigned int i; 9101173fca2SJan Medala 9111be097dcSMichal Krawczyk for (i = 0; i < ring->ring_size; ++i) { 9121be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info = &ring->rx_buffer_info[i]; 9131be097dcSMichal Krawczyk if (rx_info->mbuf) { 9141be097dcSMichal Krawczyk rte_mbuf_raw_free(rx_info->mbuf); 9151be097dcSMichal Krawczyk rx_info->mbuf = NULL; 9161be097dcSMichal Krawczyk } 9171173fca2SJan Medala } 9181173fca2SJan Medala } 9191173fca2SJan Medala 9201173fca2SJan Medala static void ena_tx_queue_release_bufs(struct ena_ring *ring) 9211173fca2SJan Medala { 922207a514cSMichal Krawczyk unsigned int i; 9231173fca2SJan Medala 924207a514cSMichal Krawczyk for (i = 0; i < ring->ring_size; ++i) { 925207a514cSMichal Krawczyk struct ena_tx_buffer *tx_buf = &ring->tx_buffer_info[i]; 9261173fca2SJan Medala 9273c8bc29fSDavid Harton if (tx_buf->mbuf) { 9281173fca2SJan Medala rte_pktmbuf_free(tx_buf->mbuf); 9293c8bc29fSDavid Harton tx_buf->mbuf = NULL; 9303c8bc29fSDavid Harton } 9311173fca2SJan Medala } 9321173fca2SJan Medala } 9331173fca2SJan Medala 9341173fca2SJan Medala static int ena_link_update(struct rte_eth_dev *dev, 9351173fca2SJan Medala __rte_unused int wait_to_complete) 9361173fca2SJan Medala { 9371173fca2SJan Medala struct rte_eth_link *link = &dev->data->dev_link; 938890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 939ca148440SMichal Krawczyk 940295968d1SFerruh Yigit link->link_status = adapter->link_status ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN; 941295968d1SFerruh Yigit link->link_speed = RTE_ETH_SPEED_NUM_NONE; 942295968d1SFerruh Yigit link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 9431173fca2SJan Medala 9441173fca2SJan Medala return 0; 9451173fca2SJan Medala } 9461173fca2SJan Medala 94726e5543dSRafal Kozik static int ena_queue_start_all(struct rte_eth_dev *dev, 9481173fca2SJan Medala enum ena_ring_type ring_type) 9491173fca2SJan Medala { 950890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 9511173fca2SJan Medala struct ena_ring *queues = NULL; 95253b61841SMichal Krawczyk int nb_queues; 9531173fca2SJan Medala int i = 0; 9541173fca2SJan Medala int rc = 0; 9551173fca2SJan Medala 95653b61841SMichal Krawczyk if (ring_type == ENA_RING_TYPE_RX) { 95753b61841SMichal Krawczyk queues = adapter->rx_ring; 95853b61841SMichal Krawczyk nb_queues = dev->data->nb_rx_queues; 95953b61841SMichal Krawczyk } else { 96053b61841SMichal Krawczyk queues = adapter->tx_ring; 96153b61841SMichal Krawczyk nb_queues = dev->data->nb_tx_queues; 96253b61841SMichal Krawczyk } 96353b61841SMichal Krawczyk for (i = 0; i < nb_queues; i++) { 9641173fca2SJan Medala if (queues[i].configured) { 9651173fca2SJan Medala if (ring_type == ENA_RING_TYPE_RX) { 9661173fca2SJan Medala ena_assert_msg( 9671173fca2SJan Medala dev->data->rx_queues[i] == &queues[i], 968617898d1SMichal Krawczyk "Inconsistent state of Rx queues\n"); 9691173fca2SJan Medala } else { 9701173fca2SJan Medala ena_assert_msg( 9711173fca2SJan Medala dev->data->tx_queues[i] == &queues[i], 972617898d1SMichal Krawczyk "Inconsistent state of Tx queues\n"); 9731173fca2SJan Medala } 9741173fca2SJan Medala 9756986cdc4SMichal Krawczyk rc = ena_queue_start(dev, &queues[i]); 9761173fca2SJan Medala 9771173fca2SJan Medala if (rc) { 9781173fca2SJan Medala PMD_INIT_LOG(ERR, 979617898d1SMichal Krawczyk "Failed to start queue[%d] of type(%d)\n", 9801173fca2SJan Medala i, ring_type); 98126e5543dSRafal Kozik goto err; 9821173fca2SJan Medala } 9831173fca2SJan Medala } 9841173fca2SJan Medala } 9851173fca2SJan Medala 9861173fca2SJan Medala return 0; 98726e5543dSRafal Kozik 98826e5543dSRafal Kozik err: 98926e5543dSRafal Kozik while (i--) 99026e5543dSRafal Kozik if (queues[i].configured) 99126e5543dSRafal Kozik ena_queue_stop(&queues[i]); 99226e5543dSRafal Kozik 99326e5543dSRafal Kozik return rc; 9941173fca2SJan Medala } 9951173fca2SJan Medala 9961173fca2SJan Medala static int 9978a7a73f2SMichal Krawczyk ena_calc_io_queue_size(struct ena_calc_queue_size_ctx *ctx, 9988a7a73f2SMichal Krawczyk bool use_large_llq_hdr) 9991173fca2SJan Medala { 10002fca2a98SMichal Krawczyk struct ena_admin_feature_llq_desc *llq = &ctx->get_feat_ctx->llq; 10012fca2a98SMichal Krawczyk struct ena_com_dev *ena_dev = ctx->ena_dev; 10025920d930SMichal Krawczyk uint32_t max_tx_queue_size; 10035920d930SMichal Krawczyk uint32_t max_rx_queue_size; 10041173fca2SJan Medala 10052fca2a98SMichal Krawczyk if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) { 1006ea93d37eSRafal Kozik struct ena_admin_queue_ext_feature_fields *max_queue_ext = 1007ea93d37eSRafal Kozik &ctx->get_feat_ctx->max_queue_ext.max_queue_ext; 10085920d930SMichal Krawczyk max_rx_queue_size = RTE_MIN(max_queue_ext->max_rx_cq_depth, 1009ea93d37eSRafal Kozik max_queue_ext->max_rx_sq_depth); 10105920d930SMichal Krawczyk max_tx_queue_size = max_queue_ext->max_tx_cq_depth; 10112fca2a98SMichal Krawczyk 10122fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == 10132fca2a98SMichal Krawczyk ENA_ADMIN_PLACEMENT_POLICY_DEV) { 10145920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 10152fca2a98SMichal Krawczyk llq->max_llq_depth); 10162fca2a98SMichal Krawczyk } else { 10175920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 1018ea93d37eSRafal Kozik max_queue_ext->max_tx_sq_depth); 10192fca2a98SMichal Krawczyk } 10202fca2a98SMichal Krawczyk 1021ea93d37eSRafal Kozik ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 1022ea93d37eSRafal Kozik max_queue_ext->max_per_packet_rx_descs); 1023ea93d37eSRafal Kozik ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 1024ea93d37eSRafal Kozik max_queue_ext->max_per_packet_tx_descs); 1025ea93d37eSRafal Kozik } else { 1026ea93d37eSRafal Kozik struct ena_admin_queue_feature_desc *max_queues = 1027ea93d37eSRafal Kozik &ctx->get_feat_ctx->max_queues; 10285920d930SMichal Krawczyk max_rx_queue_size = RTE_MIN(max_queues->max_cq_depth, 1029ea93d37eSRafal Kozik max_queues->max_sq_depth); 10305920d930SMichal Krawczyk max_tx_queue_size = max_queues->max_cq_depth; 10312fca2a98SMichal Krawczyk 10322fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == 10332fca2a98SMichal Krawczyk ENA_ADMIN_PLACEMENT_POLICY_DEV) { 10345920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 10352fca2a98SMichal Krawczyk llq->max_llq_depth); 10362fca2a98SMichal Krawczyk } else { 10375920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 10382fca2a98SMichal Krawczyk max_queues->max_sq_depth); 10392fca2a98SMichal Krawczyk } 10402fca2a98SMichal Krawczyk 1041ea93d37eSRafal Kozik ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 1042ea93d37eSRafal Kozik max_queues->max_packet_rx_descs); 10435920d930SMichal Krawczyk ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 10445920d930SMichal Krawczyk max_queues->max_packet_tx_descs); 1045ea93d37eSRafal Kozik } 10461173fca2SJan Medala 1047ea93d37eSRafal Kozik /* Round down to the nearest power of 2 */ 10485920d930SMichal Krawczyk max_rx_queue_size = rte_align32prevpow2(max_rx_queue_size); 10495920d930SMichal Krawczyk max_tx_queue_size = rte_align32prevpow2(max_tx_queue_size); 10501173fca2SJan Medala 10518a7a73f2SMichal Krawczyk if (use_large_llq_hdr) { 10528a7a73f2SMichal Krawczyk if ((llq->entry_size_ctrl_supported & 10538a7a73f2SMichal Krawczyk ENA_ADMIN_LIST_ENTRY_SIZE_256B) && 10548a7a73f2SMichal Krawczyk (ena_dev->tx_mem_queue_type == 10558a7a73f2SMichal Krawczyk ENA_ADMIN_PLACEMENT_POLICY_DEV)) { 10568a7a73f2SMichal Krawczyk max_tx_queue_size /= 2; 10578a7a73f2SMichal Krawczyk PMD_INIT_LOG(INFO, 1058617898d1SMichal Krawczyk "Forcing large headers and decreasing maximum Tx queue size to %d\n", 10598a7a73f2SMichal Krawczyk max_tx_queue_size); 10608a7a73f2SMichal Krawczyk } else { 10618a7a73f2SMichal Krawczyk PMD_INIT_LOG(ERR, 10628a7a73f2SMichal Krawczyk "Forcing large headers failed: LLQ is disabled or device does not support large headers\n"); 10638a7a73f2SMichal Krawczyk } 10648a7a73f2SMichal Krawczyk } 10658a7a73f2SMichal Krawczyk 10665920d930SMichal Krawczyk if (unlikely(max_rx_queue_size == 0 || max_tx_queue_size == 0)) { 1067617898d1SMichal Krawczyk PMD_INIT_LOG(ERR, "Invalid queue size\n"); 10681173fca2SJan Medala return -EFAULT; 10691173fca2SJan Medala } 10701173fca2SJan Medala 10715920d930SMichal Krawczyk ctx->max_tx_queue_size = max_tx_queue_size; 10725920d930SMichal Krawczyk ctx->max_rx_queue_size = max_rx_queue_size; 10732061fe41SRafal Kozik 1074ea93d37eSRafal Kozik return 0; 10751173fca2SJan Medala } 10761173fca2SJan Medala 10771173fca2SJan Medala static void ena_stats_restart(struct rte_eth_dev *dev) 10781173fca2SJan Medala { 1079890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 10801173fca2SJan Medala 10811173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->ierrors); 10821173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->oerrors); 10831173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->rx_nombuf); 1084e1e73e32SMichal Krawczyk adapter->drv_stats->rx_drops = 0; 10851173fca2SJan Medala } 10861173fca2SJan Medala 1087d5b0924bSMatan Azrad static int ena_stats_get(struct rte_eth_dev *dev, 10881173fca2SJan Medala struct rte_eth_stats *stats) 10891173fca2SJan Medala { 10901173fca2SJan Medala struct ena_admin_basic_stats ena_stats; 1091890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 10921173fca2SJan Medala struct ena_com_dev *ena_dev = &adapter->ena_dev; 10931173fca2SJan Medala int rc; 109445b6d861SMichal Krawczyk int i; 109545b6d861SMichal Krawczyk int max_rings_stats; 10961173fca2SJan Medala 10971173fca2SJan Medala memset(&ena_stats, 0, sizeof(ena_stats)); 10981343c415SMichal Krawczyk 10991343c415SMichal Krawczyk rte_spinlock_lock(&adapter->admin_lock); 1100e3595539SStanislaw Kardach rc = ENA_PROXY(adapter, ena_com_get_dev_basic_stats, ena_dev, 1101e3595539SStanislaw Kardach &ena_stats); 11021343c415SMichal Krawczyk rte_spinlock_unlock(&adapter->admin_lock); 11031173fca2SJan Medala if (unlikely(rc)) { 11046f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Could not retrieve statistics from ENA\n"); 1105d5b0924bSMatan Azrad return rc; 11061173fca2SJan Medala } 11071173fca2SJan Medala 11081173fca2SJan Medala /* Set of basic statistics from ENA */ 11091173fca2SJan Medala stats->ipackets = __MERGE_64B_H_L(ena_stats.rx_pkts_high, 11101173fca2SJan Medala ena_stats.rx_pkts_low); 11111173fca2SJan Medala stats->opackets = __MERGE_64B_H_L(ena_stats.tx_pkts_high, 11121173fca2SJan Medala ena_stats.tx_pkts_low); 11131173fca2SJan Medala stats->ibytes = __MERGE_64B_H_L(ena_stats.rx_bytes_high, 11141173fca2SJan Medala ena_stats.rx_bytes_low); 11151173fca2SJan Medala stats->obytes = __MERGE_64B_H_L(ena_stats.tx_bytes_high, 11161173fca2SJan Medala ena_stats.tx_bytes_low); 11171173fca2SJan Medala 11181173fca2SJan Medala /* Driver related stats */ 1119e1e73e32SMichal Krawczyk stats->imissed = adapter->drv_stats->rx_drops; 11201173fca2SJan Medala stats->ierrors = rte_atomic64_read(&adapter->drv_stats->ierrors); 11211173fca2SJan Medala stats->oerrors = rte_atomic64_read(&adapter->drv_stats->oerrors); 11221173fca2SJan Medala stats->rx_nombuf = rte_atomic64_read(&adapter->drv_stats->rx_nombuf); 112345b6d861SMichal Krawczyk 112445b6d861SMichal Krawczyk max_rings_stats = RTE_MIN(dev->data->nb_rx_queues, 112545b6d861SMichal Krawczyk RTE_ETHDEV_QUEUE_STAT_CNTRS); 112645b6d861SMichal Krawczyk for (i = 0; i < max_rings_stats; ++i) { 112745b6d861SMichal Krawczyk struct ena_stats_rx *rx_stats = &adapter->rx_ring[i].rx_stats; 112845b6d861SMichal Krawczyk 112945b6d861SMichal Krawczyk stats->q_ibytes[i] = rx_stats->bytes; 113045b6d861SMichal Krawczyk stats->q_ipackets[i] = rx_stats->cnt; 113145b6d861SMichal Krawczyk stats->q_errors[i] = rx_stats->bad_desc_num + 113245b6d861SMichal Krawczyk rx_stats->bad_req_id; 113345b6d861SMichal Krawczyk } 113445b6d861SMichal Krawczyk 113545b6d861SMichal Krawczyk max_rings_stats = RTE_MIN(dev->data->nb_tx_queues, 113645b6d861SMichal Krawczyk RTE_ETHDEV_QUEUE_STAT_CNTRS); 113745b6d861SMichal Krawczyk for (i = 0; i < max_rings_stats; ++i) { 113845b6d861SMichal Krawczyk struct ena_stats_tx *tx_stats = &adapter->tx_ring[i].tx_stats; 113945b6d861SMichal Krawczyk 114045b6d861SMichal Krawczyk stats->q_obytes[i] = tx_stats->bytes; 114145b6d861SMichal Krawczyk stats->q_opackets[i] = tx_stats->cnt; 114245b6d861SMichal Krawczyk } 114345b6d861SMichal Krawczyk 1144d5b0924bSMatan Azrad return 0; 11451173fca2SJan Medala } 11461173fca2SJan Medala 11471173fca2SJan Medala static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) 11481173fca2SJan Medala { 11491173fca2SJan Medala struct ena_adapter *adapter; 11501173fca2SJan Medala struct ena_com_dev *ena_dev; 11511173fca2SJan Medala int rc = 0; 11521173fca2SJan Medala 1153498c687aSRafal Kozik ena_assert_msg(dev->data != NULL, "Uninitialized device\n"); 1154498c687aSRafal Kozik ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device\n"); 1155890728ffSStephen Hemminger adapter = dev->data->dev_private; 11561173fca2SJan Medala 11571173fca2SJan Medala ena_dev = &adapter->ena_dev; 1158498c687aSRafal Kozik ena_assert_msg(ena_dev != NULL, "Uninitialized device\n"); 11591173fca2SJan Medala 1160e3595539SStanislaw Kardach rc = ENA_PROXY(adapter, ena_com_set_dev_mtu, ena_dev, mtu); 11611173fca2SJan Medala if (rc) 11626f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Could not set MTU: %d\n", mtu); 11631173fca2SJan Medala else 1164617898d1SMichal Krawczyk PMD_DRV_LOG(NOTICE, "MTU set to: %d\n", mtu); 11651173fca2SJan Medala 11661173fca2SJan Medala return rc; 11671173fca2SJan Medala } 11681173fca2SJan Medala 11691173fca2SJan Medala static int ena_start(struct rte_eth_dev *dev) 11701173fca2SJan Medala { 1171890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 1172d9b8b106SMichal Krawczyk uint64_t ticks; 11731173fca2SJan Medala int rc = 0; 11741173fca2SJan Medala 117539ecdd3dSStanislaw Kardach /* Cannot allocate memory in secondary process */ 117639ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 117739ecdd3dSStanislaw Kardach PMD_DRV_LOG(WARNING, "dev_start not supported in secondary.\n"); 117839ecdd3dSStanislaw Kardach return -EPERM; 117939ecdd3dSStanislaw Kardach } 118039ecdd3dSStanislaw Kardach 11816986cdc4SMichal Krawczyk rc = ena_setup_rx_intr(dev); 11826986cdc4SMichal Krawczyk if (rc) 11836986cdc4SMichal Krawczyk return rc; 11846986cdc4SMichal Krawczyk 118526e5543dSRafal Kozik rc = ena_queue_start_all(dev, ENA_RING_TYPE_RX); 11861173fca2SJan Medala if (rc) 11871173fca2SJan Medala return rc; 11881173fca2SJan Medala 118926e5543dSRafal Kozik rc = ena_queue_start_all(dev, ENA_RING_TYPE_TX); 11901173fca2SJan Medala if (rc) 119126e5543dSRafal Kozik goto err_start_tx; 11921173fca2SJan Medala 1193295968d1SFerruh Yigit if (adapter->edev_data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) { 119434d5e97eSMichal Krawczyk rc = ena_rss_configure(adapter); 11951173fca2SJan Medala if (rc) 119626e5543dSRafal Kozik goto err_rss_init; 11971173fca2SJan Medala } 11981173fca2SJan Medala 11991173fca2SJan Medala ena_stats_restart(dev); 12001173fca2SJan Medala 1201d9b8b106SMichal Krawczyk adapter->timestamp_wd = rte_get_timer_cycles(); 1202d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = ENA_DEVICE_KALIVE_TIMEOUT; 1203d9b8b106SMichal Krawczyk 1204d9b8b106SMichal Krawczyk ticks = rte_get_timer_hz(); 1205d9b8b106SMichal Krawczyk rte_timer_reset(&adapter->timer_wd, ticks, PERIODICAL, rte_lcore_id(), 1206aab58857SStanislaw Kardach ena_timer_wd_callback, dev); 1207d9b8b106SMichal Krawczyk 12087830e905SSolganik Alexander ++adapter->dev_stats.dev_start; 12091173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_RUNNING; 12101173fca2SJan Medala 12111173fca2SJan Medala return 0; 121226e5543dSRafal Kozik 121326e5543dSRafal Kozik err_rss_init: 121426e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_TX); 121526e5543dSRafal Kozik err_start_tx: 121626e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_RX); 121726e5543dSRafal Kozik return rc; 12181173fca2SJan Medala } 12191173fca2SJan Medala 122062024eb8SIvan Ilchenko static int ena_stop(struct rte_eth_dev *dev) 1221eb0ef49dSMichal Krawczyk { 1222890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 1223e457bc70SRafal Kozik struct ena_com_dev *ena_dev = &adapter->ena_dev; 12246986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 1225d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 1226e457bc70SRafal Kozik int rc; 1227eb0ef49dSMichal Krawczyk 122839ecdd3dSStanislaw Kardach /* Cannot free memory in secondary process */ 122939ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 123039ecdd3dSStanislaw Kardach PMD_DRV_LOG(WARNING, "dev_stop not supported in secondary.\n"); 123139ecdd3dSStanislaw Kardach return -EPERM; 123239ecdd3dSStanislaw Kardach } 123339ecdd3dSStanislaw Kardach 1234d9b8b106SMichal Krawczyk rte_timer_stop_sync(&adapter->timer_wd); 123526e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_TX); 123626e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_RX); 1237d9b8b106SMichal Krawczyk 1238e457bc70SRafal Kozik if (adapter->trigger_reset) { 1239e457bc70SRafal Kozik rc = ena_com_dev_reset(ena_dev, adapter->reset_reason); 1240e457bc70SRafal Kozik if (rc) 1241617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Device reset failed, rc: %d\n", rc); 1242e457bc70SRafal Kozik } 1243e457bc70SRafal Kozik 12446986cdc4SMichal Krawczyk rte_intr_disable(intr_handle); 12456986cdc4SMichal Krawczyk 12466986cdc4SMichal Krawczyk rte_intr_efd_disable(intr_handle); 1247d61138d4SHarman Kalra 1248d61138d4SHarman Kalra /* Cleanup vector list */ 1249d61138d4SHarman Kalra rte_intr_vec_list_free(intr_handle); 12506986cdc4SMichal Krawczyk 12516986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 12526986cdc4SMichal Krawczyk 12537830e905SSolganik Alexander ++adapter->dev_stats.dev_stop; 1254eb0ef49dSMichal Krawczyk adapter->state = ENA_ADAPTER_STATE_STOPPED; 1255b8f5d2aeSThomas Monjalon dev->data->dev_started = 0; 125662024eb8SIvan Ilchenko 125762024eb8SIvan Ilchenko return 0; 1258eb0ef49dSMichal Krawczyk } 1259eb0ef49dSMichal Krawczyk 12606986cdc4SMichal Krawczyk static int ena_create_io_queue(struct rte_eth_dev *dev, struct ena_ring *ring) 1261df238f84SMichal Krawczyk { 12626986cdc4SMichal Krawczyk struct ena_adapter *adapter = ring->adapter; 12636986cdc4SMichal Krawczyk struct ena_com_dev *ena_dev = &adapter->ena_dev; 12646986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 1265d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 1266df238f84SMichal Krawczyk struct ena_com_create_io_ctx ctx = 1267df238f84SMichal Krawczyk /* policy set to _HOST just to satisfy icc compiler */ 1268df238f84SMichal Krawczyk { ENA_ADMIN_PLACEMENT_POLICY_HOST, 1269df238f84SMichal Krawczyk 0, 0, 0, 0, 0 }; 1270df238f84SMichal Krawczyk uint16_t ena_qid; 1271778677dcSRafal Kozik unsigned int i; 1272df238f84SMichal Krawczyk int rc; 1273df238f84SMichal Krawczyk 12746986cdc4SMichal Krawczyk ctx.msix_vector = -1; 1275df238f84SMichal Krawczyk if (ring->type == ENA_RING_TYPE_TX) { 1276df238f84SMichal Krawczyk ena_qid = ENA_IO_TXQ_IDX(ring->id); 1277df238f84SMichal Krawczyk ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_TX; 1278df238f84SMichal Krawczyk ctx.mem_queue_type = ena_dev->tx_mem_queue_type; 1279778677dcSRafal Kozik for (i = 0; i < ring->ring_size; i++) 1280778677dcSRafal Kozik ring->empty_tx_reqs[i] = i; 1281df238f84SMichal Krawczyk } else { 1282df238f84SMichal Krawczyk ena_qid = ENA_IO_RXQ_IDX(ring->id); 1283df238f84SMichal Krawczyk ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_RX; 12846986cdc4SMichal Krawczyk if (rte_intr_dp_is_en(intr_handle)) 1285d61138d4SHarman Kalra ctx.msix_vector = 1286d61138d4SHarman Kalra rte_intr_vec_list_index_get(intr_handle, 1287d61138d4SHarman Kalra ring->id); 1288d61138d4SHarman Kalra 1289778677dcSRafal Kozik for (i = 0; i < ring->ring_size; i++) 1290778677dcSRafal Kozik ring->empty_rx_reqs[i] = i; 1291df238f84SMichal Krawczyk } 1292badc3a6aSMichal Krawczyk ctx.queue_size = ring->ring_size; 1293df238f84SMichal Krawczyk ctx.qid = ena_qid; 12944217cb0bSMichal Krawczyk ctx.numa_node = ring->numa_socket_id; 1295df238f84SMichal Krawczyk 1296df238f84SMichal Krawczyk rc = ena_com_create_io_queue(ena_dev, &ctx); 1297df238f84SMichal Krawczyk if (rc) { 12986f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1299617898d1SMichal Krawczyk "Failed to create IO queue[%d] (qid:%d), rc: %d\n", 1300df238f84SMichal Krawczyk ring->id, ena_qid, rc); 1301df238f84SMichal Krawczyk return rc; 1302df238f84SMichal Krawczyk } 1303df238f84SMichal Krawczyk 1304df238f84SMichal Krawczyk rc = ena_com_get_io_handlers(ena_dev, ena_qid, 1305df238f84SMichal Krawczyk &ring->ena_com_io_sq, 1306df238f84SMichal Krawczyk &ring->ena_com_io_cq); 1307df238f84SMichal Krawczyk if (rc) { 13086f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1309617898d1SMichal Krawczyk "Failed to get IO queue[%d] handlers, rc: %d\n", 1310df238f84SMichal Krawczyk ring->id, rc); 1311df238f84SMichal Krawczyk ena_com_destroy_io_queue(ena_dev, ena_qid); 1312df238f84SMichal Krawczyk return rc; 1313df238f84SMichal Krawczyk } 1314df238f84SMichal Krawczyk 1315df238f84SMichal Krawczyk if (ring->type == ENA_RING_TYPE_TX) 1316df238f84SMichal Krawczyk ena_com_update_numa_node(ring->ena_com_io_cq, ctx.numa_node); 1317df238f84SMichal Krawczyk 13186986cdc4SMichal Krawczyk /* Start with Rx interrupts being masked. */ 13196986cdc4SMichal Krawczyk if (ring->type == ENA_RING_TYPE_RX && rte_intr_dp_is_en(intr_handle)) 13206986cdc4SMichal Krawczyk ena_rx_queue_intr_disable(dev, ring->id); 13216986cdc4SMichal Krawczyk 1322df238f84SMichal Krawczyk return 0; 1323df238f84SMichal Krawczyk } 1324df238f84SMichal Krawczyk 132526e5543dSRafal Kozik static void ena_queue_stop(struct ena_ring *ring) 1326df238f84SMichal Krawczyk { 132726e5543dSRafal Kozik struct ena_com_dev *ena_dev = &ring->adapter->ena_dev; 1328df238f84SMichal Krawczyk 132926e5543dSRafal Kozik if (ring->type == ENA_RING_TYPE_RX) { 133026e5543dSRafal Kozik ena_com_destroy_io_queue(ena_dev, ENA_IO_RXQ_IDX(ring->id)); 133126e5543dSRafal Kozik ena_rx_queue_release_bufs(ring); 133226e5543dSRafal Kozik } else { 133326e5543dSRafal Kozik ena_com_destroy_io_queue(ena_dev, ENA_IO_TXQ_IDX(ring->id)); 133426e5543dSRafal Kozik ena_tx_queue_release_bufs(ring); 1335df238f84SMichal Krawczyk } 1336df238f84SMichal Krawczyk } 1337df238f84SMichal Krawczyk 133826e5543dSRafal Kozik static void ena_queue_stop_all(struct rte_eth_dev *dev, 133926e5543dSRafal Kozik enum ena_ring_type ring_type) 134026e5543dSRafal Kozik { 1341890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 134226e5543dSRafal Kozik struct ena_ring *queues = NULL; 134326e5543dSRafal Kozik uint16_t nb_queues, i; 134426e5543dSRafal Kozik 134526e5543dSRafal Kozik if (ring_type == ENA_RING_TYPE_RX) { 134626e5543dSRafal Kozik queues = adapter->rx_ring; 134726e5543dSRafal Kozik nb_queues = dev->data->nb_rx_queues; 134826e5543dSRafal Kozik } else { 134926e5543dSRafal Kozik queues = adapter->tx_ring; 135026e5543dSRafal Kozik nb_queues = dev->data->nb_tx_queues; 135126e5543dSRafal Kozik } 135226e5543dSRafal Kozik 135326e5543dSRafal Kozik for (i = 0; i < nb_queues; ++i) 135426e5543dSRafal Kozik if (queues[i].configured) 135526e5543dSRafal Kozik ena_queue_stop(&queues[i]); 135626e5543dSRafal Kozik } 135726e5543dSRafal Kozik 13586986cdc4SMichal Krawczyk static int ena_queue_start(struct rte_eth_dev *dev, struct ena_ring *ring) 13591173fca2SJan Medala { 1360a467e8f3SMichal Krawczyk int rc, bufs_num; 13611173fca2SJan Medala 13621173fca2SJan Medala ena_assert_msg(ring->configured == 1, 136326e5543dSRafal Kozik "Trying to start unconfigured queue\n"); 13641173fca2SJan Medala 13656986cdc4SMichal Krawczyk rc = ena_create_io_queue(dev, ring); 1366df238f84SMichal Krawczyk if (rc) { 1367617898d1SMichal Krawczyk PMD_INIT_LOG(ERR, "Failed to create IO queue\n"); 1368df238f84SMichal Krawczyk return rc; 1369df238f84SMichal Krawczyk } 1370df238f84SMichal Krawczyk 13711173fca2SJan Medala ring->next_to_clean = 0; 13721173fca2SJan Medala ring->next_to_use = 0; 13731173fca2SJan Medala 13747830e905SSolganik Alexander if (ring->type == ENA_RING_TYPE_TX) { 13757830e905SSolganik Alexander ring->tx_stats.available_desc = 1376b2b02edeSMichal Krawczyk ena_com_free_q_entries(ring->ena_com_io_sq); 13771173fca2SJan Medala return 0; 13787830e905SSolganik Alexander } 13791173fca2SJan Medala 1380a467e8f3SMichal Krawczyk bufs_num = ring->ring_size - 1; 1381a467e8f3SMichal Krawczyk rc = ena_populate_rx_queue(ring, bufs_num); 1382a467e8f3SMichal Krawczyk if (rc != bufs_num) { 138326e5543dSRafal Kozik ena_com_destroy_io_queue(&ring->adapter->ena_dev, 138426e5543dSRafal Kozik ENA_IO_RXQ_IDX(ring->id)); 1385617898d1SMichal Krawczyk PMD_INIT_LOG(ERR, "Failed to populate Rx ring\n"); 1386241da076SRafal Kozik return ENA_COM_FAULT; 13871173fca2SJan Medala } 13884387e81cSIdo Segev /* Flush per-core RX buffers pools cache as they can be used on other 13894387e81cSIdo Segev * cores as well. 13904387e81cSIdo Segev */ 13914387e81cSIdo Segev rte_mempool_cache_flush(NULL, ring->mb_pool); 13921173fca2SJan Medala 13931173fca2SJan Medala return 0; 13941173fca2SJan Medala } 13951173fca2SJan Medala 13961173fca2SJan Medala static int ena_tx_queue_setup(struct rte_eth_dev *dev, 13971173fca2SJan Medala uint16_t queue_idx, 13981173fca2SJan Medala uint16_t nb_desc, 13994217cb0bSMichal Krawczyk unsigned int socket_id, 140056b8b9b7SRafal Kozik const struct rte_eth_txconf *tx_conf) 14011173fca2SJan Medala { 14021173fca2SJan Medala struct ena_ring *txq = NULL; 1403890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 14041173fca2SJan Medala unsigned int i; 1405005064e5SMichal Krawczyk uint16_t dyn_thresh; 14061173fca2SJan Medala 14071173fca2SJan Medala txq = &adapter->tx_ring[queue_idx]; 14081173fca2SJan Medala 14091173fca2SJan Medala if (txq->configured) { 14106f1c9df9SStephen Hemminger PMD_DRV_LOG(CRIT, 1411617898d1SMichal Krawczyk "API violation. Queue[%d] is already configured\n", 14121173fca2SJan Medala queue_idx); 1413241da076SRafal Kozik return ENA_COM_FAULT; 14141173fca2SJan Medala } 14151173fca2SJan Medala 14161daff526SJakub Palider if (!rte_is_power_of_2(nb_desc)) { 14176f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1418617898d1SMichal Krawczyk "Unsupported size of Tx queue: %d is not a power of 2.\n", 14191daff526SJakub Palider nb_desc); 14201daff526SJakub Palider return -EINVAL; 14211daff526SJakub Palider } 14221daff526SJakub Palider 14235920d930SMichal Krawczyk if (nb_desc > adapter->max_tx_ring_size) { 14246f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1425617898d1SMichal Krawczyk "Unsupported size of Tx queue (max size: %d)\n", 14265920d930SMichal Krawczyk adapter->max_tx_ring_size); 14271173fca2SJan Medala return -EINVAL; 14281173fca2SJan Medala } 14291173fca2SJan Medala 14301173fca2SJan Medala txq->port_id = dev->data->port_id; 14311173fca2SJan Medala txq->next_to_clean = 0; 14321173fca2SJan Medala txq->next_to_use = 0; 14331173fca2SJan Medala txq->ring_size = nb_desc; 1434c0006061SMichal Krawczyk txq->size_mask = nb_desc - 1; 14354217cb0bSMichal Krawczyk txq->numa_socket_id = socket_id; 14361d973d8fSIgor Chauskin txq->pkts_without_db = false; 1437f93e20e5SMichal Krawczyk txq->last_cleanup_ticks = 0; 14381173fca2SJan Medala 143908180833SMichal Krawczyk txq->tx_buffer_info = rte_zmalloc_socket("txq->tx_buffer_info", 144008180833SMichal Krawczyk sizeof(struct ena_tx_buffer) * txq->ring_size, 144108180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 144208180833SMichal Krawczyk socket_id); 14431173fca2SJan Medala if (!txq->tx_buffer_info) { 1444617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1445617898d1SMichal Krawczyk "Failed to allocate memory for Tx buffer info\n"); 1446df238f84SMichal Krawczyk return -ENOMEM; 14471173fca2SJan Medala } 14481173fca2SJan Medala 144908180833SMichal Krawczyk txq->empty_tx_reqs = rte_zmalloc_socket("txq->empty_tx_reqs", 145008180833SMichal Krawczyk sizeof(uint16_t) * txq->ring_size, 145108180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 145208180833SMichal Krawczyk socket_id); 14531173fca2SJan Medala if (!txq->empty_tx_reqs) { 1454617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1455617898d1SMichal Krawczyk "Failed to allocate memory for empty Tx requests\n"); 1456df238f84SMichal Krawczyk rte_free(txq->tx_buffer_info); 1457df238f84SMichal Krawczyk return -ENOMEM; 14581173fca2SJan Medala } 1459241da076SRafal Kozik 14602fca2a98SMichal Krawczyk txq->push_buf_intermediate_buf = 146108180833SMichal Krawczyk rte_zmalloc_socket("txq->push_buf_intermediate_buf", 14622fca2a98SMichal Krawczyk txq->tx_max_header_size, 146308180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 146408180833SMichal Krawczyk socket_id); 14652fca2a98SMichal Krawczyk if (!txq->push_buf_intermediate_buf) { 1466617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to alloc push buffer for LLQ\n"); 14672fca2a98SMichal Krawczyk rte_free(txq->tx_buffer_info); 14682fca2a98SMichal Krawczyk rte_free(txq->empty_tx_reqs); 14692fca2a98SMichal Krawczyk return -ENOMEM; 14702fca2a98SMichal Krawczyk } 14712fca2a98SMichal Krawczyk 14721173fca2SJan Medala for (i = 0; i < txq->ring_size; i++) 14731173fca2SJan Medala txq->empty_tx_reqs[i] = i; 14741173fca2SJan Medala 1475005064e5SMichal Krawczyk txq->offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads; 1476005064e5SMichal Krawczyk 1477005064e5SMichal Krawczyk /* Check if caller provided the Tx cleanup threshold value. */ 1478005064e5SMichal Krawczyk if (tx_conf->tx_free_thresh != 0) { 1479005064e5SMichal Krawczyk txq->tx_free_thresh = tx_conf->tx_free_thresh; 1480005064e5SMichal Krawczyk } else { 1481005064e5SMichal Krawczyk dyn_thresh = txq->ring_size - 1482005064e5SMichal Krawczyk txq->ring_size / ENA_REFILL_THRESH_DIVIDER; 1483005064e5SMichal Krawczyk txq->tx_free_thresh = RTE_MAX(dyn_thresh, 1484005064e5SMichal Krawczyk txq->ring_size - ENA_REFILL_THRESH_PACKET); 14852081d5e2SMichal Krawczyk } 1486005064e5SMichal Krawczyk 1487f93e20e5SMichal Krawczyk txq->missing_tx_completion_threshold = 1488f93e20e5SMichal Krawczyk RTE_MIN(txq->ring_size / 2, ENA_DEFAULT_MISSING_COMP); 1489f93e20e5SMichal Krawczyk 14901173fca2SJan Medala /* Store pointer to this queue in upper layer */ 14911173fca2SJan Medala txq->configured = 1; 14921173fca2SJan Medala dev->data->tx_queues[queue_idx] = txq; 1493241da076SRafal Kozik 1494241da076SRafal Kozik return 0; 14951173fca2SJan Medala } 14961173fca2SJan Medala 14971173fca2SJan Medala static int ena_rx_queue_setup(struct rte_eth_dev *dev, 14981173fca2SJan Medala uint16_t queue_idx, 14991173fca2SJan Medala uint16_t nb_desc, 15004217cb0bSMichal Krawczyk unsigned int socket_id, 150134d5e97eSMichal Krawczyk const struct rte_eth_rxconf *rx_conf, 15021173fca2SJan Medala struct rte_mempool *mp) 15031173fca2SJan Medala { 1504890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 15051173fca2SJan Medala struct ena_ring *rxq = NULL; 150638364c26SMichal Krawczyk size_t buffer_size; 1507df238f84SMichal Krawczyk int i; 1508005064e5SMichal Krawczyk uint16_t dyn_thresh; 15091173fca2SJan Medala 15101173fca2SJan Medala rxq = &adapter->rx_ring[queue_idx]; 15111173fca2SJan Medala if (rxq->configured) { 15126f1c9df9SStephen Hemminger PMD_DRV_LOG(CRIT, 1513617898d1SMichal Krawczyk "API violation. Queue[%d] is already configured\n", 15141173fca2SJan Medala queue_idx); 1515241da076SRafal Kozik return ENA_COM_FAULT; 15161173fca2SJan Medala } 15171173fca2SJan Medala 15181daff526SJakub Palider if (!rte_is_power_of_2(nb_desc)) { 15196f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1520617898d1SMichal Krawczyk "Unsupported size of Rx queue: %d is not a power of 2.\n", 15211daff526SJakub Palider nb_desc); 15221daff526SJakub Palider return -EINVAL; 15231daff526SJakub Palider } 15241daff526SJakub Palider 15255920d930SMichal Krawczyk if (nb_desc > adapter->max_rx_ring_size) { 15266f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1527617898d1SMichal Krawczyk "Unsupported size of Rx queue (max size: %d)\n", 15285920d930SMichal Krawczyk adapter->max_rx_ring_size); 15291173fca2SJan Medala return -EINVAL; 15301173fca2SJan Medala } 15311173fca2SJan Medala 153238364c26SMichal Krawczyk /* ENA isn't supporting buffers smaller than 1400 bytes */ 153338364c26SMichal Krawczyk buffer_size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM; 153438364c26SMichal Krawczyk if (buffer_size < ENA_RX_BUF_MIN_SIZE) { 153538364c26SMichal Krawczyk PMD_DRV_LOG(ERR, 1536617898d1SMichal Krawczyk "Unsupported size of Rx buffer: %zu (min size: %d)\n", 153738364c26SMichal Krawczyk buffer_size, ENA_RX_BUF_MIN_SIZE); 153838364c26SMichal Krawczyk return -EINVAL; 153938364c26SMichal Krawczyk } 154038364c26SMichal Krawczyk 15411173fca2SJan Medala rxq->port_id = dev->data->port_id; 15421173fca2SJan Medala rxq->next_to_clean = 0; 15431173fca2SJan Medala rxq->next_to_use = 0; 15441173fca2SJan Medala rxq->ring_size = nb_desc; 1545c0006061SMichal Krawczyk rxq->size_mask = nb_desc - 1; 15464217cb0bSMichal Krawczyk rxq->numa_socket_id = socket_id; 15471173fca2SJan Medala rxq->mb_pool = mp; 15481173fca2SJan Medala 154908180833SMichal Krawczyk rxq->rx_buffer_info = rte_zmalloc_socket("rxq->buffer_info", 15501be097dcSMichal Krawczyk sizeof(struct ena_rx_buffer) * nb_desc, 155108180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 155208180833SMichal Krawczyk socket_id); 15531173fca2SJan Medala if (!rxq->rx_buffer_info) { 1554617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1555617898d1SMichal Krawczyk "Failed to allocate memory for Rx buffer info\n"); 15561173fca2SJan Medala return -ENOMEM; 15571173fca2SJan Medala } 15581173fca2SJan Medala 155908180833SMichal Krawczyk rxq->rx_refill_buffer = rte_zmalloc_socket("rxq->rx_refill_buffer", 156079405ee1SRafal Kozik sizeof(struct rte_mbuf *) * nb_desc, 156108180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 156208180833SMichal Krawczyk socket_id); 156379405ee1SRafal Kozik if (!rxq->rx_refill_buffer) { 1564617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1565617898d1SMichal Krawczyk "Failed to allocate memory for Rx refill buffer\n"); 156679405ee1SRafal Kozik rte_free(rxq->rx_buffer_info); 156779405ee1SRafal Kozik rxq->rx_buffer_info = NULL; 156879405ee1SRafal Kozik return -ENOMEM; 156979405ee1SRafal Kozik } 157079405ee1SRafal Kozik 157108180833SMichal Krawczyk rxq->empty_rx_reqs = rte_zmalloc_socket("rxq->empty_rx_reqs", 1572c2034976SMichal Krawczyk sizeof(uint16_t) * nb_desc, 157308180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 157408180833SMichal Krawczyk socket_id); 1575c2034976SMichal Krawczyk if (!rxq->empty_rx_reqs) { 1576617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 1577617898d1SMichal Krawczyk "Failed to allocate memory for empty Rx requests\n"); 1578c2034976SMichal Krawczyk rte_free(rxq->rx_buffer_info); 1579c2034976SMichal Krawczyk rxq->rx_buffer_info = NULL; 158079405ee1SRafal Kozik rte_free(rxq->rx_refill_buffer); 158179405ee1SRafal Kozik rxq->rx_refill_buffer = NULL; 1582c2034976SMichal Krawczyk return -ENOMEM; 1583c2034976SMichal Krawczyk } 1584c2034976SMichal Krawczyk 1585c2034976SMichal Krawczyk for (i = 0; i < nb_desc; i++) 1586eccbe2ffSRafal Kozik rxq->empty_rx_reqs[i] = i; 1587c2034976SMichal Krawczyk 158834d5e97eSMichal Krawczyk rxq->offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads; 158934d5e97eSMichal Krawczyk 1590005064e5SMichal Krawczyk if (rx_conf->rx_free_thresh != 0) { 1591005064e5SMichal Krawczyk rxq->rx_free_thresh = rx_conf->rx_free_thresh; 1592005064e5SMichal Krawczyk } else { 1593005064e5SMichal Krawczyk dyn_thresh = rxq->ring_size / ENA_REFILL_THRESH_DIVIDER; 1594005064e5SMichal Krawczyk rxq->rx_free_thresh = RTE_MIN(dyn_thresh, 1595005064e5SMichal Krawczyk (uint16_t)(ENA_REFILL_THRESH_PACKET)); 1596005064e5SMichal Krawczyk } 1597005064e5SMichal Krawczyk 15981173fca2SJan Medala /* Store pointer to this queue in upper layer */ 15991173fca2SJan Medala rxq->configured = 1; 16001173fca2SJan Medala dev->data->rx_queues[queue_idx] = rxq; 16011173fca2SJan Medala 1602df238f84SMichal Krawczyk return 0; 16031173fca2SJan Medala } 16041173fca2SJan Medala 160583fd97b2SMichal Krawczyk static int ena_add_single_rx_desc(struct ena_com_io_sq *io_sq, 160683fd97b2SMichal Krawczyk struct rte_mbuf *mbuf, uint16_t id) 160783fd97b2SMichal Krawczyk { 160883fd97b2SMichal Krawczyk struct ena_com_buf ebuf; 160983fd97b2SMichal Krawczyk int rc; 161083fd97b2SMichal Krawczyk 161183fd97b2SMichal Krawczyk /* prepare physical address for DMA transaction */ 161283fd97b2SMichal Krawczyk ebuf.paddr = mbuf->buf_iova + RTE_PKTMBUF_HEADROOM; 161383fd97b2SMichal Krawczyk ebuf.len = mbuf->buf_len - RTE_PKTMBUF_HEADROOM; 161483fd97b2SMichal Krawczyk 161583fd97b2SMichal Krawczyk /* pass resource to device */ 161683fd97b2SMichal Krawczyk rc = ena_com_add_single_rx_desc(io_sq, &ebuf, id); 161783fd97b2SMichal Krawczyk if (unlikely(rc != 0)) 16180a001d69SMichal Krawczyk PMD_RX_LOG(WARNING, "Failed adding Rx desc\n"); 161983fd97b2SMichal Krawczyk 162083fd97b2SMichal Krawczyk return rc; 162183fd97b2SMichal Krawczyk } 162283fd97b2SMichal Krawczyk 16231173fca2SJan Medala static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count) 16241173fca2SJan Medala { 16251173fca2SJan Medala unsigned int i; 16261173fca2SJan Medala int rc; 16271daff526SJakub Palider uint16_t next_to_use = rxq->next_to_use; 16280a001d69SMichal Krawczyk uint16_t req_id; 16290a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 16300a001d69SMichal Krawczyk uint16_t in_use; 16310a001d69SMichal Krawczyk #endif 163279405ee1SRafal Kozik struct rte_mbuf **mbufs = rxq->rx_refill_buffer; 16331173fca2SJan Medala 16341173fca2SJan Medala if (unlikely(!count)) 16351173fca2SJan Medala return 0; 16361173fca2SJan Medala 16370a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 1638c0006061SMichal Krawczyk in_use = rxq->ring_size - 1 - 1639c0006061SMichal Krawczyk ena_com_free_q_entries(rxq->ena_com_io_sq); 16400a001d69SMichal Krawczyk if (unlikely((in_use + count) >= rxq->ring_size)) 16410a001d69SMichal Krawczyk PMD_RX_LOG(ERR, "Bad Rx ring state\n"); 16420a001d69SMichal Krawczyk #endif 16431173fca2SJan Medala 16441173fca2SJan Medala /* get resources for incoming packets */ 16453c8bc29fSDavid Harton rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, count); 16461173fca2SJan Medala if (unlikely(rc < 0)) { 16471173fca2SJan Medala rte_atomic64_inc(&rxq->adapter->drv_stats->rx_nombuf); 16487830e905SSolganik Alexander ++rxq->rx_stats.mbuf_alloc_fail; 1649617898d1SMichal Krawczyk PMD_RX_LOG(DEBUG, "There are not enough free buffers\n"); 16501173fca2SJan Medala return 0; 16511173fca2SJan Medala } 16521173fca2SJan Medala 16531173fca2SJan Medala for (i = 0; i < count; i++) { 165479405ee1SRafal Kozik struct rte_mbuf *mbuf = mbufs[i]; 16551be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info; 16561173fca2SJan Medala 165779405ee1SRafal Kozik if (likely((i + 4) < count)) 165879405ee1SRafal Kozik rte_prefetch0(mbufs[i + 4]); 1659c2034976SMichal Krawczyk 1660c0006061SMichal Krawczyk req_id = rxq->empty_rx_reqs[next_to_use]; 16611be097dcSMichal Krawczyk rx_info = &rxq->rx_buffer_info[req_id]; 1662241da076SRafal Kozik 166383fd97b2SMichal Krawczyk rc = ena_add_single_rx_desc(rxq->ena_com_io_sq, mbuf, req_id); 166483fd97b2SMichal Krawczyk if (unlikely(rc != 0)) 16651173fca2SJan Medala break; 166683fd97b2SMichal Krawczyk 16671be097dcSMichal Krawczyk rx_info->mbuf = mbuf; 1668c0006061SMichal Krawczyk next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, rxq->size_mask); 16691173fca2SJan Medala } 16701173fca2SJan Medala 167179405ee1SRafal Kozik if (unlikely(i < count)) { 16720a001d69SMichal Krawczyk PMD_RX_LOG(WARNING, 1673617898d1SMichal Krawczyk "Refilled Rx queue[%d] with only %d/%d buffers\n", 1674617898d1SMichal Krawczyk rxq->id, i, count); 16753c8bc29fSDavid Harton rte_pktmbuf_free_bulk(&mbufs[i], count - i); 16767830e905SSolganik Alexander ++rxq->rx_stats.refill_partial; 167779405ee1SRafal Kozik } 1678241da076SRafal Kozik 16797be78d02SJosh Soref /* When we submitted free resources to device... */ 16803d19e1abSRafal Kozik if (likely(i > 0)) { 168138faa87eSMichal Krawczyk /* ...let HW know that it can fill buffers with data. */ 16821173fca2SJan Medala ena_com_write_sq_doorbell(rxq->ena_com_io_sq); 16831173fca2SJan Medala 16845e02e19eSJan Medala rxq->next_to_use = next_to_use; 16855e02e19eSJan Medala } 16865e02e19eSJan Medala 16871173fca2SJan Medala return i; 16881173fca2SJan Medala } 16891173fca2SJan Medala 1690b9b05d6fSMichal Krawczyk static int ena_device_init(struct ena_adapter *adapter, 1691aab58857SStanislaw Kardach struct rte_pci_device *pdev, 1692b9b05d6fSMichal Krawczyk struct ena_com_dev_get_features_ctx *get_feat_ctx) 16931173fca2SJan Medala { 1694b9b05d6fSMichal Krawczyk struct ena_com_dev *ena_dev = &adapter->ena_dev; 1695ca148440SMichal Krawczyk uint32_t aenq_groups; 16961173fca2SJan Medala int rc; 1697c4144557SJan Medala bool readless_supported; 16981173fca2SJan Medala 16991173fca2SJan Medala /* Initialize mmio registers */ 17001173fca2SJan Medala rc = ena_com_mmio_reg_read_request_init(ena_dev); 17011173fca2SJan Medala if (rc) { 1702617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to init MMIO read less\n"); 17031173fca2SJan Medala return rc; 17041173fca2SJan Medala } 17051173fca2SJan Medala 1706c4144557SJan Medala /* The PCIe configuration space revision id indicate if mmio reg 1707c4144557SJan Medala * read is disabled. 1708c4144557SJan Medala */ 1709aab58857SStanislaw Kardach readless_supported = !(pdev->id.class_id & ENA_MMIO_DISABLE_REG_READ); 1710c4144557SJan Medala ena_com_set_mmio_read_mode(ena_dev, readless_supported); 1711c4144557SJan Medala 17121173fca2SJan Medala /* reset device */ 17133adcba9aSMichal Krawczyk rc = ena_com_dev_reset(ena_dev, ENA_REGS_RESET_NORMAL); 17141173fca2SJan Medala if (rc) { 1715617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Cannot reset device\n"); 17161173fca2SJan Medala goto err_mmio_read_less; 17171173fca2SJan Medala } 17181173fca2SJan Medala 17191173fca2SJan Medala /* check FW version */ 17201173fca2SJan Medala rc = ena_com_validate_version(ena_dev); 17211173fca2SJan Medala if (rc) { 1722617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Device version is too low\n"); 17231173fca2SJan Medala goto err_mmio_read_less; 17241173fca2SJan Medala } 17251173fca2SJan Medala 17261173fca2SJan Medala ena_dev->dma_addr_bits = ena_com_get_dma_width(ena_dev); 17271173fca2SJan Medala 17281173fca2SJan Medala /* ENA device administration layer init */ 1729b68309beSRafal Kozik rc = ena_com_admin_init(ena_dev, &aenq_handlers); 17301173fca2SJan Medala if (rc) { 17316f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1732617898d1SMichal Krawczyk "Cannot initialize ENA admin queue\n"); 17331173fca2SJan Medala goto err_mmio_read_less; 17341173fca2SJan Medala } 17351173fca2SJan Medala 17361173fca2SJan Medala /* To enable the msix interrupts the driver needs to know the number 17371173fca2SJan Medala * of queues. So the driver uses polling mode to retrieve this 17381173fca2SJan Medala * information. 17391173fca2SJan Medala */ 17401173fca2SJan Medala ena_com_set_admin_polling_mode(ena_dev, true); 17411173fca2SJan Medala 1742201ff2e5SJakub Palider ena_config_host_info(ena_dev); 1743201ff2e5SJakub Palider 17441173fca2SJan Medala /* Get Device Attributes and features */ 17451173fca2SJan Medala rc = ena_com_get_dev_attr_feat(ena_dev, get_feat_ctx); 17461173fca2SJan Medala if (rc) { 17476f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, 1748617898d1SMichal Krawczyk "Cannot get attribute for ENA device, rc: %d\n", rc); 17491173fca2SJan Medala goto err_admin_init; 17501173fca2SJan Medala } 17511173fca2SJan Medala 1752f01f060cSRafal Kozik aenq_groups = BIT(ENA_ADMIN_LINK_CHANGE) | 1753d9b8b106SMichal Krawczyk BIT(ENA_ADMIN_NOTIFICATION) | 1754983cce2dSRafal Kozik BIT(ENA_ADMIN_KEEP_ALIVE) | 1755983cce2dSRafal Kozik BIT(ENA_ADMIN_FATAL_ERROR) | 1756983cce2dSRafal Kozik BIT(ENA_ADMIN_WARNING); 1757ca148440SMichal Krawczyk 1758ca148440SMichal Krawczyk aenq_groups &= get_feat_ctx->aenq.supported_groups; 1759ca148440SMichal Krawczyk 1760b9b05d6fSMichal Krawczyk adapter->all_aenq_groups = aenq_groups; 1761e859d2b8SRafal Kozik 17621173fca2SJan Medala return 0; 17631173fca2SJan Medala 17641173fca2SJan Medala err_admin_init: 17651173fca2SJan Medala ena_com_admin_destroy(ena_dev); 17661173fca2SJan Medala 17671173fca2SJan Medala err_mmio_read_less: 17681173fca2SJan Medala ena_com_mmio_reg_read_request_destroy(ena_dev); 17691173fca2SJan Medala 17701173fca2SJan Medala return rc; 17711173fca2SJan Medala } 17721173fca2SJan Medala 1773ca148440SMichal Krawczyk static void ena_interrupt_handler_rte(void *cb_arg) 177415773e06SMichal Krawczyk { 1775aab58857SStanislaw Kardach struct rte_eth_dev *dev = cb_arg; 1776aab58857SStanislaw Kardach struct ena_adapter *adapter = dev->data->dev_private; 177715773e06SMichal Krawczyk struct ena_com_dev *ena_dev = &adapter->ena_dev; 177815773e06SMichal Krawczyk 177915773e06SMichal Krawczyk ena_com_admin_q_comp_intr_handler(ena_dev); 17803d19e1abSRafal Kozik if (likely(adapter->state != ENA_ADAPTER_STATE_CLOSED)) 1781aab58857SStanislaw Kardach ena_com_aenq_intr_handler(ena_dev, dev); 178215773e06SMichal Krawczyk } 178315773e06SMichal Krawczyk 17845efb9fc7SMichal Krawczyk static void check_for_missing_keep_alive(struct ena_adapter *adapter) 17855efb9fc7SMichal Krawczyk { 1786b9b05d6fSMichal Krawczyk if (!(adapter->active_aenq_groups & BIT(ENA_ADMIN_KEEP_ALIVE))) 1787e859d2b8SRafal Kozik return; 1788e859d2b8SRafal Kozik 17895efb9fc7SMichal Krawczyk if (adapter->keep_alive_timeout == ENA_HW_HINTS_NO_TIMEOUT) 17905efb9fc7SMichal Krawczyk return; 17915efb9fc7SMichal Krawczyk 17925efb9fc7SMichal Krawczyk if (unlikely((rte_get_timer_cycles() - adapter->timestamp_wd) >= 17935efb9fc7SMichal Krawczyk adapter->keep_alive_timeout)) { 17946f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Keep alive timeout\n"); 17952bae75eaSDawid Gorecki ena_trigger_reset(adapter, ENA_REGS_RESET_KEEP_ALIVE_TO); 17967830e905SSolganik Alexander ++adapter->dev_stats.wd_expired; 17975efb9fc7SMichal Krawczyk } 17985efb9fc7SMichal Krawczyk } 17995efb9fc7SMichal Krawczyk 18005efb9fc7SMichal Krawczyk /* Check if admin queue is enabled */ 18015efb9fc7SMichal Krawczyk static void check_for_admin_com_state(struct ena_adapter *adapter) 18025efb9fc7SMichal Krawczyk { 18035efb9fc7SMichal Krawczyk if (unlikely(!ena_com_get_admin_running_state(&adapter->ena_dev))) { 1804617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "ENA admin queue is not in running state\n"); 18052bae75eaSDawid Gorecki ena_trigger_reset(adapter, ENA_REGS_RESET_ADMIN_TO); 18065efb9fc7SMichal Krawczyk } 18075efb9fc7SMichal Krawczyk } 18085efb9fc7SMichal Krawczyk 1809f93e20e5SMichal Krawczyk static int check_for_tx_completion_in_queue(struct ena_adapter *adapter, 1810f93e20e5SMichal Krawczyk struct ena_ring *tx_ring) 1811f93e20e5SMichal Krawczyk { 1812f93e20e5SMichal Krawczyk struct ena_tx_buffer *tx_buf; 1813f93e20e5SMichal Krawczyk uint64_t timestamp; 1814f93e20e5SMichal Krawczyk uint64_t completion_delay; 1815f93e20e5SMichal Krawczyk uint32_t missed_tx = 0; 1816f93e20e5SMichal Krawczyk unsigned int i; 1817f93e20e5SMichal Krawczyk int rc = 0; 1818f93e20e5SMichal Krawczyk 1819f93e20e5SMichal Krawczyk for (i = 0; i < tx_ring->ring_size; ++i) { 1820f93e20e5SMichal Krawczyk tx_buf = &tx_ring->tx_buffer_info[i]; 1821f93e20e5SMichal Krawczyk timestamp = tx_buf->timestamp; 1822f93e20e5SMichal Krawczyk 1823f93e20e5SMichal Krawczyk if (timestamp == 0) 1824f93e20e5SMichal Krawczyk continue; 1825f93e20e5SMichal Krawczyk 1826f93e20e5SMichal Krawczyk completion_delay = rte_get_timer_cycles() - timestamp; 1827f93e20e5SMichal Krawczyk if (completion_delay > adapter->missing_tx_completion_to) { 1828f93e20e5SMichal Krawczyk if (unlikely(!tx_buf->print_once)) { 1829f93e20e5SMichal Krawczyk PMD_TX_LOG(WARNING, 1830f93e20e5SMichal Krawczyk "Found a Tx that wasn't completed on time, qid %d, index %d. " 1831f93e20e5SMichal Krawczyk "Missing Tx outstanding for %" PRIu64 " msecs.\n", 1832f93e20e5SMichal Krawczyk tx_ring->id, i, completion_delay / 1833f93e20e5SMichal Krawczyk rte_get_timer_hz() * 1000); 1834f93e20e5SMichal Krawczyk tx_buf->print_once = true; 1835f93e20e5SMichal Krawczyk } 1836f93e20e5SMichal Krawczyk ++missed_tx; 1837f93e20e5SMichal Krawczyk } 1838f93e20e5SMichal Krawczyk } 1839f93e20e5SMichal Krawczyk 1840f93e20e5SMichal Krawczyk if (unlikely(missed_tx > tx_ring->missing_tx_completion_threshold)) { 1841f93e20e5SMichal Krawczyk PMD_DRV_LOG(ERR, 1842f93e20e5SMichal Krawczyk "The number of lost Tx completions is above the threshold (%d > %d). " 1843f93e20e5SMichal Krawczyk "Trigger the device reset.\n", 1844f93e20e5SMichal Krawczyk missed_tx, 1845f93e20e5SMichal Krawczyk tx_ring->missing_tx_completion_threshold); 1846f93e20e5SMichal Krawczyk adapter->reset_reason = ENA_REGS_RESET_MISS_TX_CMPL; 1847f93e20e5SMichal Krawczyk adapter->trigger_reset = true; 1848f93e20e5SMichal Krawczyk rc = -EIO; 1849f93e20e5SMichal Krawczyk } 1850f93e20e5SMichal Krawczyk 1851f93e20e5SMichal Krawczyk tx_ring->tx_stats.missed_tx += missed_tx; 1852f93e20e5SMichal Krawczyk 1853f93e20e5SMichal Krawczyk return rc; 1854f93e20e5SMichal Krawczyk } 1855f93e20e5SMichal Krawczyk 1856f93e20e5SMichal Krawczyk static void check_for_tx_completions(struct ena_adapter *adapter) 1857f93e20e5SMichal Krawczyk { 1858f93e20e5SMichal Krawczyk struct ena_ring *tx_ring; 1859f93e20e5SMichal Krawczyk uint64_t tx_cleanup_delay; 1860f93e20e5SMichal Krawczyk size_t qid; 1861f93e20e5SMichal Krawczyk int budget; 1862f93e20e5SMichal Krawczyk uint16_t nb_tx_queues = adapter->edev_data->nb_tx_queues; 1863f93e20e5SMichal Krawczyk 1864f93e20e5SMichal Krawczyk if (adapter->missing_tx_completion_to == ENA_HW_HINTS_NO_TIMEOUT) 1865f93e20e5SMichal Krawczyk return; 1866f93e20e5SMichal Krawczyk 1867f93e20e5SMichal Krawczyk nb_tx_queues = adapter->edev_data->nb_tx_queues; 1868f93e20e5SMichal Krawczyk budget = adapter->missing_tx_completion_budget; 1869f93e20e5SMichal Krawczyk 1870f93e20e5SMichal Krawczyk qid = adapter->last_tx_comp_qid; 1871f93e20e5SMichal Krawczyk while (budget-- > 0) { 1872f93e20e5SMichal Krawczyk tx_ring = &adapter->tx_ring[qid]; 1873f93e20e5SMichal Krawczyk 1874f93e20e5SMichal Krawczyk /* Tx cleanup is called only by the burst function and can be 1875f93e20e5SMichal Krawczyk * called dynamically by the application. Also cleanup is 1876f93e20e5SMichal Krawczyk * limited by the threshold. To avoid false detection of the 1877f93e20e5SMichal Krawczyk * missing HW Tx completion, get the delay since last cleanup 1878f93e20e5SMichal Krawczyk * function was called. 1879f93e20e5SMichal Krawczyk */ 1880f93e20e5SMichal Krawczyk tx_cleanup_delay = rte_get_timer_cycles() - 1881f93e20e5SMichal Krawczyk tx_ring->last_cleanup_ticks; 1882f93e20e5SMichal Krawczyk if (tx_cleanup_delay < adapter->tx_cleanup_stall_delay) 1883f93e20e5SMichal Krawczyk check_for_tx_completion_in_queue(adapter, tx_ring); 1884f93e20e5SMichal Krawczyk qid = (qid + 1) % nb_tx_queues; 1885f93e20e5SMichal Krawczyk } 1886f93e20e5SMichal Krawczyk 1887f93e20e5SMichal Krawczyk adapter->last_tx_comp_qid = qid; 1888f93e20e5SMichal Krawczyk } 1889f93e20e5SMichal Krawczyk 1890d9b8b106SMichal Krawczyk static void ena_timer_wd_callback(__rte_unused struct rte_timer *timer, 1891d9b8b106SMichal Krawczyk void *arg) 1892d9b8b106SMichal Krawczyk { 1893aab58857SStanislaw Kardach struct rte_eth_dev *dev = arg; 1894aab58857SStanislaw Kardach struct ena_adapter *adapter = dev->data->dev_private; 1895d9b8b106SMichal Krawczyk 1896e2174a54SMichal Krawczyk if (unlikely(adapter->trigger_reset)) 1897e2174a54SMichal Krawczyk return; 1898e2174a54SMichal Krawczyk 18995efb9fc7SMichal Krawczyk check_for_missing_keep_alive(adapter); 19005efb9fc7SMichal Krawczyk check_for_admin_com_state(adapter); 1901f93e20e5SMichal Krawczyk check_for_tx_completions(adapter); 1902d9b8b106SMichal Krawczyk 19035efb9fc7SMichal Krawczyk if (unlikely(adapter->trigger_reset)) { 19046f1c9df9SStephen Hemminger PMD_DRV_LOG(ERR, "Trigger reset is on\n"); 19055723fbedSFerruh Yigit rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, 1906d9b8b106SMichal Krawczyk NULL); 1907d9b8b106SMichal Krawczyk } 1908d9b8b106SMichal Krawczyk } 1909d9b8b106SMichal Krawczyk 19102fca2a98SMichal Krawczyk static inline void 19118a7a73f2SMichal Krawczyk set_default_llq_configurations(struct ena_llq_configurations *llq_config, 19128a7a73f2SMichal Krawczyk struct ena_admin_feature_llq_desc *llq, 19138a7a73f2SMichal Krawczyk bool use_large_llq_hdr) 19142fca2a98SMichal Krawczyk { 19152fca2a98SMichal Krawczyk llq_config->llq_header_location = ENA_ADMIN_INLINE_HEADER; 19162fca2a98SMichal Krawczyk llq_config->llq_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY; 19172fca2a98SMichal Krawczyk llq_config->llq_num_decs_before_header = 19182fca2a98SMichal Krawczyk ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2; 19198a7a73f2SMichal Krawczyk 19208a7a73f2SMichal Krawczyk if (use_large_llq_hdr && 19218a7a73f2SMichal Krawczyk (llq->entry_size_ctrl_supported & ENA_ADMIN_LIST_ENTRY_SIZE_256B)) { 19228a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size = 19238a7a73f2SMichal Krawczyk ENA_ADMIN_LIST_ENTRY_SIZE_256B; 19248a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size_value = 256; 19258a7a73f2SMichal Krawczyk } else { 19268a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size = 19278a7a73f2SMichal Krawczyk ENA_ADMIN_LIST_ENTRY_SIZE_128B; 19282fca2a98SMichal Krawczyk llq_config->llq_ring_entry_size_value = 128; 19292fca2a98SMichal Krawczyk } 19308a7a73f2SMichal Krawczyk } 19312fca2a98SMichal Krawczyk 19322fca2a98SMichal Krawczyk static int 19332fca2a98SMichal Krawczyk ena_set_queues_placement_policy(struct ena_adapter *adapter, 19342fca2a98SMichal Krawczyk struct ena_com_dev *ena_dev, 19352fca2a98SMichal Krawczyk struct ena_admin_feature_llq_desc *llq, 19362fca2a98SMichal Krawczyk struct ena_llq_configurations *llq_default_configurations) 19372fca2a98SMichal Krawczyk { 19382fca2a98SMichal Krawczyk int rc; 19392fca2a98SMichal Krawczyk u32 llq_feature_mask; 19402fca2a98SMichal Krawczyk 1941*9944919eSMichal Krawczyk if (!adapter->enable_llq) { 1942*9944919eSMichal Krawczyk PMD_DRV_LOG(WARNING, 1943*9944919eSMichal Krawczyk "NOTE: LLQ has been disabled as per user's request. " 1944*9944919eSMichal Krawczyk "This may lead to a huge performance degradation!\n"); 1945*9944919eSMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 1946*9944919eSMichal Krawczyk return 0; 1947*9944919eSMichal Krawczyk } 1948*9944919eSMichal Krawczyk 19492fca2a98SMichal Krawczyk llq_feature_mask = 1 << ENA_ADMIN_LLQ; 19502fca2a98SMichal Krawczyk if (!(ena_dev->supported_features & llq_feature_mask)) { 19516f1c9df9SStephen Hemminger PMD_DRV_LOG(INFO, 19522fca2a98SMichal Krawczyk "LLQ is not supported. Fallback to host mode policy.\n"); 19532fca2a98SMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 19542fca2a98SMichal Krawczyk return 0; 19552fca2a98SMichal Krawczyk } 19562fca2a98SMichal Krawczyk 19579ae7a13fSDawid Gorecki if (adapter->dev_mem_base == NULL) { 19589ae7a13fSDawid Gorecki PMD_DRV_LOG(ERR, 19599ae7a13fSDawid Gorecki "LLQ is advertised as supported, but device doesn't expose mem bar\n"); 19609ae7a13fSDawid Gorecki ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 19619ae7a13fSDawid Gorecki return 0; 19629ae7a13fSDawid Gorecki } 19639ae7a13fSDawid Gorecki 19642fca2a98SMichal Krawczyk rc = ena_com_config_dev_mode(ena_dev, llq, llq_default_configurations); 19652fca2a98SMichal Krawczyk if (unlikely(rc)) { 1966617898d1SMichal Krawczyk PMD_INIT_LOG(WARNING, 1967617898d1SMichal Krawczyk "Failed to config dev mode. Fallback to host mode policy.\n"); 19682fca2a98SMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 19692fca2a98SMichal Krawczyk return 0; 19702fca2a98SMichal Krawczyk } 19712fca2a98SMichal Krawczyk 19722fca2a98SMichal Krawczyk /* Nothing to config, exit */ 19732fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) 19742fca2a98SMichal Krawczyk return 0; 19752fca2a98SMichal Krawczyk 19762fca2a98SMichal Krawczyk ena_dev->mem_bar = adapter->dev_mem_base; 19772fca2a98SMichal Krawczyk 19782fca2a98SMichal Krawczyk return 0; 19792fca2a98SMichal Krawczyk } 19802fca2a98SMichal Krawczyk 19815920d930SMichal Krawczyk static uint32_t ena_calc_max_io_queue_num(struct ena_com_dev *ena_dev, 198201bd6877SRafal Kozik struct ena_com_dev_get_features_ctx *get_feat_ctx) 198301bd6877SRafal Kozik { 19845920d930SMichal Krawczyk uint32_t io_tx_sq_num, io_tx_cq_num, io_rx_num, max_num_io_queues; 198501bd6877SRafal Kozik 1986ea93d37eSRafal Kozik /* Regular queues capabilities */ 1987ea93d37eSRafal Kozik if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) { 1988ea93d37eSRafal Kozik struct ena_admin_queue_ext_feature_fields *max_queue_ext = 1989ea93d37eSRafal Kozik &get_feat_ctx->max_queue_ext.max_queue_ext; 19902fca2a98SMichal Krawczyk io_rx_num = RTE_MIN(max_queue_ext->max_rx_sq_num, 19912fca2a98SMichal Krawczyk max_queue_ext->max_rx_cq_num); 19922fca2a98SMichal Krawczyk io_tx_sq_num = max_queue_ext->max_tx_sq_num; 19932fca2a98SMichal Krawczyk io_tx_cq_num = max_queue_ext->max_tx_cq_num; 1994ea93d37eSRafal Kozik } else { 1995ea93d37eSRafal Kozik struct ena_admin_queue_feature_desc *max_queues = 1996ea93d37eSRafal Kozik &get_feat_ctx->max_queues; 19972fca2a98SMichal Krawczyk io_tx_sq_num = max_queues->max_sq_num; 19982fca2a98SMichal Krawczyk io_tx_cq_num = max_queues->max_cq_num; 19992fca2a98SMichal Krawczyk io_rx_num = RTE_MIN(io_tx_sq_num, io_tx_cq_num); 2000ea93d37eSRafal Kozik } 200101bd6877SRafal Kozik 20022fca2a98SMichal Krawczyk /* In case of LLQ use the llq number in the get feature cmd */ 20032fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) 20042fca2a98SMichal Krawczyk io_tx_sq_num = get_feat_ctx->llq.max_llq_num; 20052fca2a98SMichal Krawczyk 20065920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(ENA_MAX_NUM_IO_QUEUES, io_rx_num); 20075920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(max_num_io_queues, io_tx_sq_num); 20085920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(max_num_io_queues, io_tx_cq_num); 200901bd6877SRafal Kozik 20105920d930SMichal Krawczyk if (unlikely(max_num_io_queues == 0)) { 2011617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Number of IO queues cannot not be 0\n"); 201201bd6877SRafal Kozik return -EFAULT; 201301bd6877SRafal Kozik } 201401bd6877SRafal Kozik 20155920d930SMichal Krawczyk return max_num_io_queues; 201601bd6877SRafal Kozik } 201701bd6877SRafal Kozik 2018e8c838fdSMichal Krawczyk static void 2019e8c838fdSMichal Krawczyk ena_set_offloads(struct ena_offloads *offloads, 2020e8c838fdSMichal Krawczyk struct ena_admin_feature_offload_desc *offload_desc) 2021e8c838fdSMichal Krawczyk { 2022e8c838fdSMichal Krawczyk if (offload_desc->tx & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TSO_IPV4_MASK) 2023e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_IPV4_TSO; 2024e8c838fdSMichal Krawczyk 2025e8c838fdSMichal Krawczyk /* Tx IPv4 checksum offloads */ 2026e8c838fdSMichal Krawczyk if (offload_desc->tx & 2027e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L3_CSUM_IPV4_MASK) 2028e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L3_IPV4_CSUM; 2029e8c838fdSMichal Krawczyk if (offload_desc->tx & 2030e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_FULL_MASK) 2031e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV4_CSUM; 2032e8c838fdSMichal Krawczyk if (offload_desc->tx & 2033e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_PART_MASK) 2034e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV4_CSUM_PARTIAL; 2035e8c838fdSMichal Krawczyk 2036e8c838fdSMichal Krawczyk /* Tx IPv6 checksum offloads */ 2037e8c838fdSMichal Krawczyk if (offload_desc->tx & 2038e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_FULL_MASK) 2039e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV6_CSUM; 2040e8c838fdSMichal Krawczyk if (offload_desc->tx & 2041e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_PART_MASK) 2042e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV6_CSUM_PARTIAL; 2043e8c838fdSMichal Krawczyk 2044e8c838fdSMichal Krawczyk /* Rx IPv4 checksum offloads */ 2045e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 2046e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L3_CSUM_IPV4_MASK) 2047e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L3_IPV4_CSUM; 2048e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 2049e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV4_CSUM_MASK) 2050e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L4_IPV4_CSUM; 2051e8c838fdSMichal Krawczyk 2052e8c838fdSMichal Krawczyk /* Rx IPv6 checksum offloads */ 2053e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 2054e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV6_CSUM_MASK) 2055e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L4_IPV6_CSUM; 2056e8c838fdSMichal Krawczyk 2057e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 2058e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_HASH_MASK) 2059e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_RX_RSS_HASH; 2060e8c838fdSMichal Krawczyk } 2061e8c838fdSMichal Krawczyk 2062e3595539SStanislaw Kardach static int ena_init_once(void) 2063e3595539SStanislaw Kardach { 2064e3595539SStanislaw Kardach static bool init_done; 2065e3595539SStanislaw Kardach 2066e3595539SStanislaw Kardach if (init_done) 2067e3595539SStanislaw Kardach return 0; 2068e3595539SStanislaw Kardach 2069e3595539SStanislaw Kardach if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 2070e3595539SStanislaw Kardach /* Init timer subsystem for the ENA timer service. */ 2071e3595539SStanislaw Kardach rte_timer_subsystem_init(); 2072e3595539SStanislaw Kardach /* Register handler for requests from secondary processes. */ 2073e3595539SStanislaw Kardach rte_mp_action_register(ENA_MP_NAME, ena_mp_primary_handle); 2074e3595539SStanislaw Kardach } 2075e3595539SStanislaw Kardach 2076e3595539SStanislaw Kardach init_done = true; 2077e3595539SStanislaw Kardach return 0; 2078e3595539SStanislaw Kardach } 2079e3595539SStanislaw Kardach 20801173fca2SJan Medala static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) 20811173fca2SJan Medala { 2082ea93d37eSRafal Kozik struct ena_calc_queue_size_ctx calc_queue_ctx = { 0 }; 20831173fca2SJan Medala struct rte_pci_device *pci_dev; 2084eb0ef49dSMichal Krawczyk struct rte_intr_handle *intr_handle; 2085890728ffSStephen Hemminger struct ena_adapter *adapter = eth_dev->data->dev_private; 20861173fca2SJan Medala struct ena_com_dev *ena_dev = &adapter->ena_dev; 20871173fca2SJan Medala struct ena_com_dev_get_features_ctx get_feat_ctx; 20882fca2a98SMichal Krawczyk struct ena_llq_configurations llq_config; 20892fca2a98SMichal Krawczyk const char *queue_type_str; 20905920d930SMichal Krawczyk uint32_t max_num_io_queues; 2091ea93d37eSRafal Kozik int rc; 20921173fca2SJan Medala static int adapters_found; 209333dde075SMichal Krawczyk bool disable_meta_caching; 20941173fca2SJan Medala 20951173fca2SJan Medala eth_dev->dev_ops = &ena_dev_ops; 20961173fca2SJan Medala eth_dev->rx_pkt_burst = ð_ena_recv_pkts; 20971173fca2SJan Medala eth_dev->tx_pkt_burst = ð_ena_xmit_pkts; 2098b3fc5a1aSKonstantin Ananyev eth_dev->tx_pkt_prepare = ð_ena_prep_pkts; 20991173fca2SJan Medala 2100e3595539SStanislaw Kardach rc = ena_init_once(); 2101e3595539SStanislaw Kardach if (rc != 0) 2102e3595539SStanislaw Kardach return rc; 2103e3595539SStanislaw Kardach 21041173fca2SJan Medala if (rte_eal_process_type() != RTE_PROC_PRIMARY) 21051173fca2SJan Medala return 0; 21061173fca2SJan Medala 2107f30e69b4SFerruh Yigit eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 2108f30e69b4SFerruh Yigit 2109fd976890SMichal Krawczyk memset(adapter, 0, sizeof(struct ena_adapter)); 2110fd976890SMichal Krawczyk ena_dev = &adapter->ena_dev; 2111fd976890SMichal Krawczyk 2112aab58857SStanislaw Kardach adapter->edev_data = eth_dev->data; 2113fd976890SMichal Krawczyk 2114c0802544SFerruh Yigit pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 21151173fca2SJan Medala 2116617898d1SMichal Krawczyk PMD_INIT_LOG(INFO, "Initializing %x:%x:%x.%d\n", 21171173fca2SJan Medala pci_dev->addr.domain, 21181173fca2SJan Medala pci_dev->addr.bus, 21191173fca2SJan Medala pci_dev->addr.devid, 21201173fca2SJan Medala pci_dev->addr.function); 21211173fca2SJan Medala 2122d61138d4SHarman Kalra intr_handle = pci_dev->intr_handle; 2123eb0ef49dSMichal Krawczyk 21241173fca2SJan Medala adapter->regs = pci_dev->mem_resource[ENA_REGS_BAR].addr; 21251173fca2SJan Medala adapter->dev_mem_base = pci_dev->mem_resource[ENA_MEM_BAR].addr; 21261173fca2SJan Medala 21271d339597SRafal Kozik if (!adapter->regs) { 2128617898d1SMichal Krawczyk PMD_INIT_LOG(CRIT, "Failed to access registers BAR(%d)\n", 21291173fca2SJan Medala ENA_REGS_BAR); 21301d339597SRafal Kozik return -ENXIO; 21311d339597SRafal Kozik } 21321173fca2SJan Medala 21331173fca2SJan Medala ena_dev->reg_bar = adapter->regs; 2134850e1bb1SMichal Krawczyk /* Pass device data as a pointer which can be passed to the IO functions 2135850e1bb1SMichal Krawczyk * by the ena_com (for example - the memory allocation). 2136850e1bb1SMichal Krawczyk */ 2137850e1bb1SMichal Krawczyk ena_dev->dmadev = eth_dev->data; 21381173fca2SJan Medala 21391173fca2SJan Medala adapter->id_number = adapters_found; 21401173fca2SJan Medala 21411173fca2SJan Medala snprintf(adapter->name, ENA_NAME_MAX_LEN, "ena_%d", 21421173fca2SJan Medala adapter->id_number); 21431173fca2SJan Medala 2144*9944919eSMichal Krawczyk /* Assign default devargs values */ 2145cc0c5d25SMichal Krawczyk adapter->missing_tx_completion_to = ENA_TX_TIMEOUT; 2146*9944919eSMichal Krawczyk adapter->enable_llq = true; 2147*9944919eSMichal Krawczyk adapter->use_large_llq_hdr = false; 2148cc0c5d25SMichal Krawczyk 21498a7a73f2SMichal Krawczyk rc = ena_parse_devargs(adapter, pci_dev->device.devargs); 21508a7a73f2SMichal Krawczyk if (rc != 0) { 21518a7a73f2SMichal Krawczyk PMD_INIT_LOG(CRIT, "Failed to parse devargs\n"); 21528a7a73f2SMichal Krawczyk goto err; 21538a7a73f2SMichal Krawczyk } 21548a7a73f2SMichal Krawczyk 21551173fca2SJan Medala /* device specific initialization routine */ 2156b9b05d6fSMichal Krawczyk rc = ena_device_init(adapter, pci_dev, &get_feat_ctx); 21571173fca2SJan Medala if (rc) { 2158617898d1SMichal Krawczyk PMD_INIT_LOG(CRIT, "Failed to init ENA device\n"); 2159241da076SRafal Kozik goto err; 21601173fca2SJan Medala } 2161b9b05d6fSMichal Krawczyk 2162b9b05d6fSMichal Krawczyk /* Check if device supports LSC */ 2163b9b05d6fSMichal Krawczyk if (!(adapter->all_aenq_groups & BIT(ENA_ADMIN_LINK_CHANGE))) 2164b9b05d6fSMichal Krawczyk adapter->edev_data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC; 21651173fca2SJan Medala 21668a7a73f2SMichal Krawczyk set_default_llq_configurations(&llq_config, &get_feat_ctx.llq, 21678a7a73f2SMichal Krawczyk adapter->use_large_llq_hdr); 21682fca2a98SMichal Krawczyk rc = ena_set_queues_placement_policy(adapter, ena_dev, 21692fca2a98SMichal Krawczyk &get_feat_ctx.llq, &llq_config); 21702fca2a98SMichal Krawczyk if (unlikely(rc)) { 2171617898d1SMichal Krawczyk PMD_INIT_LOG(CRIT, "Failed to set placement policy\n"); 21722fca2a98SMichal Krawczyk return rc; 21732fca2a98SMichal Krawczyk } 21742fca2a98SMichal Krawczyk 21752fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) 21762fca2a98SMichal Krawczyk queue_type_str = "Regular"; 21772fca2a98SMichal Krawczyk else 21782fca2a98SMichal Krawczyk queue_type_str = "Low latency"; 21796f1c9df9SStephen Hemminger PMD_DRV_LOG(INFO, "Placement policy: %s\n", queue_type_str); 2180ea93d37eSRafal Kozik 2181ea93d37eSRafal Kozik calc_queue_ctx.ena_dev = ena_dev; 2182ea93d37eSRafal Kozik calc_queue_ctx.get_feat_ctx = &get_feat_ctx; 21831173fca2SJan Medala 21845920d930SMichal Krawczyk max_num_io_queues = ena_calc_max_io_queue_num(ena_dev, &get_feat_ctx); 21858a7a73f2SMichal Krawczyk rc = ena_calc_io_queue_size(&calc_queue_ctx, 21868a7a73f2SMichal Krawczyk adapter->use_large_llq_hdr); 21875920d930SMichal Krawczyk if (unlikely((rc != 0) || (max_num_io_queues == 0))) { 2188241da076SRafal Kozik rc = -EFAULT; 2189241da076SRafal Kozik goto err_device_destroy; 2190241da076SRafal Kozik } 21911173fca2SJan Medala 21925920d930SMichal Krawczyk adapter->max_tx_ring_size = calc_queue_ctx.max_tx_queue_size; 21935920d930SMichal Krawczyk adapter->max_rx_ring_size = calc_queue_ctx.max_rx_queue_size; 2194ea93d37eSRafal Kozik adapter->max_tx_sgl_size = calc_queue_ctx.max_tx_sgl_size; 2195ea93d37eSRafal Kozik adapter->max_rx_sgl_size = calc_queue_ctx.max_rx_sgl_size; 21965920d930SMichal Krawczyk adapter->max_num_io_queues = max_num_io_queues; 21972061fe41SRafal Kozik 219833dde075SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 219933dde075SMichal Krawczyk disable_meta_caching = 220033dde075SMichal Krawczyk !!(get_feat_ctx.llq.accel_mode.u.get.supported_flags & 220133dde075SMichal Krawczyk BIT(ENA_ADMIN_DISABLE_META_CACHING)); 220233dde075SMichal Krawczyk } else { 220333dde075SMichal Krawczyk disable_meta_caching = false; 220433dde075SMichal Krawczyk } 220533dde075SMichal Krawczyk 22061173fca2SJan Medala /* prepare ring structures */ 220733dde075SMichal Krawczyk ena_init_rings(adapter, disable_meta_caching); 22081173fca2SJan Medala 2209372c1af5SJan Medala ena_config_debug_area(adapter); 2210372c1af5SJan Medala 22111173fca2SJan Medala /* Set max MTU for this device */ 22121173fca2SJan Medala adapter->max_mtu = get_feat_ctx.dev_attr.max_mtu; 22131173fca2SJan Medala 2214e8c838fdSMichal Krawczyk ena_set_offloads(&adapter->offloads, &get_feat_ctx.offload); 221583277a7cSJakub Palider 22161173fca2SJan Medala /* Copy MAC address and point DPDK to it */ 22176d13ea8eSOlivier Matz eth_dev->data->mac_addrs = (struct rte_ether_addr *)adapter->mac_addr; 2218538da7a1SOlivier Matz rte_ether_addr_copy((struct rte_ether_addr *) 2219538da7a1SOlivier Matz get_feat_ctx.dev_attr.mac_addr, 22206d13ea8eSOlivier Matz (struct rte_ether_addr *)adapter->mac_addr); 22211173fca2SJan Medala 222234d5e97eSMichal Krawczyk rc = ena_com_rss_init(ena_dev, ENA_RX_RSS_TABLE_LOG_SIZE); 222334d5e97eSMichal Krawczyk if (unlikely(rc != 0)) { 222434d5e97eSMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to initialize RSS in ENA device\n"); 222534d5e97eSMichal Krawczyk goto err_delete_debug_area; 222634d5e97eSMichal Krawczyk } 222734d5e97eSMichal Krawczyk 22281173fca2SJan Medala adapter->drv_stats = rte_zmalloc("adapter stats", 22291173fca2SJan Medala sizeof(*adapter->drv_stats), 22301173fca2SJan Medala RTE_CACHE_LINE_SIZE); 22311173fca2SJan Medala if (!adapter->drv_stats) { 2232617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 2233617898d1SMichal Krawczyk "Failed to allocate memory for adapter statistics\n"); 2234241da076SRafal Kozik rc = -ENOMEM; 223534d5e97eSMichal Krawczyk goto err_rss_destroy; 22361173fca2SJan Medala } 22371173fca2SJan Medala 22381343c415SMichal Krawczyk rte_spinlock_init(&adapter->admin_lock); 22391343c415SMichal Krawczyk 2240eb0ef49dSMichal Krawczyk rte_intr_callback_register(intr_handle, 2241eb0ef49dSMichal Krawczyk ena_interrupt_handler_rte, 2242aab58857SStanislaw Kardach eth_dev); 2243eb0ef49dSMichal Krawczyk rte_intr_enable(intr_handle); 2244eb0ef49dSMichal Krawczyk ena_com_set_admin_polling_mode(ena_dev, false); 2245ca148440SMichal Krawczyk ena_com_admin_aenq_enable(ena_dev); 2246eb0ef49dSMichal Krawczyk 2247d9b8b106SMichal Krawczyk rte_timer_init(&adapter->timer_wd); 2248d9b8b106SMichal Krawczyk 22491173fca2SJan Medala adapters_found++; 22501173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_INIT; 22511173fca2SJan Medala 22521173fca2SJan Medala return 0; 2253241da076SRafal Kozik 225434d5e97eSMichal Krawczyk err_rss_destroy: 225534d5e97eSMichal Krawczyk ena_com_rss_destroy(ena_dev); 2256241da076SRafal Kozik err_delete_debug_area: 2257241da076SRafal Kozik ena_com_delete_debug_area(ena_dev); 2258241da076SRafal Kozik 2259241da076SRafal Kozik err_device_destroy: 2260241da076SRafal Kozik ena_com_delete_host_info(ena_dev); 2261241da076SRafal Kozik ena_com_admin_destroy(ena_dev); 2262241da076SRafal Kozik 2263241da076SRafal Kozik err: 2264241da076SRafal Kozik return rc; 22651173fca2SJan Medala } 22661173fca2SJan Medala 2267e457bc70SRafal Kozik static void ena_destroy_device(struct rte_eth_dev *eth_dev) 2268eb0ef49dSMichal Krawczyk { 2269890728ffSStephen Hemminger struct ena_adapter *adapter = eth_dev->data->dev_private; 2270e457bc70SRafal Kozik struct ena_com_dev *ena_dev = &adapter->ena_dev; 2271eb0ef49dSMichal Krawczyk 2272e457bc70SRafal Kozik if (adapter->state == ENA_ADAPTER_STATE_FREE) 2273e457bc70SRafal Kozik return; 2274e457bc70SRafal Kozik 2275e457bc70SRafal Kozik ena_com_set_admin_running_state(ena_dev, false); 2276eb0ef49dSMichal Krawczyk 2277eb0ef49dSMichal Krawczyk if (adapter->state != ENA_ADAPTER_STATE_CLOSED) 2278eb0ef49dSMichal Krawczyk ena_close(eth_dev); 2279eb0ef49dSMichal Krawczyk 228034d5e97eSMichal Krawczyk ena_com_rss_destroy(ena_dev); 228134d5e97eSMichal Krawczyk 2282e457bc70SRafal Kozik ena_com_delete_debug_area(ena_dev); 2283e457bc70SRafal Kozik ena_com_delete_host_info(ena_dev); 2284e457bc70SRafal Kozik 2285e457bc70SRafal Kozik ena_com_abort_admin_commands(ena_dev); 2286e457bc70SRafal Kozik ena_com_wait_for_abort_completion(ena_dev); 2287e457bc70SRafal Kozik ena_com_admin_destroy(ena_dev); 2288e457bc70SRafal Kozik ena_com_mmio_reg_read_request_destroy(ena_dev); 2289e457bc70SRafal Kozik 2290e457bc70SRafal Kozik adapter->state = ENA_ADAPTER_STATE_FREE; 2291e457bc70SRafal Kozik } 2292e457bc70SRafal Kozik 2293e457bc70SRafal Kozik static int eth_ena_dev_uninit(struct rte_eth_dev *eth_dev) 2294e457bc70SRafal Kozik { 2295e457bc70SRafal Kozik if (rte_eal_process_type() != RTE_PROC_PRIMARY) 2296e457bc70SRafal Kozik return 0; 2297e457bc70SRafal Kozik 2298e457bc70SRafal Kozik ena_destroy_device(eth_dev); 2299e457bc70SRafal Kozik 2300eb0ef49dSMichal Krawczyk return 0; 2301eb0ef49dSMichal Krawczyk } 2302eb0ef49dSMichal Krawczyk 23031173fca2SJan Medala static int ena_dev_configure(struct rte_eth_dev *dev) 23041173fca2SJan Medala { 2305890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 2306b9b05d6fSMichal Krawczyk int rc; 23077369f88fSRafal Kozik 23081173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_CONFIG; 23091173fca2SJan Medala 2310295968d1SFerruh Yigit if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) 2311295968d1SFerruh Yigit dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 2312295968d1SFerruh Yigit dev->data->dev_conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 2313b418f0d2SMichal Krawczyk 2314e2a6d08bSMichal Krawczyk /* Scattered Rx cannot be turned off in the HW, so this capability must 2315e2a6d08bSMichal Krawczyk * be forced. 2316e2a6d08bSMichal Krawczyk */ 2317e2a6d08bSMichal Krawczyk dev->data->scattered_rx = 1; 2318e2a6d08bSMichal Krawczyk 2319f93e20e5SMichal Krawczyk adapter->last_tx_comp_qid = 0; 2320f93e20e5SMichal Krawczyk 2321f93e20e5SMichal Krawczyk adapter->missing_tx_completion_budget = 2322f93e20e5SMichal Krawczyk RTE_MIN(ENA_MONITORED_TX_QUEUES, dev->data->nb_tx_queues); 2323f93e20e5SMichal Krawczyk 2324f93e20e5SMichal Krawczyk /* To avoid detection of the spurious Tx completion timeout due to 2325f93e20e5SMichal Krawczyk * application not calling the Tx cleanup function, set timeout for the 2326f93e20e5SMichal Krawczyk * Tx queue which should be half of the missing completion timeout for a 2327f93e20e5SMichal Krawczyk * safety. If there will be a lot of missing Tx completions in the 2328f93e20e5SMichal Krawczyk * queue, they will be detected sooner or later. 2329f93e20e5SMichal Krawczyk */ 2330f93e20e5SMichal Krawczyk adapter->tx_cleanup_stall_delay = adapter->missing_tx_completion_to / 2; 2331f93e20e5SMichal Krawczyk 2332b9b05d6fSMichal Krawczyk rc = ena_configure_aenq(adapter); 2333b9b05d6fSMichal Krawczyk 2334b9b05d6fSMichal Krawczyk return rc; 23351173fca2SJan Medala } 23361173fca2SJan Medala 233733dde075SMichal Krawczyk static void ena_init_rings(struct ena_adapter *adapter, 233833dde075SMichal Krawczyk bool disable_meta_caching) 23391173fca2SJan Medala { 23405920d930SMichal Krawczyk size_t i; 23411173fca2SJan Medala 23425920d930SMichal Krawczyk for (i = 0; i < adapter->max_num_io_queues; i++) { 23431173fca2SJan Medala struct ena_ring *ring = &adapter->tx_ring[i]; 23441173fca2SJan Medala 23451173fca2SJan Medala ring->configured = 0; 23461173fca2SJan Medala ring->type = ENA_RING_TYPE_TX; 23471173fca2SJan Medala ring->adapter = adapter; 23481173fca2SJan Medala ring->id = i; 23491173fca2SJan Medala ring->tx_mem_queue_type = adapter->ena_dev.tx_mem_queue_type; 23501173fca2SJan Medala ring->tx_max_header_size = adapter->ena_dev.tx_max_header_size; 23512061fe41SRafal Kozik ring->sgl_size = adapter->max_tx_sgl_size; 235233dde075SMichal Krawczyk ring->disable_meta_caching = disable_meta_caching; 23531173fca2SJan Medala } 23541173fca2SJan Medala 23555920d930SMichal Krawczyk for (i = 0; i < adapter->max_num_io_queues; i++) { 23561173fca2SJan Medala struct ena_ring *ring = &adapter->rx_ring[i]; 23571173fca2SJan Medala 23581173fca2SJan Medala ring->configured = 0; 23591173fca2SJan Medala ring->type = ENA_RING_TYPE_RX; 23601173fca2SJan Medala ring->adapter = adapter; 23611173fca2SJan Medala ring->id = i; 2362ea93d37eSRafal Kozik ring->sgl_size = adapter->max_rx_sgl_size; 23631173fca2SJan Medala } 23641173fca2SJan Medala } 23651173fca2SJan Medala 23663a822d79SMichal Krawczyk static uint64_t ena_get_rx_port_offloads(struct ena_adapter *adapter) 23673a822d79SMichal Krawczyk { 23683a822d79SMichal Krawczyk uint64_t port_offloads = 0; 23693a822d79SMichal Krawczyk 23703a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & ENA_L3_IPV4_CSUM) 2371295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM; 23723a822d79SMichal Krawczyk 23733a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & 23743a822d79SMichal Krawczyk (ENA_L4_IPV4_CSUM | ENA_L4_IPV6_CSUM)) 23753a822d79SMichal Krawczyk port_offloads |= 2376295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM; 23773a822d79SMichal Krawczyk 23783a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & ENA_RX_RSS_HASH) 2379295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 23803a822d79SMichal Krawczyk 2381295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_SCATTER; 2382e2a6d08bSMichal Krawczyk 23833a822d79SMichal Krawczyk return port_offloads; 23843a822d79SMichal Krawczyk } 23853a822d79SMichal Krawczyk 23863a822d79SMichal Krawczyk static uint64_t ena_get_tx_port_offloads(struct ena_adapter *adapter) 23873a822d79SMichal Krawczyk { 23883a822d79SMichal Krawczyk uint64_t port_offloads = 0; 23893a822d79SMichal Krawczyk 23903a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & ENA_IPV4_TSO) 2391295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO; 23923a822d79SMichal Krawczyk 23933a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & ENA_L3_IPV4_CSUM) 2394295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM; 23953a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & 23963a822d79SMichal Krawczyk (ENA_L4_IPV4_CSUM_PARTIAL | ENA_L4_IPV4_CSUM | 23973a822d79SMichal Krawczyk ENA_L4_IPV6_CSUM | ENA_L4_IPV6_CSUM_PARTIAL)) 23983a822d79SMichal Krawczyk port_offloads |= 2399295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_UDP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_CKSUM; 24003a822d79SMichal Krawczyk 2401295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 24023a822d79SMichal Krawczyk 2403c339f538SDawid Gorecki port_offloads |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 2404c339f538SDawid Gorecki 24053a822d79SMichal Krawczyk return port_offloads; 24063a822d79SMichal Krawczyk } 24073a822d79SMichal Krawczyk 24083a822d79SMichal Krawczyk static uint64_t ena_get_rx_queue_offloads(struct ena_adapter *adapter) 24093a822d79SMichal Krawczyk { 24103a822d79SMichal Krawczyk RTE_SET_USED(adapter); 24113a822d79SMichal Krawczyk 24123a822d79SMichal Krawczyk return 0; 24133a822d79SMichal Krawczyk } 24143a822d79SMichal Krawczyk 24153a822d79SMichal Krawczyk static uint64_t ena_get_tx_queue_offloads(struct ena_adapter *adapter) 24163a822d79SMichal Krawczyk { 2417c339f538SDawid Gorecki uint64_t queue_offloads = 0; 24183a822d79SMichal Krawczyk RTE_SET_USED(adapter); 24193a822d79SMichal Krawczyk 2420c339f538SDawid Gorecki queue_offloads |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 2421c339f538SDawid Gorecki 2422c339f538SDawid Gorecki return queue_offloads; 24233a822d79SMichal Krawczyk } 24243a822d79SMichal Krawczyk 2425bdad90d1SIvan Ilchenko static int ena_infos_get(struct rte_eth_dev *dev, 24261173fca2SJan Medala struct rte_eth_dev_info *dev_info) 24271173fca2SJan Medala { 24281173fca2SJan Medala struct ena_adapter *adapter; 24291173fca2SJan Medala struct ena_com_dev *ena_dev; 24301173fca2SJan Medala 2431498c687aSRafal Kozik ena_assert_msg(dev->data != NULL, "Uninitialized device\n"); 2432498c687aSRafal Kozik ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device\n"); 2433890728ffSStephen Hemminger adapter = dev->data->dev_private; 24341173fca2SJan Medala 24351173fca2SJan Medala ena_dev = &adapter->ena_dev; 2436498c687aSRafal Kozik ena_assert_msg(ena_dev != NULL, "Uninitialized device\n"); 24371173fca2SJan Medala 2438e274f573SMarc Sune dev_info->speed_capa = 2439295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_1G | 2440295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_2_5G | 2441295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_5G | 2442295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_10G | 2443295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_25G | 2444295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_40G | 2445295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_50G | 2446295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_100G; 2447e274f573SMarc Sune 24481173fca2SJan Medala /* Inform framework about available features */ 24493a822d79SMichal Krawczyk dev_info->rx_offload_capa = ena_get_rx_port_offloads(adapter); 24503a822d79SMichal Krawczyk dev_info->tx_offload_capa = ena_get_tx_port_offloads(adapter); 24513a822d79SMichal Krawczyk dev_info->rx_queue_offload_capa = ena_get_rx_queue_offloads(adapter); 24523a822d79SMichal Krawczyk dev_info->tx_queue_offload_capa = ena_get_tx_queue_offloads(adapter); 24531173fca2SJan Medala 245434d5e97eSMichal Krawczyk dev_info->flow_type_rss_offloads = ENA_ALL_RSS_HF; 245534d5e97eSMichal Krawczyk dev_info->hash_key_size = ENA_HASH_KEY_SIZE; 2456b01ead20SRafal Kozik 24571173fca2SJan Medala dev_info->min_rx_bufsize = ENA_MIN_FRAME_LEN; 24581bb4a528SFerruh Yigit dev_info->max_rx_pktlen = adapter->max_mtu + RTE_ETHER_HDR_LEN + 24591bb4a528SFerruh Yigit RTE_ETHER_CRC_LEN; 24601bb4a528SFerruh Yigit dev_info->min_mtu = ENA_MIN_MTU; 24611bb4a528SFerruh Yigit dev_info->max_mtu = adapter->max_mtu; 24621173fca2SJan Medala dev_info->max_mac_addrs = 1; 24631173fca2SJan Medala 24645920d930SMichal Krawczyk dev_info->max_rx_queues = adapter->max_num_io_queues; 24655920d930SMichal Krawczyk dev_info->max_tx_queues = adapter->max_num_io_queues; 24661173fca2SJan Medala dev_info->reta_size = ENA_RX_RSS_TABLE_SIZE; 246756b8b9b7SRafal Kozik 24685920d930SMichal Krawczyk dev_info->rx_desc_lim.nb_max = adapter->max_rx_ring_size; 246992680dc2SRafal Kozik dev_info->rx_desc_lim.nb_min = ENA_MIN_RING_DESC; 2470ea93d37eSRafal Kozik dev_info->rx_desc_lim.nb_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2471ea93d37eSRafal Kozik adapter->max_rx_sgl_size); 2472ea93d37eSRafal Kozik dev_info->rx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2473ea93d37eSRafal Kozik adapter->max_rx_sgl_size); 247492680dc2SRafal Kozik 24755920d930SMichal Krawczyk dev_info->tx_desc_lim.nb_max = adapter->max_tx_ring_size; 247692680dc2SRafal Kozik dev_info->tx_desc_lim.nb_min = ENA_MIN_RING_DESC; 247792680dc2SRafal Kozik dev_info->tx_desc_lim.nb_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2478ea93d37eSRafal Kozik adapter->max_tx_sgl_size); 247992680dc2SRafal Kozik dev_info->tx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2480ea93d37eSRafal Kozik adapter->max_tx_sgl_size); 2481bdad90d1SIvan Ilchenko 248230a6c7efSStanislaw Kardach dev_info->default_rxportconf.ring_size = ENA_DEFAULT_RING_SIZE; 248330a6c7efSStanislaw Kardach dev_info->default_txportconf.ring_size = ENA_DEFAULT_RING_SIZE; 248430a6c7efSStanislaw Kardach 2485bdad90d1SIvan Ilchenko return 0; 24861173fca2SJan Medala } 24871173fca2SJan Medala 24881be097dcSMichal Krawczyk static inline void ena_init_rx_mbuf(struct rte_mbuf *mbuf, uint16_t len) 24891be097dcSMichal Krawczyk { 24901be097dcSMichal Krawczyk mbuf->data_len = len; 24911be097dcSMichal Krawczyk mbuf->data_off = RTE_PKTMBUF_HEADROOM; 24921be097dcSMichal Krawczyk mbuf->refcnt = 1; 24931be097dcSMichal Krawczyk mbuf->next = NULL; 24941be097dcSMichal Krawczyk } 24951be097dcSMichal Krawczyk 24961be097dcSMichal Krawczyk static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, 24971be097dcSMichal Krawczyk struct ena_com_rx_buf_info *ena_bufs, 24981be097dcSMichal Krawczyk uint32_t descs, 24991be097dcSMichal Krawczyk uint16_t *next_to_clean, 25001be097dcSMichal Krawczyk uint8_t offset) 25011be097dcSMichal Krawczyk { 25021be097dcSMichal Krawczyk struct rte_mbuf *mbuf; 25031be097dcSMichal Krawczyk struct rte_mbuf *mbuf_head; 25041be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info; 250583fd97b2SMichal Krawczyk int rc; 25061be097dcSMichal Krawczyk uint16_t ntc, len, req_id, buf = 0; 25071be097dcSMichal Krawczyk 25081be097dcSMichal Krawczyk if (unlikely(descs == 0)) 25091be097dcSMichal Krawczyk return NULL; 25101be097dcSMichal Krawczyk 25111be097dcSMichal Krawczyk ntc = *next_to_clean; 25121be097dcSMichal Krawczyk 25131be097dcSMichal Krawczyk len = ena_bufs[buf].len; 25141be097dcSMichal Krawczyk req_id = ena_bufs[buf].req_id; 25151be097dcSMichal Krawczyk 25161be097dcSMichal Krawczyk rx_info = &rx_ring->rx_buffer_info[req_id]; 25171be097dcSMichal Krawczyk 25181be097dcSMichal Krawczyk mbuf = rx_info->mbuf; 25191be097dcSMichal Krawczyk RTE_ASSERT(mbuf != NULL); 25201be097dcSMichal Krawczyk 25211be097dcSMichal Krawczyk ena_init_rx_mbuf(mbuf, len); 25221be097dcSMichal Krawczyk 25231be097dcSMichal Krawczyk /* Fill the mbuf head with the data specific for 1st segment. */ 25241be097dcSMichal Krawczyk mbuf_head = mbuf; 25251be097dcSMichal Krawczyk mbuf_head->nb_segs = descs; 25261be097dcSMichal Krawczyk mbuf_head->port = rx_ring->port_id; 25271be097dcSMichal Krawczyk mbuf_head->pkt_len = len; 25281be097dcSMichal Krawczyk mbuf_head->data_off += offset; 25291be097dcSMichal Krawczyk 25301be097dcSMichal Krawczyk rx_info->mbuf = NULL; 2531c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[ntc] = req_id; 2532c0006061SMichal Krawczyk ntc = ENA_IDX_NEXT_MASKED(ntc, rx_ring->size_mask); 25331be097dcSMichal Krawczyk 25341be097dcSMichal Krawczyk while (--descs) { 25351be097dcSMichal Krawczyk ++buf; 25361be097dcSMichal Krawczyk len = ena_bufs[buf].len; 25371be097dcSMichal Krawczyk req_id = ena_bufs[buf].req_id; 25381be097dcSMichal Krawczyk 25391be097dcSMichal Krawczyk rx_info = &rx_ring->rx_buffer_info[req_id]; 25401be097dcSMichal Krawczyk RTE_ASSERT(rx_info->mbuf != NULL); 25411be097dcSMichal Krawczyk 254283fd97b2SMichal Krawczyk if (unlikely(len == 0)) { 254383fd97b2SMichal Krawczyk /* 254483fd97b2SMichal Krawczyk * Some devices can pass descriptor with the length 0. 254583fd97b2SMichal Krawczyk * To avoid confusion, the PMD is simply putting the 254683fd97b2SMichal Krawczyk * descriptor back, as it was never used. We'll avoid 254783fd97b2SMichal Krawczyk * mbuf allocation that way. 254883fd97b2SMichal Krawczyk */ 254983fd97b2SMichal Krawczyk rc = ena_add_single_rx_desc(rx_ring->ena_com_io_sq, 255083fd97b2SMichal Krawczyk rx_info->mbuf, req_id); 255183fd97b2SMichal Krawczyk if (unlikely(rc != 0)) { 255283fd97b2SMichal Krawczyk /* Free the mbuf in case of an error. */ 255383fd97b2SMichal Krawczyk rte_mbuf_raw_free(rx_info->mbuf); 255483fd97b2SMichal Krawczyk } else { 255583fd97b2SMichal Krawczyk /* 255683fd97b2SMichal Krawczyk * If there was no error, just exit the loop as 255783fd97b2SMichal Krawczyk * 0 length descriptor is always the last one. 255883fd97b2SMichal Krawczyk */ 255983fd97b2SMichal Krawczyk break; 256083fd97b2SMichal Krawczyk } 256183fd97b2SMichal Krawczyk } else { 25621be097dcSMichal Krawczyk /* Create an mbuf chain. */ 25631be097dcSMichal Krawczyk mbuf->next = rx_info->mbuf; 25641be097dcSMichal Krawczyk mbuf = mbuf->next; 25651be097dcSMichal Krawczyk 25661be097dcSMichal Krawczyk ena_init_rx_mbuf(mbuf, len); 25671be097dcSMichal Krawczyk mbuf_head->pkt_len += len; 256883fd97b2SMichal Krawczyk } 25691be097dcSMichal Krawczyk 257083fd97b2SMichal Krawczyk /* 257183fd97b2SMichal Krawczyk * Mark the descriptor as depleted and perform necessary 257283fd97b2SMichal Krawczyk * cleanup. 257383fd97b2SMichal Krawczyk * This code will execute in two cases: 257483fd97b2SMichal Krawczyk * 1. Descriptor len was greater than 0 - normal situation. 257583fd97b2SMichal Krawczyk * 2. Descriptor len was 0 and we failed to add the descriptor 257683fd97b2SMichal Krawczyk * to the device. In that situation, we should try to add 257783fd97b2SMichal Krawczyk * the mbuf again in the populate routine and mark the 257883fd97b2SMichal Krawczyk * descriptor as used up by the device. 257983fd97b2SMichal Krawczyk */ 25801be097dcSMichal Krawczyk rx_info->mbuf = NULL; 2581c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[ntc] = req_id; 2582c0006061SMichal Krawczyk ntc = ENA_IDX_NEXT_MASKED(ntc, rx_ring->size_mask); 25831be097dcSMichal Krawczyk } 25841be097dcSMichal Krawczyk 25851be097dcSMichal Krawczyk *next_to_clean = ntc; 25861be097dcSMichal Krawczyk 25871be097dcSMichal Krawczyk return mbuf_head; 25881be097dcSMichal Krawczyk } 25891be097dcSMichal Krawczyk 25901173fca2SJan Medala static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, 25911173fca2SJan Medala uint16_t nb_pkts) 25921173fca2SJan Medala { 25931173fca2SJan Medala struct ena_ring *rx_ring = (struct ena_ring *)(rx_queue); 259477550607SMichal Krawczyk unsigned int free_queue_entries; 25951173fca2SJan Medala uint16_t next_to_clean = rx_ring->next_to_clean; 259674456796SMichal Krawczyk uint16_t descs_in_use; 25971be097dcSMichal Krawczyk struct rte_mbuf *mbuf; 25981be097dcSMichal Krawczyk uint16_t completed; 25991173fca2SJan Medala struct ena_com_rx_ctx ena_rx_ctx; 26001be097dcSMichal Krawczyk int i, rc = 0; 260134d5e97eSMichal Krawczyk bool fill_hash; 26021173fca2SJan Medala 26030a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 26041173fca2SJan Medala /* Check adapter state */ 26051173fca2SJan Medala if (unlikely(rx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) { 26060a001d69SMichal Krawczyk PMD_RX_LOG(ALERT, 26071173fca2SJan Medala "Trying to receive pkts while device is NOT running\n"); 26081173fca2SJan Medala return 0; 26091173fca2SJan Medala } 26100a001d69SMichal Krawczyk #endif 26111173fca2SJan Medala 2612295968d1SFerruh Yigit fill_hash = rx_ring->offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH; 261334d5e97eSMichal Krawczyk 2614c0006061SMichal Krawczyk descs_in_use = rx_ring->ring_size - 261574456796SMichal Krawczyk ena_com_free_q_entries(rx_ring->ena_com_io_sq) - 1; 261674456796SMichal Krawczyk nb_pkts = RTE_MIN(descs_in_use, nb_pkts); 26171173fca2SJan Medala 26181173fca2SJan Medala for (completed = 0; completed < nb_pkts; completed++) { 2619ea93d37eSRafal Kozik ena_rx_ctx.max_bufs = rx_ring->sgl_size; 26201173fca2SJan Medala ena_rx_ctx.ena_bufs = rx_ring->ena_bufs; 26211173fca2SJan Medala ena_rx_ctx.descs = 0; 26227b3a3c4bSMaciej Bielski ena_rx_ctx.pkt_offset = 0; 26231173fca2SJan Medala /* receive packet context */ 26241173fca2SJan Medala rc = ena_com_rx_pkt(rx_ring->ena_com_io_cq, 26251173fca2SJan Medala rx_ring->ena_com_io_sq, 26261173fca2SJan Medala &ena_rx_ctx); 26271173fca2SJan Medala if (unlikely(rc)) { 26280a001d69SMichal Krawczyk PMD_RX_LOG(ERR, 2629617898d1SMichal Krawczyk "Failed to get the packet from the device, rc: %d\n", 2630617898d1SMichal Krawczyk rc); 263105cffdcfSMichal Krawczyk if (rc == ENA_COM_NO_SPACE) { 263205cffdcfSMichal Krawczyk ++rx_ring->rx_stats.bad_desc_num; 26332bae75eaSDawid Gorecki ena_trigger_reset(rx_ring->adapter, 26342bae75eaSDawid Gorecki ENA_REGS_RESET_TOO_MANY_RX_DESCS); 263505cffdcfSMichal Krawczyk } else { 263605cffdcfSMichal Krawczyk ++rx_ring->rx_stats.bad_req_id; 26372bae75eaSDawid Gorecki ena_trigger_reset(rx_ring->adapter, 26382bae75eaSDawid Gorecki ENA_REGS_RESET_INV_RX_REQ_ID); 263905cffdcfSMichal Krawczyk } 26401173fca2SJan Medala return 0; 26411173fca2SJan Medala } 26421173fca2SJan Medala 26431be097dcSMichal Krawczyk mbuf = ena_rx_mbuf(rx_ring, 26441be097dcSMichal Krawczyk ena_rx_ctx.ena_bufs, 26451be097dcSMichal Krawczyk ena_rx_ctx.descs, 26461be097dcSMichal Krawczyk &next_to_clean, 26471be097dcSMichal Krawczyk ena_rx_ctx.pkt_offset); 26481be097dcSMichal Krawczyk if (unlikely(mbuf == NULL)) { 26491be097dcSMichal Krawczyk for (i = 0; i < ena_rx_ctx.descs; ++i) { 2650c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[next_to_clean] = 26511be097dcSMichal Krawczyk rx_ring->ena_bufs[i].req_id; 2652c0006061SMichal Krawczyk next_to_clean = ENA_IDX_NEXT_MASKED( 2653c0006061SMichal Krawczyk next_to_clean, rx_ring->size_mask); 26541173fca2SJan Medala } 2655f00930d9SRafal Kozik break; 26561be097dcSMichal Krawczyk } 26571173fca2SJan Medala 26581173fca2SJan Medala /* fill mbuf attributes if any */ 265984daba99SMichal Krawczyk ena_rx_mbuf_prepare(rx_ring, mbuf, &ena_rx_ctx, fill_hash); 26607830e905SSolganik Alexander 26611be097dcSMichal Krawczyk if (unlikely(mbuf->ol_flags & 266284daba99SMichal Krawczyk (RTE_MBUF_F_RX_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD))) 2663ef74b5f7SMichal Krawczyk rte_atomic64_inc(&rx_ring->adapter->drv_stats->ierrors); 26647830e905SSolganik Alexander 26651be097dcSMichal Krawczyk rx_pkts[completed] = mbuf; 26661be097dcSMichal Krawczyk rx_ring->rx_stats.bytes += mbuf->pkt_len; 26671173fca2SJan Medala } 26681173fca2SJan Medala 26691be097dcSMichal Krawczyk rx_ring->rx_stats.cnt += completed; 2670ec78af6bSMichal Krawczyk rx_ring->next_to_clean = next_to_clean; 2671ec78af6bSMichal Krawczyk 267277550607SMichal Krawczyk free_queue_entries = ena_com_free_q_entries(rx_ring->ena_com_io_sq); 267377550607SMichal Krawczyk 26741173fca2SJan Medala /* Burst refill to save doorbells, memory barriers, const interval */ 2675005064e5SMichal Krawczyk if (free_queue_entries >= rx_ring->rx_free_thresh) { 2676a45462c5SRafal Kozik ena_com_update_dev_comp_head(rx_ring->ena_com_io_cq); 267777550607SMichal Krawczyk ena_populate_rx_queue(rx_ring, free_queue_entries); 2678a45462c5SRafal Kozik } 26791173fca2SJan Medala 26801be097dcSMichal Krawczyk return completed; 26811173fca2SJan Medala } 26821173fca2SJan Medala 2683b3fc5a1aSKonstantin Ananyev static uint16_t 268483277a7cSJakub Palider eth_ena_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 2685b3fc5a1aSKonstantin Ananyev uint16_t nb_pkts) 2686b3fc5a1aSKonstantin Ananyev { 2687b3fc5a1aSKonstantin Ananyev int32_t ret; 2688b3fc5a1aSKonstantin Ananyev uint32_t i; 2689b3fc5a1aSKonstantin Ananyev struct rte_mbuf *m; 269083277a7cSJakub Palider struct ena_ring *tx_ring = (struct ena_ring *)(tx_queue); 2691e8c838fdSMichal Krawczyk struct ena_adapter *adapter = tx_ring->adapter; 2692a7c528e5SOlivier Matz struct rte_ipv4_hdr *ip_hdr; 2693b3fc5a1aSKonstantin Ananyev uint64_t ol_flags; 2694e8c838fdSMichal Krawczyk uint64_t l4_csum_flag; 2695e8c838fdSMichal Krawczyk uint64_t dev_offload_capa; 269683277a7cSJakub Palider uint16_t frag_field; 2697e8c838fdSMichal Krawczyk bool need_pseudo_csum; 269883277a7cSJakub Palider 2699e8c838fdSMichal Krawczyk dev_offload_capa = adapter->offloads.tx_offloads; 2700b3fc5a1aSKonstantin Ananyev for (i = 0; i != nb_pkts; i++) { 2701b3fc5a1aSKonstantin Ananyev m = tx_pkts[i]; 2702b3fc5a1aSKonstantin Ananyev ol_flags = m->ol_flags; 2703b3fc5a1aSKonstantin Ananyev 2704e8c838fdSMichal Krawczyk /* Check if any offload flag was set */ 2705e8c838fdSMichal Krawczyk if (ol_flags == 0) 2706bc5ef57dSMichal Krawczyk continue; 2707bc5ef57dSMichal Krawczyk 2708daa02b5cSOlivier Matz l4_csum_flag = ol_flags & RTE_MBUF_F_TX_L4_MASK; 2709e8c838fdSMichal Krawczyk /* SCTP checksum offload is not supported by the ENA. */ 2710e8c838fdSMichal Krawczyk if ((ol_flags & ENA_TX_OFFLOAD_NOTSUP_MASK) || 2711daa02b5cSOlivier Matz l4_csum_flag == RTE_MBUF_F_TX_SCTP_CKSUM) { 2712e8c838fdSMichal Krawczyk PMD_TX_LOG(DEBUG, 2713e8c838fdSMichal Krawczyk "mbuf[%" PRIu32 "] has unsupported offloads flags set: 0x%" PRIu64 "\n", 2714e8c838fdSMichal Krawczyk i, ol_flags); 2715baeed5f4SMichal Krawczyk rte_errno = ENOTSUP; 2716b3fc5a1aSKonstantin Ananyev return i; 2717b3fc5a1aSKonstantin Ananyev } 2718b3fc5a1aSKonstantin Ananyev 271996ffa8a7SMichal Krawczyk if (unlikely(m->nb_segs >= tx_ring->sgl_size && 272096ffa8a7SMichal Krawczyk !(tx_ring->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV && 272196ffa8a7SMichal Krawczyk m->nb_segs == tx_ring->sgl_size && 272296ffa8a7SMichal Krawczyk m->data_len < tx_ring->tx_max_header_size))) { 272396ffa8a7SMichal Krawczyk PMD_TX_LOG(DEBUG, 272496ffa8a7SMichal Krawczyk "mbuf[%" PRIu32 "] has too many segments: %" PRIu16 "\n", 272596ffa8a7SMichal Krawczyk i, m->nb_segs); 272696ffa8a7SMichal Krawczyk rte_errno = EINVAL; 272796ffa8a7SMichal Krawczyk return i; 272896ffa8a7SMichal Krawczyk } 272996ffa8a7SMichal Krawczyk 2730b3fc5a1aSKonstantin Ananyev #ifdef RTE_LIBRTE_ETHDEV_DEBUG 2731e8c838fdSMichal Krawczyk /* Check if requested offload is also enabled for the queue */ 2732daa02b5cSOlivier Matz if ((ol_flags & RTE_MBUF_F_TX_IP_CKSUM && 2733295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) || 2734daa02b5cSOlivier Matz (l4_csum_flag == RTE_MBUF_F_TX_TCP_CKSUM && 2735295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) || 2736daa02b5cSOlivier Matz (l4_csum_flag == RTE_MBUF_F_TX_UDP_CKSUM && 2737295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM))) { 2738e8c838fdSMichal Krawczyk PMD_TX_LOG(DEBUG, 2739e8c838fdSMichal Krawczyk "mbuf[%" PRIu32 "]: requested offloads: %" PRIu16 " are not enabled for the queue[%u]\n", 2740e8c838fdSMichal Krawczyk i, m->nb_segs, tx_ring->id); 2741e8c838fdSMichal Krawczyk rte_errno = EINVAL; 2742e8c838fdSMichal Krawczyk return i; 2743e8c838fdSMichal Krawczyk } 2744e8c838fdSMichal Krawczyk 2745e8c838fdSMichal Krawczyk /* The caller is obligated to set l2 and l3 len if any cksum 2746e8c838fdSMichal Krawczyk * offload is enabled. 2747e8c838fdSMichal Krawczyk */ 2748daa02b5cSOlivier Matz if (unlikely(ol_flags & (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_L4_MASK) && 2749e8c838fdSMichal Krawczyk (m->l2_len == 0 || m->l3_len == 0))) { 2750e8c838fdSMichal Krawczyk PMD_TX_LOG(DEBUG, 2751e8c838fdSMichal Krawczyk "mbuf[%" PRIu32 "]: l2_len or l3_len values are 0 while the offload was requested\n", 2752e8c838fdSMichal Krawczyk i); 2753e8c838fdSMichal Krawczyk rte_errno = EINVAL; 2754e8c838fdSMichal Krawczyk return i; 2755e8c838fdSMichal Krawczyk } 2756b3fc5a1aSKonstantin Ananyev ret = rte_validate_tx_offload(m); 2757b3fc5a1aSKonstantin Ananyev if (ret != 0) { 2758baeed5f4SMichal Krawczyk rte_errno = -ret; 2759b3fc5a1aSKonstantin Ananyev return i; 2760b3fc5a1aSKonstantin Ananyev } 2761b3fc5a1aSKonstantin Ananyev #endif 276283277a7cSJakub Palider 2763e8c838fdSMichal Krawczyk /* Verify HW support for requested offloads and determine if 2764e8c838fdSMichal Krawczyk * pseudo header checksum is needed. 276583277a7cSJakub Palider */ 2766e8c838fdSMichal Krawczyk need_pseudo_csum = false; 2767daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_IPV4) { 2768daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM && 2769e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L3_IPV4_CSUM)) { 2770e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2771e8c838fdSMichal Krawczyk return i; 2772e8c838fdSMichal Krawczyk } 277383277a7cSJakub Palider 2774daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_TCP_SEG && 2775e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_IPV4_TSO)) { 2776e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2777e8c838fdSMichal Krawczyk return i; 2778e8c838fdSMichal Krawczyk } 2779e8c838fdSMichal Krawczyk 2780e8c838fdSMichal Krawczyk /* Check HW capabilities and if pseudo csum is needed 2781e8c838fdSMichal Krawczyk * for L4 offloads. 2782e8c838fdSMichal Krawczyk */ 2783daa02b5cSOlivier Matz if (l4_csum_flag != RTE_MBUF_F_TX_L4_NO_CKSUM && 2784e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L4_IPV4_CSUM)) { 2785e8c838fdSMichal Krawczyk if (dev_offload_capa & 2786e8c838fdSMichal Krawczyk ENA_L4_IPV4_CSUM_PARTIAL) { 2787e8c838fdSMichal Krawczyk need_pseudo_csum = true; 2788e8c838fdSMichal Krawczyk } else { 2789e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2790e8c838fdSMichal Krawczyk return i; 2791e8c838fdSMichal Krawczyk } 2792e8c838fdSMichal Krawczyk } 2793e8c838fdSMichal Krawczyk 2794e8c838fdSMichal Krawczyk /* Parse the DF flag */ 2795e8c838fdSMichal Krawczyk ip_hdr = rte_pktmbuf_mtod_offset(m, 2796e8c838fdSMichal Krawczyk struct rte_ipv4_hdr *, m->l2_len); 2797e8c838fdSMichal Krawczyk frag_field = rte_be_to_cpu_16(ip_hdr->fragment_offset); 2798e8c838fdSMichal Krawczyk if (frag_field & RTE_IPV4_HDR_DF_FLAG) { 2799e8c838fdSMichal Krawczyk m->packet_type |= RTE_PTYPE_L4_NONFRAG; 2800daa02b5cSOlivier Matz } else if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 2801e8c838fdSMichal Krawczyk /* In case we are supposed to TSO and have DF 2802e8c838fdSMichal Krawczyk * not set (DF=0) hardware must be provided with 2803e8c838fdSMichal Krawczyk * partial checksum. 2804e8c838fdSMichal Krawczyk */ 2805e8c838fdSMichal Krawczyk need_pseudo_csum = true; 2806e8c838fdSMichal Krawczyk } 2807daa02b5cSOlivier Matz } else if (ol_flags & RTE_MBUF_F_TX_IPV6) { 2808e8c838fdSMichal Krawczyk /* There is no support for IPv6 TSO as for now. */ 2809daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 2810e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2811e8c838fdSMichal Krawczyk return i; 2812e8c838fdSMichal Krawczyk } 2813e8c838fdSMichal Krawczyk 2814e8c838fdSMichal Krawczyk /* Check HW capabilities and if pseudo csum is needed */ 2815daa02b5cSOlivier Matz if (l4_csum_flag != RTE_MBUF_F_TX_L4_NO_CKSUM && 2816e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L4_IPV6_CSUM)) { 2817e8c838fdSMichal Krawczyk if (dev_offload_capa & 2818e8c838fdSMichal Krawczyk ENA_L4_IPV6_CSUM_PARTIAL) { 2819e8c838fdSMichal Krawczyk need_pseudo_csum = true; 2820e8c838fdSMichal Krawczyk } else { 2821e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2822e8c838fdSMichal Krawczyk return i; 2823e8c838fdSMichal Krawczyk } 2824e8c838fdSMichal Krawczyk } 2825e8c838fdSMichal Krawczyk } 2826e8c838fdSMichal Krawczyk 2827e8c838fdSMichal Krawczyk if (need_pseudo_csum) { 2828e8c838fdSMichal Krawczyk ret = rte_net_intel_cksum_flags_prepare(m, ol_flags); 2829b3fc5a1aSKonstantin Ananyev if (ret != 0) { 2830baeed5f4SMichal Krawczyk rte_errno = -ret; 2831b3fc5a1aSKonstantin Ananyev return i; 2832b3fc5a1aSKonstantin Ananyev } 2833b3fc5a1aSKonstantin Ananyev } 2834e8c838fdSMichal Krawczyk } 2835b3fc5a1aSKonstantin Ananyev 2836b3fc5a1aSKonstantin Ananyev return i; 2837b3fc5a1aSKonstantin Ananyev } 2838b3fc5a1aSKonstantin Ananyev 2839f01f060cSRafal Kozik static void ena_update_hints(struct ena_adapter *adapter, 2840f01f060cSRafal Kozik struct ena_admin_ena_hw_hints *hints) 2841f01f060cSRafal Kozik { 2842f01f060cSRafal Kozik if (hints->admin_completion_tx_timeout) 2843f01f060cSRafal Kozik adapter->ena_dev.admin_queue.completion_timeout = 2844f01f060cSRafal Kozik hints->admin_completion_tx_timeout * 1000; 2845f01f060cSRafal Kozik 2846f01f060cSRafal Kozik if (hints->mmio_read_timeout) 2847f01f060cSRafal Kozik /* convert to usec */ 2848f01f060cSRafal Kozik adapter->ena_dev.mmio_read.reg_read_to = 2849f01f060cSRafal Kozik hints->mmio_read_timeout * 1000; 2850d9b8b106SMichal Krawczyk 2851d9b8b106SMichal Krawczyk if (hints->driver_watchdog_timeout) { 2852d9b8b106SMichal Krawczyk if (hints->driver_watchdog_timeout == ENA_HW_HINTS_NO_TIMEOUT) 2853d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = ENA_HW_HINTS_NO_TIMEOUT; 2854d9b8b106SMichal Krawczyk else 2855d9b8b106SMichal Krawczyk // Convert msecs to ticks 2856d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = 2857d9b8b106SMichal Krawczyk (hints->driver_watchdog_timeout * 2858d9b8b106SMichal Krawczyk rte_get_timer_hz()) / 1000; 2859d9b8b106SMichal Krawczyk } 2860f01f060cSRafal Kozik } 2861f01f060cSRafal Kozik 286236278b82SMichal Krawczyk static void ena_tx_map_mbuf(struct ena_ring *tx_ring, 286336278b82SMichal Krawczyk struct ena_tx_buffer *tx_info, 286436278b82SMichal Krawczyk struct rte_mbuf *mbuf, 286536278b82SMichal Krawczyk void **push_header, 286636278b82SMichal Krawczyk uint16_t *header_len) 286736278b82SMichal Krawczyk { 286836278b82SMichal Krawczyk struct ena_com_buf *ena_buf; 286936278b82SMichal Krawczyk uint16_t delta, seg_len, push_len; 287036278b82SMichal Krawczyk 287136278b82SMichal Krawczyk delta = 0; 287236278b82SMichal Krawczyk seg_len = mbuf->data_len; 287336278b82SMichal Krawczyk 287436278b82SMichal Krawczyk tx_info->mbuf = mbuf; 287536278b82SMichal Krawczyk ena_buf = tx_info->bufs; 287636278b82SMichal Krawczyk 287736278b82SMichal Krawczyk if (tx_ring->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 287836278b82SMichal Krawczyk /* 287936278b82SMichal Krawczyk * Tx header might be (and will be in most cases) smaller than 288036278b82SMichal Krawczyk * tx_max_header_size. But it's not an issue to send more data 288136278b82SMichal Krawczyk * to the device, than actually needed if the mbuf size is 288236278b82SMichal Krawczyk * greater than tx_max_header_size. 288336278b82SMichal Krawczyk */ 288436278b82SMichal Krawczyk push_len = RTE_MIN(mbuf->pkt_len, tx_ring->tx_max_header_size); 288536278b82SMichal Krawczyk *header_len = push_len; 288636278b82SMichal Krawczyk 288736278b82SMichal Krawczyk if (likely(push_len <= seg_len)) { 288836278b82SMichal Krawczyk /* If the push header is in the single segment, then 288936278b82SMichal Krawczyk * just point it to the 1st mbuf data. 289036278b82SMichal Krawczyk */ 289136278b82SMichal Krawczyk *push_header = rte_pktmbuf_mtod(mbuf, uint8_t *); 289236278b82SMichal Krawczyk } else { 289336278b82SMichal Krawczyk /* If the push header lays in the several segments, copy 289436278b82SMichal Krawczyk * it to the intermediate buffer. 289536278b82SMichal Krawczyk */ 289636278b82SMichal Krawczyk rte_pktmbuf_read(mbuf, 0, push_len, 289736278b82SMichal Krawczyk tx_ring->push_buf_intermediate_buf); 289836278b82SMichal Krawczyk *push_header = tx_ring->push_buf_intermediate_buf; 289936278b82SMichal Krawczyk delta = push_len - seg_len; 290036278b82SMichal Krawczyk } 290136278b82SMichal Krawczyk } else { 290236278b82SMichal Krawczyk *push_header = NULL; 290336278b82SMichal Krawczyk *header_len = 0; 290436278b82SMichal Krawczyk push_len = 0; 290536278b82SMichal Krawczyk } 290636278b82SMichal Krawczyk 290736278b82SMichal Krawczyk /* Process first segment taking into consideration pushed header */ 290836278b82SMichal Krawczyk if (seg_len > push_len) { 290936278b82SMichal Krawczyk ena_buf->paddr = mbuf->buf_iova + 291036278b82SMichal Krawczyk mbuf->data_off + 291136278b82SMichal Krawczyk push_len; 291236278b82SMichal Krawczyk ena_buf->len = seg_len - push_len; 291336278b82SMichal Krawczyk ena_buf++; 291436278b82SMichal Krawczyk tx_info->num_of_bufs++; 291536278b82SMichal Krawczyk } 291636278b82SMichal Krawczyk 291736278b82SMichal Krawczyk while ((mbuf = mbuf->next) != NULL) { 291836278b82SMichal Krawczyk seg_len = mbuf->data_len; 291936278b82SMichal Krawczyk 292036278b82SMichal Krawczyk /* Skip mbufs if whole data is pushed as a header */ 292136278b82SMichal Krawczyk if (unlikely(delta > seg_len)) { 292236278b82SMichal Krawczyk delta -= seg_len; 292336278b82SMichal Krawczyk continue; 292436278b82SMichal Krawczyk } 292536278b82SMichal Krawczyk 292636278b82SMichal Krawczyk ena_buf->paddr = mbuf->buf_iova + mbuf->data_off + delta; 292736278b82SMichal Krawczyk ena_buf->len = seg_len - delta; 292836278b82SMichal Krawczyk ena_buf++; 292936278b82SMichal Krawczyk tx_info->num_of_bufs++; 293036278b82SMichal Krawczyk 293136278b82SMichal Krawczyk delta = 0; 293236278b82SMichal Krawczyk } 293336278b82SMichal Krawczyk } 293436278b82SMichal Krawczyk 293536278b82SMichal Krawczyk static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf) 293636278b82SMichal Krawczyk { 293736278b82SMichal Krawczyk struct ena_tx_buffer *tx_info; 293836278b82SMichal Krawczyk struct ena_com_tx_ctx ena_tx_ctx = { { 0 } }; 293936278b82SMichal Krawczyk uint16_t next_to_use; 294036278b82SMichal Krawczyk uint16_t header_len; 294136278b82SMichal Krawczyk uint16_t req_id; 294236278b82SMichal Krawczyk void *push_header; 294336278b82SMichal Krawczyk int nb_hw_desc; 294436278b82SMichal Krawczyk int rc; 294536278b82SMichal Krawczyk 294696ffa8a7SMichal Krawczyk /* Checking for space for 2 additional metadata descriptors due to 294796ffa8a7SMichal Krawczyk * possible header split and metadata descriptor 294896ffa8a7SMichal Krawczyk */ 294996ffa8a7SMichal Krawczyk if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq, 295096ffa8a7SMichal Krawczyk mbuf->nb_segs + 2)) { 295196ffa8a7SMichal Krawczyk PMD_DRV_LOG(DEBUG, "Not enough space in the tx queue\n"); 295296ffa8a7SMichal Krawczyk return ENA_COM_NO_MEM; 295396ffa8a7SMichal Krawczyk } 295436278b82SMichal Krawczyk 295536278b82SMichal Krawczyk next_to_use = tx_ring->next_to_use; 295636278b82SMichal Krawczyk 295736278b82SMichal Krawczyk req_id = tx_ring->empty_tx_reqs[next_to_use]; 295836278b82SMichal Krawczyk tx_info = &tx_ring->tx_buffer_info[req_id]; 295936278b82SMichal Krawczyk tx_info->num_of_bufs = 0; 29603d47e9b1SMichal Krawczyk RTE_ASSERT(tx_info->mbuf == NULL); 296136278b82SMichal Krawczyk 296236278b82SMichal Krawczyk ena_tx_map_mbuf(tx_ring, tx_info, mbuf, &push_header, &header_len); 296336278b82SMichal Krawczyk 296436278b82SMichal Krawczyk ena_tx_ctx.ena_bufs = tx_info->bufs; 296536278b82SMichal Krawczyk ena_tx_ctx.push_header = push_header; 296636278b82SMichal Krawczyk ena_tx_ctx.num_bufs = tx_info->num_of_bufs; 296736278b82SMichal Krawczyk ena_tx_ctx.req_id = req_id; 296836278b82SMichal Krawczyk ena_tx_ctx.header_len = header_len; 296936278b82SMichal Krawczyk 297036278b82SMichal Krawczyk /* Set Tx offloads flags, if applicable */ 297136278b82SMichal Krawczyk ena_tx_mbuf_prepare(mbuf, &ena_tx_ctx, tx_ring->offloads, 297236278b82SMichal Krawczyk tx_ring->disable_meta_caching); 297336278b82SMichal Krawczyk 297436278b82SMichal Krawczyk if (unlikely(ena_com_is_doorbell_needed(tx_ring->ena_com_io_sq, 297536278b82SMichal Krawczyk &ena_tx_ctx))) { 29760a001d69SMichal Krawczyk PMD_TX_LOG(DEBUG, 2977617898d1SMichal Krawczyk "LLQ Tx max burst size of queue %d achieved, writing doorbell to send burst\n", 297836278b82SMichal Krawczyk tx_ring->id); 297936278b82SMichal Krawczyk ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); 29801f949ad9SAmit Bernstein tx_ring->tx_stats.doorbells++; 29811d973d8fSIgor Chauskin tx_ring->pkts_without_db = false; 298236278b82SMichal Krawczyk } 298336278b82SMichal Krawczyk 298436278b82SMichal Krawczyk /* prepare the packet's descriptors to dma engine */ 298536278b82SMichal Krawczyk rc = ena_com_prepare_tx(tx_ring->ena_com_io_sq, &ena_tx_ctx, 298636278b82SMichal Krawczyk &nb_hw_desc); 298736278b82SMichal Krawczyk if (unlikely(rc)) { 2988b57e1053SMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to prepare Tx buffers, rc: %d\n", rc); 298936278b82SMichal Krawczyk ++tx_ring->tx_stats.prepare_ctx_err; 29902bae75eaSDawid Gorecki ena_trigger_reset(tx_ring->adapter, 29912bae75eaSDawid Gorecki ENA_REGS_RESET_DRIVER_INVALID_STATE); 299236278b82SMichal Krawczyk return rc; 299336278b82SMichal Krawczyk } 299436278b82SMichal Krawczyk 299536278b82SMichal Krawczyk tx_info->tx_descs = nb_hw_desc; 2996f93e20e5SMichal Krawczyk tx_info->timestamp = rte_get_timer_cycles(); 299736278b82SMichal Krawczyk 299836278b82SMichal Krawczyk tx_ring->tx_stats.cnt++; 299936278b82SMichal Krawczyk tx_ring->tx_stats.bytes += mbuf->pkt_len; 300036278b82SMichal Krawczyk 300136278b82SMichal Krawczyk tx_ring->next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, 300236278b82SMichal Krawczyk tx_ring->size_mask); 300336278b82SMichal Krawczyk 300436278b82SMichal Krawczyk return 0; 300536278b82SMichal Krawczyk } 300636278b82SMichal Krawczyk 3007c339f538SDawid Gorecki static __rte_always_inline size_t 3008c339f538SDawid Gorecki ena_tx_cleanup_mbuf_fast(struct rte_mbuf **mbufs_to_clean, 3009c339f538SDawid Gorecki struct rte_mbuf *mbuf, 3010c339f538SDawid Gorecki size_t mbuf_cnt, 3011c339f538SDawid Gorecki size_t buf_size) 3012c339f538SDawid Gorecki { 3013c339f538SDawid Gorecki struct rte_mbuf *m_next; 3014c339f538SDawid Gorecki 3015c339f538SDawid Gorecki while (mbuf != NULL) { 3016c339f538SDawid Gorecki m_next = mbuf->next; 3017c339f538SDawid Gorecki mbufs_to_clean[mbuf_cnt++] = mbuf; 3018c339f538SDawid Gorecki if (mbuf_cnt == buf_size) { 3019c339f538SDawid Gorecki rte_mempool_put_bulk(mbufs_to_clean[0]->pool, (void **)mbufs_to_clean, 3020c339f538SDawid Gorecki (unsigned int)mbuf_cnt); 3021c339f538SDawid Gorecki mbuf_cnt = 0; 3022c339f538SDawid Gorecki } 3023c339f538SDawid Gorecki mbuf = m_next; 3024c339f538SDawid Gorecki } 3025c339f538SDawid Gorecki 3026c339f538SDawid Gorecki return mbuf_cnt; 3027c339f538SDawid Gorecki } 3028c339f538SDawid Gorecki 3029a52b317eSDawid Gorecki static int ena_tx_cleanup(void *txp, uint32_t free_pkt_cnt) 303036278b82SMichal Krawczyk { 3031c339f538SDawid Gorecki struct rte_mbuf *mbufs_to_clean[ENA_CLEANUP_BUF_SIZE]; 3032a52b317eSDawid Gorecki struct ena_ring *tx_ring = (struct ena_ring *)txp; 3033c339f538SDawid Gorecki size_t mbuf_cnt = 0; 303436278b82SMichal Krawczyk unsigned int total_tx_descs = 0; 3035a52b317eSDawid Gorecki unsigned int total_tx_pkts = 0; 3036005064e5SMichal Krawczyk uint16_t cleanup_budget; 303736278b82SMichal Krawczyk uint16_t next_to_clean = tx_ring->next_to_clean; 3038c339f538SDawid Gorecki bool fast_free = tx_ring->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 303936278b82SMichal Krawczyk 3040a52b317eSDawid Gorecki /* 3041a52b317eSDawid Gorecki * If free_pkt_cnt is equal to 0, it means that the user requested 3042a52b317eSDawid Gorecki * full cleanup, so attempt to release all Tx descriptors 3043a52b317eSDawid Gorecki * (ring_size - 1 -> size_mask) 3044a52b317eSDawid Gorecki */ 3045a52b317eSDawid Gorecki cleanup_budget = (free_pkt_cnt == 0) ? tx_ring->size_mask : free_pkt_cnt; 304636278b82SMichal Krawczyk 3047a52b317eSDawid Gorecki while (likely(total_tx_pkts < cleanup_budget)) { 304836278b82SMichal Krawczyk struct rte_mbuf *mbuf; 304936278b82SMichal Krawczyk struct ena_tx_buffer *tx_info; 305036278b82SMichal Krawczyk uint16_t req_id; 305136278b82SMichal Krawczyk 305236278b82SMichal Krawczyk if (ena_com_tx_comp_req_id_get(tx_ring->ena_com_io_cq, &req_id) != 0) 305336278b82SMichal Krawczyk break; 305436278b82SMichal Krawczyk 305536278b82SMichal Krawczyk if (unlikely(validate_tx_req_id(tx_ring, req_id) != 0)) 305636278b82SMichal Krawczyk break; 305736278b82SMichal Krawczyk 305836278b82SMichal Krawczyk /* Get Tx info & store how many descs were processed */ 305936278b82SMichal Krawczyk tx_info = &tx_ring->tx_buffer_info[req_id]; 3060f93e20e5SMichal Krawczyk tx_info->timestamp = 0; 306136278b82SMichal Krawczyk 306236278b82SMichal Krawczyk mbuf = tx_info->mbuf; 3063c339f538SDawid Gorecki if (fast_free) { 3064c339f538SDawid Gorecki mbuf_cnt = ena_tx_cleanup_mbuf_fast(mbufs_to_clean, mbuf, mbuf_cnt, 3065c339f538SDawid Gorecki ENA_CLEANUP_BUF_SIZE); 3066c339f538SDawid Gorecki } else { 306736278b82SMichal Krawczyk rte_pktmbuf_free(mbuf); 3068c339f538SDawid Gorecki } 306936278b82SMichal Krawczyk 307036278b82SMichal Krawczyk tx_info->mbuf = NULL; 307136278b82SMichal Krawczyk tx_ring->empty_tx_reqs[next_to_clean] = req_id; 307236278b82SMichal Krawczyk 307336278b82SMichal Krawczyk total_tx_descs += tx_info->tx_descs; 3074a52b317eSDawid Gorecki total_tx_pkts++; 307536278b82SMichal Krawczyk 307636278b82SMichal Krawczyk /* Put back descriptor to the ring for reuse */ 307736278b82SMichal Krawczyk next_to_clean = ENA_IDX_NEXT_MASKED(next_to_clean, 307836278b82SMichal Krawczyk tx_ring->size_mask); 307936278b82SMichal Krawczyk } 308036278b82SMichal Krawczyk 308136278b82SMichal Krawczyk if (likely(total_tx_descs > 0)) { 308236278b82SMichal Krawczyk /* acknowledge completion of sent packets */ 308336278b82SMichal Krawczyk tx_ring->next_to_clean = next_to_clean; 308436278b82SMichal Krawczyk ena_com_comp_ack(tx_ring->ena_com_io_sq, total_tx_descs); 308536278b82SMichal Krawczyk ena_com_update_dev_comp_head(tx_ring->ena_com_io_cq); 308636278b82SMichal Krawczyk } 3087f93e20e5SMichal Krawczyk 3088c339f538SDawid Gorecki if (mbuf_cnt != 0) 3089c339f538SDawid Gorecki rte_mempool_put_bulk(mbufs_to_clean[0]->pool, 3090c339f538SDawid Gorecki (void **)mbufs_to_clean, mbuf_cnt); 3091c339f538SDawid Gorecki 3092a52b317eSDawid Gorecki /* Notify completion handler that full cleanup was performed */ 3093a52b317eSDawid Gorecki if (free_pkt_cnt == 0 || total_tx_pkts < cleanup_budget) 3094f93e20e5SMichal Krawczyk tx_ring->last_cleanup_ticks = rte_get_timer_cycles(); 3095a52b317eSDawid Gorecki 3096a52b317eSDawid Gorecki return total_tx_pkts; 309736278b82SMichal Krawczyk } 309836278b82SMichal Krawczyk 30991173fca2SJan Medala static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 31001173fca2SJan Medala uint16_t nb_pkts) 31011173fca2SJan Medala { 31021173fca2SJan Medala struct ena_ring *tx_ring = (struct ena_ring *)(tx_queue); 3103005064e5SMichal Krawczyk int available_desc; 310474456796SMichal Krawczyk uint16_t sent_idx = 0; 31051173fca2SJan Medala 31060a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_TX 31071173fca2SJan Medala /* Check adapter state */ 31081173fca2SJan Medala if (unlikely(tx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) { 31090a001d69SMichal Krawczyk PMD_TX_LOG(ALERT, 31101173fca2SJan Medala "Trying to xmit pkts while device is NOT running\n"); 31111173fca2SJan Medala return 0; 31121173fca2SJan Medala } 31130a001d69SMichal Krawczyk #endif 31141173fca2SJan Medala 311567216c31SMichal Krawczyk available_desc = ena_com_free_q_entries(tx_ring->ena_com_io_sq); 311667216c31SMichal Krawczyk if (available_desc < tx_ring->tx_free_thresh) 3117a52b317eSDawid Gorecki ena_tx_cleanup((void *)tx_ring, 0); 311867216c31SMichal Krawczyk 31191173fca2SJan Medala for (sent_idx = 0; sent_idx < nb_pkts; sent_idx++) { 312036278b82SMichal Krawczyk if (ena_xmit_mbuf(tx_ring, tx_pkts[sent_idx])) 31212061fe41SRafal Kozik break; 31221d973d8fSIgor Chauskin tx_ring->pkts_without_db = true; 312336278b82SMichal Krawczyk rte_prefetch0(tx_pkts[ENA_IDX_ADD_MASKED(sent_idx, 4, 312436278b82SMichal Krawczyk tx_ring->size_mask)]); 31252fca2a98SMichal Krawczyk } 31262fca2a98SMichal Krawczyk 31275e02e19eSJan Medala /* If there are ready packets to be xmitted... */ 31281d973d8fSIgor Chauskin if (likely(tx_ring->pkts_without_db)) { 31295e02e19eSJan Medala /* ...let HW do its best :-) */ 31301173fca2SJan Medala ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); 313145b6d861SMichal Krawczyk tx_ring->tx_stats.doorbells++; 31321d973d8fSIgor Chauskin tx_ring->pkts_without_db = false; 31335e02e19eSJan Medala } 31345e02e19eSJan Medala 31357830e905SSolganik Alexander tx_ring->tx_stats.available_desc = 3136b2b02edeSMichal Krawczyk ena_com_free_q_entries(tx_ring->ena_com_io_sq); 31377830e905SSolganik Alexander tx_ring->tx_stats.tx_poll++; 31387830e905SSolganik Alexander 31391173fca2SJan Medala return sent_idx; 31401173fca2SJan Medala } 31411173fca2SJan Medala 3142e3595539SStanislaw Kardach int ena_copy_eni_stats(struct ena_adapter *adapter, struct ena_stats_eni *stats) 314345718adaSMichal Krawczyk { 314445718adaSMichal Krawczyk int rc; 314545718adaSMichal Krawczyk 314645718adaSMichal Krawczyk rte_spinlock_lock(&adapter->admin_lock); 3147e3595539SStanislaw Kardach /* Retrieve and store the latest statistics from the AQ. This ensures 3148e3595539SStanislaw Kardach * that previous value is returned in case of a com error. 3149e3595539SStanislaw Kardach */ 3150e3595539SStanislaw Kardach rc = ENA_PROXY(adapter, ena_com_get_eni_stats, &adapter->ena_dev, 3151e3595539SStanislaw Kardach (struct ena_admin_eni_stats *)stats); 315245718adaSMichal Krawczyk rte_spinlock_unlock(&adapter->admin_lock); 315345718adaSMichal Krawczyk if (rc != 0) { 315445718adaSMichal Krawczyk if (rc == ENA_COM_UNSUPPORTED) { 315545718adaSMichal Krawczyk PMD_DRV_LOG(DEBUG, 3156617898d1SMichal Krawczyk "Retrieving ENI metrics is not supported\n"); 315745718adaSMichal Krawczyk } else { 315845718adaSMichal Krawczyk PMD_DRV_LOG(WARNING, 3159617898d1SMichal Krawczyk "Failed to get ENI metrics, rc: %d\n", rc); 316045718adaSMichal Krawczyk } 316145718adaSMichal Krawczyk return rc; 316245718adaSMichal Krawczyk } 316345718adaSMichal Krawczyk 316445718adaSMichal Krawczyk return 0; 316545718adaSMichal Krawczyk } 316645718adaSMichal Krawczyk 31677830e905SSolganik Alexander /** 31687830e905SSolganik Alexander * DPDK callback to retrieve names of extended device statistics 31697830e905SSolganik Alexander * 31707830e905SSolganik Alexander * @param dev 31717830e905SSolganik Alexander * Pointer to Ethernet device structure. 31727830e905SSolganik Alexander * @param[out] xstats_names 31737830e905SSolganik Alexander * Buffer to insert names into. 31747830e905SSolganik Alexander * @param n 31757830e905SSolganik Alexander * Number of names. 31767830e905SSolganik Alexander * 31777830e905SSolganik Alexander * @return 31787830e905SSolganik Alexander * Number of xstats names. 31797830e905SSolganik Alexander */ 31807830e905SSolganik Alexander static int ena_xstats_get_names(struct rte_eth_dev *dev, 31817830e905SSolganik Alexander struct rte_eth_xstat_name *xstats_names, 31827830e905SSolganik Alexander unsigned int n) 31837830e905SSolganik Alexander { 3184aab58857SStanislaw Kardach unsigned int xstats_count = ena_xstats_calc_num(dev->data); 31857830e905SSolganik Alexander unsigned int stat, i, count = 0; 31867830e905SSolganik Alexander 31877830e905SSolganik Alexander if (n < xstats_count || !xstats_names) 31887830e905SSolganik Alexander return xstats_count; 31897830e905SSolganik Alexander 31907830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) 31917830e905SSolganik Alexander strcpy(xstats_names[count].name, 31927830e905SSolganik Alexander ena_stats_global_strings[stat].name); 31937830e905SSolganik Alexander 319445718adaSMichal Krawczyk for (stat = 0; stat < ENA_STATS_ARRAY_ENI; stat++, count++) 319545718adaSMichal Krawczyk strcpy(xstats_names[count].name, 319645718adaSMichal Krawczyk ena_stats_eni_strings[stat].name); 319745718adaSMichal Krawczyk 31987830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) 31997830e905SSolganik Alexander for (i = 0; i < dev->data->nb_rx_queues; i++, count++) 32007830e905SSolganik Alexander snprintf(xstats_names[count].name, 32017830e905SSolganik Alexander sizeof(xstats_names[count].name), 32027830e905SSolganik Alexander "rx_q%d_%s", i, 32037830e905SSolganik Alexander ena_stats_rx_strings[stat].name); 32047830e905SSolganik Alexander 32057830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_TX; stat++) 32067830e905SSolganik Alexander for (i = 0; i < dev->data->nb_tx_queues; i++, count++) 32077830e905SSolganik Alexander snprintf(xstats_names[count].name, 32087830e905SSolganik Alexander sizeof(xstats_names[count].name), 32097830e905SSolganik Alexander "tx_q%d_%s", i, 32107830e905SSolganik Alexander ena_stats_tx_strings[stat].name); 32117830e905SSolganik Alexander 32127830e905SSolganik Alexander return xstats_count; 32137830e905SSolganik Alexander } 32147830e905SSolganik Alexander 32157830e905SSolganik Alexander /** 32163cec73faSMichal Krawczyk * DPDK callback to retrieve names of extended device statistics for the given 32173cec73faSMichal Krawczyk * ids. 32183cec73faSMichal Krawczyk * 32193cec73faSMichal Krawczyk * @param dev 32203cec73faSMichal Krawczyk * Pointer to Ethernet device structure. 32213cec73faSMichal Krawczyk * @param[out] xstats_names 32223cec73faSMichal Krawczyk * Buffer to insert names into. 32233cec73faSMichal Krawczyk * @param ids 32243cec73faSMichal Krawczyk * IDs array for which the names should be retrieved. 32253cec73faSMichal Krawczyk * @param size 32263cec73faSMichal Krawczyk * Number of ids. 32273cec73faSMichal Krawczyk * 32283cec73faSMichal Krawczyk * @return 32293cec73faSMichal Krawczyk * Positive value: number of xstats names. Negative value: error code. 32303cec73faSMichal Krawczyk */ 32313cec73faSMichal Krawczyk static int ena_xstats_get_names_by_id(struct rte_eth_dev *dev, 32323cec73faSMichal Krawczyk const uint64_t *ids, 32333cec73faSMichal Krawczyk struct rte_eth_xstat_name *xstats_names, 32343cec73faSMichal Krawczyk unsigned int size) 32353cec73faSMichal Krawczyk { 32363cec73faSMichal Krawczyk uint64_t xstats_count = ena_xstats_calc_num(dev->data); 32373cec73faSMichal Krawczyk uint64_t id, qid; 32383cec73faSMichal Krawczyk unsigned int i; 32393cec73faSMichal Krawczyk 32403cec73faSMichal Krawczyk if (xstats_names == NULL) 32413cec73faSMichal Krawczyk return xstats_count; 32423cec73faSMichal Krawczyk 32433cec73faSMichal Krawczyk for (i = 0; i < size; ++i) { 32443cec73faSMichal Krawczyk id = ids[i]; 32453cec73faSMichal Krawczyk if (id > xstats_count) { 32463cec73faSMichal Krawczyk PMD_DRV_LOG(ERR, 32473cec73faSMichal Krawczyk "ID value out of range: id=%" PRIu64 ", xstats_num=%" PRIu64 "\n", 32483cec73faSMichal Krawczyk id, xstats_count); 32493cec73faSMichal Krawczyk return -EINVAL; 32503cec73faSMichal Krawczyk } 32513cec73faSMichal Krawczyk 32523cec73faSMichal Krawczyk if (id < ENA_STATS_ARRAY_GLOBAL) { 32533cec73faSMichal Krawczyk strcpy(xstats_names[i].name, 32543cec73faSMichal Krawczyk ena_stats_global_strings[id].name); 32553cec73faSMichal Krawczyk continue; 32563cec73faSMichal Krawczyk } 32573cec73faSMichal Krawczyk 32583cec73faSMichal Krawczyk id -= ENA_STATS_ARRAY_GLOBAL; 32593cec73faSMichal Krawczyk if (id < ENA_STATS_ARRAY_ENI) { 32603cec73faSMichal Krawczyk strcpy(xstats_names[i].name, 32613cec73faSMichal Krawczyk ena_stats_eni_strings[id].name); 32623cec73faSMichal Krawczyk continue; 32633cec73faSMichal Krawczyk } 32643cec73faSMichal Krawczyk 32653cec73faSMichal Krawczyk id -= ENA_STATS_ARRAY_ENI; 32663cec73faSMichal Krawczyk if (id < ENA_STATS_ARRAY_RX) { 32673cec73faSMichal Krawczyk qid = id / dev->data->nb_rx_queues; 32683cec73faSMichal Krawczyk id %= dev->data->nb_rx_queues; 32693cec73faSMichal Krawczyk snprintf(xstats_names[i].name, 32703cec73faSMichal Krawczyk sizeof(xstats_names[i].name), 32713cec73faSMichal Krawczyk "rx_q%" PRIu64 "d_%s", 32723cec73faSMichal Krawczyk qid, ena_stats_rx_strings[id].name); 32733cec73faSMichal Krawczyk continue; 32743cec73faSMichal Krawczyk } 32753cec73faSMichal Krawczyk 32763cec73faSMichal Krawczyk id -= ENA_STATS_ARRAY_RX; 32773cec73faSMichal Krawczyk /* Although this condition is not needed, it was added for 32783cec73faSMichal Krawczyk * compatibility if new xstat structure would be ever added. 32793cec73faSMichal Krawczyk */ 32803cec73faSMichal Krawczyk if (id < ENA_STATS_ARRAY_TX) { 32813cec73faSMichal Krawczyk qid = id / dev->data->nb_tx_queues; 32823cec73faSMichal Krawczyk id %= dev->data->nb_tx_queues; 32833cec73faSMichal Krawczyk snprintf(xstats_names[i].name, 32843cec73faSMichal Krawczyk sizeof(xstats_names[i].name), 32853cec73faSMichal Krawczyk "tx_q%" PRIu64 "_%s", 32863cec73faSMichal Krawczyk qid, ena_stats_tx_strings[id].name); 32873cec73faSMichal Krawczyk continue; 32883cec73faSMichal Krawczyk } 32893cec73faSMichal Krawczyk } 32903cec73faSMichal Krawczyk 32913cec73faSMichal Krawczyk return i; 32923cec73faSMichal Krawczyk } 32933cec73faSMichal Krawczyk 32943cec73faSMichal Krawczyk /** 32957830e905SSolganik Alexander * DPDK callback to get extended device statistics. 32967830e905SSolganik Alexander * 32977830e905SSolganik Alexander * @param dev 32987830e905SSolganik Alexander * Pointer to Ethernet device structure. 32997830e905SSolganik Alexander * @param[out] stats 33007830e905SSolganik Alexander * Stats table output buffer. 33017830e905SSolganik Alexander * @param n 33027830e905SSolganik Alexander * The size of the stats table. 33037830e905SSolganik Alexander * 33047830e905SSolganik Alexander * @return 33057830e905SSolganik Alexander * Number of xstats on success, negative on failure. 33067830e905SSolganik Alexander */ 33077830e905SSolganik Alexander static int ena_xstats_get(struct rte_eth_dev *dev, 33087830e905SSolganik Alexander struct rte_eth_xstat *xstats, 33097830e905SSolganik Alexander unsigned int n) 33107830e905SSolganik Alexander { 3311890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 3312aab58857SStanislaw Kardach unsigned int xstats_count = ena_xstats_calc_num(dev->data); 3313e3595539SStanislaw Kardach struct ena_stats_eni eni_stats; 33147830e905SSolganik Alexander unsigned int stat, i, count = 0; 33157830e905SSolganik Alexander int stat_offset; 33167830e905SSolganik Alexander void *stats_begin; 33177830e905SSolganik Alexander 33187830e905SSolganik Alexander if (n < xstats_count) 33197830e905SSolganik Alexander return xstats_count; 33207830e905SSolganik Alexander 33217830e905SSolganik Alexander if (!xstats) 33227830e905SSolganik Alexander return 0; 33237830e905SSolganik Alexander 33247830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) { 3325493107fdSMichal Krawczyk stat_offset = ena_stats_global_strings[stat].stat_offset; 33267830e905SSolganik Alexander stats_begin = &adapter->dev_stats; 33277830e905SSolganik Alexander 33287830e905SSolganik Alexander xstats[count].id = count; 33297830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 33307830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 33317830e905SSolganik Alexander } 33327830e905SSolganik Alexander 333345718adaSMichal Krawczyk /* Even if the function below fails, we should copy previous (or initial 333445718adaSMichal Krawczyk * values) to keep structure of rte_eth_xstat consistent. 333545718adaSMichal Krawczyk */ 3336e3595539SStanislaw Kardach ena_copy_eni_stats(adapter, &eni_stats); 333745718adaSMichal Krawczyk for (stat = 0; stat < ENA_STATS_ARRAY_ENI; stat++, count++) { 333845718adaSMichal Krawczyk stat_offset = ena_stats_eni_strings[stat].stat_offset; 3339e3595539SStanislaw Kardach stats_begin = &eni_stats; 334045718adaSMichal Krawczyk 334145718adaSMichal Krawczyk xstats[count].id = count; 334245718adaSMichal Krawczyk xstats[count].value = *((uint64_t *) 334345718adaSMichal Krawczyk ((char *)stats_begin + stat_offset)); 334445718adaSMichal Krawczyk } 334545718adaSMichal Krawczyk 33467830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) { 33477830e905SSolganik Alexander for (i = 0; i < dev->data->nb_rx_queues; i++, count++) { 33487830e905SSolganik Alexander stat_offset = ena_stats_rx_strings[stat].stat_offset; 33497830e905SSolganik Alexander stats_begin = &adapter->rx_ring[i].rx_stats; 33507830e905SSolganik Alexander 33517830e905SSolganik Alexander xstats[count].id = count; 33527830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 33537830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 33547830e905SSolganik Alexander } 33557830e905SSolganik Alexander } 33567830e905SSolganik Alexander 33577830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_TX; stat++) { 33587830e905SSolganik Alexander for (i = 0; i < dev->data->nb_tx_queues; i++, count++) { 33597830e905SSolganik Alexander stat_offset = ena_stats_tx_strings[stat].stat_offset; 33607830e905SSolganik Alexander stats_begin = &adapter->tx_ring[i].rx_stats; 33617830e905SSolganik Alexander 33627830e905SSolganik Alexander xstats[count].id = count; 33637830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 33647830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 33657830e905SSolganik Alexander } 33667830e905SSolganik Alexander } 33677830e905SSolganik Alexander 33687830e905SSolganik Alexander return count; 33697830e905SSolganik Alexander } 33707830e905SSolganik Alexander 33717830e905SSolganik Alexander static int ena_xstats_get_by_id(struct rte_eth_dev *dev, 33727830e905SSolganik Alexander const uint64_t *ids, 33737830e905SSolganik Alexander uint64_t *values, 33747830e905SSolganik Alexander unsigned int n) 33757830e905SSolganik Alexander { 3376890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 3377e3595539SStanislaw Kardach struct ena_stats_eni eni_stats; 33787830e905SSolganik Alexander uint64_t id; 33797830e905SSolganik Alexander uint64_t rx_entries, tx_entries; 33807830e905SSolganik Alexander unsigned int i; 33817830e905SSolganik Alexander int qid; 33827830e905SSolganik Alexander int valid = 0; 338345718adaSMichal Krawczyk bool was_eni_copied = false; 338445718adaSMichal Krawczyk 33857830e905SSolganik Alexander for (i = 0; i < n; ++i) { 33867830e905SSolganik Alexander id = ids[i]; 33877830e905SSolganik Alexander /* Check if id belongs to global statistics */ 33887830e905SSolganik Alexander if (id < ENA_STATS_ARRAY_GLOBAL) { 33897830e905SSolganik Alexander values[i] = *((uint64_t *)&adapter->dev_stats + id); 33907830e905SSolganik Alexander ++valid; 33917830e905SSolganik Alexander continue; 33927830e905SSolganik Alexander } 33937830e905SSolganik Alexander 339445718adaSMichal Krawczyk /* Check if id belongs to ENI statistics */ 33957830e905SSolganik Alexander id -= ENA_STATS_ARRAY_GLOBAL; 339645718adaSMichal Krawczyk if (id < ENA_STATS_ARRAY_ENI) { 339745718adaSMichal Krawczyk /* Avoid reading ENI stats multiple times in a single 339845718adaSMichal Krawczyk * function call, as it requires communication with the 339945718adaSMichal Krawczyk * admin queue. 340045718adaSMichal Krawczyk */ 340145718adaSMichal Krawczyk if (!was_eni_copied) { 340245718adaSMichal Krawczyk was_eni_copied = true; 3403e3595539SStanislaw Kardach ena_copy_eni_stats(adapter, &eni_stats); 340445718adaSMichal Krawczyk } 3405e3595539SStanislaw Kardach values[i] = *((uint64_t *)&eni_stats + id); 340645718adaSMichal Krawczyk ++valid; 340745718adaSMichal Krawczyk continue; 340845718adaSMichal Krawczyk } 340945718adaSMichal Krawczyk 341045718adaSMichal Krawczyk /* Check if id belongs to rx queue statistics */ 341145718adaSMichal Krawczyk id -= ENA_STATS_ARRAY_ENI; 34127830e905SSolganik Alexander rx_entries = ENA_STATS_ARRAY_RX * dev->data->nb_rx_queues; 34137830e905SSolganik Alexander if (id < rx_entries) { 34147830e905SSolganik Alexander qid = id % dev->data->nb_rx_queues; 34157830e905SSolganik Alexander id /= dev->data->nb_rx_queues; 34167830e905SSolganik Alexander values[i] = *((uint64_t *) 34177830e905SSolganik Alexander &adapter->rx_ring[qid].rx_stats + id); 34187830e905SSolganik Alexander ++valid; 34197830e905SSolganik Alexander continue; 34207830e905SSolganik Alexander } 34217830e905SSolganik Alexander /* Check if id belongs to rx queue statistics */ 34227830e905SSolganik Alexander id -= rx_entries; 34237830e905SSolganik Alexander tx_entries = ENA_STATS_ARRAY_TX * dev->data->nb_tx_queues; 34247830e905SSolganik Alexander if (id < tx_entries) { 34257830e905SSolganik Alexander qid = id % dev->data->nb_tx_queues; 34267830e905SSolganik Alexander id /= dev->data->nb_tx_queues; 34277830e905SSolganik Alexander values[i] = *((uint64_t *) 34287830e905SSolganik Alexander &adapter->tx_ring[qid].tx_stats + id); 34297830e905SSolganik Alexander ++valid; 34307830e905SSolganik Alexander continue; 34317830e905SSolganik Alexander } 34327830e905SSolganik Alexander } 34337830e905SSolganik Alexander 34347830e905SSolganik Alexander return valid; 34357830e905SSolganik Alexander } 34367830e905SSolganik Alexander 3437cc0c5d25SMichal Krawczyk static int ena_process_uint_devarg(const char *key, 3438cc0c5d25SMichal Krawczyk const char *value, 3439cc0c5d25SMichal Krawczyk void *opaque) 3440cc0c5d25SMichal Krawczyk { 3441cc0c5d25SMichal Krawczyk struct ena_adapter *adapter = opaque; 3442cc0c5d25SMichal Krawczyk char *str_end; 3443cc0c5d25SMichal Krawczyk uint64_t uint_value; 3444cc0c5d25SMichal Krawczyk 3445cc0c5d25SMichal Krawczyk uint_value = strtoull(value, &str_end, 10); 3446cc0c5d25SMichal Krawczyk if (value == str_end) { 3447cc0c5d25SMichal Krawczyk PMD_INIT_LOG(ERR, 3448cc0c5d25SMichal Krawczyk "Invalid value for key '%s'. Only uint values are accepted.\n", 3449cc0c5d25SMichal Krawczyk key); 3450cc0c5d25SMichal Krawczyk return -EINVAL; 3451cc0c5d25SMichal Krawczyk } 3452cc0c5d25SMichal Krawczyk 3453cc0c5d25SMichal Krawczyk if (strcmp(key, ENA_DEVARG_MISS_TXC_TO) == 0) { 3454cc0c5d25SMichal Krawczyk if (uint_value > ENA_MAX_TX_TIMEOUT_SECONDS) { 3455cc0c5d25SMichal Krawczyk PMD_INIT_LOG(ERR, 3456cc0c5d25SMichal Krawczyk "Tx timeout too high: %" PRIu64 " sec. Maximum allowed: %d sec.\n", 3457cc0c5d25SMichal Krawczyk uint_value, ENA_MAX_TX_TIMEOUT_SECONDS); 3458cc0c5d25SMichal Krawczyk return -EINVAL; 3459cc0c5d25SMichal Krawczyk } else if (uint_value == 0) { 3460cc0c5d25SMichal Krawczyk PMD_INIT_LOG(INFO, 3461cc0c5d25SMichal Krawczyk "Check for missing Tx completions has been disabled.\n"); 3462cc0c5d25SMichal Krawczyk adapter->missing_tx_completion_to = 3463cc0c5d25SMichal Krawczyk ENA_HW_HINTS_NO_TIMEOUT; 3464cc0c5d25SMichal Krawczyk } else { 3465cc0c5d25SMichal Krawczyk PMD_INIT_LOG(INFO, 3466cc0c5d25SMichal Krawczyk "Tx packet completion timeout set to %" PRIu64 " seconds.\n", 3467cc0c5d25SMichal Krawczyk uint_value); 3468cc0c5d25SMichal Krawczyk adapter->missing_tx_completion_to = 3469cc0c5d25SMichal Krawczyk uint_value * rte_get_timer_hz(); 3470cc0c5d25SMichal Krawczyk } 3471cc0c5d25SMichal Krawczyk } 3472cc0c5d25SMichal Krawczyk 3473cc0c5d25SMichal Krawczyk return 0; 3474cc0c5d25SMichal Krawczyk } 3475cc0c5d25SMichal Krawczyk 34768a7a73f2SMichal Krawczyk static int ena_process_bool_devarg(const char *key, 34778a7a73f2SMichal Krawczyk const char *value, 34788a7a73f2SMichal Krawczyk void *opaque) 34798a7a73f2SMichal Krawczyk { 34808a7a73f2SMichal Krawczyk struct ena_adapter *adapter = opaque; 34818a7a73f2SMichal Krawczyk bool bool_value; 34828a7a73f2SMichal Krawczyk 34838a7a73f2SMichal Krawczyk /* Parse the value. */ 34848a7a73f2SMichal Krawczyk if (strcmp(value, "1") == 0) { 34858a7a73f2SMichal Krawczyk bool_value = true; 34868a7a73f2SMichal Krawczyk } else if (strcmp(value, "0") == 0) { 34878a7a73f2SMichal Krawczyk bool_value = false; 34888a7a73f2SMichal Krawczyk } else { 34898a7a73f2SMichal Krawczyk PMD_INIT_LOG(ERR, 34908a7a73f2SMichal Krawczyk "Invalid value: '%s' for key '%s'. Accepted: '0' or '1'\n", 34918a7a73f2SMichal Krawczyk value, key); 34928a7a73f2SMichal Krawczyk return -EINVAL; 34938a7a73f2SMichal Krawczyk } 34948a7a73f2SMichal Krawczyk 34958a7a73f2SMichal Krawczyk /* Now, assign it to the proper adapter field. */ 34969b312ad3SIgor Chauskin if (strcmp(key, ENA_DEVARG_LARGE_LLQ_HDR) == 0) 34978a7a73f2SMichal Krawczyk adapter->use_large_llq_hdr = bool_value; 3498*9944919eSMichal Krawczyk else if (strcmp(key, ENA_DEVARG_ENABLE_LLQ) == 0) 3499*9944919eSMichal Krawczyk adapter->enable_llq = bool_value; 35008a7a73f2SMichal Krawczyk 35018a7a73f2SMichal Krawczyk return 0; 35028a7a73f2SMichal Krawczyk } 35038a7a73f2SMichal Krawczyk 35048a7a73f2SMichal Krawczyk static int ena_parse_devargs(struct ena_adapter *adapter, 35058a7a73f2SMichal Krawczyk struct rte_devargs *devargs) 35068a7a73f2SMichal Krawczyk { 35078a7a73f2SMichal Krawczyk static const char * const allowed_args[] = { 35088a7a73f2SMichal Krawczyk ENA_DEVARG_LARGE_LLQ_HDR, 3509cc0c5d25SMichal Krawczyk ENA_DEVARG_MISS_TXC_TO, 3510*9944919eSMichal Krawczyk ENA_DEVARG_ENABLE_LLQ, 35119f220a95SMichal Krawczyk NULL, 35128a7a73f2SMichal Krawczyk }; 35138a7a73f2SMichal Krawczyk struct rte_kvargs *kvlist; 35148a7a73f2SMichal Krawczyk int rc; 35158a7a73f2SMichal Krawczyk 35168a7a73f2SMichal Krawczyk if (devargs == NULL) 35178a7a73f2SMichal Krawczyk return 0; 35188a7a73f2SMichal Krawczyk 35198a7a73f2SMichal Krawczyk kvlist = rte_kvargs_parse(devargs->args, allowed_args); 35208a7a73f2SMichal Krawczyk if (kvlist == NULL) { 35218a7a73f2SMichal Krawczyk PMD_INIT_LOG(ERR, "Invalid device arguments: %s\n", 35228a7a73f2SMichal Krawczyk devargs->args); 35238a7a73f2SMichal Krawczyk return -EINVAL; 35248a7a73f2SMichal Krawczyk } 35258a7a73f2SMichal Krawczyk 35268a7a73f2SMichal Krawczyk rc = rte_kvargs_process(kvlist, ENA_DEVARG_LARGE_LLQ_HDR, 35278a7a73f2SMichal Krawczyk ena_process_bool_devarg, adapter); 3528cc0c5d25SMichal Krawczyk if (rc != 0) 3529cc0c5d25SMichal Krawczyk goto exit; 3530cc0c5d25SMichal Krawczyk rc = rte_kvargs_process(kvlist, ENA_DEVARG_MISS_TXC_TO, 3531cc0c5d25SMichal Krawczyk ena_process_uint_devarg, adapter); 3532*9944919eSMichal Krawczyk if (rc != 0) 3533*9944919eSMichal Krawczyk goto exit; 3534*9944919eSMichal Krawczyk rc = rte_kvargs_process(kvlist, ENA_DEVARG_ENABLE_LLQ, 3535*9944919eSMichal Krawczyk ena_process_bool_devarg, adapter); 35368a7a73f2SMichal Krawczyk 3537cc0c5d25SMichal Krawczyk exit: 35388a7a73f2SMichal Krawczyk rte_kvargs_free(kvlist); 35398a7a73f2SMichal Krawczyk 35408a7a73f2SMichal Krawczyk return rc; 35418a7a73f2SMichal Krawczyk } 35428a7a73f2SMichal Krawczyk 35436986cdc4SMichal Krawczyk static int ena_setup_rx_intr(struct rte_eth_dev *dev) 35446986cdc4SMichal Krawczyk { 35456986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 3546d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 35476986cdc4SMichal Krawczyk int rc; 35486986cdc4SMichal Krawczyk uint16_t vectors_nb, i; 35496986cdc4SMichal Krawczyk bool rx_intr_requested = dev->data->dev_conf.intr_conf.rxq; 35506986cdc4SMichal Krawczyk 35516986cdc4SMichal Krawczyk if (!rx_intr_requested) 35526986cdc4SMichal Krawczyk return 0; 35536986cdc4SMichal Krawczyk 35546986cdc4SMichal Krawczyk if (!rte_intr_cap_multiple(intr_handle)) { 35556986cdc4SMichal Krawczyk PMD_DRV_LOG(ERR, 35566986cdc4SMichal Krawczyk "Rx interrupt requested, but it isn't supported by the PCI driver\n"); 35576986cdc4SMichal Krawczyk return -ENOTSUP; 35586986cdc4SMichal Krawczyk } 35596986cdc4SMichal Krawczyk 35606986cdc4SMichal Krawczyk /* Disable interrupt mapping before the configuration starts. */ 35616986cdc4SMichal Krawczyk rte_intr_disable(intr_handle); 35626986cdc4SMichal Krawczyk 35636986cdc4SMichal Krawczyk /* Verify if there are enough vectors available. */ 35646986cdc4SMichal Krawczyk vectors_nb = dev->data->nb_rx_queues; 35656986cdc4SMichal Krawczyk if (vectors_nb > RTE_MAX_RXTX_INTR_VEC_ID) { 35666986cdc4SMichal Krawczyk PMD_DRV_LOG(ERR, 35676986cdc4SMichal Krawczyk "Too many Rx interrupts requested, maximum number: %d\n", 35686986cdc4SMichal Krawczyk RTE_MAX_RXTX_INTR_VEC_ID); 35696986cdc4SMichal Krawczyk rc = -ENOTSUP; 35706986cdc4SMichal Krawczyk goto enable_intr; 35716986cdc4SMichal Krawczyk } 35726986cdc4SMichal Krawczyk 3573d61138d4SHarman Kalra /* Allocate the vector list */ 3574d61138d4SHarman Kalra if (rte_intr_vec_list_alloc(intr_handle, "intr_vec", 3575d61138d4SHarman Kalra dev->data->nb_rx_queues)) { 35766986cdc4SMichal Krawczyk PMD_DRV_LOG(ERR, 35776986cdc4SMichal Krawczyk "Failed to allocate interrupt vector for %d queues\n", 35786986cdc4SMichal Krawczyk dev->data->nb_rx_queues); 35796986cdc4SMichal Krawczyk rc = -ENOMEM; 35806986cdc4SMichal Krawczyk goto enable_intr; 35816986cdc4SMichal Krawczyk } 35826986cdc4SMichal Krawczyk 35836986cdc4SMichal Krawczyk rc = rte_intr_efd_enable(intr_handle, vectors_nb); 35846986cdc4SMichal Krawczyk if (rc != 0) 35856986cdc4SMichal Krawczyk goto free_intr_vec; 35866986cdc4SMichal Krawczyk 35876986cdc4SMichal Krawczyk if (!rte_intr_allow_others(intr_handle)) { 35886986cdc4SMichal Krawczyk PMD_DRV_LOG(ERR, 35896986cdc4SMichal Krawczyk "Not enough interrupts available to use both ENA Admin and Rx interrupts\n"); 35906986cdc4SMichal Krawczyk goto disable_intr_efd; 35916986cdc4SMichal Krawczyk } 35926986cdc4SMichal Krawczyk 35936986cdc4SMichal Krawczyk for (i = 0; i < vectors_nb; ++i) 3594d61138d4SHarman Kalra if (rte_intr_vec_list_index_set(intr_handle, i, 3595d61138d4SHarman Kalra RTE_INTR_VEC_RXTX_OFFSET + i)) 3596d61138d4SHarman Kalra goto disable_intr_efd; 35976986cdc4SMichal Krawczyk 35986986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 35996986cdc4SMichal Krawczyk return 0; 36006986cdc4SMichal Krawczyk 36016986cdc4SMichal Krawczyk disable_intr_efd: 36026986cdc4SMichal Krawczyk rte_intr_efd_disable(intr_handle); 36036986cdc4SMichal Krawczyk free_intr_vec: 3604d61138d4SHarman Kalra rte_intr_vec_list_free(intr_handle); 36056986cdc4SMichal Krawczyk enable_intr: 36066986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 36076986cdc4SMichal Krawczyk return rc; 36086986cdc4SMichal Krawczyk } 36096986cdc4SMichal Krawczyk 36106986cdc4SMichal Krawczyk static void ena_rx_queue_intr_set(struct rte_eth_dev *dev, 36116986cdc4SMichal Krawczyk uint16_t queue_id, 36126986cdc4SMichal Krawczyk bool unmask) 36136986cdc4SMichal Krawczyk { 36146986cdc4SMichal Krawczyk struct ena_adapter *adapter = dev->data->dev_private; 36156986cdc4SMichal Krawczyk struct ena_ring *rxq = &adapter->rx_ring[queue_id]; 36166986cdc4SMichal Krawczyk struct ena_eth_io_intr_reg intr_reg; 36176986cdc4SMichal Krawczyk 36186986cdc4SMichal Krawczyk ena_com_update_intr_reg(&intr_reg, 0, 0, unmask); 36196986cdc4SMichal Krawczyk ena_com_unmask_intr(rxq->ena_com_io_cq, &intr_reg); 36206986cdc4SMichal Krawczyk } 36216986cdc4SMichal Krawczyk 36226986cdc4SMichal Krawczyk static int ena_rx_queue_intr_enable(struct rte_eth_dev *dev, 36236986cdc4SMichal Krawczyk uint16_t queue_id) 36246986cdc4SMichal Krawczyk { 36256986cdc4SMichal Krawczyk ena_rx_queue_intr_set(dev, queue_id, true); 36266986cdc4SMichal Krawczyk 36276986cdc4SMichal Krawczyk return 0; 36286986cdc4SMichal Krawczyk } 36296986cdc4SMichal Krawczyk 36306986cdc4SMichal Krawczyk static int ena_rx_queue_intr_disable(struct rte_eth_dev *dev, 36316986cdc4SMichal Krawczyk uint16_t queue_id) 36326986cdc4SMichal Krawczyk { 36336986cdc4SMichal Krawczyk ena_rx_queue_intr_set(dev, queue_id, false); 36346986cdc4SMichal Krawczyk 36356986cdc4SMichal Krawczyk return 0; 36366986cdc4SMichal Krawczyk } 36376986cdc4SMichal Krawczyk 3638b9b05d6fSMichal Krawczyk static int ena_configure_aenq(struct ena_adapter *adapter) 3639b9b05d6fSMichal Krawczyk { 3640b9b05d6fSMichal Krawczyk uint32_t aenq_groups = adapter->all_aenq_groups; 3641b9b05d6fSMichal Krawczyk int rc; 3642b9b05d6fSMichal Krawczyk 3643b9b05d6fSMichal Krawczyk /* All_aenq_groups holds all AENQ functions supported by the device and 3644b9b05d6fSMichal Krawczyk * the HW, so at first we need to be sure the LSC request is valid. 3645b9b05d6fSMichal Krawczyk */ 3646b9b05d6fSMichal Krawczyk if (adapter->edev_data->dev_conf.intr_conf.lsc != 0) { 3647b9b05d6fSMichal Krawczyk if (!(aenq_groups & BIT(ENA_ADMIN_LINK_CHANGE))) { 3648b9b05d6fSMichal Krawczyk PMD_DRV_LOG(ERR, 3649b9b05d6fSMichal Krawczyk "LSC requested, but it's not supported by the AENQ\n"); 3650b9b05d6fSMichal Krawczyk return -EINVAL; 3651b9b05d6fSMichal Krawczyk } 3652b9b05d6fSMichal Krawczyk } else { 3653b9b05d6fSMichal Krawczyk /* If LSC wasn't enabled by the app, let's enable all supported 3654b9b05d6fSMichal Krawczyk * AENQ procedures except the LSC. 3655b9b05d6fSMichal Krawczyk */ 3656b9b05d6fSMichal Krawczyk aenq_groups &= ~BIT(ENA_ADMIN_LINK_CHANGE); 3657b9b05d6fSMichal Krawczyk } 3658b9b05d6fSMichal Krawczyk 3659b9b05d6fSMichal Krawczyk rc = ena_com_set_aenq_config(&adapter->ena_dev, aenq_groups); 3660b9b05d6fSMichal Krawczyk if (rc != 0) { 3661b9b05d6fSMichal Krawczyk PMD_DRV_LOG(ERR, "Cannot configure AENQ groups, rc=%d\n", rc); 3662b9b05d6fSMichal Krawczyk return rc; 3663b9b05d6fSMichal Krawczyk } 3664b9b05d6fSMichal Krawczyk 3665b9b05d6fSMichal Krawczyk adapter->active_aenq_groups = aenq_groups; 3666b9b05d6fSMichal Krawczyk 3667b9b05d6fSMichal Krawczyk return 0; 3668b9b05d6fSMichal Krawczyk } 3669b9b05d6fSMichal Krawczyk 3670e3595539SStanislaw Kardach int ena_mp_indirect_table_set(struct ena_adapter *adapter) 3671e3595539SStanislaw Kardach { 3672e3595539SStanislaw Kardach return ENA_PROXY(adapter, ena_com_indirect_table_set, &adapter->ena_dev); 3673e3595539SStanislaw Kardach } 3674e3595539SStanislaw Kardach 3675e3595539SStanislaw Kardach int ena_mp_indirect_table_get(struct ena_adapter *adapter, 3676e3595539SStanislaw Kardach uint32_t *indirect_table) 3677e3595539SStanislaw Kardach { 3678e3595539SStanislaw Kardach return ENA_PROXY(adapter, ena_com_indirect_table_get, &adapter->ena_dev, 3679e3595539SStanislaw Kardach indirect_table); 3680e3595539SStanislaw Kardach } 3681e3595539SStanislaw Kardach 3682ca148440SMichal Krawczyk /********************************************************************* 3683850e1bb1SMichal Krawczyk * ena_plat_dpdk.h functions implementations 3684850e1bb1SMichal Krawczyk *********************************************************************/ 3685850e1bb1SMichal Krawczyk 3686850e1bb1SMichal Krawczyk const struct rte_memzone * 3687850e1bb1SMichal Krawczyk ena_mem_alloc_coherent(struct rte_eth_dev_data *data, size_t size, 3688850e1bb1SMichal Krawczyk int socket_id, unsigned int alignment, void **virt_addr, 3689850e1bb1SMichal Krawczyk dma_addr_t *phys_addr) 3690850e1bb1SMichal Krawczyk { 3691850e1bb1SMichal Krawczyk char z_name[RTE_MEMZONE_NAMESIZE]; 3692850e1bb1SMichal Krawczyk struct ena_adapter *adapter = data->dev_private; 3693850e1bb1SMichal Krawczyk const struct rte_memzone *memzone; 3694850e1bb1SMichal Krawczyk int rc; 3695850e1bb1SMichal Krawczyk 3696850e1bb1SMichal Krawczyk rc = snprintf(z_name, RTE_MEMZONE_NAMESIZE, "ena_p%d_mz%" PRIu64 "", 3697850e1bb1SMichal Krawczyk data->port_id, adapter->memzone_cnt); 3698850e1bb1SMichal Krawczyk if (rc >= RTE_MEMZONE_NAMESIZE) { 3699850e1bb1SMichal Krawczyk PMD_DRV_LOG(ERR, 3700850e1bb1SMichal Krawczyk "Name for the ena_com memzone is too long. Port: %d, mz_num: %" PRIu64 "\n", 3701850e1bb1SMichal Krawczyk data->port_id, adapter->memzone_cnt); 3702850e1bb1SMichal Krawczyk goto error; 3703850e1bb1SMichal Krawczyk } 3704850e1bb1SMichal Krawczyk adapter->memzone_cnt++; 3705850e1bb1SMichal Krawczyk 3706850e1bb1SMichal Krawczyk memzone = rte_memzone_reserve_aligned(z_name, size, socket_id, 3707850e1bb1SMichal Krawczyk RTE_MEMZONE_IOVA_CONTIG, alignment); 3708850e1bb1SMichal Krawczyk if (memzone == NULL) { 3709850e1bb1SMichal Krawczyk PMD_DRV_LOG(ERR, "Failed to allocate ena_com memzone: %s\n", 3710850e1bb1SMichal Krawczyk z_name); 3711850e1bb1SMichal Krawczyk goto error; 3712850e1bb1SMichal Krawczyk } 3713850e1bb1SMichal Krawczyk 3714850e1bb1SMichal Krawczyk memset(memzone->addr, 0, size); 3715850e1bb1SMichal Krawczyk *virt_addr = memzone->addr; 3716850e1bb1SMichal Krawczyk *phys_addr = memzone->iova; 3717850e1bb1SMichal Krawczyk 3718850e1bb1SMichal Krawczyk return memzone; 3719850e1bb1SMichal Krawczyk 3720850e1bb1SMichal Krawczyk error: 3721850e1bb1SMichal Krawczyk *virt_addr = NULL; 3722850e1bb1SMichal Krawczyk *phys_addr = 0; 3723850e1bb1SMichal Krawczyk 3724850e1bb1SMichal Krawczyk return NULL; 3725850e1bb1SMichal Krawczyk } 3726850e1bb1SMichal Krawczyk 3727850e1bb1SMichal Krawczyk 3728850e1bb1SMichal Krawczyk /********************************************************************* 3729ca148440SMichal Krawczyk * PMD configuration 3730ca148440SMichal Krawczyk *********************************************************************/ 3731fdf91e0fSJan Blunck static int eth_ena_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 3732fdf91e0fSJan Blunck struct rte_pci_device *pci_dev) 3733fdf91e0fSJan Blunck { 3734fdf91e0fSJan Blunck return rte_eth_dev_pci_generic_probe(pci_dev, 3735fdf91e0fSJan Blunck sizeof(struct ena_adapter), eth_ena_dev_init); 3736fdf91e0fSJan Blunck } 3737fdf91e0fSJan Blunck 3738fdf91e0fSJan Blunck static int eth_ena_pci_remove(struct rte_pci_device *pci_dev) 3739fdf91e0fSJan Blunck { 3740eb0ef49dSMichal Krawczyk return rte_eth_dev_pci_generic_remove(pci_dev, eth_ena_dev_uninit); 3741fdf91e0fSJan Blunck } 3742fdf91e0fSJan Blunck 3743fdf91e0fSJan Blunck static struct rte_pci_driver rte_ena_pmd = { 37441173fca2SJan Medala .id_table = pci_id_ena_map, 374505e0eee0SRafal Kozik .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | 374605e0eee0SRafal Kozik RTE_PCI_DRV_WC_ACTIVATE, 3747fdf91e0fSJan Blunck .probe = eth_ena_pci_probe, 3748fdf91e0fSJan Blunck .remove = eth_ena_pci_remove, 37491173fca2SJan Medala }; 37501173fca2SJan Medala 3751fdf91e0fSJan Blunck RTE_PMD_REGISTER_PCI(net_ena, rte_ena_pmd); 375201f19227SShreyansh Jain RTE_PMD_REGISTER_PCI_TABLE(net_ena, pci_id_ena_map); 375306e81dc9SDavid Marchand RTE_PMD_REGISTER_KMOD_DEP(net_ena, "* igb_uio | uio_pci_generic | vfio-pci"); 3754*9944919eSMichal Krawczyk RTE_PMD_REGISTER_PARAM_STRING(net_ena, 3755*9944919eSMichal Krawczyk ENA_DEVARG_LARGE_LLQ_HDR "=<0|1> " 3756*9944919eSMichal Krawczyk ENA_DEVARG_ENABLE_LLQ "=<0|1> " 3757*9944919eSMichal Krawczyk ENA_DEVARG_MISS_TXC_TO "=<uint>"); 3758eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(ena_logtype_init, init, NOTICE); 3759eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(ena_logtype_driver, driver, NOTICE); 37600a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 37610a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_rx, rx, DEBUG); 37626f1c9df9SStephen Hemminger #endif 37630a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_TX 37640a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_tx, tx, DEBUG); 37656f1c9df9SStephen Hemminger #endif 37660a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_com, com, WARNING); 37673adcba9aSMichal Krawczyk 37683adcba9aSMichal Krawczyk /****************************************************************************** 37693adcba9aSMichal Krawczyk ******************************** AENQ Handlers ******************************* 37703adcba9aSMichal Krawczyk *****************************************************************************/ 3771ca148440SMichal Krawczyk static void ena_update_on_link_change(void *adapter_data, 3772ca148440SMichal Krawczyk struct ena_admin_aenq_entry *aenq_e) 3773ca148440SMichal Krawczyk { 3774aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 3775aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 3776ca148440SMichal Krawczyk struct ena_admin_aenq_link_change_desc *aenq_link_desc; 3777ca148440SMichal Krawczyk uint32_t status; 3778ca148440SMichal Krawczyk 3779ca148440SMichal Krawczyk aenq_link_desc = (struct ena_admin_aenq_link_change_desc *)aenq_e; 3780ca148440SMichal Krawczyk 3781ca148440SMichal Krawczyk status = get_ena_admin_aenq_link_change_desc_link_status(aenq_link_desc); 3782ca148440SMichal Krawczyk adapter->link_status = status; 3783ca148440SMichal Krawczyk 3784ca148440SMichal Krawczyk ena_link_update(eth_dev, 0); 37855723fbedSFerruh Yigit rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL); 3786ca148440SMichal Krawczyk } 3787ca148440SMichal Krawczyk 3788aab58857SStanislaw Kardach static void ena_notification(void *adapter_data, 3789f01f060cSRafal Kozik struct ena_admin_aenq_entry *aenq_e) 3790f01f060cSRafal Kozik { 3791aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 3792aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 3793f01f060cSRafal Kozik struct ena_admin_ena_hw_hints *hints; 3794f01f060cSRafal Kozik 3795f01f060cSRafal Kozik if (aenq_e->aenq_common_desc.group != ENA_ADMIN_NOTIFICATION) 3796617898d1SMichal Krawczyk PMD_DRV_LOG(WARNING, "Invalid AENQ group: %x. Expected: %x\n", 3797f01f060cSRafal Kozik aenq_e->aenq_common_desc.group, 3798f01f060cSRafal Kozik ENA_ADMIN_NOTIFICATION); 3799f01f060cSRafal Kozik 3800b19f366cSMichal Krawczyk switch (aenq_e->aenq_common_desc.syndrome) { 3801f01f060cSRafal Kozik case ENA_ADMIN_UPDATE_HINTS: 3802f01f060cSRafal Kozik hints = (struct ena_admin_ena_hw_hints *) 3803f01f060cSRafal Kozik (&aenq_e->inline_data_w4); 3804f01f060cSRafal Kozik ena_update_hints(adapter, hints); 3805f01f060cSRafal Kozik break; 3806f01f060cSRafal Kozik default: 3807617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, "Invalid AENQ notification link state: %d\n", 3808b19f366cSMichal Krawczyk aenq_e->aenq_common_desc.syndrome); 3809f01f060cSRafal Kozik } 3810f01f060cSRafal Kozik } 3811f01f060cSRafal Kozik 3812d9b8b106SMichal Krawczyk static void ena_keep_alive(void *adapter_data, 3813d9b8b106SMichal Krawczyk __rte_unused struct ena_admin_aenq_entry *aenq_e) 3814d9b8b106SMichal Krawczyk { 3815aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 3816aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 381794c3e376SRafal Kozik struct ena_admin_aenq_keep_alive_desc *desc; 381894c3e376SRafal Kozik uint64_t rx_drops; 3819e1e73e32SMichal Krawczyk uint64_t tx_drops; 3820d9b8b106SMichal Krawczyk 3821d9b8b106SMichal Krawczyk adapter->timestamp_wd = rte_get_timer_cycles(); 382294c3e376SRafal Kozik 382394c3e376SRafal Kozik desc = (struct ena_admin_aenq_keep_alive_desc *)aenq_e; 382494c3e376SRafal Kozik rx_drops = ((uint64_t)desc->rx_drops_high << 32) | desc->rx_drops_low; 3825e1e73e32SMichal Krawczyk tx_drops = ((uint64_t)desc->tx_drops_high << 32) | desc->tx_drops_low; 3826e1e73e32SMichal Krawczyk 3827e1e73e32SMichal Krawczyk adapter->drv_stats->rx_drops = rx_drops; 3828e1e73e32SMichal Krawczyk adapter->dev_stats.tx_drops = tx_drops; 3829d9b8b106SMichal Krawczyk } 3830d9b8b106SMichal Krawczyk 38313adcba9aSMichal Krawczyk /** 38323adcba9aSMichal Krawczyk * This handler will called for unknown event group or unimplemented handlers 38333adcba9aSMichal Krawczyk **/ 38343adcba9aSMichal Krawczyk static void unimplemented_aenq_handler(__rte_unused void *data, 38353adcba9aSMichal Krawczyk __rte_unused struct ena_admin_aenq_entry *aenq_e) 38363adcba9aSMichal Krawczyk { 3837617898d1SMichal Krawczyk PMD_DRV_LOG(ERR, 3838617898d1SMichal Krawczyk "Unknown event was received or event with unimplemented handler\n"); 38393adcba9aSMichal Krawczyk } 38403adcba9aSMichal Krawczyk 3841ca148440SMichal Krawczyk static struct ena_aenq_handlers aenq_handlers = { 38423adcba9aSMichal Krawczyk .handlers = { 3843ca148440SMichal Krawczyk [ENA_ADMIN_LINK_CHANGE] = ena_update_on_link_change, 3844f01f060cSRafal Kozik [ENA_ADMIN_NOTIFICATION] = ena_notification, 3845d9b8b106SMichal Krawczyk [ENA_ADMIN_KEEP_ALIVE] = ena_keep_alive 38463adcba9aSMichal Krawczyk }, 38473adcba9aSMichal Krawczyk .unimplemented_handler = unimplemented_aenq_handler 38483adcba9aSMichal Krawczyk }; 3849e3595539SStanislaw Kardach 3850e3595539SStanislaw Kardach /********************************************************************* 3851e3595539SStanislaw Kardach * Multi-Process communication request handling (in primary) 3852e3595539SStanislaw Kardach *********************************************************************/ 3853e3595539SStanislaw Kardach static int 3854e3595539SStanislaw Kardach ena_mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer) 3855e3595539SStanislaw Kardach { 3856e3595539SStanislaw Kardach const struct ena_mp_body *req = 3857e3595539SStanislaw Kardach (const struct ena_mp_body *)mp_msg->param; 3858e3595539SStanislaw Kardach struct ena_adapter *adapter; 3859e3595539SStanislaw Kardach struct ena_com_dev *ena_dev; 3860e3595539SStanislaw Kardach struct ena_mp_body *rsp; 3861e3595539SStanislaw Kardach struct rte_mp_msg mp_rsp; 3862e3595539SStanislaw Kardach struct rte_eth_dev *dev; 3863e3595539SStanislaw Kardach int res = 0; 3864e3595539SStanislaw Kardach 3865e3595539SStanislaw Kardach rsp = (struct ena_mp_body *)&mp_rsp.param; 3866e3595539SStanislaw Kardach mp_msg_init(&mp_rsp, req->type, req->port_id); 3867e3595539SStanislaw Kardach 3868e3595539SStanislaw Kardach if (!rte_eth_dev_is_valid_port(req->port_id)) { 3869e3595539SStanislaw Kardach rte_errno = ENODEV; 3870e3595539SStanislaw Kardach res = -rte_errno; 3871e3595539SStanislaw Kardach PMD_DRV_LOG(ERR, "Unknown port %d in request %d\n", 3872e3595539SStanislaw Kardach req->port_id, req->type); 3873e3595539SStanislaw Kardach goto end; 3874e3595539SStanislaw Kardach } 3875e3595539SStanislaw Kardach dev = &rte_eth_devices[req->port_id]; 3876e3595539SStanislaw Kardach adapter = dev->data->dev_private; 3877e3595539SStanislaw Kardach ena_dev = &adapter->ena_dev; 3878e3595539SStanislaw Kardach 3879e3595539SStanislaw Kardach switch (req->type) { 3880e3595539SStanislaw Kardach case ENA_MP_DEV_STATS_GET: 3881e3595539SStanislaw Kardach res = ena_com_get_dev_basic_stats(ena_dev, 3882e3595539SStanislaw Kardach &adapter->basic_stats); 3883e3595539SStanislaw Kardach break; 3884e3595539SStanislaw Kardach case ENA_MP_ENI_STATS_GET: 3885e3595539SStanislaw Kardach res = ena_com_get_eni_stats(ena_dev, 3886e3595539SStanislaw Kardach (struct ena_admin_eni_stats *)&adapter->eni_stats); 3887e3595539SStanislaw Kardach break; 3888e3595539SStanislaw Kardach case ENA_MP_MTU_SET: 3889e3595539SStanislaw Kardach res = ena_com_set_dev_mtu(ena_dev, req->args.mtu); 3890e3595539SStanislaw Kardach break; 3891e3595539SStanislaw Kardach case ENA_MP_IND_TBL_GET: 3892e3595539SStanislaw Kardach res = ena_com_indirect_table_get(ena_dev, 3893e3595539SStanislaw Kardach adapter->indirect_table); 3894e3595539SStanislaw Kardach break; 3895e3595539SStanislaw Kardach case ENA_MP_IND_TBL_SET: 3896e3595539SStanislaw Kardach res = ena_com_indirect_table_set(ena_dev); 3897e3595539SStanislaw Kardach break; 3898e3595539SStanislaw Kardach default: 3899e3595539SStanislaw Kardach PMD_DRV_LOG(ERR, "Unknown request type %d\n", req->type); 3900e3595539SStanislaw Kardach res = -EINVAL; 3901e3595539SStanislaw Kardach break; 3902e3595539SStanislaw Kardach } 3903e3595539SStanislaw Kardach 3904e3595539SStanislaw Kardach end: 3905e3595539SStanislaw Kardach /* Save processing result in the reply */ 3906e3595539SStanislaw Kardach rsp->result = res; 3907e3595539SStanislaw Kardach /* Return just IPC processing status */ 3908e3595539SStanislaw Kardach return rte_mp_reply(&mp_rsp, peer); 3909e3595539SStanislaw Kardach } 3910