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 6ca1dfa85SShai Brandes #include <rte_alarm.h> 76723c0fcSBruce Richardson #include <rte_string_fns.h> 81173fca2SJan Medala #include <rte_errno.h> 9372c1af5SJan Medala #include <rte_version.h> 10b3fc5a1aSKonstantin Ananyev #include <rte_net.h> 118a7a73f2SMichal Krawczyk #include <rte_kvargs.h> 121173fca2SJan Medala 131173fca2SJan Medala #include "ena_ethdev.h" 141173fca2SJan Medala #include "ena_logs.h" 151173fca2SJan Medala #include "ena_platform.h" 161173fca2SJan Medala #include "ena_com.h" 171173fca2SJan Medala #include "ena_eth_com.h" 181173fca2SJan Medala 191173fca2SJan Medala #include <ena_common_defs.h> 201173fca2SJan Medala #include <ena_regs_defs.h> 211173fca2SJan Medala #include <ena_admin_defs.h> 221173fca2SJan Medala #include <ena_eth_io_defs.h> 231173fca2SJan Medala 24419c3e3eSMichal Krawczyk #define DRV_MODULE_VER_MAJOR 2 253a2509abSShai Brandes #define DRV_MODULE_VER_MINOR 11 261b48c60dSMichal Krawczyk #define DRV_MODULE_VER_SUBMINOR 0 27372c1af5SJan Medala 281173fca2SJan Medala #define __MERGE_64B_H_L(h, l) (((uint64_t)h << 32) | l) 291173fca2SJan Medala 301173fca2SJan Medala #define GET_L4_HDR_LEN(mbuf) \ 31f41b5156SOlivier Matz ((rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, \ 321173fca2SJan Medala mbuf->l3_len + mbuf->l2_len)->data_off) >> 4) 331173fca2SJan Medala 34372c1af5SJan Medala #define ETH_GSTRING_LEN 32 35372c1af5SJan Medala 36a3c9a11aSAndrew Boyer #define ARRAY_SIZE(x) RTE_DIM(x) 37372c1af5SJan Medala 3892680dc2SRafal Kozik #define ENA_MIN_RING_DESC 128 3992680dc2SRafal Kozik 40ca1dfa85SShai Brandes #define USEC_PER_MSEC 1000UL 41ca1dfa85SShai Brandes 422c0f7536SShai Brandes #define BITS_PER_BYTE 8 432c0f7536SShai Brandes 442c0f7536SShai Brandes #define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) 452c0f7536SShai Brandes 461f11149dSShai Brandes #define DECIMAL_BASE 10 471f11149dSShai Brandes 48bf5fe95cSShai Brandes #define MAX_WIDE_LLQ_DEPTH_UNSUPPORTED 0 49bf5fe95cSShai Brandes 50c339f538SDawid Gorecki /* 51237407f0SShai Brandes * We should try to keep ENA_CLEANUP_BUF_THRESH lower than 52c339f538SDawid Gorecki * RTE_MEMPOOL_CACHE_MAX_SIZE, so we can fit this in mempool local cache. 53c339f538SDawid Gorecki */ 54237407f0SShai Brandes #define ENA_CLEANUP_BUF_THRESH 256 55c339f538SDawid Gorecki 56372c1af5SJan Medala struct ena_stats { 57372c1af5SJan Medala char name[ETH_GSTRING_LEN]; 58372c1af5SJan Medala int stat_offset; 59372c1af5SJan Medala }; 60372c1af5SJan Medala 61372c1af5SJan Medala #define ENA_STAT_ENTRY(stat, stat_type) { \ 62372c1af5SJan Medala .name = #stat, \ 63372c1af5SJan Medala .stat_offset = offsetof(struct ena_stats_##stat_type, stat) \ 64372c1af5SJan Medala } 65372c1af5SJan Medala 66372c1af5SJan Medala #define ENA_STAT_RX_ENTRY(stat) \ 67372c1af5SJan Medala ENA_STAT_ENTRY(stat, rx) 68372c1af5SJan Medala 69372c1af5SJan Medala #define ENA_STAT_TX_ENTRY(stat) \ 70372c1af5SJan Medala ENA_STAT_ENTRY(stat, tx) 71372c1af5SJan Medala 7292401abfSShai Brandes #define ENA_STAT_METRICS_ENTRY(stat) \ 7392401abfSShai Brandes ENA_STAT_ENTRY(stat, metrics) 7445718adaSMichal Krawczyk 75372c1af5SJan Medala #define ENA_STAT_GLOBAL_ENTRY(stat) \ 76372c1af5SJan Medala ENA_STAT_ENTRY(stat, dev) 77372c1af5SJan Medala 78a73dd098SShai Brandes #define ENA_STAT_ENA_SRD_ENTRY(stat) \ 79a73dd098SShai Brandes ENA_STAT_ENTRY(stat, srd) 80a73dd098SShai Brandes 818a7a73f2SMichal Krawczyk /* Device arguments */ 82d7918d19SShai Brandes 83d7918d19SShai Brandes /* llq_policy Controls whether to disable LLQ, use device recommended 84d7918d19SShai Brandes * header policy or overriding the device recommendation. 85d7918d19SShai Brandes * 0 - Disable LLQ. Use with extreme caution as it leads to a huge 86d7918d19SShai Brandes * performance degradation on AWS instances built with Nitro v4 onwards. 87d7918d19SShai Brandes * 1 - Accept device recommended LLQ policy (Default). 88d7918d19SShai Brandes * Device can recommend normal or large LLQ policy. 89d7918d19SShai Brandes * 2 - Enforce normal LLQ policy. 90d7918d19SShai Brandes * 3 - Enforce large LLQ policy. 91d7918d19SShai Brandes * Required for packets with header that exceed 96 bytes on 92d7918d19SShai Brandes * AWS instances built with Nitro v2 and Nitro v1. 93d7918d19SShai Brandes */ 94d7918d19SShai Brandes #define ENA_DEVARG_LLQ_POLICY "llq_policy" 95d7918d19SShai Brandes 96cc0c5d25SMichal Krawczyk /* Timeout in seconds after which a single uncompleted Tx packet should be 97cc0c5d25SMichal Krawczyk * considered as a missing. 98cc0c5d25SMichal Krawczyk */ 99cc0c5d25SMichal Krawczyk #define ENA_DEVARG_MISS_TXC_TO "miss_txc_to" 100d7918d19SShai Brandes 101ca1dfa85SShai Brandes /* 102ca1dfa85SShai Brandes * Controls the period of time (in milliseconds) between two consecutive inspections of 103ca1dfa85SShai Brandes * the control queues when the driver is in poll mode and not using interrupts. 104ca1dfa85SShai Brandes * By default, this value is zero, indicating that the driver will not be in poll mode and will 105ca1dfa85SShai Brandes * use interrupts. A non-zero value for this argument is mandatory when using uio_pci_generic 106ca1dfa85SShai Brandes * driver. 107ca1dfa85SShai Brandes */ 108ca1dfa85SShai Brandes #define ENA_DEVARG_CONTROL_PATH_POLL_INTERVAL "control_path_poll_interval" 1098a7a73f2SMichal Krawczyk 1103adcba9aSMichal Krawczyk /* 1113adcba9aSMichal Krawczyk * Each rte_memzone should have unique name. 1123adcba9aSMichal Krawczyk * To satisfy it, count number of allocation and add it to name. 1133adcba9aSMichal Krawczyk */ 1147c0a233eSAmit Bernstein rte_atomic64_t ena_alloc_cnt; 1153adcba9aSMichal Krawczyk 116372c1af5SJan Medala static const struct ena_stats ena_stats_global_strings[] = { 117372c1af5SJan Medala ENA_STAT_GLOBAL_ENTRY(wd_expired), 1187830e905SSolganik Alexander ENA_STAT_GLOBAL_ENTRY(dev_start), 1197830e905SSolganik Alexander ENA_STAT_GLOBAL_ENTRY(dev_stop), 120e1e73e32SMichal Krawczyk ENA_STAT_GLOBAL_ENTRY(tx_drops), 121372c1af5SJan Medala }; 122372c1af5SJan Medala 12392401abfSShai Brandes /* 12492401abfSShai Brandes * The legacy metrics (also known as eni stats) consisted of 5 stats, while the reworked 12592401abfSShai Brandes * metrics (also known as customer metrics) support an additional stat. 12692401abfSShai Brandes */ 12792401abfSShai Brandes static struct ena_stats ena_stats_metrics_strings[] = { 12892401abfSShai Brandes ENA_STAT_METRICS_ENTRY(bw_in_allowance_exceeded), 12992401abfSShai Brandes ENA_STAT_METRICS_ENTRY(bw_out_allowance_exceeded), 13092401abfSShai Brandes ENA_STAT_METRICS_ENTRY(pps_allowance_exceeded), 13192401abfSShai Brandes ENA_STAT_METRICS_ENTRY(conntrack_allowance_exceeded), 13292401abfSShai Brandes ENA_STAT_METRICS_ENTRY(linklocal_allowance_exceeded), 13392401abfSShai Brandes ENA_STAT_METRICS_ENTRY(conntrack_allowance_available), 13445718adaSMichal Krawczyk }; 13545718adaSMichal Krawczyk 136a73dd098SShai Brandes static const struct ena_stats ena_stats_srd_strings[] = { 137a73dd098SShai Brandes ENA_STAT_ENA_SRD_ENTRY(ena_srd_mode), 138a73dd098SShai Brandes ENA_STAT_ENA_SRD_ENTRY(ena_srd_tx_pkts), 139a73dd098SShai Brandes ENA_STAT_ENA_SRD_ENTRY(ena_srd_eligible_tx_pkts), 140a73dd098SShai Brandes ENA_STAT_ENA_SRD_ENTRY(ena_srd_rx_pkts), 141a73dd098SShai Brandes ENA_STAT_ENA_SRD_ENTRY(ena_srd_resource_utilization), 142a73dd098SShai Brandes }; 143a73dd098SShai Brandes 144372c1af5SJan Medala static const struct ena_stats ena_stats_tx_strings[] = { 145372c1af5SJan Medala ENA_STAT_TX_ENTRY(cnt), 146372c1af5SJan Medala ENA_STAT_TX_ENTRY(bytes), 1477830e905SSolganik Alexander ENA_STAT_TX_ENTRY(prepare_ctx_err), 148372c1af5SJan Medala ENA_STAT_TX_ENTRY(tx_poll), 149372c1af5SJan Medala ENA_STAT_TX_ENTRY(doorbells), 150372c1af5SJan Medala ENA_STAT_TX_ENTRY(bad_req_id), 1517830e905SSolganik Alexander ENA_STAT_TX_ENTRY(available_desc), 152f93e20e5SMichal Krawczyk ENA_STAT_TX_ENTRY(missed_tx), 153372c1af5SJan Medala }; 154372c1af5SJan Medala 155372c1af5SJan Medala static const struct ena_stats ena_stats_rx_strings[] = { 156372c1af5SJan Medala ENA_STAT_RX_ENTRY(cnt), 157372c1af5SJan Medala ENA_STAT_RX_ENTRY(bytes), 1587830e905SSolganik Alexander ENA_STAT_RX_ENTRY(refill_partial), 15984daba99SMichal Krawczyk ENA_STAT_RX_ENTRY(l3_csum_bad), 16084daba99SMichal Krawczyk ENA_STAT_RX_ENTRY(l4_csum_bad), 16184daba99SMichal Krawczyk ENA_STAT_RX_ENTRY(l4_csum_good), 1627830e905SSolganik Alexander ENA_STAT_RX_ENTRY(mbuf_alloc_fail), 163372c1af5SJan Medala ENA_STAT_RX_ENTRY(bad_desc_num), 1647830e905SSolganik Alexander ENA_STAT_RX_ENTRY(bad_req_id), 1657a166990SShai Brandes ENA_STAT_RX_ENTRY(bad_desc), 1667a166990SShai Brandes ENA_STAT_RX_ENTRY(unknown_error), 167372c1af5SJan Medala }; 168372c1af5SJan Medala 169372c1af5SJan Medala #define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings) 17092401abfSShai Brandes #define ENA_STATS_ARRAY_METRICS ARRAY_SIZE(ena_stats_metrics_strings) 17192401abfSShai Brandes #define ENA_STATS_ARRAY_METRICS_LEGACY (ENA_STATS_ARRAY_METRICS - 1) 172a73dd098SShai Brandes #define ENA_STATS_ARRAY_ENA_SRD ARRAY_SIZE(ena_stats_srd_strings) 173372c1af5SJan Medala #define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) 174372c1af5SJan Medala #define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) 1751173fca2SJan Medala 176295968d1SFerruh Yigit #define QUEUE_OFFLOADS (RTE_ETH_TX_OFFLOAD_TCP_CKSUM |\ 177295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_UDP_CKSUM |\ 178295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |\ 179295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_TCP_TSO) 180daa02b5cSOlivier Matz #define MBUF_OFFLOADS (RTE_MBUF_F_TX_L4_MASK |\ 181daa02b5cSOlivier Matz RTE_MBUF_F_TX_IP_CKSUM |\ 182daa02b5cSOlivier Matz RTE_MBUF_F_TX_TCP_SEG) 18356b8b9b7SRafal Kozik 1841173fca2SJan Medala /** Vendor ID used by Amazon devices */ 1851173fca2SJan Medala #define PCI_VENDOR_ID_AMAZON 0x1D0F 1861173fca2SJan Medala /** Amazon devices */ 1871173fca2SJan Medala #define PCI_DEVICE_ID_ENA_VF 0xEC20 188f7138b91SMichal Krawczyk #define PCI_DEVICE_ID_ENA_VF_RSERV0 0xEC21 1891173fca2SJan Medala 190daa02b5cSOlivier Matz #define ENA_TX_OFFLOAD_MASK (RTE_MBUF_F_TX_L4_MASK | \ 191daa02b5cSOlivier Matz RTE_MBUF_F_TX_IPV6 | \ 192daa02b5cSOlivier Matz RTE_MBUF_F_TX_IPV4 | \ 193daa02b5cSOlivier Matz RTE_MBUF_F_TX_IP_CKSUM | \ 194daa02b5cSOlivier Matz RTE_MBUF_F_TX_TCP_SEG) 195b3fc5a1aSKonstantin Ananyev 196b3fc5a1aSKonstantin Ananyev #define ENA_TX_OFFLOAD_NOTSUP_MASK \ 197daa02b5cSOlivier Matz (RTE_MBUF_F_TX_OFFLOAD_MASK ^ ENA_TX_OFFLOAD_MASK) 198b3fc5a1aSKonstantin Ananyev 199e8c838fdSMichal Krawczyk /** HW specific offloads capabilities. */ 200e8c838fdSMichal Krawczyk /* IPv4 checksum offload. */ 201e8c838fdSMichal Krawczyk #define ENA_L3_IPV4_CSUM 0x0001 202e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv4 packets. */ 203e8c838fdSMichal Krawczyk #define ENA_L4_IPV4_CSUM 0x0002 204e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv4 packets with pseudo header checksum. */ 205e8c838fdSMichal Krawczyk #define ENA_L4_IPV4_CSUM_PARTIAL 0x0004 206e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv6 packets. */ 207e8c838fdSMichal Krawczyk #define ENA_L4_IPV6_CSUM 0x0008 208e8c838fdSMichal Krawczyk /* TCP/UDP checksum offload for IPv6 packets with pseudo header checksum. */ 209e8c838fdSMichal Krawczyk #define ENA_L4_IPV6_CSUM_PARTIAL 0x0010 210e8c838fdSMichal Krawczyk /* TSO support for IPv4 packets. */ 211e8c838fdSMichal Krawczyk #define ENA_IPV4_TSO 0x0020 212e8c838fdSMichal Krawczyk 213e8c838fdSMichal Krawczyk /* Device supports setting RSS hash. */ 214e8c838fdSMichal Krawczyk #define ENA_RX_RSS_HASH 0x0040 215e8c838fdSMichal Krawczyk 21628a1fd4fSFerruh Yigit static const struct rte_pci_id pci_id_ena_map[] = { 217cb990571SDavid Marchand { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF) }, 218f7138b91SMichal Krawczyk { RTE_PCI_DEVICE(PCI_VENDOR_ID_AMAZON, PCI_DEVICE_ID_ENA_VF_RSERV0) }, 2191173fca2SJan Medala { .device_id = 0 }, 2201173fca2SJan Medala }; 2211173fca2SJan Medala 222ca148440SMichal Krawczyk static struct ena_aenq_handlers aenq_handlers; 2233adcba9aSMichal Krawczyk 224b9b05d6fSMichal Krawczyk static int ena_device_init(struct ena_adapter *adapter, 225aab58857SStanislaw Kardach struct rte_pci_device *pdev, 226b9b05d6fSMichal Krawczyk struct ena_com_dev_get_features_ctx *get_feat_ctx); 2271173fca2SJan Medala static int ena_dev_configure(struct rte_eth_dev *dev); 22836278b82SMichal Krawczyk static void ena_tx_map_mbuf(struct ena_ring *tx_ring, 22936278b82SMichal Krawczyk struct ena_tx_buffer *tx_info, 23036278b82SMichal Krawczyk struct rte_mbuf *mbuf, 23136278b82SMichal Krawczyk void **push_header, 23236278b82SMichal Krawczyk uint16_t *header_len); 23336278b82SMichal Krawczyk static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf); 234a52b317eSDawid Gorecki static int ena_tx_cleanup(void *txp, uint32_t free_pkt_cnt); 2351173fca2SJan Medala static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 2361173fca2SJan Medala uint16_t nb_pkts); 237b3fc5a1aSKonstantin Ananyev static uint16_t eth_ena_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 238b3fc5a1aSKonstantin Ananyev uint16_t nb_pkts); 2391173fca2SJan Medala static int ena_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 2401173fca2SJan Medala uint16_t nb_desc, unsigned int socket_id, 2411173fca2SJan Medala const struct rte_eth_txconf *tx_conf); 2421173fca2SJan Medala static int ena_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 2431173fca2SJan Medala uint16_t nb_desc, unsigned int socket_id, 2441173fca2SJan Medala const struct rte_eth_rxconf *rx_conf, 2451173fca2SJan Medala struct rte_mempool *mp); 2461be097dcSMichal Krawczyk static inline void ena_init_rx_mbuf(struct rte_mbuf *mbuf, uint16_t len); 2471be097dcSMichal Krawczyk static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, 2481be097dcSMichal Krawczyk struct ena_com_rx_buf_info *ena_bufs, 2491be097dcSMichal Krawczyk uint32_t descs, 2501be097dcSMichal Krawczyk uint16_t *next_to_clean, 2511be097dcSMichal Krawczyk uint8_t offset); 2521173fca2SJan Medala static uint16_t eth_ena_recv_pkts(void *rx_queue, 2531173fca2SJan Medala struct rte_mbuf **rx_pkts, uint16_t nb_pkts); 25483fd97b2SMichal Krawczyk static int ena_add_single_rx_desc(struct ena_com_io_sq *io_sq, 25583fd97b2SMichal Krawczyk struct rte_mbuf *mbuf, uint16_t id); 2561173fca2SJan Medala static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count); 25733dde075SMichal Krawczyk static void ena_init_rings(struct ena_adapter *adapter, 25833dde075SMichal Krawczyk bool disable_meta_caching); 2591173fca2SJan Medala static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); 2601173fca2SJan Medala static int ena_start(struct rte_eth_dev *dev); 26162024eb8SIvan Ilchenko static int ena_stop(struct rte_eth_dev *dev); 262b142387bSThomas Monjalon static int ena_close(struct rte_eth_dev *dev); 2632081d5e2SMichal Krawczyk static int ena_dev_reset(struct rte_eth_dev *dev); 264d5b0924bSMatan Azrad static int ena_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); 2651173fca2SJan Medala static void ena_rx_queue_release_all(struct rte_eth_dev *dev); 2661173fca2SJan Medala static void ena_tx_queue_release_all(struct rte_eth_dev *dev); 2677483341aSXueming Li static void ena_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 2687483341aSXueming Li static void ena_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 2691173fca2SJan Medala static void ena_rx_queue_release_bufs(struct ena_ring *ring); 2701173fca2SJan Medala static void ena_tx_queue_release_bufs(struct ena_ring *ring); 2711173fca2SJan Medala static int ena_link_update(struct rte_eth_dev *dev, 272dd2c630aSFerruh Yigit int wait_to_complete); 2736986cdc4SMichal Krawczyk static int ena_create_io_queue(struct rte_eth_dev *dev, struct ena_ring *ring); 27426e5543dSRafal Kozik static void ena_queue_stop(struct ena_ring *ring); 27526e5543dSRafal Kozik static void ena_queue_stop_all(struct rte_eth_dev *dev, 27626e5543dSRafal Kozik enum ena_ring_type ring_type); 2776986cdc4SMichal Krawczyk static int ena_queue_start(struct rte_eth_dev *dev, struct ena_ring *ring); 27826e5543dSRafal Kozik static int ena_queue_start_all(struct rte_eth_dev *dev, 2791173fca2SJan Medala enum ena_ring_type ring_type); 2801173fca2SJan Medala static void ena_stats_restart(struct rte_eth_dev *dev); 2813a822d79SMichal Krawczyk static uint64_t ena_get_rx_port_offloads(struct ena_adapter *adapter); 2823a822d79SMichal Krawczyk static uint64_t ena_get_tx_port_offloads(struct ena_adapter *adapter); 2833a822d79SMichal Krawczyk static uint64_t ena_get_rx_queue_offloads(struct ena_adapter *adapter); 2843a822d79SMichal Krawczyk static uint64_t ena_get_tx_queue_offloads(struct ena_adapter *adapter); 285bdad90d1SIvan Ilchenko static int ena_infos_get(struct rte_eth_dev *dev, 2861173fca2SJan Medala struct rte_eth_dev_info *dev_info); 287ca1dfa85SShai Brandes static void ena_control_path_handler(void *cb_arg); 288ca1dfa85SShai Brandes static void ena_control_path_poll_handler(void *cb_arg); 289d9b8b106SMichal Krawczyk static void ena_timer_wd_callback(struct rte_timer *timer, void *arg); 290e457bc70SRafal Kozik static int eth_ena_dev_init(struct rte_eth_dev *eth_dev); 2918af56083SShai Brandes static int eth_ena_dev_uninit(struct rte_eth_dev *eth_dev); 2927830e905SSolganik Alexander static int ena_xstats_get_names(struct rte_eth_dev *dev, 2937830e905SSolganik Alexander struct rte_eth_xstat_name *xstats_names, 2947830e905SSolganik Alexander unsigned int n); 2953cec73faSMichal Krawczyk static int ena_xstats_get_names_by_id(struct rte_eth_dev *dev, 2963cec73faSMichal Krawczyk const uint64_t *ids, 2973cec73faSMichal Krawczyk struct rte_eth_xstat_name *xstats_names, 2983cec73faSMichal Krawczyk unsigned int size); 2997830e905SSolganik Alexander static int ena_xstats_get(struct rte_eth_dev *dev, 3007830e905SSolganik Alexander struct rte_eth_xstat *stats, 3017830e905SSolganik Alexander unsigned int n); 3027830e905SSolganik Alexander static int ena_xstats_get_by_id(struct rte_eth_dev *dev, 3037830e905SSolganik Alexander const uint64_t *ids, 3047830e905SSolganik Alexander uint64_t *values, 3057830e905SSolganik Alexander unsigned int n); 306d7918d19SShai Brandes static int ena_process_llq_policy_devarg(const char *key, 3078a7a73f2SMichal Krawczyk const char *value, 3088a7a73f2SMichal Krawczyk void *opaque); 3098a7a73f2SMichal Krawczyk static int ena_parse_devargs(struct ena_adapter *adapter, 3108a7a73f2SMichal Krawczyk struct rte_devargs *devargs); 31192401abfSShai Brandes static void ena_copy_customer_metrics(struct ena_adapter *adapter, 31292401abfSShai Brandes uint64_t *buf, 31392401abfSShai Brandes size_t buf_size); 314a73dd098SShai Brandes static void ena_copy_ena_srd_info(struct ena_adapter *adapter, 315a73dd098SShai Brandes struct ena_stats_srd *srd_info); 3166986cdc4SMichal Krawczyk static int ena_setup_rx_intr(struct rte_eth_dev *dev); 3176986cdc4SMichal Krawczyk static int ena_rx_queue_intr_enable(struct rte_eth_dev *dev, 3186986cdc4SMichal Krawczyk uint16_t queue_id); 3196986cdc4SMichal Krawczyk static int ena_rx_queue_intr_disable(struct rte_eth_dev *dev, 3206986cdc4SMichal Krawczyk uint16_t queue_id); 321b9b05d6fSMichal Krawczyk static int ena_configure_aenq(struct ena_adapter *adapter); 322e3595539SStanislaw Kardach static int ena_mp_primary_handle(const struct rte_mp_msg *mp_msg, 323e3595539SStanislaw Kardach const void *peer); 3241f11149dSShai Brandes static bool ena_use_large_llq_hdr(struct ena_adapter *adapter, uint8_t recommended_entry_size); 3251173fca2SJan Medala 326103ab18cSFerruh Yigit static const struct eth_dev_ops ena_dev_ops = { 3271173fca2SJan Medala .dev_configure = ena_dev_configure, 3281173fca2SJan Medala .dev_infos_get = ena_infos_get, 3291173fca2SJan Medala .rx_queue_setup = ena_rx_queue_setup, 3301173fca2SJan Medala .tx_queue_setup = ena_tx_queue_setup, 3311173fca2SJan Medala .dev_start = ena_start, 332eb0ef49dSMichal Krawczyk .dev_stop = ena_stop, 3331173fca2SJan Medala .link_update = ena_link_update, 3341173fca2SJan Medala .stats_get = ena_stats_get, 3357830e905SSolganik Alexander .xstats_get_names = ena_xstats_get_names, 3363cec73faSMichal Krawczyk .xstats_get_names_by_id = ena_xstats_get_names_by_id, 3377830e905SSolganik Alexander .xstats_get = ena_xstats_get, 3387830e905SSolganik Alexander .xstats_get_by_id = ena_xstats_get_by_id, 3391173fca2SJan Medala .mtu_set = ena_mtu_set, 3401173fca2SJan Medala .rx_queue_release = ena_rx_queue_release, 3411173fca2SJan Medala .tx_queue_release = ena_tx_queue_release, 3421173fca2SJan Medala .dev_close = ena_close, 3432081d5e2SMichal Krawczyk .dev_reset = ena_dev_reset, 3441173fca2SJan Medala .reta_update = ena_rss_reta_update, 3451173fca2SJan Medala .reta_query = ena_rss_reta_query, 3466986cdc4SMichal Krawczyk .rx_queue_intr_enable = ena_rx_queue_intr_enable, 3476986cdc4SMichal Krawczyk .rx_queue_intr_disable = ena_rx_queue_intr_disable, 34834d5e97eSMichal Krawczyk .rss_hash_update = ena_rss_hash_update, 34934d5e97eSMichal Krawczyk .rss_hash_conf_get = ena_rss_hash_conf_get, 350a52b317eSDawid Gorecki .tx_done_cleanup = ena_tx_cleanup, 3511173fca2SJan Medala }; 3521173fca2SJan Medala 353e3595539SStanislaw Kardach /********************************************************************* 354e3595539SStanislaw Kardach * Multi-Process communication bits 355e3595539SStanislaw Kardach *********************************************************************/ 356e3595539SStanislaw Kardach /* rte_mp IPC message name */ 357e3595539SStanislaw Kardach #define ENA_MP_NAME "net_ena_mp" 358e3595539SStanislaw Kardach /* Request timeout in seconds */ 359e3595539SStanislaw Kardach #define ENA_MP_REQ_TMO 5 360e3595539SStanislaw Kardach 361e3595539SStanislaw Kardach /** Proxy request type */ 362e3595539SStanislaw Kardach enum ena_mp_req { 363e3595539SStanislaw Kardach ENA_MP_DEV_STATS_GET, 364e3595539SStanislaw Kardach ENA_MP_ENI_STATS_GET, 365e3595539SStanislaw Kardach ENA_MP_MTU_SET, 366e3595539SStanislaw Kardach ENA_MP_IND_TBL_GET, 36792401abfSShai Brandes ENA_MP_IND_TBL_SET, 36892401abfSShai Brandes ENA_MP_CUSTOMER_METRICS_GET, 369a73dd098SShai Brandes ENA_MP_SRD_STATS_GET, 370e3595539SStanislaw Kardach }; 371e3595539SStanislaw Kardach 372e3595539SStanislaw Kardach /** Proxy message body. Shared between requests and responses. */ 373e3595539SStanislaw Kardach struct ena_mp_body { 374e3595539SStanislaw Kardach /* Message type */ 375e3595539SStanislaw Kardach enum ena_mp_req type; 376e3595539SStanislaw Kardach int port_id; 377e3595539SStanislaw Kardach /* Processing result. Set in replies. 0 if message succeeded, negative 378e3595539SStanislaw Kardach * error code otherwise. 379e3595539SStanislaw Kardach */ 380e3595539SStanislaw Kardach int result; 381e3595539SStanislaw Kardach union { 382e3595539SStanislaw Kardach int mtu; /* For ENA_MP_MTU_SET */ 383e3595539SStanislaw Kardach } args; 384e3595539SStanislaw Kardach }; 385e3595539SStanislaw Kardach 386e3595539SStanislaw Kardach /** 387e3595539SStanislaw Kardach * Initialize IPC message. 388e3595539SStanislaw Kardach * 389e3595539SStanislaw Kardach * @param[out] msg 390e3595539SStanislaw Kardach * Pointer to the message to initialize. 391e3595539SStanislaw Kardach * @param[in] type 392e3595539SStanislaw Kardach * Message type. 393e3595539SStanislaw Kardach * @param[in] port_id 394e3595539SStanislaw Kardach * Port ID of target device. 395e3595539SStanislaw Kardach * 396e3595539SStanislaw Kardach */ 397e3595539SStanislaw Kardach static void 398e3595539SStanislaw Kardach mp_msg_init(struct rte_mp_msg *msg, enum ena_mp_req type, int port_id) 399e3595539SStanislaw Kardach { 400e3595539SStanislaw Kardach struct ena_mp_body *body = (struct ena_mp_body *)&msg->param; 401e3595539SStanislaw Kardach 402e3595539SStanislaw Kardach memset(msg, 0, sizeof(*msg)); 403e3595539SStanislaw Kardach strlcpy(msg->name, ENA_MP_NAME, sizeof(msg->name)); 404e3595539SStanislaw Kardach msg->len_param = sizeof(*body); 405e3595539SStanislaw Kardach body->type = type; 406e3595539SStanislaw Kardach body->port_id = port_id; 407e3595539SStanislaw Kardach } 408e3595539SStanislaw Kardach 409e3595539SStanislaw Kardach /********************************************************************* 410e3595539SStanislaw Kardach * Multi-Process communication PMD API 411e3595539SStanislaw Kardach *********************************************************************/ 412e3595539SStanislaw Kardach /** 413e3595539SStanislaw Kardach * Define proxy request descriptor 414e3595539SStanislaw Kardach * 415e3595539SStanislaw Kardach * Used to define all structures and functions required for proxying a given 416e3595539SStanislaw Kardach * function to the primary process including the code to perform to prepare the 417e3595539SStanislaw Kardach * request and process the response. 418e3595539SStanislaw Kardach * 419e3595539SStanislaw Kardach * @param[in] f 420e3595539SStanislaw Kardach * Name of the function to proxy 421e3595539SStanislaw Kardach * @param[in] t 422e3595539SStanislaw Kardach * Message type to use 423e3595539SStanislaw Kardach * @param[in] prep 424e3595539SStanislaw Kardach * Body of a function to prepare the request in form of a statement 425e3595539SStanislaw Kardach * expression. It is passed all the original function arguments along with two 426e3595539SStanislaw Kardach * extra ones: 427e3595539SStanislaw Kardach * - struct ena_adapter *adapter - PMD data of the device calling the proxy. 428e3595539SStanislaw Kardach * - struct ena_mp_body *req - body of a request to prepare. 429e3595539SStanislaw Kardach * @param[in] proc 430e3595539SStanislaw Kardach * Body of a function to process the response in form of a statement 431e3595539SStanislaw Kardach * expression. It is passed all the original function arguments along with two 432e3595539SStanislaw Kardach * extra ones: 433e3595539SStanislaw Kardach * - struct ena_adapter *adapter - PMD data of the device calling the proxy. 434e3595539SStanislaw Kardach * - struct ena_mp_body *rsp - body of a response to process. 435e3595539SStanislaw Kardach * @param ... 436e3595539SStanislaw Kardach * Proxied function's arguments 437e3595539SStanislaw Kardach * 438e3595539SStanislaw Kardach * @note Inside prep and proc any parameters which aren't used should be marked 439e3595539SStanislaw Kardach * as such (with ENA_TOUCH or __rte_unused). 440e3595539SStanislaw Kardach */ 441e3595539SStanislaw Kardach #define ENA_PROXY_DESC(f, t, prep, proc, ...) \ 442e3595539SStanislaw Kardach static const enum ena_mp_req mp_type_ ## f = t; \ 443e3595539SStanislaw Kardach static const char *mp_name_ ## f = #t; \ 444e3595539SStanislaw Kardach static void mp_prep_ ## f(struct ena_adapter *adapter, \ 445e3595539SStanislaw Kardach struct ena_mp_body *req, \ 446e3595539SStanislaw Kardach __VA_ARGS__) \ 447e3595539SStanislaw Kardach { \ 448e3595539SStanislaw Kardach prep; \ 449e3595539SStanislaw Kardach } \ 450e3595539SStanislaw Kardach static void mp_proc_ ## f(struct ena_adapter *adapter, \ 451e3595539SStanislaw Kardach struct ena_mp_body *rsp, \ 452e3595539SStanislaw Kardach __VA_ARGS__) \ 453e3595539SStanislaw Kardach { \ 454e3595539SStanislaw Kardach proc; \ 455e3595539SStanislaw Kardach } 456e3595539SStanislaw Kardach 457e3595539SStanislaw Kardach /** 458e3595539SStanislaw Kardach * Proxy wrapper for calling primary functions in a secondary process. 459e3595539SStanislaw Kardach * 460e3595539SStanislaw Kardach * Depending on whether called in primary or secondary process, calls the 461e3595539SStanislaw Kardach * @p func directly or proxies the call to the primary process via rte_mp IPC. 462e3595539SStanislaw Kardach * This macro requires a proxy request descriptor to be defined for @p func 463e3595539SStanislaw Kardach * using ENA_PROXY_DESC() macro. 464e3595539SStanislaw Kardach * 465e3595539SStanislaw Kardach * @param[in/out] a 466e3595539SStanislaw Kardach * Device PMD data. Used for sending the message and sharing message results 467e3595539SStanislaw Kardach * between primary and secondary. 468e3595539SStanislaw Kardach * @param[in] f 469e3595539SStanislaw Kardach * Function to proxy. 470e3595539SStanislaw Kardach * @param ... 471e3595539SStanislaw Kardach * Arguments of @p func. 472e3595539SStanislaw Kardach * 473e3595539SStanislaw Kardach * @return 474e3595539SStanislaw Kardach * - 0: Processing succeeded and response handler was called. 475e3595539SStanislaw Kardach * - -EPERM: IPC is unavailable on this platform. This means only primary 476e3595539SStanislaw Kardach * process may call the proxied function. 477e3595539SStanislaw Kardach * - -EIO: IPC returned error on request send. Inspect rte_errno detailed 478e3595539SStanislaw Kardach * error code. 479e3595539SStanislaw Kardach * - Negative error code from the proxied function. 480e3595539SStanislaw Kardach * 481e3595539SStanislaw Kardach * @note This mechanism is geared towards control-path tasks. Avoid calling it 482e3595539SStanislaw Kardach * in fast-path unless unbound delays are allowed. This is due to the IPC 483e3595539SStanislaw Kardach * mechanism itself (socket based). 484e3595539SStanislaw Kardach * @note Due to IPC parameter size limitations the proxy logic shares call 485e3595539SStanislaw Kardach * results through the struct ena_adapter shared memory. This makes the 486e3595539SStanislaw Kardach * proxy mechanism strictly single-threaded. Therefore be sure to make all 487e3595539SStanislaw Kardach * calls to the same proxied function under the same lock. 488e3595539SStanislaw Kardach */ 489e3595539SStanislaw Kardach #define ENA_PROXY(a, f, ...) \ 49093998f3cSTyler Retzlaff __extension__ ({ \ 491e3595539SStanislaw Kardach struct ena_adapter *_a = (a); \ 492e3595539SStanislaw Kardach struct timespec ts = { .tv_sec = ENA_MP_REQ_TMO }; \ 493e3595539SStanislaw Kardach struct ena_mp_body *req, *rsp; \ 494e3595539SStanislaw Kardach struct rte_mp_reply mp_rep; \ 495e3595539SStanislaw Kardach struct rte_mp_msg mp_req; \ 496e3595539SStanislaw Kardach int ret; \ 497e3595539SStanislaw Kardach \ 498e3595539SStanislaw Kardach if (rte_eal_process_type() == RTE_PROC_PRIMARY) { \ 499e3595539SStanislaw Kardach ret = f(__VA_ARGS__); \ 500e3595539SStanislaw Kardach } else { \ 501e3595539SStanislaw Kardach /* Prepare and send request */ \ 502e3595539SStanislaw Kardach req = (struct ena_mp_body *)&mp_req.param; \ 503e3595539SStanislaw Kardach mp_msg_init(&mp_req, mp_type_ ## f, _a->edev_data->port_id); \ 504e3595539SStanislaw Kardach mp_prep_ ## f(_a, req, ## __VA_ARGS__); \ 505e3595539SStanislaw Kardach \ 506e3595539SStanislaw Kardach ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts); \ 507e3595539SStanislaw Kardach if (likely(!ret)) { \ 508e3595539SStanislaw Kardach RTE_ASSERT(mp_rep.nb_received == 1); \ 509e3595539SStanislaw Kardach rsp = (struct ena_mp_body *)&mp_rep.msgs[0].param; \ 510e3595539SStanislaw Kardach ret = rsp->result; \ 511e3595539SStanislaw Kardach if (ret == 0) { \ 512e3595539SStanislaw Kardach mp_proc_##f(_a, rsp, ## __VA_ARGS__); \ 513e3595539SStanislaw Kardach } else { \ 514e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, \ 515e99981afSDavid Marchand "%s returned error: %d", \ 516e3595539SStanislaw Kardach mp_name_ ## f, rsp->result);\ 517e3595539SStanislaw Kardach } \ 518e3595539SStanislaw Kardach free(mp_rep.msgs); \ 519e3595539SStanislaw Kardach } else if (rte_errno == ENOTSUP) { \ 520e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, \ 521e99981afSDavid Marchand "No IPC, can't proxy to primary");\ 522e3595539SStanislaw Kardach ret = -rte_errno; \ 523e3595539SStanislaw Kardach } else { \ 524e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Request %s failed: %s", \ 525e3595539SStanislaw Kardach mp_name_ ## f, \ 526e3595539SStanislaw Kardach rte_strerror(rte_errno)); \ 527e3595539SStanislaw Kardach ret = -EIO; \ 528e3595539SStanislaw Kardach } \ 529e3595539SStanislaw Kardach } \ 530e3595539SStanislaw Kardach ret; \ 531e3595539SStanislaw Kardach }) 532e3595539SStanislaw Kardach 533e3595539SStanislaw Kardach /********************************************************************* 534e3595539SStanislaw Kardach * Multi-Process communication request descriptors 535e3595539SStanislaw Kardach *********************************************************************/ 536e3595539SStanislaw Kardach 537e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_get_dev_basic_stats, ENA_MP_DEV_STATS_GET, 53893998f3cSTyler Retzlaff __extension__ ({ 539e3595539SStanislaw Kardach ENA_TOUCH(adapter); 540e3595539SStanislaw Kardach ENA_TOUCH(req); 541e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 542e3595539SStanislaw Kardach ENA_TOUCH(stats); 543e3595539SStanislaw Kardach }), 54493998f3cSTyler Retzlaff __extension__ ({ 545e3595539SStanislaw Kardach ENA_TOUCH(rsp); 546e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 547e3595539SStanislaw Kardach if (stats != &adapter->basic_stats) 548e3595539SStanislaw Kardach rte_memcpy(stats, &adapter->basic_stats, sizeof(*stats)); 549e3595539SStanislaw Kardach }), 550e3595539SStanislaw Kardach struct ena_com_dev *ena_dev, struct ena_admin_basic_stats *stats); 551e3595539SStanislaw Kardach 552e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_get_eni_stats, ENA_MP_ENI_STATS_GET, 55393998f3cSTyler Retzlaff __extension__ ({ 554e3595539SStanislaw Kardach ENA_TOUCH(adapter); 555e3595539SStanislaw Kardach ENA_TOUCH(req); 556e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 557e3595539SStanislaw Kardach ENA_TOUCH(stats); 558e3595539SStanislaw Kardach }), 55993998f3cSTyler Retzlaff __extension__ ({ 560e3595539SStanislaw Kardach ENA_TOUCH(rsp); 561e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 562980d0ba4SShai Brandes if (stats != (struct ena_admin_eni_stats *)adapter->metrics_stats) 563980d0ba4SShai Brandes rte_memcpy(stats, adapter->metrics_stats, sizeof(*stats)); 564e3595539SStanislaw Kardach }), 565e3595539SStanislaw Kardach struct ena_com_dev *ena_dev, struct ena_admin_eni_stats *stats); 566e3595539SStanislaw Kardach 567e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_set_dev_mtu, ENA_MP_MTU_SET, 56893998f3cSTyler Retzlaff __extension__ ({ 569e3595539SStanislaw Kardach ENA_TOUCH(adapter); 570e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 571e3595539SStanislaw Kardach req->args.mtu = mtu; 572e3595539SStanislaw Kardach }), 57393998f3cSTyler Retzlaff __extension__ ({ 574e3595539SStanislaw Kardach ENA_TOUCH(adapter); 575e3595539SStanislaw Kardach ENA_TOUCH(rsp); 576e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 577e3595539SStanislaw Kardach ENA_TOUCH(mtu); 578e3595539SStanislaw Kardach }), 579e3595539SStanislaw Kardach struct ena_com_dev *ena_dev, int mtu); 580e3595539SStanislaw Kardach 581e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_indirect_table_set, ENA_MP_IND_TBL_SET, 58293998f3cSTyler Retzlaff __extension__ ({ 583e3595539SStanislaw Kardach ENA_TOUCH(adapter); 584e3595539SStanislaw Kardach ENA_TOUCH(req); 585e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 586e3595539SStanislaw Kardach }), 58793998f3cSTyler Retzlaff __extension__ ({ 588e3595539SStanislaw Kardach ENA_TOUCH(adapter); 589e3595539SStanislaw Kardach ENA_TOUCH(rsp); 590e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 591e3595539SStanislaw Kardach }), 592e3595539SStanislaw Kardach struct ena_com_dev *ena_dev); 593e3595539SStanislaw Kardach 594e3595539SStanislaw Kardach ENA_PROXY_DESC(ena_com_indirect_table_get, ENA_MP_IND_TBL_GET, 59593998f3cSTyler Retzlaff __extension__ ({ 596e3595539SStanislaw Kardach ENA_TOUCH(adapter); 597e3595539SStanislaw Kardach ENA_TOUCH(req); 598e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 599e3595539SStanislaw Kardach ENA_TOUCH(ind_tbl); 600e3595539SStanislaw Kardach }), 60193998f3cSTyler Retzlaff __extension__ ({ 602e3595539SStanislaw Kardach ENA_TOUCH(rsp); 603e3595539SStanislaw Kardach ENA_TOUCH(ena_dev); 604e3595539SStanislaw Kardach if (ind_tbl != adapter->indirect_table) 605e3595539SStanislaw Kardach rte_memcpy(ind_tbl, adapter->indirect_table, 606e3595539SStanislaw Kardach sizeof(adapter->indirect_table)); 607e3595539SStanislaw Kardach }), 608e3595539SStanislaw Kardach struct ena_com_dev *ena_dev, u32 *ind_tbl); 609e3595539SStanislaw Kardach 61092401abfSShai Brandes ENA_PROXY_DESC(ena_com_get_customer_metrics, ENA_MP_CUSTOMER_METRICS_GET, 61193998f3cSTyler Retzlaff __extension__ ({ 61292401abfSShai Brandes ENA_TOUCH(adapter); 61392401abfSShai Brandes ENA_TOUCH(req); 61492401abfSShai Brandes ENA_TOUCH(ena_dev); 61592401abfSShai Brandes ENA_TOUCH(buf); 61692401abfSShai Brandes ENA_TOUCH(buf_size); 61792401abfSShai Brandes }), 61893998f3cSTyler Retzlaff __extension__ ({ 61992401abfSShai Brandes ENA_TOUCH(rsp); 62092401abfSShai Brandes ENA_TOUCH(ena_dev); 621980d0ba4SShai Brandes if (buf != (char *)adapter->metrics_stats) 622980d0ba4SShai Brandes rte_memcpy(buf, adapter->metrics_stats, buf_size); 62392401abfSShai Brandes }), 62492401abfSShai Brandes struct ena_com_dev *ena_dev, char *buf, size_t buf_size); 62592401abfSShai Brandes 626a73dd098SShai Brandes ENA_PROXY_DESC(ena_com_get_ena_srd_info, ENA_MP_SRD_STATS_GET, 62793998f3cSTyler Retzlaff __extension__ ({ 628a73dd098SShai Brandes ENA_TOUCH(adapter); 629a73dd098SShai Brandes ENA_TOUCH(req); 630a73dd098SShai Brandes ENA_TOUCH(ena_dev); 631a73dd098SShai Brandes ENA_TOUCH(info); 632a73dd098SShai Brandes }), 63393998f3cSTyler Retzlaff __extension__ ({ 634a73dd098SShai Brandes ENA_TOUCH(rsp); 635a73dd098SShai Brandes ENA_TOUCH(ena_dev); 636a73dd098SShai Brandes if ((struct ena_stats_srd *)info != &adapter->srd_stats) 637a73dd098SShai Brandes rte_memcpy((struct ena_stats_srd *)info, 638a73dd098SShai Brandes &adapter->srd_stats, 639a73dd098SShai Brandes sizeof(struct ena_stats_srd)); 640a73dd098SShai Brandes }), 641a73dd098SShai Brandes struct ena_com_dev *ena_dev, struct ena_admin_ena_srd_info *info); 64292401abfSShai Brandes 6432bae75eaSDawid Gorecki static inline void ena_trigger_reset(struct ena_adapter *adapter, 6442bae75eaSDawid Gorecki enum ena_regs_reset_reason_types reason) 6452bae75eaSDawid Gorecki { 6462bae75eaSDawid Gorecki if (likely(!adapter->trigger_reset)) { 6472bae75eaSDawid Gorecki adapter->reset_reason = reason; 6482bae75eaSDawid Gorecki adapter->trigger_reset = true; 6492bae75eaSDawid Gorecki } 6502bae75eaSDawid Gorecki } 6512bae75eaSDawid Gorecki 65284daba99SMichal Krawczyk static inline void ena_rx_mbuf_prepare(struct ena_ring *rx_ring, 65384daba99SMichal Krawczyk struct rte_mbuf *mbuf, 6545ac1749fSShai Brandes struct ena_com_rx_ctx *ena_rx_ctx) 6551173fca2SJan Medala { 65684daba99SMichal Krawczyk struct ena_stats_rx *rx_stats = &rx_ring->rx_stats; 6571173fca2SJan Medala uint64_t ol_flags = 0; 658fd617795SRafal Kozik uint32_t packet_type = 0; 6591173fca2SJan Medala 6605ac1749fSShai Brandes switch (ena_rx_ctx->l3_proto) { 6615ac1749fSShai Brandes case ENA_ETH_IO_L3_PROTO_IPV4: 662fd617795SRafal Kozik packet_type |= RTE_PTYPE_L3_IPV4; 66384daba99SMichal Krawczyk if (unlikely(ena_rx_ctx->l3_csum_err)) { 66484daba99SMichal Krawczyk ++rx_stats->l3_csum_bad; 665daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; 66684daba99SMichal Krawczyk } else { 667daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD; 66884daba99SMichal Krawczyk } 6695ac1749fSShai Brandes break; 6705ac1749fSShai Brandes case ENA_ETH_IO_L3_PROTO_IPV6: 671856edce2SMichal Krawczyk packet_type |= RTE_PTYPE_L3_IPV6; 6725ac1749fSShai Brandes break; 6735ac1749fSShai Brandes default: 6745ac1749fSShai Brandes break; 675856edce2SMichal Krawczyk } 676856edce2SMichal Krawczyk 6775ac1749fSShai Brandes switch (ena_rx_ctx->l4_proto) { 6785ac1749fSShai Brandes case ENA_ETH_IO_L4_PROTO_TCP: 6795ac1749fSShai Brandes packet_type |= RTE_PTYPE_L4_TCP; 6805ac1749fSShai Brandes break; 6815ac1749fSShai Brandes case ENA_ETH_IO_L4_PROTO_UDP: 6825ac1749fSShai Brandes packet_type |= RTE_PTYPE_L4_UDP; 6835ac1749fSShai Brandes break; 6845ac1749fSShai Brandes default: 6855ac1749fSShai Brandes break; 6865ac1749fSShai Brandes } 6875ac1749fSShai Brandes 6885ac1749fSShai Brandes /* L4 csum is relevant only for TCP/UDP packets */ 6895ac1749fSShai Brandes if ((packet_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP)) && !ena_rx_ctx->frag) { 6905ac1749fSShai Brandes if (ena_rx_ctx->l4_csum_checked) { 6915ac1749fSShai Brandes if (likely(!ena_rx_ctx->l4_csum_err)) { 69284daba99SMichal Krawczyk ++rx_stats->l4_csum_good; 693daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; 6945ac1749fSShai Brandes } else { 6955ac1749fSShai Brandes ++rx_stats->l4_csum_bad; 6965ac1749fSShai Brandes ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; 69784daba99SMichal Krawczyk } 6985ac1749fSShai Brandes } else { 6995ac1749fSShai Brandes ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN; 70084daba99SMichal Krawczyk } 7011173fca2SJan Medala 7025ac1749fSShai Brandes if (rx_ring->offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH) { 703daa02b5cSOlivier Matz ol_flags |= RTE_MBUF_F_RX_RSS_HASH; 704b418f0d2SMichal Krawczyk mbuf->hash.rss = ena_rx_ctx->hash; 705b418f0d2SMichal Krawczyk } 7065ac1749fSShai Brandes } else { 7075ac1749fSShai Brandes ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN; 7085ac1749fSShai Brandes } 709b418f0d2SMichal Krawczyk 7101173fca2SJan Medala mbuf->ol_flags = ol_flags; 711fd617795SRafal Kozik mbuf->packet_type = packet_type; 7121173fca2SJan Medala } 7131173fca2SJan Medala 7141173fca2SJan Medala static inline void ena_tx_mbuf_prepare(struct rte_mbuf *mbuf, 71556b8b9b7SRafal Kozik struct ena_com_tx_ctx *ena_tx_ctx, 71633dde075SMichal Krawczyk uint64_t queue_offloads, 71733dde075SMichal Krawczyk bool disable_meta_caching) 7181173fca2SJan Medala { 7191173fca2SJan Medala struct ena_com_tx_meta *ena_meta = &ena_tx_ctx->ena_meta; 7201173fca2SJan Medala 72156b8b9b7SRafal Kozik if ((mbuf->ol_flags & MBUF_OFFLOADS) && 72256b8b9b7SRafal Kozik (queue_offloads & QUEUE_OFFLOADS)) { 7231173fca2SJan Medala /* check if TSO is required */ 724daa02b5cSOlivier Matz if ((mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) && 725295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO)) { 7261173fca2SJan Medala ena_tx_ctx->tso_enable = true; 7271173fca2SJan Medala 7281173fca2SJan Medala ena_meta->l4_hdr_len = GET_L4_HDR_LEN(mbuf); 7291173fca2SJan Medala } 7301173fca2SJan Medala 7311173fca2SJan Medala /* check if L3 checksum is needed */ 732daa02b5cSOlivier Matz if ((mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) && 733295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) 7341173fca2SJan Medala ena_tx_ctx->l3_csum_enable = true; 7351173fca2SJan Medala 736daa02b5cSOlivier Matz if (mbuf->ol_flags & RTE_MBUF_F_TX_IPV6) { 7371173fca2SJan Medala ena_tx_ctx->l3_proto = ENA_ETH_IO_L3_PROTO_IPV6; 738022fb61bSMichal Krawczyk /* For the IPv6 packets, DF always needs to be true. */ 739022fb61bSMichal Krawczyk ena_tx_ctx->df = 1; 7401173fca2SJan Medala } else { 7411173fca2SJan Medala ena_tx_ctx->l3_proto = ENA_ETH_IO_L3_PROTO_IPV4; 7421173fca2SJan Medala 7431173fca2SJan Medala /* set don't fragment (DF) flag */ 7441173fca2SJan Medala if (mbuf->packet_type & 7451173fca2SJan Medala (RTE_PTYPE_L4_NONFRAG 7461173fca2SJan Medala | RTE_PTYPE_INNER_L4_NONFRAG)) 747022fb61bSMichal Krawczyk ena_tx_ctx->df = 1; 7481173fca2SJan Medala } 7491173fca2SJan Medala 7501173fca2SJan Medala /* check if L4 checksum is needed */ 751daa02b5cSOlivier Matz if (((mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK) == RTE_MBUF_F_TX_TCP_CKSUM) && 752295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) { 7531173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_TCP; 7541173fca2SJan Medala ena_tx_ctx->l4_csum_enable = true; 755daa02b5cSOlivier Matz } else if (((mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK) == 756daa02b5cSOlivier Matz RTE_MBUF_F_TX_UDP_CKSUM) && 757295968d1SFerruh Yigit (queue_offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM)) { 7581173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_UDP; 7591173fca2SJan Medala ena_tx_ctx->l4_csum_enable = true; 76056b8b9b7SRafal Kozik } else { 7611173fca2SJan Medala ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_UNKNOWN; 7621173fca2SJan Medala ena_tx_ctx->l4_csum_enable = false; 7631173fca2SJan Medala } 7641173fca2SJan Medala 7651173fca2SJan Medala ena_meta->mss = mbuf->tso_segsz; 7661173fca2SJan Medala ena_meta->l3_hdr_len = mbuf->l3_len; 7671173fca2SJan Medala ena_meta->l3_hdr_offset = mbuf->l2_len; 7681173fca2SJan Medala 7691173fca2SJan Medala ena_tx_ctx->meta_valid = true; 77033dde075SMichal Krawczyk } else if (disable_meta_caching) { 77133dde075SMichal Krawczyk memset(ena_meta, 0, sizeof(*ena_meta)); 77233dde075SMichal Krawczyk ena_tx_ctx->meta_valid = true; 7731173fca2SJan Medala } else { 7741173fca2SJan Medala ena_tx_ctx->meta_valid = false; 7751173fca2SJan Medala } 7761173fca2SJan Medala } 7771173fca2SJan Medala 778f7d82d24SRafal Kozik static int validate_tx_req_id(struct ena_ring *tx_ring, u16 req_id) 779f7d82d24SRafal Kozik { 780f7d82d24SRafal Kozik struct ena_tx_buffer *tx_info = NULL; 781f7d82d24SRafal Kozik 782f7d82d24SRafal Kozik if (likely(req_id < tx_ring->ring_size)) { 783f7d82d24SRafal Kozik tx_info = &tx_ring->tx_buffer_info[req_id]; 784f7d82d24SRafal Kozik if (likely(tx_info->mbuf)) 785f7d82d24SRafal Kozik return 0; 786f7d82d24SRafal Kozik } 787f7d82d24SRafal Kozik 788f7d82d24SRafal Kozik if (tx_info) 789e99981afSDavid Marchand PMD_TX_LOG_LINE(ERR, "tx_info doesn't have valid mbuf. queue %d:%d req_id %u", 79077e764c7SDawid Gorecki tx_ring->port_id, tx_ring->id, req_id); 791f7d82d24SRafal Kozik else 792e99981afSDavid Marchand PMD_TX_LOG_LINE(ERR, "Invalid req_id: %hu in queue %d:%d", 79377e764c7SDawid Gorecki req_id, tx_ring->port_id, tx_ring->id); 794f7d82d24SRafal Kozik 795f7d82d24SRafal Kozik /* Trigger device reset */ 7967830e905SSolganik Alexander ++tx_ring->tx_stats.bad_req_id; 7972bae75eaSDawid Gorecki ena_trigger_reset(tx_ring->adapter, ENA_REGS_RESET_INV_TX_REQ_ID); 798f7d82d24SRafal Kozik return -EFAULT; 799f7d82d24SRafal Kozik } 800f7d82d24SRafal Kozik 801372c1af5SJan Medala static void ena_config_host_info(struct ena_com_dev *ena_dev) 802372c1af5SJan Medala { 803372c1af5SJan Medala struct ena_admin_host_info *host_info; 804372c1af5SJan Medala int rc; 805372c1af5SJan Medala 806372c1af5SJan Medala /* Allocate only the host info */ 807372c1af5SJan Medala rc = ena_com_allocate_host_info(ena_dev); 808372c1af5SJan Medala if (rc) { 809e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Cannot allocate host info"); 810372c1af5SJan Medala return; 811372c1af5SJan Medala } 812372c1af5SJan Medala 813372c1af5SJan Medala host_info = ena_dev->host_attr.host_info; 814372c1af5SJan Medala 815372c1af5SJan Medala host_info->os_type = ENA_ADMIN_OS_DPDK; 816372c1af5SJan Medala host_info->kernel_ver = RTE_VERSION; 8176723c0fcSBruce Richardson strlcpy((char *)host_info->kernel_ver_str, rte_version(), 8186723c0fcSBruce Richardson sizeof(host_info->kernel_ver_str)); 819372c1af5SJan Medala host_info->os_dist = RTE_VERSION; 8206723c0fcSBruce Richardson strlcpy((char *)host_info->os_dist_str, rte_version(), 8216723c0fcSBruce Richardson sizeof(host_info->os_dist_str)); 822372c1af5SJan Medala host_info->driver_version = 823372c1af5SJan Medala (DRV_MODULE_VER_MAJOR) | 824372c1af5SJan Medala (DRV_MODULE_VER_MINOR << ENA_ADMIN_HOST_INFO_MINOR_SHIFT) | 825c4144557SJan Medala (DRV_MODULE_VER_SUBMINOR << 826c4144557SJan Medala ENA_ADMIN_HOST_INFO_SUB_MINOR_SHIFT); 827b9302eb9SRafal Kozik host_info->num_cpus = rte_lcore_count(); 828372c1af5SJan Medala 8297b3a3c4bSMaciej Bielski host_info->driver_supported_features = 83034d5e97eSMichal Krawczyk ENA_ADMIN_HOST_INFO_RX_OFFSET_MASK | 83134d5e97eSMichal Krawczyk ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK; 8327b3a3c4bSMaciej Bielski 833372c1af5SJan Medala rc = ena_com_set_host_attributes(ena_dev); 834372c1af5SJan Medala if (rc) { 8358936b01aSShai Brandes if (rc == ENA_COM_UNSUPPORTED) 836e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, "Cannot set host attributes"); 837241da076SRafal Kozik else 838e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Cannot set host attributes"); 839241da076SRafal Kozik 840372c1af5SJan Medala goto err; 841372c1af5SJan Medala } 842372c1af5SJan Medala 843372c1af5SJan Medala return; 844372c1af5SJan Medala 845372c1af5SJan Medala err: 846372c1af5SJan Medala ena_com_delete_host_info(ena_dev); 847372c1af5SJan Medala } 848372c1af5SJan Medala 8497830e905SSolganik Alexander /* This function calculates the number of xstats based on the current config */ 850aab58857SStanislaw Kardach static unsigned int ena_xstats_calc_num(struct rte_eth_dev_data *data) 851372c1af5SJan Medala { 85292401abfSShai Brandes struct ena_adapter *adapter = data->dev_private; 85392401abfSShai Brandes 85492401abfSShai Brandes return ENA_STATS_ARRAY_GLOBAL + 85592401abfSShai Brandes adapter->metrics_num + 856a73dd098SShai Brandes ENA_STATS_ARRAY_ENA_SRD + 857aab58857SStanislaw Kardach (data->nb_tx_queues * ENA_STATS_ARRAY_TX) + 858aab58857SStanislaw Kardach (data->nb_rx_queues * ENA_STATS_ARRAY_RX); 859372c1af5SJan Medala } 860372c1af5SJan Medala 861372c1af5SJan Medala static void ena_config_debug_area(struct ena_adapter *adapter) 862372c1af5SJan Medala { 863372c1af5SJan Medala u32 debug_area_size; 864372c1af5SJan Medala int rc, ss_count; 865372c1af5SJan Medala 866aab58857SStanislaw Kardach ss_count = ena_xstats_calc_num(adapter->edev_data); 867372c1af5SJan Medala 868372c1af5SJan Medala /* allocate 32 bytes for each string and 64bit for the value */ 869372c1af5SJan Medala debug_area_size = ss_count * ETH_GSTRING_LEN + sizeof(u64) * ss_count; 870372c1af5SJan Medala 871372c1af5SJan Medala rc = ena_com_allocate_debug_area(&adapter->ena_dev, debug_area_size); 872372c1af5SJan Medala if (rc) { 873e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Cannot allocate debug area"); 874372c1af5SJan Medala return; 875372c1af5SJan Medala } 876372c1af5SJan Medala 877372c1af5SJan Medala rc = ena_com_set_host_attributes(&adapter->ena_dev); 878372c1af5SJan Medala if (rc) { 8798936b01aSShai Brandes if (rc == ENA_COM_UNSUPPORTED) 880e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, "Cannot set host attributes"); 881241da076SRafal Kozik else 882e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Cannot set host attributes"); 883241da076SRafal Kozik 884372c1af5SJan Medala goto err; 885372c1af5SJan Medala } 886372c1af5SJan Medala 887372c1af5SJan Medala return; 888372c1af5SJan Medala err: 889372c1af5SJan Medala ena_com_delete_debug_area(&adapter->ena_dev); 890372c1af5SJan Medala } 891372c1af5SJan Medala 892b142387bSThomas Monjalon static int ena_close(struct rte_eth_dev *dev) 8931173fca2SJan Medala { 8944d7877fdSMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 895d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 896890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 8978af56083SShai Brandes struct ena_com_dev *ena_dev = &adapter->ena_dev; 89862024eb8SIvan Ilchenko int ret = 0; 8999d3a9851SShai Brandes int rc; 9001173fca2SJan Medala 90130410493SThomas Monjalon if (rte_eal_process_type() != RTE_PROC_PRIMARY) 90230410493SThomas Monjalon return 0; 90330410493SThomas Monjalon 9048af56083SShai Brandes if (adapter->state == ENA_ADAPTER_STATE_CLOSED) 9058af56083SShai Brandes return 0; 9068af56083SShai Brandes 907df238f84SMichal Krawczyk if (adapter->state == ENA_ADAPTER_STATE_RUNNING) 90862024eb8SIvan Ilchenko ret = ena_stop(dev); 909eb0ef49dSMichal Krawczyk adapter->state = ENA_ADAPTER_STATE_CLOSED; 91015773e06SMichal Krawczyk 911ca1dfa85SShai Brandes if (!adapter->control_path_poll_interval) { 9129d3a9851SShai Brandes rte_intr_disable(intr_handle); 913ca1dfa85SShai Brandes rc = rte_intr_callback_unregister_sync(intr_handle, ena_control_path_handler, dev); 9149d3a9851SShai Brandes if (unlikely(rc != 0)) 915e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, "Failed to unregister interrupt handler"); 916ca1dfa85SShai Brandes } else { 917ca1dfa85SShai Brandes rte_eal_alarm_cancel(ena_control_path_poll_handler, dev); 918ca1dfa85SShai Brandes } 9199d3a9851SShai Brandes 9201173fca2SJan Medala ena_rx_queue_release_all(dev); 9211173fca2SJan Medala ena_tx_queue_release_all(dev); 9224d7877fdSMichal Krawczyk 9234d7877fdSMichal Krawczyk rte_free(adapter->drv_stats); 9244d7877fdSMichal Krawczyk adapter->drv_stats = NULL; 9254d7877fdSMichal Krawczyk 9268af56083SShai Brandes ena_com_set_admin_running_state(ena_dev, false); 9278af56083SShai Brandes 9288af56083SShai Brandes ena_com_rss_destroy(ena_dev); 9298af56083SShai Brandes 9308af56083SShai Brandes ena_com_delete_debug_area(ena_dev); 9318af56083SShai Brandes ena_com_delete_host_info(ena_dev); 9328af56083SShai Brandes 9338af56083SShai Brandes ena_com_abort_admin_commands(ena_dev); 9348af56083SShai Brandes ena_com_wait_for_abort_completion(ena_dev); 9358af56083SShai Brandes ena_com_admin_destroy(ena_dev); 9368af56083SShai Brandes ena_com_mmio_reg_read_request_destroy(ena_dev); 9378af56083SShai Brandes ena_com_delete_customer_metrics_buffer(ena_dev); 9388af56083SShai Brandes 9394d7877fdSMichal Krawczyk /* 9404d7877fdSMichal Krawczyk * MAC is not allocated dynamically. Setting NULL should prevent from 9414d7877fdSMichal Krawczyk * release of the resource in the rte_eth_dev_release_port(). 9424d7877fdSMichal Krawczyk */ 9434d7877fdSMichal Krawczyk dev->data->mac_addrs = NULL; 944b142387bSThomas Monjalon 94562024eb8SIvan Ilchenko return ret; 9461173fca2SJan Medala } 9471173fca2SJan Medala 9482081d5e2SMichal Krawczyk static int 9492081d5e2SMichal Krawczyk ena_dev_reset(struct rte_eth_dev *dev) 9502081d5e2SMichal Krawczyk { 951e457bc70SRafal Kozik int rc = 0; 9522081d5e2SMichal Krawczyk 95339ecdd3dSStanislaw Kardach /* Cannot release memory in secondary process */ 95439ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 955e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, "dev_reset not supported in secondary."); 95639ecdd3dSStanislaw Kardach return -EPERM; 95739ecdd3dSStanislaw Kardach } 95839ecdd3dSStanislaw Kardach 9598af56083SShai Brandes rc = eth_ena_dev_uninit(dev); 9608af56083SShai Brandes if (rc) { 961e99981afSDavid Marchand PMD_INIT_LOG_LINE(CRIT, "Failed to un-initialize device"); 9628af56083SShai Brandes return rc; 9638af56083SShai Brandes } 9648af56083SShai Brandes 965e457bc70SRafal Kozik rc = eth_ena_dev_init(dev); 966241da076SRafal Kozik if (rc) 967e99981afSDavid Marchand PMD_INIT_LOG_LINE(CRIT, "Cannot initialize device"); 968e457bc70SRafal Kozik 9692081d5e2SMichal Krawczyk return rc; 9702081d5e2SMichal Krawczyk } 9712081d5e2SMichal Krawczyk 9721173fca2SJan Medala static void ena_rx_queue_release_all(struct rte_eth_dev *dev) 9731173fca2SJan Medala { 9741173fca2SJan Medala int nb_queues = dev->data->nb_rx_queues; 9751173fca2SJan Medala int i; 9761173fca2SJan Medala 9771173fca2SJan Medala for (i = 0; i < nb_queues; i++) 9787483341aSXueming Li ena_rx_queue_release(dev, i); 9791173fca2SJan Medala } 9801173fca2SJan Medala 9811173fca2SJan Medala static void ena_tx_queue_release_all(struct rte_eth_dev *dev) 9821173fca2SJan Medala { 9831173fca2SJan Medala int nb_queues = dev->data->nb_tx_queues; 9841173fca2SJan Medala int i; 9851173fca2SJan Medala 9861173fca2SJan Medala for (i = 0; i < nb_queues; i++) 9877483341aSXueming Li ena_tx_queue_release(dev, i); 9881173fca2SJan Medala } 9891173fca2SJan Medala 9907483341aSXueming Li static void ena_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 9911173fca2SJan Medala { 9927483341aSXueming Li struct ena_ring *ring = dev->data->rx_queues[qid]; 9931173fca2SJan Medala 9941173fca2SJan Medala /* Free ring resources */ 9951173fca2SJan Medala rte_free(ring->rx_buffer_info); 9961173fca2SJan Medala ring->rx_buffer_info = NULL; 9971173fca2SJan Medala 99879405ee1SRafal Kozik rte_free(ring->rx_refill_buffer); 99979405ee1SRafal Kozik ring->rx_refill_buffer = NULL; 100079405ee1SRafal Kozik 1001c2034976SMichal Krawczyk rte_free(ring->empty_rx_reqs); 1002c2034976SMichal Krawczyk ring->empty_rx_reqs = NULL; 1003c2034976SMichal Krawczyk 10041173fca2SJan Medala ring->configured = 0; 10051173fca2SJan Medala 1006e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "Rx queue %d:%d released", 10071173fca2SJan Medala ring->port_id, ring->id); 10081173fca2SJan Medala } 10091173fca2SJan Medala 10107483341aSXueming Li static void ena_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 10111173fca2SJan Medala { 10127483341aSXueming Li struct ena_ring *ring = dev->data->tx_queues[qid]; 10131173fca2SJan Medala 10141173fca2SJan Medala /* Free ring resources */ 10152fca2a98SMichal Krawczyk rte_free(ring->push_buf_intermediate_buf); 10162fca2a98SMichal Krawczyk 10171173fca2SJan Medala rte_free(ring->tx_buffer_info); 10181173fca2SJan Medala 10191173fca2SJan Medala rte_free(ring->empty_tx_reqs); 10201173fca2SJan Medala 10211173fca2SJan Medala ring->empty_tx_reqs = NULL; 10221173fca2SJan Medala ring->tx_buffer_info = NULL; 10232fca2a98SMichal Krawczyk ring->push_buf_intermediate_buf = NULL; 10241173fca2SJan Medala 10251173fca2SJan Medala ring->configured = 0; 10261173fca2SJan Medala 1027e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "Tx queue %d:%d released", 10281173fca2SJan Medala ring->port_id, ring->id); 10291173fca2SJan Medala } 10301173fca2SJan Medala 10311173fca2SJan Medala static void ena_rx_queue_release_bufs(struct ena_ring *ring) 10321173fca2SJan Medala { 1033709b1dcbSRafal Kozik unsigned int i; 10341173fca2SJan Medala 10351be097dcSMichal Krawczyk for (i = 0; i < ring->ring_size; ++i) { 10361be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info = &ring->rx_buffer_info[i]; 10371be097dcSMichal Krawczyk if (rx_info->mbuf) { 10381be097dcSMichal Krawczyk rte_mbuf_raw_free(rx_info->mbuf); 10391be097dcSMichal Krawczyk rx_info->mbuf = NULL; 10401be097dcSMichal Krawczyk } 10411173fca2SJan Medala } 10421173fca2SJan Medala } 10431173fca2SJan Medala 10441173fca2SJan Medala static void ena_tx_queue_release_bufs(struct ena_ring *ring) 10451173fca2SJan Medala { 1046207a514cSMichal Krawczyk unsigned int i; 10471173fca2SJan Medala 1048207a514cSMichal Krawczyk for (i = 0; i < ring->ring_size; ++i) { 1049207a514cSMichal Krawczyk struct ena_tx_buffer *tx_buf = &ring->tx_buffer_info[i]; 10501173fca2SJan Medala 10513c8bc29fSDavid Harton if (tx_buf->mbuf) { 10521173fca2SJan Medala rte_pktmbuf_free(tx_buf->mbuf); 10533c8bc29fSDavid Harton tx_buf->mbuf = NULL; 10543c8bc29fSDavid Harton } 10551173fca2SJan Medala } 10561173fca2SJan Medala } 10571173fca2SJan Medala 10581173fca2SJan Medala static int ena_link_update(struct rte_eth_dev *dev, 10591173fca2SJan Medala __rte_unused int wait_to_complete) 10601173fca2SJan Medala { 10611173fca2SJan Medala struct rte_eth_link *link = &dev->data->dev_link; 1062890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 1063ca148440SMichal Krawczyk 1064295968d1SFerruh Yigit link->link_status = adapter->link_status ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN; 1065295968d1SFerruh Yigit link->link_speed = RTE_ETH_SPEED_NUM_NONE; 1066295968d1SFerruh Yigit link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 10671173fca2SJan Medala 10681173fca2SJan Medala return 0; 10691173fca2SJan Medala } 10701173fca2SJan Medala 107126e5543dSRafal Kozik static int ena_queue_start_all(struct rte_eth_dev *dev, 10721173fca2SJan Medala enum ena_ring_type ring_type) 10731173fca2SJan Medala { 1074890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 10751173fca2SJan Medala struct ena_ring *queues = NULL; 107653b61841SMichal Krawczyk int nb_queues; 10771173fca2SJan Medala int i = 0; 10781173fca2SJan Medala int rc = 0; 10791173fca2SJan Medala 108053b61841SMichal Krawczyk if (ring_type == ENA_RING_TYPE_RX) { 108153b61841SMichal Krawczyk queues = adapter->rx_ring; 108253b61841SMichal Krawczyk nb_queues = dev->data->nb_rx_queues; 108353b61841SMichal Krawczyk } else { 108453b61841SMichal Krawczyk queues = adapter->tx_ring; 108553b61841SMichal Krawczyk nb_queues = dev->data->nb_tx_queues; 108653b61841SMichal Krawczyk } 108753b61841SMichal Krawczyk for (i = 0; i < nb_queues; i++) { 10881173fca2SJan Medala if (queues[i].configured) { 10891173fca2SJan Medala if (ring_type == ENA_RING_TYPE_RX) { 10901173fca2SJan Medala ena_assert_msg( 10911173fca2SJan Medala dev->data->rx_queues[i] == &queues[i], 1092617898d1SMichal Krawczyk "Inconsistent state of Rx queues\n"); 10931173fca2SJan Medala } else { 10941173fca2SJan Medala ena_assert_msg( 10951173fca2SJan Medala dev->data->tx_queues[i] == &queues[i], 1096617898d1SMichal Krawczyk "Inconsistent state of Tx queues\n"); 10971173fca2SJan Medala } 10981173fca2SJan Medala 10996986cdc4SMichal Krawczyk rc = ena_queue_start(dev, &queues[i]); 11001173fca2SJan Medala 11011173fca2SJan Medala if (rc) { 1102e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, 1103e99981afSDavid Marchand "Failed to start queue[%d] of type(%d)", 11041173fca2SJan Medala i, ring_type); 110526e5543dSRafal Kozik goto err; 11061173fca2SJan Medala } 11071173fca2SJan Medala } 11081173fca2SJan Medala } 11091173fca2SJan Medala 11101173fca2SJan Medala return 0; 111126e5543dSRafal Kozik 111226e5543dSRafal Kozik err: 111326e5543dSRafal Kozik while (i--) 111426e5543dSRafal Kozik if (queues[i].configured) 111526e5543dSRafal Kozik ena_queue_stop(&queues[i]); 111626e5543dSRafal Kozik 111726e5543dSRafal Kozik return rc; 11181173fca2SJan Medala } 11191173fca2SJan Medala 11201173fca2SJan Medala static int 11218a7a73f2SMichal Krawczyk ena_calc_io_queue_size(struct ena_calc_queue_size_ctx *ctx, 11228a7a73f2SMichal Krawczyk bool use_large_llq_hdr) 11231173fca2SJan Medala { 1124bf5fe95cSShai Brandes struct ena_admin_feature_llq_desc *dev = &ctx->get_feat_ctx->llq; 11252fca2a98SMichal Krawczyk struct ena_com_dev *ena_dev = ctx->ena_dev; 11265920d930SMichal Krawczyk uint32_t max_tx_queue_size; 11275920d930SMichal Krawczyk uint32_t max_rx_queue_size; 11281173fca2SJan Medala 11292fca2a98SMichal Krawczyk if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) { 1130ea93d37eSRafal Kozik struct ena_admin_queue_ext_feature_fields *max_queue_ext = 1131ea93d37eSRafal Kozik &ctx->get_feat_ctx->max_queue_ext.max_queue_ext; 11325920d930SMichal Krawczyk max_rx_queue_size = RTE_MIN(max_queue_ext->max_rx_cq_depth, 1133ea93d37eSRafal Kozik max_queue_ext->max_rx_sq_depth); 11345920d930SMichal Krawczyk max_tx_queue_size = max_queue_ext->max_tx_cq_depth; 11352fca2a98SMichal Krawczyk 11362fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == 11372fca2a98SMichal Krawczyk ENA_ADMIN_PLACEMENT_POLICY_DEV) { 11385920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 1139bf5fe95cSShai Brandes dev->max_llq_depth); 11402fca2a98SMichal Krawczyk } else { 11415920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 1142ea93d37eSRafal Kozik max_queue_ext->max_tx_sq_depth); 11432fca2a98SMichal Krawczyk } 11442fca2a98SMichal Krawczyk 1145ea93d37eSRafal Kozik ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 1146ea93d37eSRafal Kozik max_queue_ext->max_per_packet_rx_descs); 1147ea93d37eSRafal Kozik ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 1148ea93d37eSRafal Kozik max_queue_ext->max_per_packet_tx_descs); 1149ea93d37eSRafal Kozik } else { 1150ea93d37eSRafal Kozik struct ena_admin_queue_feature_desc *max_queues = 1151ea93d37eSRafal Kozik &ctx->get_feat_ctx->max_queues; 11525920d930SMichal Krawczyk max_rx_queue_size = RTE_MIN(max_queues->max_cq_depth, 1153ea93d37eSRafal Kozik max_queues->max_sq_depth); 11545920d930SMichal Krawczyk max_tx_queue_size = max_queues->max_cq_depth; 11552fca2a98SMichal Krawczyk 11562fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == 11572fca2a98SMichal Krawczyk ENA_ADMIN_PLACEMENT_POLICY_DEV) { 11585920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 1159bf5fe95cSShai Brandes dev->max_llq_depth); 11602fca2a98SMichal Krawczyk } else { 11615920d930SMichal Krawczyk max_tx_queue_size = RTE_MIN(max_tx_queue_size, 11622fca2a98SMichal Krawczyk max_queues->max_sq_depth); 11632fca2a98SMichal Krawczyk } 11642fca2a98SMichal Krawczyk 1165ea93d37eSRafal Kozik ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 1166ea93d37eSRafal Kozik max_queues->max_packet_rx_descs); 11675920d930SMichal Krawczyk ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS, 11685920d930SMichal Krawczyk max_queues->max_packet_tx_descs); 1169ea93d37eSRafal Kozik } 11701173fca2SJan Medala 1171ea93d37eSRafal Kozik /* Round down to the nearest power of 2 */ 11725920d930SMichal Krawczyk max_rx_queue_size = rte_align32prevpow2(max_rx_queue_size); 11735920d930SMichal Krawczyk max_tx_queue_size = rte_align32prevpow2(max_tx_queue_size); 11741173fca2SJan Medala 1175bf5fe95cSShai Brandes if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV && use_large_llq_hdr) { 1176bf5fe95cSShai Brandes /* intersection between driver configuration and device capabilities */ 1177bf5fe95cSShai Brandes if (dev->entry_size_ctrl_supported & ENA_ADMIN_LIST_ENTRY_SIZE_256B) { 1178bf5fe95cSShai Brandes if (dev->max_wide_llq_depth == MAX_WIDE_LLQ_DEPTH_UNSUPPORTED) { 1179bf5fe95cSShai Brandes /* Devices that do not support the double-sized ENA memory BAR will 1180bf5fe95cSShai Brandes * report max_wide_llq_depth as 0. In such case, driver halves the 1181bf5fe95cSShai Brandes * queue depth when working in large llq policy. 1182bf5fe95cSShai Brandes */ 1183bf5fe95cSShai Brandes max_tx_queue_size >>= 1; 1184e99981afSDavid Marchand PMD_INIT_LOG_LINE(INFO, 1185e99981afSDavid Marchand "large LLQ policy requires limiting Tx queue size to %u entries", 11868a7a73f2SMichal Krawczyk max_tx_queue_size); 1187bf5fe95cSShai Brandes } else if (dev->max_wide_llq_depth < max_tx_queue_size) { 1188bf5fe95cSShai Brandes /* In case the queue depth that the driver calculated exceeds 1189bf5fe95cSShai Brandes * the maximal value that the device allows, it will be limited 1190bf5fe95cSShai Brandes * to that maximal value 1191bf5fe95cSShai Brandes */ 1192bf5fe95cSShai Brandes max_tx_queue_size = dev->max_wide_llq_depth; 1193bf5fe95cSShai Brandes } 11948a7a73f2SMichal Krawczyk } else { 1195e99981afSDavid Marchand PMD_INIT_LOG_LINE(INFO, 1196e99981afSDavid Marchand "Forcing large LLQ headers failed since device lacks this support"); 11978a7a73f2SMichal Krawczyk } 11988a7a73f2SMichal Krawczyk } 11998a7a73f2SMichal Krawczyk 12005920d930SMichal Krawczyk if (unlikely(max_rx_queue_size == 0 || max_tx_queue_size == 0)) { 1201e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, "Invalid queue size"); 12021173fca2SJan Medala return -EFAULT; 12031173fca2SJan Medala } 12041173fca2SJan Medala 12055920d930SMichal Krawczyk ctx->max_tx_queue_size = max_tx_queue_size; 12065920d930SMichal Krawczyk ctx->max_rx_queue_size = max_rx_queue_size; 12072061fe41SRafal Kozik 1208e99981afSDavid Marchand PMD_DRV_LOG_LINE(INFO, "tx queue size %u", max_tx_queue_size); 1209ea93d37eSRafal Kozik return 0; 12101173fca2SJan Medala } 12111173fca2SJan Medala 12121173fca2SJan Medala static void ena_stats_restart(struct rte_eth_dev *dev) 12131173fca2SJan Medala { 1214890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 12151173fca2SJan Medala 12161173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->ierrors); 12171173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->oerrors); 12181173fca2SJan Medala rte_atomic64_init(&adapter->drv_stats->rx_nombuf); 1219e1e73e32SMichal Krawczyk adapter->drv_stats->rx_drops = 0; 12201173fca2SJan Medala } 12211173fca2SJan Medala 1222d5b0924bSMatan Azrad static int ena_stats_get(struct rte_eth_dev *dev, 12231173fca2SJan Medala struct rte_eth_stats *stats) 12241173fca2SJan Medala { 12251173fca2SJan Medala struct ena_admin_basic_stats ena_stats; 1226890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 12271173fca2SJan Medala struct ena_com_dev *ena_dev = &adapter->ena_dev; 12281173fca2SJan Medala int rc; 122945b6d861SMichal Krawczyk int i; 123045b6d861SMichal Krawczyk int max_rings_stats; 12311173fca2SJan Medala 12321173fca2SJan Medala memset(&ena_stats, 0, sizeof(ena_stats)); 12331343c415SMichal Krawczyk 12341343c415SMichal Krawczyk rte_spinlock_lock(&adapter->admin_lock); 1235e3595539SStanislaw Kardach rc = ENA_PROXY(adapter, ena_com_get_dev_basic_stats, ena_dev, 1236e3595539SStanislaw Kardach &ena_stats); 12371343c415SMichal Krawczyk rte_spinlock_unlock(&adapter->admin_lock); 12381173fca2SJan Medala if (unlikely(rc)) { 1239e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Could not retrieve statistics from ENA"); 1240d5b0924bSMatan Azrad return rc; 12411173fca2SJan Medala } 12421173fca2SJan Medala 12431173fca2SJan Medala /* Set of basic statistics from ENA */ 12441173fca2SJan Medala stats->ipackets = __MERGE_64B_H_L(ena_stats.rx_pkts_high, 12451173fca2SJan Medala ena_stats.rx_pkts_low); 12461173fca2SJan Medala stats->opackets = __MERGE_64B_H_L(ena_stats.tx_pkts_high, 12471173fca2SJan Medala ena_stats.tx_pkts_low); 12481173fca2SJan Medala stats->ibytes = __MERGE_64B_H_L(ena_stats.rx_bytes_high, 12491173fca2SJan Medala ena_stats.rx_bytes_low); 12501173fca2SJan Medala stats->obytes = __MERGE_64B_H_L(ena_stats.tx_bytes_high, 12511173fca2SJan Medala ena_stats.tx_bytes_low); 12521173fca2SJan Medala 12531173fca2SJan Medala /* Driver related stats */ 1254e1e73e32SMichal Krawczyk stats->imissed = adapter->drv_stats->rx_drops; 12551173fca2SJan Medala stats->ierrors = rte_atomic64_read(&adapter->drv_stats->ierrors); 12561173fca2SJan Medala stats->oerrors = rte_atomic64_read(&adapter->drv_stats->oerrors); 12571173fca2SJan Medala stats->rx_nombuf = rte_atomic64_read(&adapter->drv_stats->rx_nombuf); 125845b6d861SMichal Krawczyk 125945b6d861SMichal Krawczyk max_rings_stats = RTE_MIN(dev->data->nb_rx_queues, 126045b6d861SMichal Krawczyk RTE_ETHDEV_QUEUE_STAT_CNTRS); 126145b6d861SMichal Krawczyk for (i = 0; i < max_rings_stats; ++i) { 126245b6d861SMichal Krawczyk struct ena_stats_rx *rx_stats = &adapter->rx_ring[i].rx_stats; 126345b6d861SMichal Krawczyk 126445b6d861SMichal Krawczyk stats->q_ibytes[i] = rx_stats->bytes; 126545b6d861SMichal Krawczyk stats->q_ipackets[i] = rx_stats->cnt; 126645b6d861SMichal Krawczyk stats->q_errors[i] = rx_stats->bad_desc_num + 12677a166990SShai Brandes rx_stats->bad_req_id + 12687a166990SShai Brandes rx_stats->bad_desc + 12697a166990SShai Brandes rx_stats->unknown_error; 127045b6d861SMichal Krawczyk } 127145b6d861SMichal Krawczyk 127245b6d861SMichal Krawczyk max_rings_stats = RTE_MIN(dev->data->nb_tx_queues, 127345b6d861SMichal Krawczyk RTE_ETHDEV_QUEUE_STAT_CNTRS); 127445b6d861SMichal Krawczyk for (i = 0; i < max_rings_stats; ++i) { 127545b6d861SMichal Krawczyk struct ena_stats_tx *tx_stats = &adapter->tx_ring[i].tx_stats; 127645b6d861SMichal Krawczyk 127745b6d861SMichal Krawczyk stats->q_obytes[i] = tx_stats->bytes; 127845b6d861SMichal Krawczyk stats->q_opackets[i] = tx_stats->cnt; 127945b6d861SMichal Krawczyk } 128045b6d861SMichal Krawczyk 1281d5b0924bSMatan Azrad return 0; 12821173fca2SJan Medala } 12831173fca2SJan Medala 12841173fca2SJan Medala static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) 12851173fca2SJan Medala { 12861173fca2SJan Medala struct ena_adapter *adapter; 12871173fca2SJan Medala struct ena_com_dev *ena_dev; 12881173fca2SJan Medala int rc = 0; 12891173fca2SJan Medala 1290498c687aSRafal Kozik ena_assert_msg(dev->data != NULL, "Uninitialized device\n"); 1291498c687aSRafal Kozik ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device\n"); 1292890728ffSStephen Hemminger adapter = dev->data->dev_private; 12931173fca2SJan Medala 12941173fca2SJan Medala ena_dev = &adapter->ena_dev; 1295498c687aSRafal Kozik ena_assert_msg(ena_dev != NULL, "Uninitialized device\n"); 12961173fca2SJan Medala 1297e3595539SStanislaw Kardach rc = ENA_PROXY(adapter, ena_com_set_dev_mtu, ena_dev, mtu); 12981173fca2SJan Medala if (rc) 1299e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Could not set MTU: %d", mtu); 13001173fca2SJan Medala else 1301e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "MTU set to: %d", mtu); 13021173fca2SJan Medala 13031173fca2SJan Medala return rc; 13041173fca2SJan Medala } 13051173fca2SJan Medala 13061173fca2SJan Medala static int ena_start(struct rte_eth_dev *dev) 13071173fca2SJan Medala { 1308890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 1309d9b8b106SMichal Krawczyk uint64_t ticks; 13101173fca2SJan Medala int rc = 0; 13119210f0caSJie Hai uint16_t i; 13121173fca2SJan Medala 131339ecdd3dSStanislaw Kardach /* Cannot allocate memory in secondary process */ 131439ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 1315e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, "dev_start not supported in secondary."); 131639ecdd3dSStanislaw Kardach return -EPERM; 131739ecdd3dSStanislaw Kardach } 131839ecdd3dSStanislaw Kardach 13196986cdc4SMichal Krawczyk rc = ena_setup_rx_intr(dev); 13206986cdc4SMichal Krawczyk if (rc) 13216986cdc4SMichal Krawczyk return rc; 13226986cdc4SMichal Krawczyk 132326e5543dSRafal Kozik rc = ena_queue_start_all(dev, ENA_RING_TYPE_RX); 13241173fca2SJan Medala if (rc) 13251173fca2SJan Medala return rc; 13261173fca2SJan Medala 132726e5543dSRafal Kozik rc = ena_queue_start_all(dev, ENA_RING_TYPE_TX); 13281173fca2SJan Medala if (rc) 132926e5543dSRafal Kozik goto err_start_tx; 13301173fca2SJan Medala 1331295968d1SFerruh Yigit if (adapter->edev_data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) { 133234d5e97eSMichal Krawczyk rc = ena_rss_configure(adapter); 13331173fca2SJan Medala if (rc) 133426e5543dSRafal Kozik goto err_rss_init; 13351173fca2SJan Medala } 13361173fca2SJan Medala 13371173fca2SJan Medala ena_stats_restart(dev); 13381173fca2SJan Medala 1339d9b8b106SMichal Krawczyk adapter->timestamp_wd = rte_get_timer_cycles(); 1340d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = ENA_DEVICE_KALIVE_TIMEOUT; 1341d9b8b106SMichal Krawczyk 1342d9b8b106SMichal Krawczyk ticks = rte_get_timer_hz(); 1343d9b8b106SMichal Krawczyk rte_timer_reset(&adapter->timer_wd, ticks, PERIODICAL, rte_lcore_id(), 1344aab58857SStanislaw Kardach ena_timer_wd_callback, dev); 1345d9b8b106SMichal Krawczyk 13467830e905SSolganik Alexander ++adapter->dev_stats.dev_start; 13471173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_RUNNING; 13481173fca2SJan Medala 13499210f0caSJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 13509210f0caSJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 13519210f0caSJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 13529210f0caSJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 13539210f0caSJie Hai 13541173fca2SJan Medala return 0; 135526e5543dSRafal Kozik 135626e5543dSRafal Kozik err_rss_init: 135726e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_TX); 135826e5543dSRafal Kozik err_start_tx: 135926e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_RX); 136026e5543dSRafal Kozik return rc; 13611173fca2SJan Medala } 13621173fca2SJan Medala 136362024eb8SIvan Ilchenko static int ena_stop(struct rte_eth_dev *dev) 1364eb0ef49dSMichal Krawczyk { 1365890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 1366e457bc70SRafal Kozik struct ena_com_dev *ena_dev = &adapter->ena_dev; 13676986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 1368d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 13699210f0caSJie Hai uint16_t i; 1370e457bc70SRafal Kozik int rc; 1371eb0ef49dSMichal Krawczyk 137239ecdd3dSStanislaw Kardach /* Cannot free memory in secondary process */ 137339ecdd3dSStanislaw Kardach if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 1374e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, "dev_stop not supported in secondary."); 137539ecdd3dSStanislaw Kardach return -EPERM; 137639ecdd3dSStanislaw Kardach } 137739ecdd3dSStanislaw Kardach 1378d9b8b106SMichal Krawczyk rte_timer_stop_sync(&adapter->timer_wd); 137926e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_TX); 138026e5543dSRafal Kozik ena_queue_stop_all(dev, ENA_RING_TYPE_RX); 1381d9b8b106SMichal Krawczyk 1382e457bc70SRafal Kozik if (adapter->trigger_reset) { 1383e457bc70SRafal Kozik rc = ena_com_dev_reset(ena_dev, adapter->reset_reason); 1384e457bc70SRafal Kozik if (rc) 1385e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Device reset failed, rc: %d", rc); 1386e457bc70SRafal Kozik } 1387e457bc70SRafal Kozik 13886986cdc4SMichal Krawczyk rte_intr_disable(intr_handle); 13896986cdc4SMichal Krawczyk 13906986cdc4SMichal Krawczyk rte_intr_efd_disable(intr_handle); 1391d61138d4SHarman Kalra 1392d61138d4SHarman Kalra /* Cleanup vector list */ 1393d61138d4SHarman Kalra rte_intr_vec_list_free(intr_handle); 13946986cdc4SMichal Krawczyk 13956986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 13966986cdc4SMichal Krawczyk 13977830e905SSolganik Alexander ++adapter->dev_stats.dev_stop; 1398eb0ef49dSMichal Krawczyk adapter->state = ENA_ADAPTER_STATE_STOPPED; 1399b8f5d2aeSThomas Monjalon dev->data->dev_started = 0; 140062024eb8SIvan Ilchenko 14019210f0caSJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 14029210f0caSJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 14039210f0caSJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 14049210f0caSJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 14059210f0caSJie Hai 140662024eb8SIvan Ilchenko return 0; 1407eb0ef49dSMichal Krawczyk } 1408eb0ef49dSMichal Krawczyk 14096986cdc4SMichal Krawczyk static int ena_create_io_queue(struct rte_eth_dev *dev, struct ena_ring *ring) 1410df238f84SMichal Krawczyk { 14116986cdc4SMichal Krawczyk struct ena_adapter *adapter = ring->adapter; 14126986cdc4SMichal Krawczyk struct ena_com_dev *ena_dev = &adapter->ena_dev; 14136986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 1414d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 1415df238f84SMichal Krawczyk struct ena_com_create_io_ctx ctx = 1416df238f84SMichal Krawczyk /* policy set to _HOST just to satisfy icc compiler */ 1417df238f84SMichal Krawczyk { ENA_ADMIN_PLACEMENT_POLICY_HOST, 1418df238f84SMichal Krawczyk 0, 0, 0, 0, 0 }; 1419df238f84SMichal Krawczyk uint16_t ena_qid; 1420778677dcSRafal Kozik unsigned int i; 1421df238f84SMichal Krawczyk int rc; 1422df238f84SMichal Krawczyk 14236986cdc4SMichal Krawczyk ctx.msix_vector = -1; 1424df238f84SMichal Krawczyk if (ring->type == ENA_RING_TYPE_TX) { 1425df238f84SMichal Krawczyk ena_qid = ENA_IO_TXQ_IDX(ring->id); 1426df238f84SMichal Krawczyk ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_TX; 1427df238f84SMichal Krawczyk ctx.mem_queue_type = ena_dev->tx_mem_queue_type; 1428778677dcSRafal Kozik for (i = 0; i < ring->ring_size; i++) 1429778677dcSRafal Kozik ring->empty_tx_reqs[i] = i; 1430df238f84SMichal Krawczyk } else { 1431df238f84SMichal Krawczyk ena_qid = ENA_IO_RXQ_IDX(ring->id); 1432df238f84SMichal Krawczyk ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_RX; 14336986cdc4SMichal Krawczyk if (rte_intr_dp_is_en(intr_handle)) 1434d61138d4SHarman Kalra ctx.msix_vector = 1435d61138d4SHarman Kalra rte_intr_vec_list_index_get(intr_handle, 1436d61138d4SHarman Kalra ring->id); 1437d61138d4SHarman Kalra 1438778677dcSRafal Kozik for (i = 0; i < ring->ring_size; i++) 1439778677dcSRafal Kozik ring->empty_rx_reqs[i] = i; 1440df238f84SMichal Krawczyk } 1441badc3a6aSMichal Krawczyk ctx.queue_size = ring->ring_size; 1442df238f84SMichal Krawczyk ctx.qid = ena_qid; 14434217cb0bSMichal Krawczyk ctx.numa_node = ring->numa_socket_id; 1444df238f84SMichal Krawczyk 1445df238f84SMichal Krawczyk rc = ena_com_create_io_queue(ena_dev, &ctx); 1446df238f84SMichal Krawczyk if (rc) { 1447e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1448e99981afSDavid Marchand "Failed to create IO queue[%d] (qid:%d), rc: %d", 1449df238f84SMichal Krawczyk ring->id, ena_qid, rc); 1450df238f84SMichal Krawczyk return rc; 1451df238f84SMichal Krawczyk } 1452df238f84SMichal Krawczyk 1453df238f84SMichal Krawczyk rc = ena_com_get_io_handlers(ena_dev, ena_qid, 1454df238f84SMichal Krawczyk &ring->ena_com_io_sq, 1455df238f84SMichal Krawczyk &ring->ena_com_io_cq); 1456df238f84SMichal Krawczyk if (rc) { 1457e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1458e99981afSDavid Marchand "Failed to get IO queue[%d] handlers, rc: %d", 1459df238f84SMichal Krawczyk ring->id, rc); 1460df238f84SMichal Krawczyk ena_com_destroy_io_queue(ena_dev, ena_qid); 1461df238f84SMichal Krawczyk return rc; 1462df238f84SMichal Krawczyk } 1463df238f84SMichal Krawczyk 1464df238f84SMichal Krawczyk if (ring->type == ENA_RING_TYPE_TX) 1465df238f84SMichal Krawczyk ena_com_update_numa_node(ring->ena_com_io_cq, ctx.numa_node); 1466df238f84SMichal Krawczyk 14676986cdc4SMichal Krawczyk /* Start with Rx interrupts being masked. */ 14686986cdc4SMichal Krawczyk if (ring->type == ENA_RING_TYPE_RX && rte_intr_dp_is_en(intr_handle)) 14696986cdc4SMichal Krawczyk ena_rx_queue_intr_disable(dev, ring->id); 14706986cdc4SMichal Krawczyk 1471df238f84SMichal Krawczyk return 0; 1472df238f84SMichal Krawczyk } 1473df238f84SMichal Krawczyk 147426e5543dSRafal Kozik static void ena_queue_stop(struct ena_ring *ring) 1475df238f84SMichal Krawczyk { 147626e5543dSRafal Kozik struct ena_com_dev *ena_dev = &ring->adapter->ena_dev; 1477df238f84SMichal Krawczyk 147826e5543dSRafal Kozik if (ring->type == ENA_RING_TYPE_RX) { 147926e5543dSRafal Kozik ena_com_destroy_io_queue(ena_dev, ENA_IO_RXQ_IDX(ring->id)); 148026e5543dSRafal Kozik ena_rx_queue_release_bufs(ring); 148126e5543dSRafal Kozik } else { 148226e5543dSRafal Kozik ena_com_destroy_io_queue(ena_dev, ENA_IO_TXQ_IDX(ring->id)); 148326e5543dSRafal Kozik ena_tx_queue_release_bufs(ring); 1484df238f84SMichal Krawczyk } 1485df238f84SMichal Krawczyk } 1486df238f84SMichal Krawczyk 148726e5543dSRafal Kozik static void ena_queue_stop_all(struct rte_eth_dev *dev, 148826e5543dSRafal Kozik enum ena_ring_type ring_type) 148926e5543dSRafal Kozik { 1490890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 149126e5543dSRafal Kozik struct ena_ring *queues = NULL; 149226e5543dSRafal Kozik uint16_t nb_queues, i; 149326e5543dSRafal Kozik 149426e5543dSRafal Kozik if (ring_type == ENA_RING_TYPE_RX) { 149526e5543dSRafal Kozik queues = adapter->rx_ring; 149626e5543dSRafal Kozik nb_queues = dev->data->nb_rx_queues; 149726e5543dSRafal Kozik } else { 149826e5543dSRafal Kozik queues = adapter->tx_ring; 149926e5543dSRafal Kozik nb_queues = dev->data->nb_tx_queues; 150026e5543dSRafal Kozik } 150126e5543dSRafal Kozik 150226e5543dSRafal Kozik for (i = 0; i < nb_queues; ++i) 150326e5543dSRafal Kozik if (queues[i].configured) 150426e5543dSRafal Kozik ena_queue_stop(&queues[i]); 150526e5543dSRafal Kozik } 150626e5543dSRafal Kozik 15076986cdc4SMichal Krawczyk static int ena_queue_start(struct rte_eth_dev *dev, struct ena_ring *ring) 15081173fca2SJan Medala { 1509a467e8f3SMichal Krawczyk int rc, bufs_num; 15101173fca2SJan Medala 15111173fca2SJan Medala ena_assert_msg(ring->configured == 1, 151226e5543dSRafal Kozik "Trying to start unconfigured queue\n"); 15131173fca2SJan Medala 15146986cdc4SMichal Krawczyk rc = ena_create_io_queue(dev, ring); 1515df238f84SMichal Krawczyk if (rc) { 1516e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, "Failed to create IO queue"); 1517df238f84SMichal Krawczyk return rc; 1518df238f84SMichal Krawczyk } 1519df238f84SMichal Krawczyk 15201173fca2SJan Medala ring->next_to_clean = 0; 15211173fca2SJan Medala ring->next_to_use = 0; 15221173fca2SJan Medala 15237830e905SSolganik Alexander if (ring->type == ENA_RING_TYPE_TX) { 15247830e905SSolganik Alexander ring->tx_stats.available_desc = 1525b2b02edeSMichal Krawczyk ena_com_free_q_entries(ring->ena_com_io_sq); 15261173fca2SJan Medala return 0; 15277830e905SSolganik Alexander } 15281173fca2SJan Medala 1529a467e8f3SMichal Krawczyk bufs_num = ring->ring_size - 1; 1530a467e8f3SMichal Krawczyk rc = ena_populate_rx_queue(ring, bufs_num); 1531a467e8f3SMichal Krawczyk if (rc != bufs_num) { 153226e5543dSRafal Kozik ena_com_destroy_io_queue(&ring->adapter->ena_dev, 153326e5543dSRafal Kozik ENA_IO_RXQ_IDX(ring->id)); 1534e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, "Failed to populate Rx ring"); 1535241da076SRafal Kozik return ENA_COM_FAULT; 15361173fca2SJan Medala } 15374387e81cSIdo Segev /* Flush per-core RX buffers pools cache as they can be used on other 15384387e81cSIdo Segev * cores as well. 15394387e81cSIdo Segev */ 15404387e81cSIdo Segev rte_mempool_cache_flush(NULL, ring->mb_pool); 15411173fca2SJan Medala 15421173fca2SJan Medala return 0; 15431173fca2SJan Medala } 15441173fca2SJan Medala 15451173fca2SJan Medala static int ena_tx_queue_setup(struct rte_eth_dev *dev, 15461173fca2SJan Medala uint16_t queue_idx, 15471173fca2SJan Medala uint16_t nb_desc, 15484217cb0bSMichal Krawczyk unsigned int socket_id, 154956b8b9b7SRafal Kozik const struct rte_eth_txconf *tx_conf) 15501173fca2SJan Medala { 15511173fca2SJan Medala struct ena_ring *txq = NULL; 1552890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 15531173fca2SJan Medala unsigned int i; 1554005064e5SMichal Krawczyk uint16_t dyn_thresh; 15551173fca2SJan Medala 15561173fca2SJan Medala txq = &adapter->tx_ring[queue_idx]; 15571173fca2SJan Medala 15581173fca2SJan Medala if (txq->configured) { 1559e99981afSDavid Marchand PMD_DRV_LOG_LINE(CRIT, 1560e99981afSDavid Marchand "API violation. Queue[%d] is already configured", 15611173fca2SJan Medala queue_idx); 1562241da076SRafal Kozik return ENA_COM_FAULT; 15631173fca2SJan Medala } 15641173fca2SJan Medala 15651daff526SJakub Palider if (!rte_is_power_of_2(nb_desc)) { 1566e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1567e99981afSDavid Marchand "Unsupported size of Tx queue: %d is not a power of 2.", 15681daff526SJakub Palider nb_desc); 15691daff526SJakub Palider return -EINVAL; 15701daff526SJakub Palider } 15711daff526SJakub Palider 15725920d930SMichal Krawczyk if (nb_desc > adapter->max_tx_ring_size) { 1573e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1574e99981afSDavid Marchand "Unsupported size of Tx queue (max size: %d)", 15755920d930SMichal Krawczyk adapter->max_tx_ring_size); 15761173fca2SJan Medala return -EINVAL; 15771173fca2SJan Medala } 15781173fca2SJan Medala 15791173fca2SJan Medala txq->port_id = dev->data->port_id; 15801173fca2SJan Medala txq->next_to_clean = 0; 15811173fca2SJan Medala txq->next_to_use = 0; 15821173fca2SJan Medala txq->ring_size = nb_desc; 1583c0006061SMichal Krawczyk txq->size_mask = nb_desc - 1; 15844217cb0bSMichal Krawczyk txq->numa_socket_id = socket_id; 15851d973d8fSIgor Chauskin txq->pkts_without_db = false; 1586f93e20e5SMichal Krawczyk txq->last_cleanup_ticks = 0; 15871173fca2SJan Medala 158808180833SMichal Krawczyk txq->tx_buffer_info = rte_zmalloc_socket("txq->tx_buffer_info", 158908180833SMichal Krawczyk sizeof(struct ena_tx_buffer) * txq->ring_size, 159008180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 159108180833SMichal Krawczyk socket_id); 15921173fca2SJan Medala if (!txq->tx_buffer_info) { 1593e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1594e99981afSDavid Marchand "Failed to allocate memory for Tx buffer info"); 1595df238f84SMichal Krawczyk return -ENOMEM; 15961173fca2SJan Medala } 15971173fca2SJan Medala 159808180833SMichal Krawczyk txq->empty_tx_reqs = rte_zmalloc_socket("txq->empty_tx_reqs", 159908180833SMichal Krawczyk sizeof(uint16_t) * txq->ring_size, 160008180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 160108180833SMichal Krawczyk socket_id); 16021173fca2SJan Medala if (!txq->empty_tx_reqs) { 1603e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1604e99981afSDavid Marchand "Failed to allocate memory for empty Tx requests"); 1605df238f84SMichal Krawczyk rte_free(txq->tx_buffer_info); 1606df238f84SMichal Krawczyk return -ENOMEM; 16071173fca2SJan Medala } 1608241da076SRafal Kozik 16092fca2a98SMichal Krawczyk txq->push_buf_intermediate_buf = 161008180833SMichal Krawczyk rte_zmalloc_socket("txq->push_buf_intermediate_buf", 16112fca2a98SMichal Krawczyk txq->tx_max_header_size, 161208180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 161308180833SMichal Krawczyk socket_id); 16142fca2a98SMichal Krawczyk if (!txq->push_buf_intermediate_buf) { 1615e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to alloc push buffer for LLQ"); 16162fca2a98SMichal Krawczyk rte_free(txq->tx_buffer_info); 16172fca2a98SMichal Krawczyk rte_free(txq->empty_tx_reqs); 16182fca2a98SMichal Krawczyk return -ENOMEM; 16192fca2a98SMichal Krawczyk } 16202fca2a98SMichal Krawczyk 16211173fca2SJan Medala for (i = 0; i < txq->ring_size; i++) 16221173fca2SJan Medala txq->empty_tx_reqs[i] = i; 16231173fca2SJan Medala 1624005064e5SMichal Krawczyk txq->offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads; 1625005064e5SMichal Krawczyk 1626005064e5SMichal Krawczyk /* Check if caller provided the Tx cleanup threshold value. */ 1627005064e5SMichal Krawczyk if (tx_conf->tx_free_thresh != 0) { 1628005064e5SMichal Krawczyk txq->tx_free_thresh = tx_conf->tx_free_thresh; 1629005064e5SMichal Krawczyk } else { 1630005064e5SMichal Krawczyk dyn_thresh = txq->ring_size - 1631005064e5SMichal Krawczyk txq->ring_size / ENA_REFILL_THRESH_DIVIDER; 1632005064e5SMichal Krawczyk txq->tx_free_thresh = RTE_MAX(dyn_thresh, 1633005064e5SMichal Krawczyk txq->ring_size - ENA_REFILL_THRESH_PACKET); 16342081d5e2SMichal Krawczyk } 1635005064e5SMichal Krawczyk 1636f93e20e5SMichal Krawczyk txq->missing_tx_completion_threshold = 1637f93e20e5SMichal Krawczyk RTE_MIN(txq->ring_size / 2, ENA_DEFAULT_MISSING_COMP); 1638f93e20e5SMichal Krawczyk 16391173fca2SJan Medala /* Store pointer to this queue in upper layer */ 16401173fca2SJan Medala txq->configured = 1; 16411173fca2SJan Medala dev->data->tx_queues[queue_idx] = txq; 1642241da076SRafal Kozik 1643241da076SRafal Kozik return 0; 16441173fca2SJan Medala } 16451173fca2SJan Medala 16461173fca2SJan Medala static int ena_rx_queue_setup(struct rte_eth_dev *dev, 16471173fca2SJan Medala uint16_t queue_idx, 16481173fca2SJan Medala uint16_t nb_desc, 16494217cb0bSMichal Krawczyk unsigned int socket_id, 165034d5e97eSMichal Krawczyk const struct rte_eth_rxconf *rx_conf, 16511173fca2SJan Medala struct rte_mempool *mp) 16521173fca2SJan Medala { 1653890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 16541173fca2SJan Medala struct ena_ring *rxq = NULL; 165538364c26SMichal Krawczyk size_t buffer_size; 1656df238f84SMichal Krawczyk int i; 1657005064e5SMichal Krawczyk uint16_t dyn_thresh; 16581173fca2SJan Medala 16591173fca2SJan Medala rxq = &adapter->rx_ring[queue_idx]; 16601173fca2SJan Medala if (rxq->configured) { 1661e99981afSDavid Marchand PMD_DRV_LOG_LINE(CRIT, 1662e99981afSDavid Marchand "API violation. Queue[%d] is already configured", 16631173fca2SJan Medala queue_idx); 1664241da076SRafal Kozik return ENA_COM_FAULT; 16651173fca2SJan Medala } 16661173fca2SJan Medala 16671daff526SJakub Palider if (!rte_is_power_of_2(nb_desc)) { 1668e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1669e99981afSDavid Marchand "Unsupported size of Rx queue: %d is not a power of 2.", 16701daff526SJakub Palider nb_desc); 16711daff526SJakub Palider return -EINVAL; 16721daff526SJakub Palider } 16731daff526SJakub Palider 16745920d930SMichal Krawczyk if (nb_desc > adapter->max_rx_ring_size) { 1675e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1676e99981afSDavid Marchand "Unsupported size of Rx queue (max size: %d)", 16775920d930SMichal Krawczyk adapter->max_rx_ring_size); 16781173fca2SJan Medala return -EINVAL; 16791173fca2SJan Medala } 16801173fca2SJan Medala 168138364c26SMichal Krawczyk /* ENA isn't supporting buffers smaller than 1400 bytes */ 168238364c26SMichal Krawczyk buffer_size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM; 168338364c26SMichal Krawczyk if (buffer_size < ENA_RX_BUF_MIN_SIZE) { 1684e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1685e99981afSDavid Marchand "Unsupported size of Rx buffer: %zu (min size: %d)", 168638364c26SMichal Krawczyk buffer_size, ENA_RX_BUF_MIN_SIZE); 168738364c26SMichal Krawczyk return -EINVAL; 168838364c26SMichal Krawczyk } 168938364c26SMichal Krawczyk 16901173fca2SJan Medala rxq->port_id = dev->data->port_id; 16911173fca2SJan Medala rxq->next_to_clean = 0; 16921173fca2SJan Medala rxq->next_to_use = 0; 16931173fca2SJan Medala rxq->ring_size = nb_desc; 1694c0006061SMichal Krawczyk rxq->size_mask = nb_desc - 1; 16954217cb0bSMichal Krawczyk rxq->numa_socket_id = socket_id; 16961173fca2SJan Medala rxq->mb_pool = mp; 16971173fca2SJan Medala 169808180833SMichal Krawczyk rxq->rx_buffer_info = rte_zmalloc_socket("rxq->buffer_info", 16991be097dcSMichal Krawczyk sizeof(struct ena_rx_buffer) * nb_desc, 170008180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 170108180833SMichal Krawczyk socket_id); 17021173fca2SJan Medala if (!rxq->rx_buffer_info) { 1703e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1704e99981afSDavid Marchand "Failed to allocate memory for Rx buffer info"); 17051173fca2SJan Medala return -ENOMEM; 17061173fca2SJan Medala } 17071173fca2SJan Medala 170808180833SMichal Krawczyk rxq->rx_refill_buffer = rte_zmalloc_socket("rxq->rx_refill_buffer", 170979405ee1SRafal Kozik sizeof(struct rte_mbuf *) * nb_desc, 171008180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 171108180833SMichal Krawczyk socket_id); 171279405ee1SRafal Kozik if (!rxq->rx_refill_buffer) { 1713e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1714e99981afSDavid Marchand "Failed to allocate memory for Rx refill buffer"); 171579405ee1SRafal Kozik rte_free(rxq->rx_buffer_info); 171679405ee1SRafal Kozik rxq->rx_buffer_info = NULL; 171779405ee1SRafal Kozik return -ENOMEM; 171879405ee1SRafal Kozik } 171979405ee1SRafal Kozik 172008180833SMichal Krawczyk rxq->empty_rx_reqs = rte_zmalloc_socket("rxq->empty_rx_reqs", 1721c2034976SMichal Krawczyk sizeof(uint16_t) * nb_desc, 172208180833SMichal Krawczyk RTE_CACHE_LINE_SIZE, 172308180833SMichal Krawczyk socket_id); 1724c2034976SMichal Krawczyk if (!rxq->empty_rx_reqs) { 1725e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1726e99981afSDavid Marchand "Failed to allocate memory for empty Rx requests"); 1727c2034976SMichal Krawczyk rte_free(rxq->rx_buffer_info); 1728c2034976SMichal Krawczyk rxq->rx_buffer_info = NULL; 172979405ee1SRafal Kozik rte_free(rxq->rx_refill_buffer); 173079405ee1SRafal Kozik rxq->rx_refill_buffer = NULL; 1731c2034976SMichal Krawczyk return -ENOMEM; 1732c2034976SMichal Krawczyk } 1733c2034976SMichal Krawczyk 1734c2034976SMichal Krawczyk for (i = 0; i < nb_desc; i++) 1735eccbe2ffSRafal Kozik rxq->empty_rx_reqs[i] = i; 1736c2034976SMichal Krawczyk 173734d5e97eSMichal Krawczyk rxq->offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads; 173834d5e97eSMichal Krawczyk 1739005064e5SMichal Krawczyk if (rx_conf->rx_free_thresh != 0) { 1740005064e5SMichal Krawczyk rxq->rx_free_thresh = rx_conf->rx_free_thresh; 1741005064e5SMichal Krawczyk } else { 1742005064e5SMichal Krawczyk dyn_thresh = rxq->ring_size / ENA_REFILL_THRESH_DIVIDER; 1743005064e5SMichal Krawczyk rxq->rx_free_thresh = RTE_MIN(dyn_thresh, 1744005064e5SMichal Krawczyk (uint16_t)(ENA_REFILL_THRESH_PACKET)); 1745005064e5SMichal Krawczyk } 1746005064e5SMichal Krawczyk 17471173fca2SJan Medala /* Store pointer to this queue in upper layer */ 17481173fca2SJan Medala rxq->configured = 1; 17491173fca2SJan Medala dev->data->rx_queues[queue_idx] = rxq; 17501173fca2SJan Medala 1751df238f84SMichal Krawczyk return 0; 17521173fca2SJan Medala } 17531173fca2SJan Medala 175483fd97b2SMichal Krawczyk static int ena_add_single_rx_desc(struct ena_com_io_sq *io_sq, 175583fd97b2SMichal Krawczyk struct rte_mbuf *mbuf, uint16_t id) 175683fd97b2SMichal Krawczyk { 175783fd97b2SMichal Krawczyk struct ena_com_buf ebuf; 175883fd97b2SMichal Krawczyk int rc; 175983fd97b2SMichal Krawczyk 176083fd97b2SMichal Krawczyk /* prepare physical address for DMA transaction */ 176183fd97b2SMichal Krawczyk ebuf.paddr = mbuf->buf_iova + RTE_PKTMBUF_HEADROOM; 176283fd97b2SMichal Krawczyk ebuf.len = mbuf->buf_len - RTE_PKTMBUF_HEADROOM; 176383fd97b2SMichal Krawczyk 176483fd97b2SMichal Krawczyk /* pass resource to device */ 176583fd97b2SMichal Krawczyk rc = ena_com_add_single_rx_desc(io_sq, &ebuf, id); 176683fd97b2SMichal Krawczyk if (unlikely(rc != 0)) 1767e99981afSDavid Marchand PMD_RX_LOG_LINE(WARNING, "Failed adding Rx desc"); 176883fd97b2SMichal Krawczyk 176983fd97b2SMichal Krawczyk return rc; 177083fd97b2SMichal Krawczyk } 177183fd97b2SMichal Krawczyk 17721173fca2SJan Medala static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count) 17731173fca2SJan Medala { 17741173fca2SJan Medala unsigned int i; 17751173fca2SJan Medala int rc; 17761daff526SJakub Palider uint16_t next_to_use = rxq->next_to_use; 17770a001d69SMichal Krawczyk uint16_t req_id; 17780a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 17790a001d69SMichal Krawczyk uint16_t in_use; 17800a001d69SMichal Krawczyk #endif 178179405ee1SRafal Kozik struct rte_mbuf **mbufs = rxq->rx_refill_buffer; 17821173fca2SJan Medala 17831173fca2SJan Medala if (unlikely(!count)) 17841173fca2SJan Medala return 0; 17851173fca2SJan Medala 17860a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 1787c0006061SMichal Krawczyk in_use = rxq->ring_size - 1 - 1788c0006061SMichal Krawczyk ena_com_free_q_entries(rxq->ena_com_io_sq); 17890a001d69SMichal Krawczyk if (unlikely((in_use + count) >= rxq->ring_size)) 1790e99981afSDavid Marchand PMD_RX_LOG_LINE(ERR, "Bad Rx ring state"); 17910a001d69SMichal Krawczyk #endif 17921173fca2SJan Medala 17931173fca2SJan Medala /* get resources for incoming packets */ 17943c8bc29fSDavid Harton rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, count); 17951173fca2SJan Medala if (unlikely(rc < 0)) { 17961173fca2SJan Medala rte_atomic64_inc(&rxq->adapter->drv_stats->rx_nombuf); 17977830e905SSolganik Alexander ++rxq->rx_stats.mbuf_alloc_fail; 1798e99981afSDavid Marchand PMD_RX_LOG_LINE(DEBUG, "There are not enough free buffers"); 17991173fca2SJan Medala return 0; 18001173fca2SJan Medala } 18011173fca2SJan Medala 18021173fca2SJan Medala for (i = 0; i < count; i++) { 180379405ee1SRafal Kozik struct rte_mbuf *mbuf = mbufs[i]; 18041be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info; 18051173fca2SJan Medala 180679405ee1SRafal Kozik if (likely((i + 4) < count)) 180779405ee1SRafal Kozik rte_prefetch0(mbufs[i + 4]); 1808c2034976SMichal Krawczyk 1809c0006061SMichal Krawczyk req_id = rxq->empty_rx_reqs[next_to_use]; 18101be097dcSMichal Krawczyk rx_info = &rxq->rx_buffer_info[req_id]; 1811241da076SRafal Kozik 181283fd97b2SMichal Krawczyk rc = ena_add_single_rx_desc(rxq->ena_com_io_sq, mbuf, req_id); 181383fd97b2SMichal Krawczyk if (unlikely(rc != 0)) 18141173fca2SJan Medala break; 181583fd97b2SMichal Krawczyk 18161be097dcSMichal Krawczyk rx_info->mbuf = mbuf; 1817c0006061SMichal Krawczyk next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, rxq->size_mask); 18181173fca2SJan Medala } 18191173fca2SJan Medala 182079405ee1SRafal Kozik if (unlikely(i < count)) { 1821e99981afSDavid Marchand PMD_RX_LOG_LINE(WARNING, 1822e99981afSDavid Marchand "Refilled Rx queue[%d] with only %d/%d buffers", 1823617898d1SMichal Krawczyk rxq->id, i, count); 18243c8bc29fSDavid Harton rte_pktmbuf_free_bulk(&mbufs[i], count - i); 18257830e905SSolganik Alexander ++rxq->rx_stats.refill_partial; 182679405ee1SRafal Kozik } 1827241da076SRafal Kozik 18287be78d02SJosh Soref /* When we submitted free resources to device... */ 18293d19e1abSRafal Kozik if (likely(i > 0)) { 183038faa87eSMichal Krawczyk /* ...let HW know that it can fill buffers with data. */ 18311173fca2SJan Medala ena_com_write_sq_doorbell(rxq->ena_com_io_sq); 18321173fca2SJan Medala 18335e02e19eSJan Medala rxq->next_to_use = next_to_use; 18345e02e19eSJan Medala } 18355e02e19eSJan Medala 18361173fca2SJan Medala return i; 18371173fca2SJan Medala } 18381173fca2SJan Medala 183992401abfSShai Brandes static size_t ena_get_metrics_entries(struct ena_adapter *adapter) 184092401abfSShai Brandes { 184192401abfSShai Brandes struct ena_com_dev *ena_dev = &adapter->ena_dev; 184292401abfSShai Brandes size_t metrics_num = 0; 184392401abfSShai Brandes 184492401abfSShai Brandes if (ena_com_get_cap(ena_dev, ENA_ADMIN_CUSTOMER_METRICS)) 184592401abfSShai Brandes metrics_num = ENA_STATS_ARRAY_METRICS; 184692401abfSShai Brandes else if (ena_com_get_cap(ena_dev, ENA_ADMIN_ENI_STATS)) 184792401abfSShai Brandes metrics_num = ENA_STATS_ARRAY_METRICS_LEGACY; 1848e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "0x%x customer metrics are supported", (unsigned int)metrics_num); 184992401abfSShai Brandes if (metrics_num > ENA_MAX_CUSTOMER_METRICS) { 1850e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "Not enough space for the requested customer metrics"); 185192401abfSShai Brandes metrics_num = ENA_MAX_CUSTOMER_METRICS; 185292401abfSShai Brandes } 185392401abfSShai Brandes return metrics_num; 185492401abfSShai Brandes } 185592401abfSShai Brandes 1856b9b05d6fSMichal Krawczyk static int ena_device_init(struct ena_adapter *adapter, 1857aab58857SStanislaw Kardach struct rte_pci_device *pdev, 1858b9b05d6fSMichal Krawczyk struct ena_com_dev_get_features_ctx *get_feat_ctx) 18591173fca2SJan Medala { 1860b9b05d6fSMichal Krawczyk struct ena_com_dev *ena_dev = &adapter->ena_dev; 1861ca148440SMichal Krawczyk uint32_t aenq_groups; 18621173fca2SJan Medala int rc; 1863c4144557SJan Medala bool readless_supported; 18641173fca2SJan Medala 18651173fca2SJan Medala /* Initialize mmio registers */ 18661173fca2SJan Medala rc = ena_com_mmio_reg_read_request_init(ena_dev); 18671173fca2SJan Medala if (rc) { 1868e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to init MMIO read less"); 18691173fca2SJan Medala return rc; 18701173fca2SJan Medala } 18711173fca2SJan Medala 1872c4144557SJan Medala /* The PCIe configuration space revision id indicate if mmio reg 1873c4144557SJan Medala * read is disabled. 1874c4144557SJan Medala */ 1875aab58857SStanislaw Kardach readless_supported = !(pdev->id.class_id & ENA_MMIO_DISABLE_REG_READ); 1876c4144557SJan Medala ena_com_set_mmio_read_mode(ena_dev, readless_supported); 1877c4144557SJan Medala 18781173fca2SJan Medala /* reset device */ 18793adcba9aSMichal Krawczyk rc = ena_com_dev_reset(ena_dev, ENA_REGS_RESET_NORMAL); 18801173fca2SJan Medala if (rc) { 1881e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Cannot reset device"); 18821173fca2SJan Medala goto err_mmio_read_less; 18831173fca2SJan Medala } 18841173fca2SJan Medala 18851173fca2SJan Medala /* check FW version */ 18861173fca2SJan Medala rc = ena_com_validate_version(ena_dev); 18871173fca2SJan Medala if (rc) { 1888e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Device version is too low"); 18891173fca2SJan Medala goto err_mmio_read_less; 18901173fca2SJan Medala } 18911173fca2SJan Medala 18921173fca2SJan Medala ena_dev->dma_addr_bits = ena_com_get_dma_width(ena_dev); 18931173fca2SJan Medala 18941173fca2SJan Medala /* ENA device administration layer init */ 1895b68309beSRafal Kozik rc = ena_com_admin_init(ena_dev, &aenq_handlers); 18961173fca2SJan Medala if (rc) { 1897e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1898e99981afSDavid Marchand "Cannot initialize ENA admin queue"); 18991173fca2SJan Medala goto err_mmio_read_less; 19001173fca2SJan Medala } 19011173fca2SJan Medala 19021173fca2SJan Medala /* To enable the msix interrupts the driver needs to know the number 19031173fca2SJan Medala * of queues. So the driver uses polling mode to retrieve this 19041173fca2SJan Medala * information. 19051173fca2SJan Medala */ 19061173fca2SJan Medala ena_com_set_admin_polling_mode(ena_dev, true); 19071173fca2SJan Medala 1908201ff2e5SJakub Palider ena_config_host_info(ena_dev); 1909201ff2e5SJakub Palider 19101173fca2SJan Medala /* Get Device Attributes and features */ 19111173fca2SJan Medala rc = ena_com_get_dev_attr_feat(ena_dev, get_feat_ctx); 19121173fca2SJan Medala if (rc) { 1913e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 1914e99981afSDavid Marchand "Cannot get attribute for ENA device, rc: %d", rc); 19151173fca2SJan Medala goto err_admin_init; 19161173fca2SJan Medala } 19171173fca2SJan Medala 1918f01f060cSRafal Kozik aenq_groups = BIT(ENA_ADMIN_LINK_CHANGE) | 1919d9b8b106SMichal Krawczyk BIT(ENA_ADMIN_NOTIFICATION) | 1920983cce2dSRafal Kozik BIT(ENA_ADMIN_KEEP_ALIVE) | 1921983cce2dSRafal Kozik BIT(ENA_ADMIN_FATAL_ERROR) | 19222c0f7536SShai Brandes BIT(ENA_ADMIN_WARNING) | 19232c0f7536SShai Brandes BIT(ENA_ADMIN_CONF_NOTIFICATIONS); 1924ca148440SMichal Krawczyk 1925ca148440SMichal Krawczyk aenq_groups &= get_feat_ctx->aenq.supported_groups; 1926ca148440SMichal Krawczyk 1927b9b05d6fSMichal Krawczyk adapter->all_aenq_groups = aenq_groups; 192892401abfSShai Brandes /* The actual supported number of metrics is negotiated with the device at runtime */ 192992401abfSShai Brandes adapter->metrics_num = ena_get_metrics_entries(adapter); 1930e859d2b8SRafal Kozik 19311173fca2SJan Medala return 0; 19321173fca2SJan Medala 19331173fca2SJan Medala err_admin_init: 19341173fca2SJan Medala ena_com_admin_destroy(ena_dev); 19351173fca2SJan Medala 19361173fca2SJan Medala err_mmio_read_less: 19371173fca2SJan Medala ena_com_mmio_reg_read_request_destroy(ena_dev); 19381173fca2SJan Medala 19391173fca2SJan Medala return rc; 19401173fca2SJan Medala } 19411173fca2SJan Medala 1942ca1dfa85SShai Brandes static void ena_control_path_handler(void *cb_arg) 194315773e06SMichal Krawczyk { 1944aab58857SStanislaw Kardach struct rte_eth_dev *dev = cb_arg; 1945aab58857SStanislaw Kardach struct ena_adapter *adapter = dev->data->dev_private; 194615773e06SMichal Krawczyk struct ena_com_dev *ena_dev = &adapter->ena_dev; 194715773e06SMichal Krawczyk 1948ca1dfa85SShai Brandes if (likely(adapter->state != ENA_ADAPTER_STATE_CLOSED)) { 194915773e06SMichal Krawczyk ena_com_admin_q_comp_intr_handler(ena_dev); 1950aab58857SStanislaw Kardach ena_com_aenq_intr_handler(ena_dev, dev); 195115773e06SMichal Krawczyk } 1952ca1dfa85SShai Brandes } 1953ca1dfa85SShai Brandes 1954ca1dfa85SShai Brandes static void ena_control_path_poll_handler(void *cb_arg) 1955ca1dfa85SShai Brandes { 1956ca1dfa85SShai Brandes struct rte_eth_dev *dev = cb_arg; 1957ca1dfa85SShai Brandes struct ena_adapter *adapter = dev->data->dev_private; 1958ca1dfa85SShai Brandes int rc; 1959ca1dfa85SShai Brandes 1960ca1dfa85SShai Brandes if (likely(adapter->state != ENA_ADAPTER_STATE_CLOSED)) { 1961ca1dfa85SShai Brandes ena_control_path_handler(cb_arg); 1962ca1dfa85SShai Brandes rc = rte_eal_alarm_set(adapter->control_path_poll_interval, 1963ca1dfa85SShai Brandes ena_control_path_poll_handler, cb_arg); 1964ca1dfa85SShai Brandes if (unlikely(rc != 0)) { 1965e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to retrigger control path alarm"); 1966ca1dfa85SShai Brandes ena_trigger_reset(adapter, ENA_REGS_RESET_GENERIC); 1967ca1dfa85SShai Brandes } 1968ca1dfa85SShai Brandes } 1969ca1dfa85SShai Brandes } 197015773e06SMichal Krawczyk 19715efb9fc7SMichal Krawczyk static void check_for_missing_keep_alive(struct ena_adapter *adapter) 19725efb9fc7SMichal Krawczyk { 1973b9b05d6fSMichal Krawczyk if (!(adapter->active_aenq_groups & BIT(ENA_ADMIN_KEEP_ALIVE))) 1974e859d2b8SRafal Kozik return; 1975e859d2b8SRafal Kozik 19765efb9fc7SMichal Krawczyk if (adapter->keep_alive_timeout == ENA_HW_HINTS_NO_TIMEOUT) 19775efb9fc7SMichal Krawczyk return; 19785efb9fc7SMichal Krawczyk 19795efb9fc7SMichal Krawczyk if (unlikely((rte_get_timer_cycles() - adapter->timestamp_wd) >= 19805efb9fc7SMichal Krawczyk adapter->keep_alive_timeout)) { 1981e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Keep alive timeout"); 19822bae75eaSDawid Gorecki ena_trigger_reset(adapter, ENA_REGS_RESET_KEEP_ALIVE_TO); 19837830e905SSolganik Alexander ++adapter->dev_stats.wd_expired; 19845efb9fc7SMichal Krawczyk } 19855efb9fc7SMichal Krawczyk } 19865efb9fc7SMichal Krawczyk 19875efb9fc7SMichal Krawczyk /* Check if admin queue is enabled */ 19885efb9fc7SMichal Krawczyk static void check_for_admin_com_state(struct ena_adapter *adapter) 19895efb9fc7SMichal Krawczyk { 19905efb9fc7SMichal Krawczyk if (unlikely(!ena_com_get_admin_running_state(&adapter->ena_dev))) { 1991e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "ENA admin queue is not in running state"); 19922bae75eaSDawid Gorecki ena_trigger_reset(adapter, ENA_REGS_RESET_ADMIN_TO); 19935efb9fc7SMichal Krawczyk } 19945efb9fc7SMichal Krawczyk } 19955efb9fc7SMichal Krawczyk 1996f93e20e5SMichal Krawczyk static int check_for_tx_completion_in_queue(struct ena_adapter *adapter, 1997f93e20e5SMichal Krawczyk struct ena_ring *tx_ring) 1998f93e20e5SMichal Krawczyk { 1999f93e20e5SMichal Krawczyk struct ena_tx_buffer *tx_buf; 2000f93e20e5SMichal Krawczyk uint64_t timestamp; 2001f93e20e5SMichal Krawczyk uint64_t completion_delay; 2002f93e20e5SMichal Krawczyk uint32_t missed_tx = 0; 2003f93e20e5SMichal Krawczyk unsigned int i; 2004f93e20e5SMichal Krawczyk int rc = 0; 2005f93e20e5SMichal Krawczyk 2006f93e20e5SMichal Krawczyk for (i = 0; i < tx_ring->ring_size; ++i) { 2007f93e20e5SMichal Krawczyk tx_buf = &tx_ring->tx_buffer_info[i]; 2008f93e20e5SMichal Krawczyk timestamp = tx_buf->timestamp; 2009f93e20e5SMichal Krawczyk 2010f93e20e5SMichal Krawczyk if (timestamp == 0) 2011f93e20e5SMichal Krawczyk continue; 2012f93e20e5SMichal Krawczyk 2013f93e20e5SMichal Krawczyk completion_delay = rte_get_timer_cycles() - timestamp; 2014f93e20e5SMichal Krawczyk if (completion_delay > adapter->missing_tx_completion_to) { 2015f93e20e5SMichal Krawczyk if (unlikely(!tx_buf->print_once)) { 2016e99981afSDavid Marchand PMD_TX_LOG_LINE(WARNING, 2017f93e20e5SMichal Krawczyk "Found a Tx that wasn't completed on time, qid %d, index %d. " 2018e99981afSDavid Marchand "Missing Tx outstanding for %" PRIu64 " msecs.", 2019f93e20e5SMichal Krawczyk tx_ring->id, i, completion_delay / 2020f93e20e5SMichal Krawczyk rte_get_timer_hz() * 1000); 2021f93e20e5SMichal Krawczyk tx_buf->print_once = true; 2022f93e20e5SMichal Krawczyk } 2023f93e20e5SMichal Krawczyk ++missed_tx; 2024f93e20e5SMichal Krawczyk } 2025f93e20e5SMichal Krawczyk } 2026f93e20e5SMichal Krawczyk 2027f93e20e5SMichal Krawczyk if (unlikely(missed_tx > tx_ring->missing_tx_completion_threshold)) { 2028e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 2029f93e20e5SMichal Krawczyk "The number of lost Tx completions is above the threshold (%d > %d). " 2030e99981afSDavid Marchand "Trigger the device reset.", 2031f93e20e5SMichal Krawczyk missed_tx, 2032f93e20e5SMichal Krawczyk tx_ring->missing_tx_completion_threshold); 2033f93e20e5SMichal Krawczyk adapter->reset_reason = ENA_REGS_RESET_MISS_TX_CMPL; 2034f93e20e5SMichal Krawczyk adapter->trigger_reset = true; 2035f93e20e5SMichal Krawczyk rc = -EIO; 2036f93e20e5SMichal Krawczyk } 2037f93e20e5SMichal Krawczyk 2038f93e20e5SMichal Krawczyk tx_ring->tx_stats.missed_tx += missed_tx; 2039f93e20e5SMichal Krawczyk 2040f93e20e5SMichal Krawczyk return rc; 2041f93e20e5SMichal Krawczyk } 2042f93e20e5SMichal Krawczyk 2043f93e20e5SMichal Krawczyk static void check_for_tx_completions(struct ena_adapter *adapter) 2044f93e20e5SMichal Krawczyk { 2045f93e20e5SMichal Krawczyk struct ena_ring *tx_ring; 2046f93e20e5SMichal Krawczyk uint64_t tx_cleanup_delay; 2047f93e20e5SMichal Krawczyk size_t qid; 2048f93e20e5SMichal Krawczyk int budget; 2049f93e20e5SMichal Krawczyk uint16_t nb_tx_queues = adapter->edev_data->nb_tx_queues; 2050f93e20e5SMichal Krawczyk 2051f93e20e5SMichal Krawczyk if (adapter->missing_tx_completion_to == ENA_HW_HINTS_NO_TIMEOUT) 2052f93e20e5SMichal Krawczyk return; 2053f93e20e5SMichal Krawczyk 2054f93e20e5SMichal Krawczyk nb_tx_queues = adapter->edev_data->nb_tx_queues; 2055f93e20e5SMichal Krawczyk budget = adapter->missing_tx_completion_budget; 2056f93e20e5SMichal Krawczyk 2057f93e20e5SMichal Krawczyk qid = adapter->last_tx_comp_qid; 2058f93e20e5SMichal Krawczyk while (budget-- > 0) { 2059f93e20e5SMichal Krawczyk tx_ring = &adapter->tx_ring[qid]; 2060f93e20e5SMichal Krawczyk 2061f93e20e5SMichal Krawczyk /* Tx cleanup is called only by the burst function and can be 2062f93e20e5SMichal Krawczyk * called dynamically by the application. Also cleanup is 2063f93e20e5SMichal Krawczyk * limited by the threshold. To avoid false detection of the 2064f93e20e5SMichal Krawczyk * missing HW Tx completion, get the delay since last cleanup 2065f93e20e5SMichal Krawczyk * function was called. 2066f93e20e5SMichal Krawczyk */ 2067f93e20e5SMichal Krawczyk tx_cleanup_delay = rte_get_timer_cycles() - 2068f93e20e5SMichal Krawczyk tx_ring->last_cleanup_ticks; 2069f93e20e5SMichal Krawczyk if (tx_cleanup_delay < adapter->tx_cleanup_stall_delay) 2070f93e20e5SMichal Krawczyk check_for_tx_completion_in_queue(adapter, tx_ring); 2071f93e20e5SMichal Krawczyk qid = (qid + 1) % nb_tx_queues; 2072f93e20e5SMichal Krawczyk } 2073f93e20e5SMichal Krawczyk 2074f93e20e5SMichal Krawczyk adapter->last_tx_comp_qid = qid; 2075f93e20e5SMichal Krawczyk } 2076f93e20e5SMichal Krawczyk 2077d9b8b106SMichal Krawczyk static void ena_timer_wd_callback(__rte_unused struct rte_timer *timer, 2078d9b8b106SMichal Krawczyk void *arg) 2079d9b8b106SMichal Krawczyk { 2080aab58857SStanislaw Kardach struct rte_eth_dev *dev = arg; 2081aab58857SStanislaw Kardach struct ena_adapter *adapter = dev->data->dev_private; 2082d9b8b106SMichal Krawczyk 2083e2174a54SMichal Krawczyk if (unlikely(adapter->trigger_reset)) 2084e2174a54SMichal Krawczyk return; 2085e2174a54SMichal Krawczyk 20865efb9fc7SMichal Krawczyk check_for_missing_keep_alive(adapter); 20875efb9fc7SMichal Krawczyk check_for_admin_com_state(adapter); 2088f93e20e5SMichal Krawczyk check_for_tx_completions(adapter); 2089d9b8b106SMichal Krawczyk 20905efb9fc7SMichal Krawczyk if (unlikely(adapter->trigger_reset)) { 2091e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Trigger reset is on"); 20925723fbedSFerruh Yigit rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, 2093d9b8b106SMichal Krawczyk NULL); 2094d9b8b106SMichal Krawczyk } 2095d9b8b106SMichal Krawczyk } 2096d9b8b106SMichal Krawczyk 20972fca2a98SMichal Krawczyk static inline void 20988a7a73f2SMichal Krawczyk set_default_llq_configurations(struct ena_llq_configurations *llq_config, 20998a7a73f2SMichal Krawczyk struct ena_admin_feature_llq_desc *llq, 21008a7a73f2SMichal Krawczyk bool use_large_llq_hdr) 21012fca2a98SMichal Krawczyk { 21022fca2a98SMichal Krawczyk llq_config->llq_header_location = ENA_ADMIN_INLINE_HEADER; 21032fca2a98SMichal Krawczyk llq_config->llq_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY; 21042fca2a98SMichal Krawczyk llq_config->llq_num_decs_before_header = 21052fca2a98SMichal Krawczyk ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2; 21068a7a73f2SMichal Krawczyk 21078a7a73f2SMichal Krawczyk if (use_large_llq_hdr && 21088a7a73f2SMichal Krawczyk (llq->entry_size_ctrl_supported & ENA_ADMIN_LIST_ENTRY_SIZE_256B)) { 21098a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size = 21108a7a73f2SMichal Krawczyk ENA_ADMIN_LIST_ENTRY_SIZE_256B; 21118a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size_value = 256; 21128a7a73f2SMichal Krawczyk } else { 21138a7a73f2SMichal Krawczyk llq_config->llq_ring_entry_size = 21148a7a73f2SMichal Krawczyk ENA_ADMIN_LIST_ENTRY_SIZE_128B; 21152fca2a98SMichal Krawczyk llq_config->llq_ring_entry_size_value = 128; 21162fca2a98SMichal Krawczyk } 21178a7a73f2SMichal Krawczyk } 21182fca2a98SMichal Krawczyk 21192fca2a98SMichal Krawczyk static int 21202fca2a98SMichal Krawczyk ena_set_queues_placement_policy(struct ena_adapter *adapter, 21212fca2a98SMichal Krawczyk struct ena_com_dev *ena_dev, 21222fca2a98SMichal Krawczyk struct ena_admin_feature_llq_desc *llq, 21232fca2a98SMichal Krawczyk struct ena_llq_configurations *llq_default_configurations) 21242fca2a98SMichal Krawczyk { 21252fca2a98SMichal Krawczyk int rc; 21262fca2a98SMichal Krawczyk u32 llq_feature_mask; 21272fca2a98SMichal Krawczyk 21281f11149dSShai Brandes if (adapter->llq_header_policy == ENA_LLQ_POLICY_DISABLED) { 2129e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, 21309944919eSMichal Krawczyk "NOTE: LLQ has been disabled as per user's request. " 2131e99981afSDavid Marchand "This may lead to a huge performance degradation!"); 21329944919eSMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 21339944919eSMichal Krawczyk return 0; 21349944919eSMichal Krawczyk } 21359944919eSMichal Krawczyk 21362fca2a98SMichal Krawczyk llq_feature_mask = 1 << ENA_ADMIN_LLQ; 21372fca2a98SMichal Krawczyk if (!(ena_dev->supported_features & llq_feature_mask)) { 2138e99981afSDavid Marchand PMD_DRV_LOG_LINE(INFO, 2139e99981afSDavid Marchand "LLQ is not supported. Fallback to host mode policy."); 21402fca2a98SMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 21412fca2a98SMichal Krawczyk return 0; 21422fca2a98SMichal Krawczyk } 21432fca2a98SMichal Krawczyk 21449ae7a13fSDawid Gorecki if (adapter->dev_mem_base == NULL) { 2145e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 2146e99981afSDavid Marchand "LLQ is advertised as supported, but device doesn't expose mem bar"); 21479ae7a13fSDawid Gorecki ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 21489ae7a13fSDawid Gorecki return 0; 21499ae7a13fSDawid Gorecki } 21509ae7a13fSDawid Gorecki 21512fca2a98SMichal Krawczyk rc = ena_com_config_dev_mode(ena_dev, llq, llq_default_configurations); 21522fca2a98SMichal Krawczyk if (unlikely(rc)) { 2153e99981afSDavid Marchand PMD_INIT_LOG_LINE(WARNING, 2154e99981afSDavid Marchand "Failed to config dev mode. Fallback to host mode policy."); 21552fca2a98SMichal Krawczyk ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 21562fca2a98SMichal Krawczyk return 0; 21572fca2a98SMichal Krawczyk } 21582fca2a98SMichal Krawczyk 21592fca2a98SMichal Krawczyk /* Nothing to config, exit */ 21602fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) 21612fca2a98SMichal Krawczyk return 0; 21622fca2a98SMichal Krawczyk 21632fca2a98SMichal Krawczyk ena_dev->mem_bar = adapter->dev_mem_base; 21642fca2a98SMichal Krawczyk 21652fca2a98SMichal Krawczyk return 0; 21662fca2a98SMichal Krawczyk } 21672fca2a98SMichal Krawczyk 21685920d930SMichal Krawczyk static uint32_t ena_calc_max_io_queue_num(struct ena_com_dev *ena_dev, 216901bd6877SRafal Kozik struct ena_com_dev_get_features_ctx *get_feat_ctx) 217001bd6877SRafal Kozik { 21715920d930SMichal Krawczyk uint32_t io_tx_sq_num, io_tx_cq_num, io_rx_num, max_num_io_queues; 217201bd6877SRafal Kozik 2173ea93d37eSRafal Kozik /* Regular queues capabilities */ 2174ea93d37eSRafal Kozik if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) { 2175ea93d37eSRafal Kozik struct ena_admin_queue_ext_feature_fields *max_queue_ext = 2176ea93d37eSRafal Kozik &get_feat_ctx->max_queue_ext.max_queue_ext; 21772fca2a98SMichal Krawczyk io_rx_num = RTE_MIN(max_queue_ext->max_rx_sq_num, 21782fca2a98SMichal Krawczyk max_queue_ext->max_rx_cq_num); 21792fca2a98SMichal Krawczyk io_tx_sq_num = max_queue_ext->max_tx_sq_num; 21802fca2a98SMichal Krawczyk io_tx_cq_num = max_queue_ext->max_tx_cq_num; 2181ea93d37eSRafal Kozik } else { 2182ea93d37eSRafal Kozik struct ena_admin_queue_feature_desc *max_queues = 2183ea93d37eSRafal Kozik &get_feat_ctx->max_queues; 21842fca2a98SMichal Krawczyk io_tx_sq_num = max_queues->max_sq_num; 21852fca2a98SMichal Krawczyk io_tx_cq_num = max_queues->max_cq_num; 21862fca2a98SMichal Krawczyk io_rx_num = RTE_MIN(io_tx_sq_num, io_tx_cq_num); 2187ea93d37eSRafal Kozik } 218801bd6877SRafal Kozik 21892fca2a98SMichal Krawczyk /* In case of LLQ use the llq number in the get feature cmd */ 21902fca2a98SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) 21912fca2a98SMichal Krawczyk io_tx_sq_num = get_feat_ctx->llq.max_llq_num; 21922fca2a98SMichal Krawczyk 21935920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(ENA_MAX_NUM_IO_QUEUES, io_rx_num); 21945920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(max_num_io_queues, io_tx_sq_num); 21955920d930SMichal Krawczyk max_num_io_queues = RTE_MIN(max_num_io_queues, io_tx_cq_num); 219601bd6877SRafal Kozik 21975920d930SMichal Krawczyk if (unlikely(max_num_io_queues == 0)) { 2198e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Number of IO queues cannot not be 0"); 219901bd6877SRafal Kozik return -EFAULT; 220001bd6877SRafal Kozik } 220101bd6877SRafal Kozik 22025920d930SMichal Krawczyk return max_num_io_queues; 220301bd6877SRafal Kozik } 220401bd6877SRafal Kozik 2205e8c838fdSMichal Krawczyk static void 2206e8c838fdSMichal Krawczyk ena_set_offloads(struct ena_offloads *offloads, 2207e8c838fdSMichal Krawczyk struct ena_admin_feature_offload_desc *offload_desc) 2208e8c838fdSMichal Krawczyk { 2209e8c838fdSMichal Krawczyk if (offload_desc->tx & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TSO_IPV4_MASK) 2210e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_IPV4_TSO; 2211e8c838fdSMichal Krawczyk 2212e8c838fdSMichal Krawczyk /* Tx IPv4 checksum offloads */ 2213e8c838fdSMichal Krawczyk if (offload_desc->tx & 2214e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L3_CSUM_IPV4_MASK) 2215e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L3_IPV4_CSUM; 2216e8c838fdSMichal Krawczyk if (offload_desc->tx & 2217e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_FULL_MASK) 2218e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV4_CSUM; 2219e8c838fdSMichal Krawczyk if (offload_desc->tx & 2220e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_PART_MASK) 2221e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV4_CSUM_PARTIAL; 2222e8c838fdSMichal Krawczyk 2223e8c838fdSMichal Krawczyk /* Tx IPv6 checksum offloads */ 2224e8c838fdSMichal Krawczyk if (offload_desc->tx & 2225e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_FULL_MASK) 2226e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV6_CSUM; 2227e8c838fdSMichal Krawczyk if (offload_desc->tx & 2228e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_PART_MASK) 2229e8c838fdSMichal Krawczyk offloads->tx_offloads |= ENA_L4_IPV6_CSUM_PARTIAL; 2230e8c838fdSMichal Krawczyk 2231e8c838fdSMichal Krawczyk /* Rx IPv4 checksum offloads */ 2232e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 2233e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L3_CSUM_IPV4_MASK) 2234e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L3_IPV4_CSUM; 2235e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 2236e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV4_CSUM_MASK) 2237e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L4_IPV4_CSUM; 2238e8c838fdSMichal Krawczyk 2239e8c838fdSMichal Krawczyk /* Rx IPv6 checksum offloads */ 2240e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 2241e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV6_CSUM_MASK) 2242e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_L4_IPV6_CSUM; 2243e8c838fdSMichal Krawczyk 2244e8c838fdSMichal Krawczyk if (offload_desc->rx_supported & 2245e8c838fdSMichal Krawczyk ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_HASH_MASK) 2246e8c838fdSMichal Krawczyk offloads->rx_offloads |= ENA_RX_RSS_HASH; 2247e8c838fdSMichal Krawczyk } 2248e8c838fdSMichal Krawczyk 2249e3595539SStanislaw Kardach static int ena_init_once(void) 2250e3595539SStanislaw Kardach { 2251e3595539SStanislaw Kardach static bool init_done; 2252e3595539SStanislaw Kardach 2253e3595539SStanislaw Kardach if (init_done) 2254e3595539SStanislaw Kardach return 0; 2255e3595539SStanislaw Kardach 2256e3595539SStanislaw Kardach if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 2257e3595539SStanislaw Kardach /* Init timer subsystem for the ENA timer service. */ 2258e3595539SStanislaw Kardach rte_timer_subsystem_init(); 2259e3595539SStanislaw Kardach /* Register handler for requests from secondary processes. */ 2260e3595539SStanislaw Kardach rte_mp_action_register(ENA_MP_NAME, ena_mp_primary_handle); 2261e3595539SStanislaw Kardach } 2262e3595539SStanislaw Kardach 2263e3595539SStanislaw Kardach init_done = true; 2264e3595539SStanislaw Kardach return 0; 2265e3595539SStanislaw Kardach } 2266e3595539SStanislaw Kardach 22671173fca2SJan Medala static int eth_ena_dev_init(struct rte_eth_dev *eth_dev) 22681173fca2SJan Medala { 2269ea93d37eSRafal Kozik struct ena_calc_queue_size_ctx calc_queue_ctx = { 0 }; 22701173fca2SJan Medala struct rte_pci_device *pci_dev; 2271eb0ef49dSMichal Krawczyk struct rte_intr_handle *intr_handle; 2272890728ffSStephen Hemminger struct ena_adapter *adapter = eth_dev->data->dev_private; 22731173fca2SJan Medala struct ena_com_dev *ena_dev = &adapter->ena_dev; 22741173fca2SJan Medala struct ena_com_dev_get_features_ctx get_feat_ctx; 22752fca2a98SMichal Krawczyk struct ena_llq_configurations llq_config; 22762fca2a98SMichal Krawczyk const char *queue_type_str; 22775920d930SMichal Krawczyk uint32_t max_num_io_queues; 2278ea93d37eSRafal Kozik int rc; 22791173fca2SJan Medala static int adapters_found; 228033dde075SMichal Krawczyk bool disable_meta_caching; 22811173fca2SJan Medala 22821173fca2SJan Medala eth_dev->dev_ops = &ena_dev_ops; 22831173fca2SJan Medala eth_dev->rx_pkt_burst = ð_ena_recv_pkts; 22841173fca2SJan Medala eth_dev->tx_pkt_burst = ð_ena_xmit_pkts; 2285b3fc5a1aSKonstantin Ananyev eth_dev->tx_pkt_prepare = ð_ena_prep_pkts; 22861173fca2SJan Medala 2287e3595539SStanislaw Kardach rc = ena_init_once(); 2288e3595539SStanislaw Kardach if (rc != 0) 2289e3595539SStanislaw Kardach return rc; 2290e3595539SStanislaw Kardach 22911173fca2SJan Medala if (rte_eal_process_type() != RTE_PROC_PRIMARY) 22921173fca2SJan Medala return 0; 22931173fca2SJan Medala 2294f30e69b4SFerruh Yigit eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 2295f30e69b4SFerruh Yigit 2296fd976890SMichal Krawczyk memset(adapter, 0, sizeof(struct ena_adapter)); 2297fd976890SMichal Krawczyk ena_dev = &adapter->ena_dev; 2298fd976890SMichal Krawczyk 2299aab58857SStanislaw Kardach adapter->edev_data = eth_dev->data; 2300fd976890SMichal Krawczyk 2301c0802544SFerruh Yigit pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 23021173fca2SJan Medala 2303e99981afSDavid Marchand PMD_INIT_LOG_LINE(INFO, "Initializing " PCI_PRI_FMT, 23041173fca2SJan Medala pci_dev->addr.domain, 23051173fca2SJan Medala pci_dev->addr.bus, 23061173fca2SJan Medala pci_dev->addr.devid, 23071173fca2SJan Medala pci_dev->addr.function); 23081173fca2SJan Medala 2309d61138d4SHarman Kalra intr_handle = pci_dev->intr_handle; 2310eb0ef49dSMichal Krawczyk 23111173fca2SJan Medala adapter->regs = pci_dev->mem_resource[ENA_REGS_BAR].addr; 23121173fca2SJan Medala adapter->dev_mem_base = pci_dev->mem_resource[ENA_MEM_BAR].addr; 23131173fca2SJan Medala 23141d339597SRafal Kozik if (!adapter->regs) { 2315e99981afSDavid Marchand PMD_INIT_LOG_LINE(CRIT, "Failed to access registers BAR(%d)", 23161173fca2SJan Medala ENA_REGS_BAR); 23171d339597SRafal Kozik return -ENXIO; 23181d339597SRafal Kozik } 23191173fca2SJan Medala 23201173fca2SJan Medala ena_dev->reg_bar = adapter->regs; 2321850e1bb1SMichal Krawczyk /* Pass device data as a pointer which can be passed to the IO functions 2322850e1bb1SMichal Krawczyk * by the ena_com (for example - the memory allocation). 2323850e1bb1SMichal Krawczyk */ 2324850e1bb1SMichal Krawczyk ena_dev->dmadev = eth_dev->data; 23251173fca2SJan Medala 23261173fca2SJan Medala adapter->id_number = adapters_found; 23271173fca2SJan Medala 23281173fca2SJan Medala snprintf(adapter->name, ENA_NAME_MAX_LEN, "ena_%d", 23291173fca2SJan Medala adapter->id_number); 23301173fca2SJan Medala 23319944919eSMichal Krawczyk /* Assign default devargs values */ 2332cc0c5d25SMichal Krawczyk adapter->missing_tx_completion_to = ENA_TX_TIMEOUT; 2333*c4f16ab0SShai Brandes adapter->llq_header_policy = ENA_LLQ_POLICY_RECOMMENDED; 2334cc0c5d25SMichal Krawczyk 23351f11149dSShai Brandes /* Get user bypass */ 23368a7a73f2SMichal Krawczyk rc = ena_parse_devargs(adapter, pci_dev->device.devargs); 23378a7a73f2SMichal Krawczyk if (rc != 0) { 2338e99981afSDavid Marchand PMD_INIT_LOG_LINE(CRIT, "Failed to parse devargs"); 23398a7a73f2SMichal Krawczyk goto err; 23408a7a73f2SMichal Krawczyk } 234192401abfSShai Brandes rc = ena_com_allocate_customer_metrics_buffer(ena_dev); 234292401abfSShai Brandes if (rc != 0) { 2343e99981afSDavid Marchand PMD_INIT_LOG_LINE(CRIT, "Failed to allocate customer metrics buffer"); 234492401abfSShai Brandes goto err; 234592401abfSShai Brandes } 23468a7a73f2SMichal Krawczyk 23471173fca2SJan Medala /* device specific initialization routine */ 2348b9b05d6fSMichal Krawczyk rc = ena_device_init(adapter, pci_dev, &get_feat_ctx); 23491173fca2SJan Medala if (rc) { 2350e99981afSDavid Marchand PMD_INIT_LOG_LINE(CRIT, "Failed to init ENA device"); 235192401abfSShai Brandes goto err_metrics_delete; 23521173fca2SJan Medala } 2353b9b05d6fSMichal Krawczyk 2354b9b05d6fSMichal Krawczyk /* Check if device supports LSC */ 2355b9b05d6fSMichal Krawczyk if (!(adapter->all_aenq_groups & BIT(ENA_ADMIN_LINK_CHANGE))) 2356b9b05d6fSMichal Krawczyk adapter->edev_data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC; 23571173fca2SJan Medala 23581f11149dSShai Brandes bool use_large_llq_hdr = ena_use_large_llq_hdr(adapter, 23591f11149dSShai Brandes get_feat_ctx.llq.entry_size_recommended); 23601f11149dSShai Brandes set_default_llq_configurations(&llq_config, &get_feat_ctx.llq, use_large_llq_hdr); 23612fca2a98SMichal Krawczyk rc = ena_set_queues_placement_policy(adapter, ena_dev, 23622fca2a98SMichal Krawczyk &get_feat_ctx.llq, &llq_config); 23632fca2a98SMichal Krawczyk if (unlikely(rc)) { 2364e99981afSDavid Marchand PMD_INIT_LOG_LINE(CRIT, "Failed to set placement policy"); 23652fca2a98SMichal Krawczyk return rc; 23662fca2a98SMichal Krawczyk } 23672fca2a98SMichal Krawczyk 23681f11149dSShai Brandes if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) { 23692fca2a98SMichal Krawczyk queue_type_str = "Regular"; 23701f11149dSShai Brandes } else { 23712fca2a98SMichal Krawczyk queue_type_str = "Low latency"; 2372e99981afSDavid Marchand PMD_DRV_LOG_LINE(INFO, "LLQ entry size %uB", llq_config.llq_ring_entry_size_value); 23731f11149dSShai Brandes } 2374e99981afSDavid Marchand PMD_DRV_LOG_LINE(INFO, "Placement policy: %s", queue_type_str); 2375ea93d37eSRafal Kozik 2376ea93d37eSRafal Kozik calc_queue_ctx.ena_dev = ena_dev; 2377ea93d37eSRafal Kozik calc_queue_ctx.get_feat_ctx = &get_feat_ctx; 23781173fca2SJan Medala 23795920d930SMichal Krawczyk max_num_io_queues = ena_calc_max_io_queue_num(ena_dev, &get_feat_ctx); 23801f11149dSShai Brandes rc = ena_calc_io_queue_size(&calc_queue_ctx, use_large_llq_hdr); 23815920d930SMichal Krawczyk if (unlikely((rc != 0) || (max_num_io_queues == 0))) { 2382241da076SRafal Kozik rc = -EFAULT; 2383241da076SRafal Kozik goto err_device_destroy; 2384241da076SRafal Kozik } 23851173fca2SJan Medala 23865920d930SMichal Krawczyk adapter->max_tx_ring_size = calc_queue_ctx.max_tx_queue_size; 23875920d930SMichal Krawczyk adapter->max_rx_ring_size = calc_queue_ctx.max_rx_queue_size; 2388ea93d37eSRafal Kozik adapter->max_tx_sgl_size = calc_queue_ctx.max_tx_sgl_size; 2389ea93d37eSRafal Kozik adapter->max_rx_sgl_size = calc_queue_ctx.max_rx_sgl_size; 23905920d930SMichal Krawczyk adapter->max_num_io_queues = max_num_io_queues; 23912061fe41SRafal Kozik 239233dde075SMichal Krawczyk if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 239333dde075SMichal Krawczyk disable_meta_caching = 239433dde075SMichal Krawczyk !!(get_feat_ctx.llq.accel_mode.u.get.supported_flags & 239533dde075SMichal Krawczyk BIT(ENA_ADMIN_DISABLE_META_CACHING)); 239633dde075SMichal Krawczyk } else { 239733dde075SMichal Krawczyk disable_meta_caching = false; 239833dde075SMichal Krawczyk } 239933dde075SMichal Krawczyk 24001173fca2SJan Medala /* prepare ring structures */ 240133dde075SMichal Krawczyk ena_init_rings(adapter, disable_meta_caching); 24021173fca2SJan Medala 2403372c1af5SJan Medala ena_config_debug_area(adapter); 2404372c1af5SJan Medala 24051173fca2SJan Medala /* Set max MTU for this device */ 24061173fca2SJan Medala adapter->max_mtu = get_feat_ctx.dev_attr.max_mtu; 24071173fca2SJan Medala 2408e8c838fdSMichal Krawczyk ena_set_offloads(&adapter->offloads, &get_feat_ctx.offload); 240983277a7cSJakub Palider 24101173fca2SJan Medala /* Copy MAC address and point DPDK to it */ 24116d13ea8eSOlivier Matz eth_dev->data->mac_addrs = (struct rte_ether_addr *)adapter->mac_addr; 2412538da7a1SOlivier Matz rte_ether_addr_copy((struct rte_ether_addr *) 2413538da7a1SOlivier Matz get_feat_ctx.dev_attr.mac_addr, 24146d13ea8eSOlivier Matz (struct rte_ether_addr *)adapter->mac_addr); 24151173fca2SJan Medala 241634d5e97eSMichal Krawczyk rc = ena_com_rss_init(ena_dev, ENA_RX_RSS_TABLE_LOG_SIZE); 241734d5e97eSMichal Krawczyk if (unlikely(rc != 0)) { 2418e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to initialize RSS in ENA device"); 241934d5e97eSMichal Krawczyk goto err_delete_debug_area; 242034d5e97eSMichal Krawczyk } 242134d5e97eSMichal Krawczyk 24221173fca2SJan Medala adapter->drv_stats = rte_zmalloc("adapter stats", 24231173fca2SJan Medala sizeof(*adapter->drv_stats), 24241173fca2SJan Medala RTE_CACHE_LINE_SIZE); 24251173fca2SJan Medala if (!adapter->drv_stats) { 2426e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 2427e99981afSDavid Marchand "Failed to allocate memory for adapter statistics"); 2428241da076SRafal Kozik rc = -ENOMEM; 242934d5e97eSMichal Krawczyk goto err_rss_destroy; 24301173fca2SJan Medala } 24311173fca2SJan Medala 24321343c415SMichal Krawczyk rte_spinlock_init(&adapter->admin_lock); 24331343c415SMichal Krawczyk 2434ca1dfa85SShai Brandes if (!adapter->control_path_poll_interval) { 2435ca1dfa85SShai Brandes /* Control path interrupt mode */ 2436ca1dfa85SShai Brandes rte_intr_callback_register(intr_handle, ena_control_path_handler, eth_dev); 2437eb0ef49dSMichal Krawczyk rte_intr_enable(intr_handle); 2438eb0ef49dSMichal Krawczyk ena_com_set_admin_polling_mode(ena_dev, false); 2439ca1dfa85SShai Brandes } else { 2440ca1dfa85SShai Brandes /* Control path polling mode */ 2441ca1dfa85SShai Brandes rc = rte_eal_alarm_set(adapter->control_path_poll_interval, 2442ca1dfa85SShai Brandes ena_control_path_poll_handler, eth_dev); 2443ca1dfa85SShai Brandes if (unlikely(rc != 0)) { 2444e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to set control path alarm"); 2445ca1dfa85SShai Brandes goto err_control_path_destroy; 2446ca1dfa85SShai Brandes } 2447ca1dfa85SShai Brandes } 2448ca148440SMichal Krawczyk ena_com_admin_aenq_enable(ena_dev); 2449d9b8b106SMichal Krawczyk rte_timer_init(&adapter->timer_wd); 2450d9b8b106SMichal Krawczyk 24511173fca2SJan Medala adapters_found++; 24521173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_INIT; 24531173fca2SJan Medala 24541173fca2SJan Medala return 0; 2455ca1dfa85SShai Brandes err_control_path_destroy: 2456ca1dfa85SShai Brandes rte_free(adapter->drv_stats); 245734d5e97eSMichal Krawczyk err_rss_destroy: 245834d5e97eSMichal Krawczyk ena_com_rss_destroy(ena_dev); 2459241da076SRafal Kozik err_delete_debug_area: 2460241da076SRafal Kozik ena_com_delete_debug_area(ena_dev); 2461241da076SRafal Kozik 2462241da076SRafal Kozik err_device_destroy: 2463241da076SRafal Kozik ena_com_delete_host_info(ena_dev); 2464241da076SRafal Kozik ena_com_admin_destroy(ena_dev); 246592401abfSShai Brandes err_metrics_delete: 246692401abfSShai Brandes ena_com_delete_customer_metrics_buffer(ena_dev); 2467241da076SRafal Kozik err: 2468241da076SRafal Kozik return rc; 24691173fca2SJan Medala } 24701173fca2SJan Medala 2471e457bc70SRafal Kozik static int eth_ena_dev_uninit(struct rte_eth_dev *eth_dev) 2472e457bc70SRafal Kozik { 2473e457bc70SRafal Kozik if (rte_eal_process_type() != RTE_PROC_PRIMARY) 2474e457bc70SRafal Kozik return 0; 2475e457bc70SRafal Kozik 24768af56083SShai Brandes ena_close(eth_dev); 2477e457bc70SRafal Kozik 2478eb0ef49dSMichal Krawczyk return 0; 2479eb0ef49dSMichal Krawczyk } 2480eb0ef49dSMichal Krawczyk 24811173fca2SJan Medala static int ena_dev_configure(struct rte_eth_dev *dev) 24821173fca2SJan Medala { 2483890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 2484b9b05d6fSMichal Krawczyk int rc; 24857369f88fSRafal Kozik 24861173fca2SJan Medala adapter->state = ENA_ADAPTER_STATE_CONFIG; 24871173fca2SJan Medala 2488295968d1SFerruh Yigit if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) 2489295968d1SFerruh Yigit dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 2490295968d1SFerruh Yigit dev->data->dev_conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 2491b418f0d2SMichal Krawczyk 2492e2a6d08bSMichal Krawczyk /* Scattered Rx cannot be turned off in the HW, so this capability must 2493e2a6d08bSMichal Krawczyk * be forced. 2494e2a6d08bSMichal Krawczyk */ 2495e2a6d08bSMichal Krawczyk dev->data->scattered_rx = 1; 2496e2a6d08bSMichal Krawczyk 2497f93e20e5SMichal Krawczyk adapter->last_tx_comp_qid = 0; 2498f93e20e5SMichal Krawczyk 2499f93e20e5SMichal Krawczyk adapter->missing_tx_completion_budget = 2500f93e20e5SMichal Krawczyk RTE_MIN(ENA_MONITORED_TX_QUEUES, dev->data->nb_tx_queues); 2501f93e20e5SMichal Krawczyk 2502f93e20e5SMichal Krawczyk /* To avoid detection of the spurious Tx completion timeout due to 2503f93e20e5SMichal Krawczyk * application not calling the Tx cleanup function, set timeout for the 2504f93e20e5SMichal Krawczyk * Tx queue which should be half of the missing completion timeout for a 2505f93e20e5SMichal Krawczyk * safety. If there will be a lot of missing Tx completions in the 2506f93e20e5SMichal Krawczyk * queue, they will be detected sooner or later. 2507f93e20e5SMichal Krawczyk */ 2508f93e20e5SMichal Krawczyk adapter->tx_cleanup_stall_delay = adapter->missing_tx_completion_to / 2; 2509f93e20e5SMichal Krawczyk 2510b9b05d6fSMichal Krawczyk rc = ena_configure_aenq(adapter); 2511b9b05d6fSMichal Krawczyk 2512b9b05d6fSMichal Krawczyk return rc; 25131173fca2SJan Medala } 25141173fca2SJan Medala 251533dde075SMichal Krawczyk static void ena_init_rings(struct ena_adapter *adapter, 251633dde075SMichal Krawczyk bool disable_meta_caching) 25171173fca2SJan Medala { 25185920d930SMichal Krawczyk size_t i; 25191173fca2SJan Medala 25205920d930SMichal Krawczyk for (i = 0; i < adapter->max_num_io_queues; i++) { 25211173fca2SJan Medala struct ena_ring *ring = &adapter->tx_ring[i]; 25221173fca2SJan Medala 25231173fca2SJan Medala ring->configured = 0; 25241173fca2SJan Medala ring->type = ENA_RING_TYPE_TX; 25251173fca2SJan Medala ring->adapter = adapter; 25261173fca2SJan Medala ring->id = i; 25271173fca2SJan Medala ring->tx_mem_queue_type = adapter->ena_dev.tx_mem_queue_type; 25281173fca2SJan Medala ring->tx_max_header_size = adapter->ena_dev.tx_max_header_size; 25292061fe41SRafal Kozik ring->sgl_size = adapter->max_tx_sgl_size; 253033dde075SMichal Krawczyk ring->disable_meta_caching = disable_meta_caching; 25311173fca2SJan Medala } 25321173fca2SJan Medala 25335920d930SMichal Krawczyk for (i = 0; i < adapter->max_num_io_queues; i++) { 25341173fca2SJan Medala struct ena_ring *ring = &adapter->rx_ring[i]; 25351173fca2SJan Medala 25361173fca2SJan Medala ring->configured = 0; 25371173fca2SJan Medala ring->type = ENA_RING_TYPE_RX; 25381173fca2SJan Medala ring->adapter = adapter; 25391173fca2SJan Medala ring->id = i; 2540ea93d37eSRafal Kozik ring->sgl_size = adapter->max_rx_sgl_size; 25411173fca2SJan Medala } 25421173fca2SJan Medala } 25431173fca2SJan Medala 25443a822d79SMichal Krawczyk static uint64_t ena_get_rx_port_offloads(struct ena_adapter *adapter) 25453a822d79SMichal Krawczyk { 25463a822d79SMichal Krawczyk uint64_t port_offloads = 0; 25473a822d79SMichal Krawczyk 25483a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & ENA_L3_IPV4_CSUM) 2549295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM; 25503a822d79SMichal Krawczyk 25513a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & 25523a822d79SMichal Krawczyk (ENA_L4_IPV4_CSUM | ENA_L4_IPV6_CSUM)) 25533a822d79SMichal Krawczyk port_offloads |= 2554295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM; 25553a822d79SMichal Krawczyk 25563a822d79SMichal Krawczyk if (adapter->offloads.rx_offloads & ENA_RX_RSS_HASH) 2557295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 25583a822d79SMichal Krawczyk 2559295968d1SFerruh Yigit port_offloads |= RTE_ETH_RX_OFFLOAD_SCATTER; 2560e2a6d08bSMichal Krawczyk 25613a822d79SMichal Krawczyk return port_offloads; 25623a822d79SMichal Krawczyk } 25633a822d79SMichal Krawczyk 25643a822d79SMichal Krawczyk static uint64_t ena_get_tx_port_offloads(struct ena_adapter *adapter) 25653a822d79SMichal Krawczyk { 25663a822d79SMichal Krawczyk uint64_t port_offloads = 0; 25673a822d79SMichal Krawczyk 25683a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & ENA_IPV4_TSO) 2569295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO; 25703a822d79SMichal Krawczyk 25713a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & ENA_L3_IPV4_CSUM) 2572295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM; 25733a822d79SMichal Krawczyk if (adapter->offloads.tx_offloads & 25743a822d79SMichal Krawczyk (ENA_L4_IPV4_CSUM_PARTIAL | ENA_L4_IPV4_CSUM | 25753a822d79SMichal Krawczyk ENA_L4_IPV6_CSUM | ENA_L4_IPV6_CSUM_PARTIAL)) 25763a822d79SMichal Krawczyk port_offloads |= 2577295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_UDP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_CKSUM; 25783a822d79SMichal Krawczyk 2579295968d1SFerruh Yigit port_offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 25803a822d79SMichal Krawczyk 2581c339f538SDawid Gorecki port_offloads |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 2582c339f538SDawid Gorecki 25833a822d79SMichal Krawczyk return port_offloads; 25843a822d79SMichal Krawczyk } 25853a822d79SMichal Krawczyk 25863a822d79SMichal Krawczyk static uint64_t ena_get_rx_queue_offloads(struct ena_adapter *adapter) 25873a822d79SMichal Krawczyk { 25883a822d79SMichal Krawczyk RTE_SET_USED(adapter); 25893a822d79SMichal Krawczyk 25903a822d79SMichal Krawczyk return 0; 25913a822d79SMichal Krawczyk } 25923a822d79SMichal Krawczyk 25933a822d79SMichal Krawczyk static uint64_t ena_get_tx_queue_offloads(struct ena_adapter *adapter) 25943a822d79SMichal Krawczyk { 2595c339f538SDawid Gorecki uint64_t queue_offloads = 0; 25963a822d79SMichal Krawczyk RTE_SET_USED(adapter); 25973a822d79SMichal Krawczyk 2598c339f538SDawid Gorecki queue_offloads |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 2599c339f538SDawid Gorecki 2600c339f538SDawid Gorecki return queue_offloads; 26013a822d79SMichal Krawczyk } 26023a822d79SMichal Krawczyk 2603bdad90d1SIvan Ilchenko static int ena_infos_get(struct rte_eth_dev *dev, 26041173fca2SJan Medala struct rte_eth_dev_info *dev_info) 26051173fca2SJan Medala { 26061173fca2SJan Medala struct ena_adapter *adapter; 26071173fca2SJan Medala struct ena_com_dev *ena_dev; 26081173fca2SJan Medala 2609498c687aSRafal Kozik ena_assert_msg(dev->data != NULL, "Uninitialized device\n"); 2610498c687aSRafal Kozik ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device\n"); 2611890728ffSStephen Hemminger adapter = dev->data->dev_private; 26121173fca2SJan Medala 26131173fca2SJan Medala ena_dev = &adapter->ena_dev; 2614498c687aSRafal Kozik ena_assert_msg(ena_dev != NULL, "Uninitialized device\n"); 26151173fca2SJan Medala 2616e274f573SMarc Sune dev_info->speed_capa = 2617295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_1G | 2618295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_2_5G | 2619295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_5G | 2620295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_10G | 2621295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_25G | 2622295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_40G | 2623295968d1SFerruh Yigit RTE_ETH_LINK_SPEED_50G | 26244ebe5efaSShai Brandes RTE_ETH_LINK_SPEED_100G | 26254ebe5efaSShai Brandes RTE_ETH_LINK_SPEED_200G | 26264ebe5efaSShai Brandes RTE_ETH_LINK_SPEED_400G; 2627e274f573SMarc Sune 26281173fca2SJan Medala /* Inform framework about available features */ 26293a822d79SMichal Krawczyk dev_info->rx_offload_capa = ena_get_rx_port_offloads(adapter); 26303a822d79SMichal Krawczyk dev_info->tx_offload_capa = ena_get_tx_port_offloads(adapter); 26313a822d79SMichal Krawczyk dev_info->rx_queue_offload_capa = ena_get_rx_queue_offloads(adapter); 26323a822d79SMichal Krawczyk dev_info->tx_queue_offload_capa = ena_get_tx_queue_offloads(adapter); 26331173fca2SJan Medala 263434d5e97eSMichal Krawczyk dev_info->flow_type_rss_offloads = ENA_ALL_RSS_HF; 263534d5e97eSMichal Krawczyk dev_info->hash_key_size = ENA_HASH_KEY_SIZE; 2636b01ead20SRafal Kozik 26371173fca2SJan Medala dev_info->min_rx_bufsize = ENA_MIN_FRAME_LEN; 26381bb4a528SFerruh Yigit dev_info->max_rx_pktlen = adapter->max_mtu + RTE_ETHER_HDR_LEN + 26391bb4a528SFerruh Yigit RTE_ETHER_CRC_LEN; 26401bb4a528SFerruh Yigit dev_info->min_mtu = ENA_MIN_MTU; 26411bb4a528SFerruh Yigit dev_info->max_mtu = adapter->max_mtu; 26421173fca2SJan Medala dev_info->max_mac_addrs = 1; 26431173fca2SJan Medala 26445920d930SMichal Krawczyk dev_info->max_rx_queues = adapter->max_num_io_queues; 26455920d930SMichal Krawczyk dev_info->max_tx_queues = adapter->max_num_io_queues; 26461173fca2SJan Medala dev_info->reta_size = ENA_RX_RSS_TABLE_SIZE; 264756b8b9b7SRafal Kozik 26485920d930SMichal Krawczyk dev_info->rx_desc_lim.nb_max = adapter->max_rx_ring_size; 264992680dc2SRafal Kozik dev_info->rx_desc_lim.nb_min = ENA_MIN_RING_DESC; 2650ea93d37eSRafal Kozik dev_info->rx_desc_lim.nb_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2651ea93d37eSRafal Kozik adapter->max_rx_sgl_size); 2652ea93d37eSRafal Kozik dev_info->rx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2653ea93d37eSRafal Kozik adapter->max_rx_sgl_size); 265492680dc2SRafal Kozik 26555920d930SMichal Krawczyk dev_info->tx_desc_lim.nb_max = adapter->max_tx_ring_size; 265692680dc2SRafal Kozik dev_info->tx_desc_lim.nb_min = ENA_MIN_RING_DESC; 265792680dc2SRafal Kozik dev_info->tx_desc_lim.nb_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2658ea93d37eSRafal Kozik adapter->max_tx_sgl_size); 265992680dc2SRafal Kozik dev_info->tx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS, 2660ea93d37eSRafal Kozik adapter->max_tx_sgl_size); 2661bdad90d1SIvan Ilchenko 266296fc5e08SShai Brandes dev_info->default_rxportconf.ring_size = RTE_MIN(ENA_DEFAULT_RING_SIZE, 266396fc5e08SShai Brandes dev_info->rx_desc_lim.nb_max); 266496fc5e08SShai Brandes dev_info->default_txportconf.ring_size = RTE_MIN(ENA_DEFAULT_RING_SIZE, 266596fc5e08SShai Brandes dev_info->tx_desc_lim.nb_max); 266630a6c7efSStanislaw Kardach 26670d5c38baSChengwen Feng dev_info->err_handle_mode = RTE_ETH_ERROR_HANDLE_MODE_PASSIVE; 26680d5c38baSChengwen Feng 2669bdad90d1SIvan Ilchenko return 0; 26701173fca2SJan Medala } 26711173fca2SJan Medala 26721be097dcSMichal Krawczyk static inline void ena_init_rx_mbuf(struct rte_mbuf *mbuf, uint16_t len) 26731be097dcSMichal Krawczyk { 26741be097dcSMichal Krawczyk mbuf->data_len = len; 26751be097dcSMichal Krawczyk mbuf->data_off = RTE_PKTMBUF_HEADROOM; 26761be097dcSMichal Krawczyk mbuf->refcnt = 1; 26771be097dcSMichal Krawczyk mbuf->next = NULL; 26781be097dcSMichal Krawczyk } 26791be097dcSMichal Krawczyk 26801be097dcSMichal Krawczyk static struct rte_mbuf *ena_rx_mbuf(struct ena_ring *rx_ring, 26811be097dcSMichal Krawczyk struct ena_com_rx_buf_info *ena_bufs, 26821be097dcSMichal Krawczyk uint32_t descs, 26831be097dcSMichal Krawczyk uint16_t *next_to_clean, 26841be097dcSMichal Krawczyk uint8_t offset) 26851be097dcSMichal Krawczyk { 26861be097dcSMichal Krawczyk struct rte_mbuf *mbuf; 26871be097dcSMichal Krawczyk struct rte_mbuf *mbuf_head; 26881be097dcSMichal Krawczyk struct ena_rx_buffer *rx_info; 268983fd97b2SMichal Krawczyk int rc; 26901be097dcSMichal Krawczyk uint16_t ntc, len, req_id, buf = 0; 26911be097dcSMichal Krawczyk 26921be097dcSMichal Krawczyk if (unlikely(descs == 0)) 26931be097dcSMichal Krawczyk return NULL; 26941be097dcSMichal Krawczyk 26951be097dcSMichal Krawczyk ntc = *next_to_clean; 26961be097dcSMichal Krawczyk 26971be097dcSMichal Krawczyk len = ena_bufs[buf].len; 26981be097dcSMichal Krawczyk req_id = ena_bufs[buf].req_id; 26991be097dcSMichal Krawczyk 27001be097dcSMichal Krawczyk rx_info = &rx_ring->rx_buffer_info[req_id]; 27011be097dcSMichal Krawczyk 27021be097dcSMichal Krawczyk mbuf = rx_info->mbuf; 27031be097dcSMichal Krawczyk RTE_ASSERT(mbuf != NULL); 27041be097dcSMichal Krawczyk 27051be097dcSMichal Krawczyk ena_init_rx_mbuf(mbuf, len); 27061be097dcSMichal Krawczyk 27071be097dcSMichal Krawczyk /* Fill the mbuf head with the data specific for 1st segment. */ 27081be097dcSMichal Krawczyk mbuf_head = mbuf; 27091be097dcSMichal Krawczyk mbuf_head->nb_segs = descs; 27101be097dcSMichal Krawczyk mbuf_head->port = rx_ring->port_id; 27111be097dcSMichal Krawczyk mbuf_head->pkt_len = len; 27121be097dcSMichal Krawczyk mbuf_head->data_off += offset; 27131be097dcSMichal Krawczyk 27141be097dcSMichal Krawczyk rx_info->mbuf = NULL; 2715c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[ntc] = req_id; 2716c0006061SMichal Krawczyk ntc = ENA_IDX_NEXT_MASKED(ntc, rx_ring->size_mask); 27171be097dcSMichal Krawczyk 27181be097dcSMichal Krawczyk while (--descs) { 27191be097dcSMichal Krawczyk ++buf; 27201be097dcSMichal Krawczyk len = ena_bufs[buf].len; 27211be097dcSMichal Krawczyk req_id = ena_bufs[buf].req_id; 27221be097dcSMichal Krawczyk 27231be097dcSMichal Krawczyk rx_info = &rx_ring->rx_buffer_info[req_id]; 27241be097dcSMichal Krawczyk RTE_ASSERT(rx_info->mbuf != NULL); 27251be097dcSMichal Krawczyk 272683fd97b2SMichal Krawczyk if (unlikely(len == 0)) { 272783fd97b2SMichal Krawczyk /* 272883fd97b2SMichal Krawczyk * Some devices can pass descriptor with the length 0. 272983fd97b2SMichal Krawczyk * To avoid confusion, the PMD is simply putting the 273083fd97b2SMichal Krawczyk * descriptor back, as it was never used. We'll avoid 273183fd97b2SMichal Krawczyk * mbuf allocation that way. 273283fd97b2SMichal Krawczyk */ 273383fd97b2SMichal Krawczyk rc = ena_add_single_rx_desc(rx_ring->ena_com_io_sq, 273483fd97b2SMichal Krawczyk rx_info->mbuf, req_id); 273583fd97b2SMichal Krawczyk if (unlikely(rc != 0)) { 273683fd97b2SMichal Krawczyk /* Free the mbuf in case of an error. */ 273783fd97b2SMichal Krawczyk rte_mbuf_raw_free(rx_info->mbuf); 273883fd97b2SMichal Krawczyk } else { 273983fd97b2SMichal Krawczyk /* 274083fd97b2SMichal Krawczyk * If there was no error, just exit the loop as 274183fd97b2SMichal Krawczyk * 0 length descriptor is always the last one. 274283fd97b2SMichal Krawczyk */ 274383fd97b2SMichal Krawczyk break; 274483fd97b2SMichal Krawczyk } 274583fd97b2SMichal Krawczyk } else { 27461be097dcSMichal Krawczyk /* Create an mbuf chain. */ 27471be097dcSMichal Krawczyk mbuf->next = rx_info->mbuf; 27481be097dcSMichal Krawczyk mbuf = mbuf->next; 27491be097dcSMichal Krawczyk 27501be097dcSMichal Krawczyk ena_init_rx_mbuf(mbuf, len); 27511be097dcSMichal Krawczyk mbuf_head->pkt_len += len; 275283fd97b2SMichal Krawczyk } 27531be097dcSMichal Krawczyk 275483fd97b2SMichal Krawczyk /* 275583fd97b2SMichal Krawczyk * Mark the descriptor as depleted and perform necessary 275683fd97b2SMichal Krawczyk * cleanup. 275783fd97b2SMichal Krawczyk * This code will execute in two cases: 275883fd97b2SMichal Krawczyk * 1. Descriptor len was greater than 0 - normal situation. 275983fd97b2SMichal Krawczyk * 2. Descriptor len was 0 and we failed to add the descriptor 276083fd97b2SMichal Krawczyk * to the device. In that situation, we should try to add 276183fd97b2SMichal Krawczyk * the mbuf again in the populate routine and mark the 276283fd97b2SMichal Krawczyk * descriptor as used up by the device. 276383fd97b2SMichal Krawczyk */ 27641be097dcSMichal Krawczyk rx_info->mbuf = NULL; 2765c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[ntc] = req_id; 2766c0006061SMichal Krawczyk ntc = ENA_IDX_NEXT_MASKED(ntc, rx_ring->size_mask); 27671be097dcSMichal Krawczyk } 27681be097dcSMichal Krawczyk 27691be097dcSMichal Krawczyk *next_to_clean = ntc; 27701be097dcSMichal Krawczyk 27711be097dcSMichal Krawczyk return mbuf_head; 27721be097dcSMichal Krawczyk } 27731be097dcSMichal Krawczyk 27741173fca2SJan Medala static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, 27751173fca2SJan Medala uint16_t nb_pkts) 27761173fca2SJan Medala { 27771173fca2SJan Medala struct ena_ring *rx_ring = (struct ena_ring *)(rx_queue); 277877550607SMichal Krawczyk unsigned int free_queue_entries; 27791173fca2SJan Medala uint16_t next_to_clean = rx_ring->next_to_clean; 27807a166990SShai Brandes enum ena_regs_reset_reason_types reset_reason; 278174456796SMichal Krawczyk uint16_t descs_in_use; 27821be097dcSMichal Krawczyk struct rte_mbuf *mbuf; 27831be097dcSMichal Krawczyk uint16_t completed; 27841173fca2SJan Medala struct ena_com_rx_ctx ena_rx_ctx; 27851be097dcSMichal Krawczyk int i, rc = 0; 27861173fca2SJan Medala 27870a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 27881173fca2SJan Medala /* Check adapter state */ 27891173fca2SJan Medala if (unlikely(rx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) { 2790e99981afSDavid Marchand PMD_RX_LOG_LINE(ALERT, 2791e99981afSDavid Marchand "Trying to receive pkts while device is NOT running"); 27921173fca2SJan Medala return 0; 27931173fca2SJan Medala } 27940a001d69SMichal Krawczyk #endif 27951173fca2SJan Medala 2796c0006061SMichal Krawczyk descs_in_use = rx_ring->ring_size - 279774456796SMichal Krawczyk ena_com_free_q_entries(rx_ring->ena_com_io_sq) - 1; 279874456796SMichal Krawczyk nb_pkts = RTE_MIN(descs_in_use, nb_pkts); 27991173fca2SJan Medala 28001173fca2SJan Medala for (completed = 0; completed < nb_pkts; completed++) { 2801ea93d37eSRafal Kozik ena_rx_ctx.max_bufs = rx_ring->sgl_size; 28021173fca2SJan Medala ena_rx_ctx.ena_bufs = rx_ring->ena_bufs; 28031173fca2SJan Medala ena_rx_ctx.descs = 0; 28047b3a3c4bSMaciej Bielski ena_rx_ctx.pkt_offset = 0; 28051173fca2SJan Medala /* receive packet context */ 28061173fca2SJan Medala rc = ena_com_rx_pkt(rx_ring->ena_com_io_cq, 28071173fca2SJan Medala rx_ring->ena_com_io_sq, 28081173fca2SJan Medala &ena_rx_ctx); 28091173fca2SJan Medala if (unlikely(rc)) { 2810e99981afSDavid Marchand PMD_RX_LOG_LINE(ERR, 2811e99981afSDavid Marchand "Failed to get the packet from the device, rc: %d", 2812617898d1SMichal Krawczyk rc); 28137a166990SShai Brandes switch (rc) { 28147a166990SShai Brandes case ENA_COM_NO_SPACE: 281505cffdcfSMichal Krawczyk ++rx_ring->rx_stats.bad_desc_num; 28167a166990SShai Brandes reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS; 28177a166990SShai Brandes break; 28187a166990SShai Brandes case ENA_COM_FAULT: 28197a166990SShai Brandes ++rx_ring->rx_stats.bad_desc; 28207a166990SShai Brandes reset_reason = ENA_REGS_RESET_RX_DESCRIPTOR_MALFORMED; 28217a166990SShai Brandes break; 28227a166990SShai Brandes case ENA_COM_EIO: 282305cffdcfSMichal Krawczyk ++rx_ring->rx_stats.bad_req_id; 28247a166990SShai Brandes reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID; 28257a166990SShai Brandes break; 28267a166990SShai Brandes default: 28277a166990SShai Brandes ++rx_ring->rx_stats.unknown_error; 28287a166990SShai Brandes reset_reason = ENA_REGS_RESET_DRIVER_INVALID_STATE; 28297a166990SShai Brandes break; 283005cffdcfSMichal Krawczyk } 28317a166990SShai Brandes ena_trigger_reset(rx_ring->adapter, reset_reason); 28321173fca2SJan Medala return 0; 28331173fca2SJan Medala } 28341173fca2SJan Medala 28351be097dcSMichal Krawczyk mbuf = ena_rx_mbuf(rx_ring, 28361be097dcSMichal Krawczyk ena_rx_ctx.ena_bufs, 28371be097dcSMichal Krawczyk ena_rx_ctx.descs, 28381be097dcSMichal Krawczyk &next_to_clean, 28391be097dcSMichal Krawczyk ena_rx_ctx.pkt_offset); 28401be097dcSMichal Krawczyk if (unlikely(mbuf == NULL)) { 28411be097dcSMichal Krawczyk for (i = 0; i < ena_rx_ctx.descs; ++i) { 2842c0006061SMichal Krawczyk rx_ring->empty_rx_reqs[next_to_clean] = 28431be097dcSMichal Krawczyk rx_ring->ena_bufs[i].req_id; 2844c0006061SMichal Krawczyk next_to_clean = ENA_IDX_NEXT_MASKED( 2845c0006061SMichal Krawczyk next_to_clean, rx_ring->size_mask); 28461173fca2SJan Medala } 2847f00930d9SRafal Kozik break; 28481be097dcSMichal Krawczyk } 28491173fca2SJan Medala 28501173fca2SJan Medala /* fill mbuf attributes if any */ 28515ac1749fSShai Brandes ena_rx_mbuf_prepare(rx_ring, mbuf, &ena_rx_ctx); 28527830e905SSolganik Alexander 28531be097dcSMichal Krawczyk if (unlikely(mbuf->ol_flags & 285484daba99SMichal Krawczyk (RTE_MBUF_F_RX_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD))) 2855ef74b5f7SMichal Krawczyk rte_atomic64_inc(&rx_ring->adapter->drv_stats->ierrors); 28567830e905SSolganik Alexander 28571be097dcSMichal Krawczyk rx_pkts[completed] = mbuf; 28581be097dcSMichal Krawczyk rx_ring->rx_stats.bytes += mbuf->pkt_len; 28591173fca2SJan Medala } 28601173fca2SJan Medala 28611be097dcSMichal Krawczyk rx_ring->rx_stats.cnt += completed; 2862ec78af6bSMichal Krawczyk rx_ring->next_to_clean = next_to_clean; 2863ec78af6bSMichal Krawczyk 286477550607SMichal Krawczyk free_queue_entries = ena_com_free_q_entries(rx_ring->ena_com_io_sq); 286577550607SMichal Krawczyk 28661173fca2SJan Medala /* Burst refill to save doorbells, memory barriers, const interval */ 2867005064e5SMichal Krawczyk if (free_queue_entries >= rx_ring->rx_free_thresh) { 286877550607SMichal Krawczyk ena_populate_rx_queue(rx_ring, free_queue_entries); 2869a45462c5SRafal Kozik } 28701173fca2SJan Medala 28711be097dcSMichal Krawczyk return completed; 28721173fca2SJan Medala } 28731173fca2SJan Medala 2874b3fc5a1aSKonstantin Ananyev static uint16_t 287583277a7cSJakub Palider eth_ena_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 2876b3fc5a1aSKonstantin Ananyev uint16_t nb_pkts) 2877b3fc5a1aSKonstantin Ananyev { 2878b3fc5a1aSKonstantin Ananyev int32_t ret; 2879b3fc5a1aSKonstantin Ananyev uint32_t i; 2880b3fc5a1aSKonstantin Ananyev struct rte_mbuf *m; 288183277a7cSJakub Palider struct ena_ring *tx_ring = (struct ena_ring *)(tx_queue); 2882e8c838fdSMichal Krawczyk struct ena_adapter *adapter = tx_ring->adapter; 2883a7c528e5SOlivier Matz struct rte_ipv4_hdr *ip_hdr; 2884b3fc5a1aSKonstantin Ananyev uint64_t ol_flags; 2885e8c838fdSMichal Krawczyk uint64_t l4_csum_flag; 2886e8c838fdSMichal Krawczyk uint64_t dev_offload_capa; 288783277a7cSJakub Palider uint16_t frag_field; 2888e8c838fdSMichal Krawczyk bool need_pseudo_csum; 288983277a7cSJakub Palider 2890e8c838fdSMichal Krawczyk dev_offload_capa = adapter->offloads.tx_offloads; 2891b3fc5a1aSKonstantin Ananyev for (i = 0; i != nb_pkts; i++) { 2892b3fc5a1aSKonstantin Ananyev m = tx_pkts[i]; 2893b3fc5a1aSKonstantin Ananyev ol_flags = m->ol_flags; 2894b3fc5a1aSKonstantin Ananyev 2895e8c838fdSMichal Krawczyk /* Check if any offload flag was set */ 2896e8c838fdSMichal Krawczyk if (ol_flags == 0) 2897bc5ef57dSMichal Krawczyk continue; 2898bc5ef57dSMichal Krawczyk 2899daa02b5cSOlivier Matz l4_csum_flag = ol_flags & RTE_MBUF_F_TX_L4_MASK; 2900e8c838fdSMichal Krawczyk /* SCTP checksum offload is not supported by the ENA. */ 2901e8c838fdSMichal Krawczyk if ((ol_flags & ENA_TX_OFFLOAD_NOTSUP_MASK) || 2902daa02b5cSOlivier Matz l4_csum_flag == RTE_MBUF_F_TX_SCTP_CKSUM) { 2903e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, 2904e99981afSDavid Marchand "mbuf[%" PRIu32 "] has unsupported offloads flags set: 0x%" PRIu64, 2905e8c838fdSMichal Krawczyk i, ol_flags); 2906baeed5f4SMichal Krawczyk rte_errno = ENOTSUP; 2907b3fc5a1aSKonstantin Ananyev return i; 2908b3fc5a1aSKonstantin Ananyev } 2909b3fc5a1aSKonstantin Ananyev 291096ffa8a7SMichal Krawczyk if (unlikely(m->nb_segs >= tx_ring->sgl_size && 291196ffa8a7SMichal Krawczyk !(tx_ring->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV && 291296ffa8a7SMichal Krawczyk m->nb_segs == tx_ring->sgl_size && 291396ffa8a7SMichal Krawczyk m->data_len < tx_ring->tx_max_header_size))) { 2914e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, 2915e99981afSDavid Marchand "mbuf[%" PRIu32 "] has too many segments: %" PRIu16, 291696ffa8a7SMichal Krawczyk i, m->nb_segs); 291796ffa8a7SMichal Krawczyk rte_errno = EINVAL; 291896ffa8a7SMichal Krawczyk return i; 291996ffa8a7SMichal Krawczyk } 292096ffa8a7SMichal Krawczyk 2921b3fc5a1aSKonstantin Ananyev #ifdef RTE_LIBRTE_ETHDEV_DEBUG 2922e8c838fdSMichal Krawczyk /* Check if requested offload is also enabled for the queue */ 2923daa02b5cSOlivier Matz if ((ol_flags & RTE_MBUF_F_TX_IP_CKSUM && 2924295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) || 2925daa02b5cSOlivier Matz (l4_csum_flag == RTE_MBUF_F_TX_TCP_CKSUM && 2926295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) || 2927daa02b5cSOlivier Matz (l4_csum_flag == RTE_MBUF_F_TX_UDP_CKSUM && 2928295968d1SFerruh Yigit !(tx_ring->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM))) { 2929e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, 2930e99981afSDavid Marchand "mbuf[%" PRIu32 "]: requested offloads: %" PRIu16 " are not enabled for the queue[%u]", 2931e8c838fdSMichal Krawczyk i, m->nb_segs, tx_ring->id); 2932e8c838fdSMichal Krawczyk rte_errno = EINVAL; 2933e8c838fdSMichal Krawczyk return i; 2934e8c838fdSMichal Krawczyk } 2935e8c838fdSMichal Krawczyk 2936e8c838fdSMichal Krawczyk /* The caller is obligated to set l2 and l3 len if any cksum 2937e8c838fdSMichal Krawczyk * offload is enabled. 2938e8c838fdSMichal Krawczyk */ 2939daa02b5cSOlivier Matz if (unlikely(ol_flags & (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_L4_MASK) && 2940e8c838fdSMichal Krawczyk (m->l2_len == 0 || m->l3_len == 0))) { 2941e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, 2942e99981afSDavid Marchand "mbuf[%" PRIu32 "]: l2_len or l3_len values are 0 while the offload was requested", 2943e8c838fdSMichal Krawczyk i); 2944e8c838fdSMichal Krawczyk rte_errno = EINVAL; 2945e8c838fdSMichal Krawczyk return i; 2946e8c838fdSMichal Krawczyk } 2947b3fc5a1aSKonstantin Ananyev ret = rte_validate_tx_offload(m); 2948b3fc5a1aSKonstantin Ananyev if (ret != 0) { 2949baeed5f4SMichal Krawczyk rte_errno = -ret; 2950b3fc5a1aSKonstantin Ananyev return i; 2951b3fc5a1aSKonstantin Ananyev } 2952b3fc5a1aSKonstantin Ananyev #endif 295383277a7cSJakub Palider 2954e8c838fdSMichal Krawczyk /* Verify HW support for requested offloads and determine if 2955e8c838fdSMichal Krawczyk * pseudo header checksum is needed. 295683277a7cSJakub Palider */ 2957e8c838fdSMichal Krawczyk need_pseudo_csum = false; 2958daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_IPV4) { 2959daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM && 2960e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L3_IPV4_CSUM)) { 2961e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2962e8c838fdSMichal Krawczyk return i; 2963e8c838fdSMichal Krawczyk } 296483277a7cSJakub Palider 2965daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_TCP_SEG && 2966e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_IPV4_TSO)) { 2967e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2968e8c838fdSMichal Krawczyk return i; 2969e8c838fdSMichal Krawczyk } 2970e8c838fdSMichal Krawczyk 2971e8c838fdSMichal Krawczyk /* Check HW capabilities and if pseudo csum is needed 2972e8c838fdSMichal Krawczyk * for L4 offloads. 2973e8c838fdSMichal Krawczyk */ 2974daa02b5cSOlivier Matz if (l4_csum_flag != RTE_MBUF_F_TX_L4_NO_CKSUM && 2975e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L4_IPV4_CSUM)) { 2976e8c838fdSMichal Krawczyk if (dev_offload_capa & 2977e8c838fdSMichal Krawczyk ENA_L4_IPV4_CSUM_PARTIAL) { 2978e8c838fdSMichal Krawczyk need_pseudo_csum = true; 2979e8c838fdSMichal Krawczyk } else { 2980e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 2981e8c838fdSMichal Krawczyk return i; 2982e8c838fdSMichal Krawczyk } 2983e8c838fdSMichal Krawczyk } 2984e8c838fdSMichal Krawczyk 2985e8c838fdSMichal Krawczyk /* Parse the DF flag */ 2986e8c838fdSMichal Krawczyk ip_hdr = rte_pktmbuf_mtod_offset(m, 2987e8c838fdSMichal Krawczyk struct rte_ipv4_hdr *, m->l2_len); 2988e8c838fdSMichal Krawczyk frag_field = rte_be_to_cpu_16(ip_hdr->fragment_offset); 2989e8c838fdSMichal Krawczyk if (frag_field & RTE_IPV4_HDR_DF_FLAG) { 2990e8c838fdSMichal Krawczyk m->packet_type |= RTE_PTYPE_L4_NONFRAG; 2991daa02b5cSOlivier Matz } else if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 2992e8c838fdSMichal Krawczyk /* In case we are supposed to TSO and have DF 2993e8c838fdSMichal Krawczyk * not set (DF=0) hardware must be provided with 2994e8c838fdSMichal Krawczyk * partial checksum. 2995e8c838fdSMichal Krawczyk */ 2996e8c838fdSMichal Krawczyk need_pseudo_csum = true; 2997e8c838fdSMichal Krawczyk } 2998daa02b5cSOlivier Matz } else if (ol_flags & RTE_MBUF_F_TX_IPV6) { 2999e8c838fdSMichal Krawczyk /* There is no support for IPv6 TSO as for now. */ 3000daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) { 3001e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 3002e8c838fdSMichal Krawczyk return i; 3003e8c838fdSMichal Krawczyk } 3004e8c838fdSMichal Krawczyk 3005e8c838fdSMichal Krawczyk /* Check HW capabilities and if pseudo csum is needed */ 3006daa02b5cSOlivier Matz if (l4_csum_flag != RTE_MBUF_F_TX_L4_NO_CKSUM && 3007e8c838fdSMichal Krawczyk !(dev_offload_capa & ENA_L4_IPV6_CSUM)) { 3008e8c838fdSMichal Krawczyk if (dev_offload_capa & 3009e8c838fdSMichal Krawczyk ENA_L4_IPV6_CSUM_PARTIAL) { 3010e8c838fdSMichal Krawczyk need_pseudo_csum = true; 3011e8c838fdSMichal Krawczyk } else { 3012e8c838fdSMichal Krawczyk rte_errno = ENOTSUP; 3013e8c838fdSMichal Krawczyk return i; 3014e8c838fdSMichal Krawczyk } 3015e8c838fdSMichal Krawczyk } 3016e8c838fdSMichal Krawczyk } 3017e8c838fdSMichal Krawczyk 3018e8c838fdSMichal Krawczyk if (need_pseudo_csum) { 3019e8c838fdSMichal Krawczyk ret = rte_net_intel_cksum_flags_prepare(m, ol_flags); 3020b3fc5a1aSKonstantin Ananyev if (ret != 0) { 3021baeed5f4SMichal Krawczyk rte_errno = -ret; 3022b3fc5a1aSKonstantin Ananyev return i; 3023b3fc5a1aSKonstantin Ananyev } 3024b3fc5a1aSKonstantin Ananyev } 3025e8c838fdSMichal Krawczyk } 3026b3fc5a1aSKonstantin Ananyev 3027b3fc5a1aSKonstantin Ananyev return i; 3028b3fc5a1aSKonstantin Ananyev } 3029b3fc5a1aSKonstantin Ananyev 3030f01f060cSRafal Kozik static void ena_update_hints(struct ena_adapter *adapter, 3031f01f060cSRafal Kozik struct ena_admin_ena_hw_hints *hints) 3032f01f060cSRafal Kozik { 3033f01f060cSRafal Kozik if (hints->admin_completion_tx_timeout) 3034f01f060cSRafal Kozik adapter->ena_dev.admin_queue.completion_timeout = 3035f01f060cSRafal Kozik hints->admin_completion_tx_timeout * 1000; 3036f01f060cSRafal Kozik 3037f01f060cSRafal Kozik if (hints->mmio_read_timeout) 3038f01f060cSRafal Kozik /* convert to usec */ 3039f01f060cSRafal Kozik adapter->ena_dev.mmio_read.reg_read_to = 3040f01f060cSRafal Kozik hints->mmio_read_timeout * 1000; 3041d9b8b106SMichal Krawczyk 3042d9b8b106SMichal Krawczyk if (hints->driver_watchdog_timeout) { 3043d9b8b106SMichal Krawczyk if (hints->driver_watchdog_timeout == ENA_HW_HINTS_NO_TIMEOUT) 3044d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = ENA_HW_HINTS_NO_TIMEOUT; 3045d9b8b106SMichal Krawczyk else 3046d9b8b106SMichal Krawczyk // Convert msecs to ticks 3047d9b8b106SMichal Krawczyk adapter->keep_alive_timeout = 3048d9b8b106SMichal Krawczyk (hints->driver_watchdog_timeout * 3049d9b8b106SMichal Krawczyk rte_get_timer_hz()) / 1000; 3050d9b8b106SMichal Krawczyk } 3051f01f060cSRafal Kozik } 3052f01f060cSRafal Kozik 305336278b82SMichal Krawczyk static void ena_tx_map_mbuf(struct ena_ring *tx_ring, 305436278b82SMichal Krawczyk struct ena_tx_buffer *tx_info, 305536278b82SMichal Krawczyk struct rte_mbuf *mbuf, 305636278b82SMichal Krawczyk void **push_header, 305736278b82SMichal Krawczyk uint16_t *header_len) 305836278b82SMichal Krawczyk { 305936278b82SMichal Krawczyk struct ena_com_buf *ena_buf; 306036278b82SMichal Krawczyk uint16_t delta, seg_len, push_len; 306136278b82SMichal Krawczyk 306236278b82SMichal Krawczyk delta = 0; 306336278b82SMichal Krawczyk seg_len = mbuf->data_len; 306436278b82SMichal Krawczyk 306536278b82SMichal Krawczyk tx_info->mbuf = mbuf; 306636278b82SMichal Krawczyk ena_buf = tx_info->bufs; 306736278b82SMichal Krawczyk 306836278b82SMichal Krawczyk if (tx_ring->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 306936278b82SMichal Krawczyk /* 307036278b82SMichal Krawczyk * Tx header might be (and will be in most cases) smaller than 307136278b82SMichal Krawczyk * tx_max_header_size. But it's not an issue to send more data 307236278b82SMichal Krawczyk * to the device, than actually needed if the mbuf size is 307336278b82SMichal Krawczyk * greater than tx_max_header_size. 307436278b82SMichal Krawczyk */ 307536278b82SMichal Krawczyk push_len = RTE_MIN(mbuf->pkt_len, tx_ring->tx_max_header_size); 307636278b82SMichal Krawczyk *header_len = push_len; 307736278b82SMichal Krawczyk 307836278b82SMichal Krawczyk if (likely(push_len <= seg_len)) { 307936278b82SMichal Krawczyk /* If the push header is in the single segment, then 308036278b82SMichal Krawczyk * just point it to the 1st mbuf data. 308136278b82SMichal Krawczyk */ 308236278b82SMichal Krawczyk *push_header = rte_pktmbuf_mtod(mbuf, uint8_t *); 308336278b82SMichal Krawczyk } else { 308436278b82SMichal Krawczyk /* If the push header lays in the several segments, copy 308536278b82SMichal Krawczyk * it to the intermediate buffer. 308636278b82SMichal Krawczyk */ 308736278b82SMichal Krawczyk rte_pktmbuf_read(mbuf, 0, push_len, 308836278b82SMichal Krawczyk tx_ring->push_buf_intermediate_buf); 308936278b82SMichal Krawczyk *push_header = tx_ring->push_buf_intermediate_buf; 309036278b82SMichal Krawczyk delta = push_len - seg_len; 309136278b82SMichal Krawczyk } 309236278b82SMichal Krawczyk } else { 309336278b82SMichal Krawczyk *push_header = NULL; 309436278b82SMichal Krawczyk *header_len = 0; 309536278b82SMichal Krawczyk push_len = 0; 309636278b82SMichal Krawczyk } 309736278b82SMichal Krawczyk 309836278b82SMichal Krawczyk /* Process first segment taking into consideration pushed header */ 309936278b82SMichal Krawczyk if (seg_len > push_len) { 310036278b82SMichal Krawczyk ena_buf->paddr = mbuf->buf_iova + 310136278b82SMichal Krawczyk mbuf->data_off + 310236278b82SMichal Krawczyk push_len; 310336278b82SMichal Krawczyk ena_buf->len = seg_len - push_len; 310436278b82SMichal Krawczyk ena_buf++; 310536278b82SMichal Krawczyk tx_info->num_of_bufs++; 310636278b82SMichal Krawczyk } 310736278b82SMichal Krawczyk 310836278b82SMichal Krawczyk while ((mbuf = mbuf->next) != NULL) { 310936278b82SMichal Krawczyk seg_len = mbuf->data_len; 311036278b82SMichal Krawczyk 311136278b82SMichal Krawczyk /* Skip mbufs if whole data is pushed as a header */ 311236278b82SMichal Krawczyk if (unlikely(delta > seg_len)) { 311336278b82SMichal Krawczyk delta -= seg_len; 311436278b82SMichal Krawczyk continue; 311536278b82SMichal Krawczyk } 311636278b82SMichal Krawczyk 311736278b82SMichal Krawczyk ena_buf->paddr = mbuf->buf_iova + mbuf->data_off + delta; 311836278b82SMichal Krawczyk ena_buf->len = seg_len - delta; 311936278b82SMichal Krawczyk ena_buf++; 312036278b82SMichal Krawczyk tx_info->num_of_bufs++; 312136278b82SMichal Krawczyk 312236278b82SMichal Krawczyk delta = 0; 312336278b82SMichal Krawczyk } 312436278b82SMichal Krawczyk } 312536278b82SMichal Krawczyk 312636278b82SMichal Krawczyk static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf) 312736278b82SMichal Krawczyk { 312836278b82SMichal Krawczyk struct ena_tx_buffer *tx_info; 312936278b82SMichal Krawczyk struct ena_com_tx_ctx ena_tx_ctx = { { 0 } }; 313036278b82SMichal Krawczyk uint16_t next_to_use; 313136278b82SMichal Krawczyk uint16_t header_len; 313236278b82SMichal Krawczyk uint16_t req_id; 313336278b82SMichal Krawczyk void *push_header; 313436278b82SMichal Krawczyk int nb_hw_desc; 313536278b82SMichal Krawczyk int rc; 313636278b82SMichal Krawczyk 313796ffa8a7SMichal Krawczyk /* Checking for space for 2 additional metadata descriptors due to 313896ffa8a7SMichal Krawczyk * possible header split and metadata descriptor 313996ffa8a7SMichal Krawczyk */ 314096ffa8a7SMichal Krawczyk if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq, 314196ffa8a7SMichal Krawczyk mbuf->nb_segs + 2)) { 3142e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, "Not enough space in the tx queue"); 314396ffa8a7SMichal Krawczyk return ENA_COM_NO_MEM; 314496ffa8a7SMichal Krawczyk } 314536278b82SMichal Krawczyk 314636278b82SMichal Krawczyk next_to_use = tx_ring->next_to_use; 314736278b82SMichal Krawczyk 314836278b82SMichal Krawczyk req_id = tx_ring->empty_tx_reqs[next_to_use]; 314936278b82SMichal Krawczyk tx_info = &tx_ring->tx_buffer_info[req_id]; 315036278b82SMichal Krawczyk tx_info->num_of_bufs = 0; 31513d47e9b1SMichal Krawczyk RTE_ASSERT(tx_info->mbuf == NULL); 315236278b82SMichal Krawczyk 315336278b82SMichal Krawczyk ena_tx_map_mbuf(tx_ring, tx_info, mbuf, &push_header, &header_len); 315436278b82SMichal Krawczyk 315536278b82SMichal Krawczyk ena_tx_ctx.ena_bufs = tx_info->bufs; 315636278b82SMichal Krawczyk ena_tx_ctx.push_header = push_header; 315736278b82SMichal Krawczyk ena_tx_ctx.num_bufs = tx_info->num_of_bufs; 315836278b82SMichal Krawczyk ena_tx_ctx.req_id = req_id; 315936278b82SMichal Krawczyk ena_tx_ctx.header_len = header_len; 316036278b82SMichal Krawczyk 316136278b82SMichal Krawczyk /* Set Tx offloads flags, if applicable */ 316236278b82SMichal Krawczyk ena_tx_mbuf_prepare(mbuf, &ena_tx_ctx, tx_ring->offloads, 316336278b82SMichal Krawczyk tx_ring->disable_meta_caching); 316436278b82SMichal Krawczyk 316536278b82SMichal Krawczyk if (unlikely(ena_com_is_doorbell_needed(tx_ring->ena_com_io_sq, 316636278b82SMichal Krawczyk &ena_tx_ctx))) { 3167e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, 3168e99981afSDavid Marchand "LLQ Tx max burst size of queue %d achieved, writing doorbell to send burst", 316936278b82SMichal Krawczyk tx_ring->id); 317036278b82SMichal Krawczyk ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); 31711f949ad9SAmit Bernstein tx_ring->tx_stats.doorbells++; 31721d973d8fSIgor Chauskin tx_ring->pkts_without_db = false; 317336278b82SMichal Krawczyk } 317436278b82SMichal Krawczyk 317536278b82SMichal Krawczyk /* prepare the packet's descriptors to dma engine */ 317636278b82SMichal Krawczyk rc = ena_com_prepare_tx(tx_ring->ena_com_io_sq, &ena_tx_ctx, 317736278b82SMichal Krawczyk &nb_hw_desc); 317836278b82SMichal Krawczyk if (unlikely(rc)) { 3179e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to prepare Tx buffers, rc: %d", rc); 318036278b82SMichal Krawczyk ++tx_ring->tx_stats.prepare_ctx_err; 31812bae75eaSDawid Gorecki ena_trigger_reset(tx_ring->adapter, 31822bae75eaSDawid Gorecki ENA_REGS_RESET_DRIVER_INVALID_STATE); 318336278b82SMichal Krawczyk return rc; 318436278b82SMichal Krawczyk } 318536278b82SMichal Krawczyk 318636278b82SMichal Krawczyk tx_info->tx_descs = nb_hw_desc; 3187f93e20e5SMichal Krawczyk tx_info->timestamp = rte_get_timer_cycles(); 318836278b82SMichal Krawczyk 318936278b82SMichal Krawczyk tx_ring->tx_stats.cnt++; 319036278b82SMichal Krawczyk tx_ring->tx_stats.bytes += mbuf->pkt_len; 319136278b82SMichal Krawczyk 319236278b82SMichal Krawczyk tx_ring->next_to_use = ENA_IDX_NEXT_MASKED(next_to_use, 319336278b82SMichal Krawczyk tx_ring->size_mask); 319436278b82SMichal Krawczyk 319536278b82SMichal Krawczyk return 0; 319636278b82SMichal Krawczyk } 319736278b82SMichal Krawczyk 3198a52b317eSDawid Gorecki static int ena_tx_cleanup(void *txp, uint32_t free_pkt_cnt) 319936278b82SMichal Krawczyk { 3200237407f0SShai Brandes struct rte_mbuf *pkts_to_clean[ENA_CLEANUP_BUF_THRESH]; 3201a52b317eSDawid Gorecki struct ena_ring *tx_ring = (struct ena_ring *)txp; 3202c339f538SDawid Gorecki size_t mbuf_cnt = 0; 3203237407f0SShai Brandes size_t pkt_cnt = 0; 320436278b82SMichal Krawczyk unsigned int total_tx_descs = 0; 3205a52b317eSDawid Gorecki unsigned int total_tx_pkts = 0; 3206005064e5SMichal Krawczyk uint16_t cleanup_budget; 320736278b82SMichal Krawczyk uint16_t next_to_clean = tx_ring->next_to_clean; 3208c339f538SDawid Gorecki bool fast_free = tx_ring->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 320936278b82SMichal Krawczyk 3210a52b317eSDawid Gorecki /* 3211a52b317eSDawid Gorecki * If free_pkt_cnt is equal to 0, it means that the user requested 3212a52b317eSDawid Gorecki * full cleanup, so attempt to release all Tx descriptors 3213a52b317eSDawid Gorecki * (ring_size - 1 -> size_mask) 3214a52b317eSDawid Gorecki */ 3215a52b317eSDawid Gorecki cleanup_budget = (free_pkt_cnt == 0) ? tx_ring->size_mask : free_pkt_cnt; 321636278b82SMichal Krawczyk 3217a52b317eSDawid Gorecki while (likely(total_tx_pkts < cleanup_budget)) { 321836278b82SMichal Krawczyk struct rte_mbuf *mbuf; 321936278b82SMichal Krawczyk struct ena_tx_buffer *tx_info; 322036278b82SMichal Krawczyk uint16_t req_id; 322136278b82SMichal Krawczyk 322236278b82SMichal Krawczyk if (ena_com_tx_comp_req_id_get(tx_ring->ena_com_io_cq, &req_id) != 0) 322336278b82SMichal Krawczyk break; 322436278b82SMichal Krawczyk 322536278b82SMichal Krawczyk if (unlikely(validate_tx_req_id(tx_ring, req_id) != 0)) 322636278b82SMichal Krawczyk break; 322736278b82SMichal Krawczyk 322836278b82SMichal Krawczyk /* Get Tx info & store how many descs were processed */ 322936278b82SMichal Krawczyk tx_info = &tx_ring->tx_buffer_info[req_id]; 3230f93e20e5SMichal Krawczyk tx_info->timestamp = 0; 323136278b82SMichal Krawczyk 323236278b82SMichal Krawczyk mbuf = tx_info->mbuf; 3233c339f538SDawid Gorecki if (fast_free) { 3234237407f0SShai Brandes pkts_to_clean[pkt_cnt++] = mbuf; 3235237407f0SShai Brandes mbuf_cnt += mbuf->nb_segs; 3236237407f0SShai Brandes if (mbuf_cnt >= ENA_CLEANUP_BUF_THRESH) { 3237237407f0SShai Brandes rte_pktmbuf_free_bulk(pkts_to_clean, pkt_cnt); 3238237407f0SShai Brandes mbuf_cnt = 0; 3239237407f0SShai Brandes pkt_cnt = 0; 3240237407f0SShai Brandes } 3241c339f538SDawid Gorecki } else { 324236278b82SMichal Krawczyk rte_pktmbuf_free(mbuf); 3243c339f538SDawid Gorecki } 324436278b82SMichal Krawczyk 324536278b82SMichal Krawczyk tx_info->mbuf = NULL; 324636278b82SMichal Krawczyk tx_ring->empty_tx_reqs[next_to_clean] = req_id; 324736278b82SMichal Krawczyk 324836278b82SMichal Krawczyk total_tx_descs += tx_info->tx_descs; 3249a52b317eSDawid Gorecki total_tx_pkts++; 325036278b82SMichal Krawczyk 325136278b82SMichal Krawczyk /* Put back descriptor to the ring for reuse */ 325236278b82SMichal Krawczyk next_to_clean = ENA_IDX_NEXT_MASKED(next_to_clean, 325336278b82SMichal Krawczyk tx_ring->size_mask); 325436278b82SMichal Krawczyk } 325536278b82SMichal Krawczyk 325636278b82SMichal Krawczyk if (likely(total_tx_descs > 0)) { 325736278b82SMichal Krawczyk /* acknowledge completion of sent packets */ 325836278b82SMichal Krawczyk tx_ring->next_to_clean = next_to_clean; 325936278b82SMichal Krawczyk ena_com_comp_ack(tx_ring->ena_com_io_sq, total_tx_descs); 326036278b82SMichal Krawczyk } 3261f93e20e5SMichal Krawczyk 3262c339f538SDawid Gorecki if (mbuf_cnt != 0) 3263237407f0SShai Brandes rte_pktmbuf_free_bulk(pkts_to_clean, pkt_cnt); 3264c339f538SDawid Gorecki 3265a52b317eSDawid Gorecki /* Notify completion handler that full cleanup was performed */ 3266a52b317eSDawid Gorecki if (free_pkt_cnt == 0 || total_tx_pkts < cleanup_budget) 3267f93e20e5SMichal Krawczyk tx_ring->last_cleanup_ticks = rte_get_timer_cycles(); 3268a52b317eSDawid Gorecki 3269a52b317eSDawid Gorecki return total_tx_pkts; 327036278b82SMichal Krawczyk } 327136278b82SMichal Krawczyk 32721173fca2SJan Medala static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 32731173fca2SJan Medala uint16_t nb_pkts) 32741173fca2SJan Medala { 32751173fca2SJan Medala struct ena_ring *tx_ring = (struct ena_ring *)(tx_queue); 3276005064e5SMichal Krawczyk int available_desc; 327774456796SMichal Krawczyk uint16_t sent_idx = 0; 32781173fca2SJan Medala 32790a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_TX 32801173fca2SJan Medala /* Check adapter state */ 32811173fca2SJan Medala if (unlikely(tx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) { 3282e99981afSDavid Marchand PMD_TX_LOG_LINE(ALERT, 3283e99981afSDavid Marchand "Trying to xmit pkts while device is NOT running"); 32841173fca2SJan Medala return 0; 32851173fca2SJan Medala } 32860a001d69SMichal Krawczyk #endif 32871173fca2SJan Medala 328867216c31SMichal Krawczyk available_desc = ena_com_free_q_entries(tx_ring->ena_com_io_sq); 328967216c31SMichal Krawczyk if (available_desc < tx_ring->tx_free_thresh) 3290a52b317eSDawid Gorecki ena_tx_cleanup((void *)tx_ring, 0); 329167216c31SMichal Krawczyk 32921173fca2SJan Medala for (sent_idx = 0; sent_idx < nb_pkts; sent_idx++) { 329336278b82SMichal Krawczyk if (ena_xmit_mbuf(tx_ring, tx_pkts[sent_idx])) 32942061fe41SRafal Kozik break; 32951d973d8fSIgor Chauskin tx_ring->pkts_without_db = true; 329636278b82SMichal Krawczyk rte_prefetch0(tx_pkts[ENA_IDX_ADD_MASKED(sent_idx, 4, 329736278b82SMichal Krawczyk tx_ring->size_mask)]); 32982fca2a98SMichal Krawczyk } 32992fca2a98SMichal Krawczyk 33005e02e19eSJan Medala /* If there are ready packets to be xmitted... */ 33011d973d8fSIgor Chauskin if (likely(tx_ring->pkts_without_db)) { 33025e02e19eSJan Medala /* ...let HW do its best :-) */ 33031173fca2SJan Medala ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq); 330445b6d861SMichal Krawczyk tx_ring->tx_stats.doorbells++; 33051d973d8fSIgor Chauskin tx_ring->pkts_without_db = false; 33065e02e19eSJan Medala } 33075e02e19eSJan Medala 33087830e905SSolganik Alexander tx_ring->tx_stats.available_desc = 3309b2b02edeSMichal Krawczyk ena_com_free_q_entries(tx_ring->ena_com_io_sq); 33107830e905SSolganik Alexander tx_ring->tx_stats.tx_poll++; 33117830e905SSolganik Alexander 33121173fca2SJan Medala return sent_idx; 33131173fca2SJan Medala } 33141173fca2SJan Medala 331592401abfSShai Brandes static void ena_copy_customer_metrics(struct ena_adapter *adapter, uint64_t *buf, 331692401abfSShai Brandes size_t num_metrics) 331745718adaSMichal Krawczyk { 331892401abfSShai Brandes struct ena_com_dev *ena_dev = &adapter->ena_dev; 331945718adaSMichal Krawczyk int rc; 332045718adaSMichal Krawczyk 332192401abfSShai Brandes if (ena_com_get_cap(ena_dev, ENA_ADMIN_CUSTOMER_METRICS)) { 332292401abfSShai Brandes if (num_metrics != ENA_STATS_ARRAY_METRICS) { 3323e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Detected discrepancy in the number of customer metrics"); 332492401abfSShai Brandes return; 332592401abfSShai Brandes } 332645718adaSMichal Krawczyk rte_spinlock_lock(&adapter->admin_lock); 332792401abfSShai Brandes rc = ENA_PROXY(adapter, 332892401abfSShai Brandes ena_com_get_customer_metrics, 332992401abfSShai Brandes &adapter->ena_dev, 333092401abfSShai Brandes (char *)buf, 333192401abfSShai Brandes num_metrics * sizeof(uint64_t)); 333245718adaSMichal Krawczyk rte_spinlock_unlock(&adapter->admin_lock); 333345718adaSMichal Krawczyk if (rc != 0) { 3334e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, "Failed to get customer metrics, rc: %d", rc); 333592401abfSShai Brandes return; 333645718adaSMichal Krawczyk } 333745718adaSMichal Krawczyk 333892401abfSShai Brandes } else if (ena_com_get_cap(ena_dev, ENA_ADMIN_ENI_STATS)) { 333992401abfSShai Brandes if (num_metrics != ENA_STATS_ARRAY_METRICS_LEGACY) { 3340e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Detected discrepancy in the number of legacy metrics"); 334192401abfSShai Brandes return; 334292401abfSShai Brandes } 334392401abfSShai Brandes 334492401abfSShai Brandes rte_spinlock_lock(&adapter->admin_lock); 334592401abfSShai Brandes rc = ENA_PROXY(adapter, 334692401abfSShai Brandes ena_com_get_eni_stats, 334792401abfSShai Brandes &adapter->ena_dev, 334892401abfSShai Brandes (struct ena_admin_eni_stats *)buf); 334992401abfSShai Brandes rte_spinlock_unlock(&adapter->admin_lock); 335092401abfSShai Brandes if (rc != 0) { 3351e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, 3352e99981afSDavid Marchand "Failed to get ENI metrics, rc: %d", rc); 335392401abfSShai Brandes return; 335492401abfSShai Brandes } 335592401abfSShai Brandes } 335645718adaSMichal Krawczyk } 335745718adaSMichal Krawczyk 3358a73dd098SShai Brandes static void ena_copy_ena_srd_info(struct ena_adapter *adapter, 3359a73dd098SShai Brandes struct ena_stats_srd *srd_info) 3360a73dd098SShai Brandes { 3361a73dd098SShai Brandes int rc; 3362a73dd098SShai Brandes 3363a73dd098SShai Brandes if (!ena_com_get_cap(&adapter->ena_dev, ENA_ADMIN_ENA_SRD_INFO)) 3364a73dd098SShai Brandes return; 3365a73dd098SShai Brandes 3366a73dd098SShai Brandes rte_spinlock_lock(&adapter->admin_lock); 3367a73dd098SShai Brandes rc = ENA_PROXY(adapter, 3368a73dd098SShai Brandes ena_com_get_ena_srd_info, 3369a73dd098SShai Brandes &adapter->ena_dev, 3370a73dd098SShai Brandes (struct ena_admin_ena_srd_info *)srd_info); 3371a73dd098SShai Brandes rte_spinlock_unlock(&adapter->admin_lock); 3372a73dd098SShai Brandes if (rc != ENA_COM_OK && rc != ENA_COM_UNSUPPORTED) { 3373e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, 3374e99981afSDavid Marchand "Failed to get ENA express srd info, rc: %d", rc); 3375a73dd098SShai Brandes return; 3376a73dd098SShai Brandes } 3377a73dd098SShai Brandes } 3378a73dd098SShai Brandes 33797830e905SSolganik Alexander /** 33807830e905SSolganik Alexander * DPDK callback to retrieve names of extended device statistics 33817830e905SSolganik Alexander * 33827830e905SSolganik Alexander * @param dev 33837830e905SSolganik Alexander * Pointer to Ethernet device structure. 33847830e905SSolganik Alexander * @param[out] xstats_names 33857830e905SSolganik Alexander * Buffer to insert names into. 33867830e905SSolganik Alexander * @param n 33877830e905SSolganik Alexander * Number of names. 33887830e905SSolganik Alexander * 33897830e905SSolganik Alexander * @return 33907830e905SSolganik Alexander * Number of xstats names. 33917830e905SSolganik Alexander */ 33927830e905SSolganik Alexander static int ena_xstats_get_names(struct rte_eth_dev *dev, 33937830e905SSolganik Alexander struct rte_eth_xstat_name *xstats_names, 33947830e905SSolganik Alexander unsigned int n) 33957830e905SSolganik Alexander { 339692401abfSShai Brandes struct ena_adapter *adapter = dev->data->dev_private; 3397aab58857SStanislaw Kardach unsigned int xstats_count = ena_xstats_calc_num(dev->data); 33987830e905SSolganik Alexander unsigned int stat, i, count = 0; 33997830e905SSolganik Alexander 34007830e905SSolganik Alexander if (n < xstats_count || !xstats_names) 34017830e905SSolganik Alexander return xstats_count; 34027830e905SSolganik Alexander 34037830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) 34047830e905SSolganik Alexander strcpy(xstats_names[count].name, 34057830e905SSolganik Alexander ena_stats_global_strings[stat].name); 34067830e905SSolganik Alexander 340792401abfSShai Brandes for (stat = 0; stat < adapter->metrics_num; stat++, count++) 340892401abfSShai Brandes rte_strscpy(xstats_names[count].name, 340992401abfSShai Brandes ena_stats_metrics_strings[stat].name, 341092401abfSShai Brandes RTE_ETH_XSTATS_NAME_SIZE); 3411a73dd098SShai Brandes for (stat = 0; stat < ENA_STATS_ARRAY_ENA_SRD; stat++, count++) 3412a73dd098SShai Brandes rte_strscpy(xstats_names[count].name, 3413a73dd098SShai Brandes ena_stats_srd_strings[stat].name, 3414a73dd098SShai Brandes RTE_ETH_XSTATS_NAME_SIZE); 341545718adaSMichal Krawczyk 34167830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) 34177830e905SSolganik Alexander for (i = 0; i < dev->data->nb_rx_queues; i++, count++) 34187830e905SSolganik Alexander snprintf(xstats_names[count].name, 34197830e905SSolganik Alexander sizeof(xstats_names[count].name), 34207830e905SSolganik Alexander "rx_q%d_%s", i, 34217830e905SSolganik Alexander ena_stats_rx_strings[stat].name); 34227830e905SSolganik Alexander 34237830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_TX; stat++) 34247830e905SSolganik Alexander for (i = 0; i < dev->data->nb_tx_queues; i++, count++) 34257830e905SSolganik Alexander snprintf(xstats_names[count].name, 34267830e905SSolganik Alexander sizeof(xstats_names[count].name), 34277830e905SSolganik Alexander "tx_q%d_%s", i, 34287830e905SSolganik Alexander ena_stats_tx_strings[stat].name); 34297830e905SSolganik Alexander 34307830e905SSolganik Alexander return xstats_count; 34317830e905SSolganik Alexander } 34327830e905SSolganik Alexander 34337830e905SSolganik Alexander /** 34343cec73faSMichal Krawczyk * DPDK callback to retrieve names of extended device statistics for the given 34353cec73faSMichal Krawczyk * ids. 34363cec73faSMichal Krawczyk * 34373cec73faSMichal Krawczyk * @param dev 34383cec73faSMichal Krawczyk * Pointer to Ethernet device structure. 34393cec73faSMichal Krawczyk * @param[out] xstats_names 34403cec73faSMichal Krawczyk * Buffer to insert names into. 34413cec73faSMichal Krawczyk * @param ids 34423cec73faSMichal Krawczyk * IDs array for which the names should be retrieved. 34433cec73faSMichal Krawczyk * @param size 34443cec73faSMichal Krawczyk * Number of ids. 34453cec73faSMichal Krawczyk * 34463cec73faSMichal Krawczyk * @return 34473cec73faSMichal Krawczyk * Positive value: number of xstats names. Negative value: error code. 34483cec73faSMichal Krawczyk */ 34493cec73faSMichal Krawczyk static int ena_xstats_get_names_by_id(struct rte_eth_dev *dev, 34503cec73faSMichal Krawczyk const uint64_t *ids, 34513cec73faSMichal Krawczyk struct rte_eth_xstat_name *xstats_names, 34523cec73faSMichal Krawczyk unsigned int size) 34533cec73faSMichal Krawczyk { 345492401abfSShai Brandes struct ena_adapter *adapter = dev->data->dev_private; 34553cec73faSMichal Krawczyk uint64_t xstats_count = ena_xstats_calc_num(dev->data); 34563cec73faSMichal Krawczyk uint64_t id, qid; 34573cec73faSMichal Krawczyk unsigned int i; 34583cec73faSMichal Krawczyk 34593cec73faSMichal Krawczyk if (xstats_names == NULL) 34603cec73faSMichal Krawczyk return xstats_count; 34613cec73faSMichal Krawczyk 34623cec73faSMichal Krawczyk for (i = 0; i < size; ++i) { 34633cec73faSMichal Krawczyk id = ids[i]; 34643cec73faSMichal Krawczyk if (id > xstats_count) { 3465e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 3466e99981afSDavid Marchand "ID value out of range: id=%" PRIu64 ", xstats_num=%" PRIu64, 34673cec73faSMichal Krawczyk id, xstats_count); 34683cec73faSMichal Krawczyk return -EINVAL; 34693cec73faSMichal Krawczyk } 34703cec73faSMichal Krawczyk 34713cec73faSMichal Krawczyk if (id < ENA_STATS_ARRAY_GLOBAL) { 34723cec73faSMichal Krawczyk strcpy(xstats_names[i].name, 34733cec73faSMichal Krawczyk ena_stats_global_strings[id].name); 34743cec73faSMichal Krawczyk continue; 34753cec73faSMichal Krawczyk } 34763cec73faSMichal Krawczyk 34773cec73faSMichal Krawczyk id -= ENA_STATS_ARRAY_GLOBAL; 347892401abfSShai Brandes if (id < adapter->metrics_num) { 347992401abfSShai Brandes rte_strscpy(xstats_names[i].name, 348092401abfSShai Brandes ena_stats_metrics_strings[id].name, 348192401abfSShai Brandes RTE_ETH_XSTATS_NAME_SIZE); 34823cec73faSMichal Krawczyk continue; 34833cec73faSMichal Krawczyk } 34843cec73faSMichal Krawczyk 348592401abfSShai Brandes id -= adapter->metrics_num; 3486a73dd098SShai Brandes 3487a73dd098SShai Brandes if (id < ENA_STATS_ARRAY_ENA_SRD) { 3488a73dd098SShai Brandes rte_strscpy(xstats_names[i].name, 3489a73dd098SShai Brandes ena_stats_srd_strings[id].name, 3490a73dd098SShai Brandes RTE_ETH_XSTATS_NAME_SIZE); 3491a73dd098SShai Brandes continue; 3492a73dd098SShai Brandes } 3493a73dd098SShai Brandes id -= ENA_STATS_ARRAY_ENA_SRD; 3494a73dd098SShai Brandes 34953cec73faSMichal Krawczyk if (id < ENA_STATS_ARRAY_RX) { 34963cec73faSMichal Krawczyk qid = id / dev->data->nb_rx_queues; 34973cec73faSMichal Krawczyk id %= dev->data->nb_rx_queues; 34983cec73faSMichal Krawczyk snprintf(xstats_names[i].name, 34993cec73faSMichal Krawczyk sizeof(xstats_names[i].name), 35003cec73faSMichal Krawczyk "rx_q%" PRIu64 "d_%s", 35013cec73faSMichal Krawczyk qid, ena_stats_rx_strings[id].name); 35023cec73faSMichal Krawczyk continue; 35033cec73faSMichal Krawczyk } 35043cec73faSMichal Krawczyk 35053cec73faSMichal Krawczyk id -= ENA_STATS_ARRAY_RX; 35063cec73faSMichal Krawczyk /* Although this condition is not needed, it was added for 35073cec73faSMichal Krawczyk * compatibility if new xstat structure would be ever added. 35083cec73faSMichal Krawczyk */ 35093cec73faSMichal Krawczyk if (id < ENA_STATS_ARRAY_TX) { 35103cec73faSMichal Krawczyk qid = id / dev->data->nb_tx_queues; 35113cec73faSMichal Krawczyk id %= dev->data->nb_tx_queues; 35123cec73faSMichal Krawczyk snprintf(xstats_names[i].name, 35133cec73faSMichal Krawczyk sizeof(xstats_names[i].name), 35143cec73faSMichal Krawczyk "tx_q%" PRIu64 "_%s", 35153cec73faSMichal Krawczyk qid, ena_stats_tx_strings[id].name); 35163cec73faSMichal Krawczyk continue; 35173cec73faSMichal Krawczyk } 35183cec73faSMichal Krawczyk } 35193cec73faSMichal Krawczyk 35203cec73faSMichal Krawczyk return i; 35213cec73faSMichal Krawczyk } 35223cec73faSMichal Krawczyk 35233cec73faSMichal Krawczyk /** 35247830e905SSolganik Alexander * DPDK callback to get extended device statistics. 35257830e905SSolganik Alexander * 35267830e905SSolganik Alexander * @param dev 35277830e905SSolganik Alexander * Pointer to Ethernet device structure. 35287830e905SSolganik Alexander * @param[out] stats 35297830e905SSolganik Alexander * Stats table output buffer. 35307830e905SSolganik Alexander * @param n 35317830e905SSolganik Alexander * The size of the stats table. 35327830e905SSolganik Alexander * 35337830e905SSolganik Alexander * @return 35347830e905SSolganik Alexander * Number of xstats on success, negative on failure. 35357830e905SSolganik Alexander */ 35367830e905SSolganik Alexander static int ena_xstats_get(struct rte_eth_dev *dev, 35377830e905SSolganik Alexander struct rte_eth_xstat *xstats, 35387830e905SSolganik Alexander unsigned int n) 35397830e905SSolganik Alexander { 3540890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 3541aab58857SStanislaw Kardach unsigned int xstats_count = ena_xstats_calc_num(dev->data); 35427830e905SSolganik Alexander unsigned int stat, i, count = 0; 35437830e905SSolganik Alexander int stat_offset; 35447830e905SSolganik Alexander void *stats_begin; 354592401abfSShai Brandes uint64_t metrics_stats[ENA_MAX_CUSTOMER_METRICS]; 3546a73dd098SShai Brandes struct ena_stats_srd srd_info = {0}; 35477830e905SSolganik Alexander 35487830e905SSolganik Alexander if (n < xstats_count) 35497830e905SSolganik Alexander return xstats_count; 35507830e905SSolganik Alexander 35517830e905SSolganik Alexander if (!xstats) 35527830e905SSolganik Alexander return 0; 35537830e905SSolganik Alexander 35547830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) { 3555493107fdSMichal Krawczyk stat_offset = ena_stats_global_strings[stat].stat_offset; 35567830e905SSolganik Alexander stats_begin = &adapter->dev_stats; 35577830e905SSolganik Alexander 35587830e905SSolganik Alexander xstats[count].id = count; 35597830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 35607830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 35617830e905SSolganik Alexander } 35627830e905SSolganik Alexander 356392401abfSShai Brandes ena_copy_customer_metrics(adapter, metrics_stats, adapter->metrics_num); 356492401abfSShai Brandes stats_begin = metrics_stats; 356592401abfSShai Brandes for (stat = 0; stat < adapter->metrics_num; stat++, count++) { 356692401abfSShai Brandes stat_offset = ena_stats_metrics_strings[stat].stat_offset; 356745718adaSMichal Krawczyk 356845718adaSMichal Krawczyk xstats[count].id = count; 356945718adaSMichal Krawczyk xstats[count].value = *((uint64_t *) 357045718adaSMichal Krawczyk ((char *)stats_begin + stat_offset)); 357145718adaSMichal Krawczyk } 357245718adaSMichal Krawczyk 3573a73dd098SShai Brandes ena_copy_ena_srd_info(adapter, &srd_info); 3574a73dd098SShai Brandes stats_begin = &srd_info; 3575a73dd098SShai Brandes for (stat = 0; stat < ENA_STATS_ARRAY_ENA_SRD; stat++, count++) { 3576a73dd098SShai Brandes stat_offset = ena_stats_srd_strings[stat].stat_offset; 3577a73dd098SShai Brandes xstats[count].id = count; 3578a73dd098SShai Brandes xstats[count].value = *((uint64_t *) 3579a73dd098SShai Brandes ((char *)stats_begin + stat_offset)); 3580a73dd098SShai Brandes } 3581a73dd098SShai Brandes 35827830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) { 35837830e905SSolganik Alexander for (i = 0; i < dev->data->nb_rx_queues; i++, count++) { 35847830e905SSolganik Alexander stat_offset = ena_stats_rx_strings[stat].stat_offset; 35857830e905SSolganik Alexander stats_begin = &adapter->rx_ring[i].rx_stats; 35867830e905SSolganik Alexander 35877830e905SSolganik Alexander xstats[count].id = count; 35887830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 35897830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 35907830e905SSolganik Alexander } 35917830e905SSolganik Alexander } 35927830e905SSolganik Alexander 35937830e905SSolganik Alexander for (stat = 0; stat < ENA_STATS_ARRAY_TX; stat++) { 35947830e905SSolganik Alexander for (i = 0; i < dev->data->nb_tx_queues; i++, count++) { 35957830e905SSolganik Alexander stat_offset = ena_stats_tx_strings[stat].stat_offset; 35967830e905SSolganik Alexander stats_begin = &adapter->tx_ring[i].rx_stats; 35977830e905SSolganik Alexander 35987830e905SSolganik Alexander xstats[count].id = count; 35997830e905SSolganik Alexander xstats[count].value = *((uint64_t *) 36007830e905SSolganik Alexander ((char *)stats_begin + stat_offset)); 36017830e905SSolganik Alexander } 36027830e905SSolganik Alexander } 36037830e905SSolganik Alexander 36047830e905SSolganik Alexander return count; 36057830e905SSolganik Alexander } 36067830e905SSolganik Alexander 36077830e905SSolganik Alexander static int ena_xstats_get_by_id(struct rte_eth_dev *dev, 36087830e905SSolganik Alexander const uint64_t *ids, 36097830e905SSolganik Alexander uint64_t *values, 36107830e905SSolganik Alexander unsigned int n) 36117830e905SSolganik Alexander { 3612890728ffSStephen Hemminger struct ena_adapter *adapter = dev->data->dev_private; 36137830e905SSolganik Alexander uint64_t id; 36147830e905SSolganik Alexander uint64_t rx_entries, tx_entries; 36157830e905SSolganik Alexander unsigned int i; 36167830e905SSolganik Alexander int qid; 36177830e905SSolganik Alexander int valid = 0; 361892401abfSShai Brandes bool were_metrics_copied = false; 3619a73dd098SShai Brandes bool was_srd_info_copied = false; 362092401abfSShai Brandes uint64_t metrics_stats[ENA_MAX_CUSTOMER_METRICS]; 3621a73dd098SShai Brandes struct ena_stats_srd srd_info = {0}; 362245718adaSMichal Krawczyk 36237830e905SSolganik Alexander for (i = 0; i < n; ++i) { 36247830e905SSolganik Alexander id = ids[i]; 36257830e905SSolganik Alexander /* Check if id belongs to global statistics */ 36267830e905SSolganik Alexander if (id < ENA_STATS_ARRAY_GLOBAL) { 36277830e905SSolganik Alexander values[i] = *((uint64_t *)&adapter->dev_stats + id); 36287830e905SSolganik Alexander ++valid; 36297830e905SSolganik Alexander continue; 36307830e905SSolganik Alexander } 36317830e905SSolganik Alexander 363245718adaSMichal Krawczyk /* Check if id belongs to ENI statistics */ 36337830e905SSolganik Alexander id -= ENA_STATS_ARRAY_GLOBAL; 363492401abfSShai Brandes if (id < adapter->metrics_num) { 363592401abfSShai Brandes /* Avoid reading metrics multiple times in a single 363645718adaSMichal Krawczyk * function call, as it requires communication with the 363745718adaSMichal Krawczyk * admin queue. 363845718adaSMichal Krawczyk */ 363992401abfSShai Brandes if (!were_metrics_copied) { 364092401abfSShai Brandes were_metrics_copied = true; 364192401abfSShai Brandes ena_copy_customer_metrics(adapter, 364292401abfSShai Brandes metrics_stats, 364392401abfSShai Brandes adapter->metrics_num); 364445718adaSMichal Krawczyk } 364592401abfSShai Brandes 364692401abfSShai Brandes values[i] = *((uint64_t *)&metrics_stats + id); 364745718adaSMichal Krawczyk ++valid; 364845718adaSMichal Krawczyk continue; 364945718adaSMichal Krawczyk } 365045718adaSMichal Krawczyk 3651a73dd098SShai Brandes /* Check if id belongs to SRD info statistics */ 365292401abfSShai Brandes id -= adapter->metrics_num; 3653a73dd098SShai Brandes 3654a73dd098SShai Brandes if (id < ENA_STATS_ARRAY_ENA_SRD) { 3655a73dd098SShai Brandes /* 3656a73dd098SShai Brandes * Avoid reading srd info multiple times in a single 3657a73dd098SShai Brandes * function call, as it requires communication with the 3658a73dd098SShai Brandes * admin queue. 3659a73dd098SShai Brandes */ 3660a73dd098SShai Brandes if (!was_srd_info_copied) { 3661a73dd098SShai Brandes was_srd_info_copied = true; 3662a73dd098SShai Brandes ena_copy_ena_srd_info(adapter, &srd_info); 3663a73dd098SShai Brandes } 3664a73dd098SShai Brandes values[i] = *((uint64_t *)&adapter->srd_stats + id); 3665a73dd098SShai Brandes ++valid; 3666a73dd098SShai Brandes continue; 3667a73dd098SShai Brandes } 3668a73dd098SShai Brandes 3669a73dd098SShai Brandes /* Check if id belongs to rx queue statistics */ 3670a73dd098SShai Brandes id -= ENA_STATS_ARRAY_ENA_SRD; 3671a73dd098SShai Brandes 36727830e905SSolganik Alexander rx_entries = ENA_STATS_ARRAY_RX * dev->data->nb_rx_queues; 36737830e905SSolganik Alexander if (id < rx_entries) { 36747830e905SSolganik Alexander qid = id % dev->data->nb_rx_queues; 36757830e905SSolganik Alexander id /= dev->data->nb_rx_queues; 36767830e905SSolganik Alexander values[i] = *((uint64_t *) 36777830e905SSolganik Alexander &adapter->rx_ring[qid].rx_stats + id); 36787830e905SSolganik Alexander ++valid; 36797830e905SSolganik Alexander continue; 36807830e905SSolganik Alexander } 36817830e905SSolganik Alexander /* Check if id belongs to rx queue statistics */ 36827830e905SSolganik Alexander id -= rx_entries; 36837830e905SSolganik Alexander tx_entries = ENA_STATS_ARRAY_TX * dev->data->nb_tx_queues; 36847830e905SSolganik Alexander if (id < tx_entries) { 36857830e905SSolganik Alexander qid = id % dev->data->nb_tx_queues; 36867830e905SSolganik Alexander id /= dev->data->nb_tx_queues; 36877830e905SSolganik Alexander values[i] = *((uint64_t *) 36887830e905SSolganik Alexander &adapter->tx_ring[qid].tx_stats + id); 36897830e905SSolganik Alexander ++valid; 36907830e905SSolganik Alexander continue; 36917830e905SSolganik Alexander } 36927830e905SSolganik Alexander } 36937830e905SSolganik Alexander 36947830e905SSolganik Alexander return valid; 36957830e905SSolganik Alexander } 36967830e905SSolganik Alexander 3697cc0c5d25SMichal Krawczyk static int ena_process_uint_devarg(const char *key, 3698cc0c5d25SMichal Krawczyk const char *value, 3699cc0c5d25SMichal Krawczyk void *opaque) 3700cc0c5d25SMichal Krawczyk { 3701cc0c5d25SMichal Krawczyk struct ena_adapter *adapter = opaque; 3702cc0c5d25SMichal Krawczyk char *str_end; 3703ca1dfa85SShai Brandes uint64_t uint64_value; 3704cc0c5d25SMichal Krawczyk 3705ca1dfa85SShai Brandes uint64_value = strtoull(value, &str_end, DECIMAL_BASE); 3706cc0c5d25SMichal Krawczyk if (value == str_end) { 3707e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, 3708e99981afSDavid Marchand "Invalid value for key '%s'. Only uint values are accepted.", 3709cc0c5d25SMichal Krawczyk key); 3710cc0c5d25SMichal Krawczyk return -EINVAL; 3711cc0c5d25SMichal Krawczyk } 3712cc0c5d25SMichal Krawczyk 3713cc0c5d25SMichal Krawczyk if (strcmp(key, ENA_DEVARG_MISS_TXC_TO) == 0) { 3714ca1dfa85SShai Brandes if (uint64_value > ENA_MAX_TX_TIMEOUT_SECONDS) { 3715e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, 3716e99981afSDavid Marchand "Tx timeout too high: %" PRIu64 " sec. Maximum allowed: %d sec.", 3717ca1dfa85SShai Brandes uint64_value, ENA_MAX_TX_TIMEOUT_SECONDS); 3718cc0c5d25SMichal Krawczyk return -EINVAL; 3719ca1dfa85SShai Brandes } else if (uint64_value == 0) { 3720e99981afSDavid Marchand PMD_INIT_LOG_LINE(INFO, 3721e99981afSDavid Marchand "Check for missing Tx completions has been disabled."); 3722cc0c5d25SMichal Krawczyk adapter->missing_tx_completion_to = 3723cc0c5d25SMichal Krawczyk ENA_HW_HINTS_NO_TIMEOUT; 3724cc0c5d25SMichal Krawczyk } else { 3725e99981afSDavid Marchand PMD_INIT_LOG_LINE(INFO, 3726e99981afSDavid Marchand "Tx packet completion timeout set to %" PRIu64 " seconds.", 3727ca1dfa85SShai Brandes uint64_value); 3728cc0c5d25SMichal Krawczyk adapter->missing_tx_completion_to = 3729ca1dfa85SShai Brandes uint64_value * rte_get_timer_hz(); 3730ca1dfa85SShai Brandes } 3731ca1dfa85SShai Brandes } else if (strcmp(key, ENA_DEVARG_CONTROL_PATH_POLL_INTERVAL) == 0) { 3732ca1dfa85SShai Brandes if (uint64_value > ENA_MAX_CONTROL_PATH_POLL_INTERVAL_MSEC) { 3733e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, 3734ca1dfa85SShai Brandes "Control path polling interval is too long: %" PRIu64 " msecs. " 3735e99981afSDavid Marchand "Maximum allowed: %d msecs.", 3736ca1dfa85SShai Brandes uint64_value, ENA_MAX_CONTROL_PATH_POLL_INTERVAL_MSEC); 3737ca1dfa85SShai Brandes return -EINVAL; 3738ca1dfa85SShai Brandes } else if (uint64_value == 0) { 3739e99981afSDavid Marchand PMD_INIT_LOG_LINE(INFO, 3740ca1dfa85SShai Brandes "Control path polling interval is set to zero. Operating in " 3741e99981afSDavid Marchand "interrupt mode."); 3742ca1dfa85SShai Brandes adapter->control_path_poll_interval = 0; 3743ca1dfa85SShai Brandes } else { 3744e99981afSDavid Marchand PMD_INIT_LOG_LINE(INFO, 3745e99981afSDavid Marchand "Control path polling interval is set to %" PRIu64 " msecs.", 3746ca1dfa85SShai Brandes uint64_value); 3747ca1dfa85SShai Brandes adapter->control_path_poll_interval = uint64_value * USEC_PER_MSEC; 3748cc0c5d25SMichal Krawczyk } 3749cc0c5d25SMichal Krawczyk } 3750cc0c5d25SMichal Krawczyk 3751cc0c5d25SMichal Krawczyk return 0; 3752cc0c5d25SMichal Krawczyk } 3753cc0c5d25SMichal Krawczyk 3754d7918d19SShai Brandes static int ena_process_llq_policy_devarg(const char *key, const char *value, void *opaque) 37558a7a73f2SMichal Krawczyk { 37568a7a73f2SMichal Krawczyk struct ena_adapter *adapter = opaque; 3757d7918d19SShai Brandes uint32_t policy; 37588a7a73f2SMichal Krawczyk 3759d7918d19SShai Brandes policy = strtoul(value, NULL, DECIMAL_BASE); 3760d7918d19SShai Brandes if (policy < ENA_LLQ_POLICY_LAST) { 3761d7918d19SShai Brandes adapter->llq_header_policy = policy; 37628a7a73f2SMichal Krawczyk } else { 3763e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, 3764d7918d19SShai Brandes "Invalid value: '%s' for key '%s'. valid [0-3]", 37658a7a73f2SMichal Krawczyk value, key); 37668a7a73f2SMichal Krawczyk return -EINVAL; 37678a7a73f2SMichal Krawczyk } 3768d7918d19SShai Brandes PMD_INIT_LOG_LINE(INFO, 3769d7918d19SShai Brandes "LLQ policy is %u [0 - disabled, 1 - device recommended, 2 - normal, 3 - large]", 3770d7918d19SShai Brandes adapter->llq_header_policy); 37718a7a73f2SMichal Krawczyk return 0; 37728a7a73f2SMichal Krawczyk } 37738a7a73f2SMichal Krawczyk 3774d7918d19SShai Brandes static int ena_parse_devargs(struct ena_adapter *adapter, struct rte_devargs *devargs) 37758a7a73f2SMichal Krawczyk { 37768a7a73f2SMichal Krawczyk static const char * const allowed_args[] = { 3777d7918d19SShai Brandes ENA_DEVARG_LLQ_POLICY, 3778cc0c5d25SMichal Krawczyk ENA_DEVARG_MISS_TXC_TO, 3779ca1dfa85SShai Brandes ENA_DEVARG_CONTROL_PATH_POLL_INTERVAL, 37809f220a95SMichal Krawczyk NULL, 37818a7a73f2SMichal Krawczyk }; 37828a7a73f2SMichal Krawczyk struct rte_kvargs *kvlist; 37838a7a73f2SMichal Krawczyk int rc; 37848a7a73f2SMichal Krawczyk 37858a7a73f2SMichal Krawczyk if (devargs == NULL) 37868a7a73f2SMichal Krawczyk return 0; 37878a7a73f2SMichal Krawczyk 37888a7a73f2SMichal Krawczyk kvlist = rte_kvargs_parse(devargs->args, allowed_args); 37898a7a73f2SMichal Krawczyk if (kvlist == NULL) { 3790e99981afSDavid Marchand PMD_INIT_LOG_LINE(ERR, "Invalid device arguments: %s", 37918a7a73f2SMichal Krawczyk devargs->args); 37928a7a73f2SMichal Krawczyk return -EINVAL; 37938a7a73f2SMichal Krawczyk } 3794d7918d19SShai Brandes rc = rte_kvargs_process(kvlist, ENA_DEVARG_LLQ_POLICY, 3795d7918d19SShai Brandes ena_process_llq_policy_devarg, adapter); 37961f11149dSShai Brandes if (rc != 0) 37971f11149dSShai Brandes goto exit; 3798cc0c5d25SMichal Krawczyk rc = rte_kvargs_process(kvlist, ENA_DEVARG_MISS_TXC_TO, 3799cc0c5d25SMichal Krawczyk ena_process_uint_devarg, adapter); 38009944919eSMichal Krawczyk if (rc != 0) 38019944919eSMichal Krawczyk goto exit; 3802ca1dfa85SShai Brandes rc = rte_kvargs_process(kvlist, ENA_DEVARG_CONTROL_PATH_POLL_INTERVAL, 3803ca1dfa85SShai Brandes ena_process_uint_devarg, adapter); 3804ca1dfa85SShai Brandes if (rc != 0) 3805ca1dfa85SShai Brandes goto exit; 38068a7a73f2SMichal Krawczyk 3807cc0c5d25SMichal Krawczyk exit: 38088a7a73f2SMichal Krawczyk rte_kvargs_free(kvlist); 38098a7a73f2SMichal Krawczyk 38108a7a73f2SMichal Krawczyk return rc; 38118a7a73f2SMichal Krawczyk } 38128a7a73f2SMichal Krawczyk 38136986cdc4SMichal Krawczyk static int ena_setup_rx_intr(struct rte_eth_dev *dev) 38146986cdc4SMichal Krawczyk { 38156986cdc4SMichal Krawczyk struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 3816d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 38176986cdc4SMichal Krawczyk int rc; 38186986cdc4SMichal Krawczyk uint16_t vectors_nb, i; 38196986cdc4SMichal Krawczyk bool rx_intr_requested = dev->data->dev_conf.intr_conf.rxq; 38206986cdc4SMichal Krawczyk 38216986cdc4SMichal Krawczyk if (!rx_intr_requested) 38226986cdc4SMichal Krawczyk return 0; 38236986cdc4SMichal Krawczyk 38246986cdc4SMichal Krawczyk if (!rte_intr_cap_multiple(intr_handle)) { 3825e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 3826e99981afSDavid Marchand "Rx interrupt requested, but it isn't supported by the PCI driver"); 38276986cdc4SMichal Krawczyk return -ENOTSUP; 38286986cdc4SMichal Krawczyk } 38296986cdc4SMichal Krawczyk 38306986cdc4SMichal Krawczyk /* Disable interrupt mapping before the configuration starts. */ 38316986cdc4SMichal Krawczyk rte_intr_disable(intr_handle); 38326986cdc4SMichal Krawczyk 38336986cdc4SMichal Krawczyk /* Verify if there are enough vectors available. */ 38346986cdc4SMichal Krawczyk vectors_nb = dev->data->nb_rx_queues; 38356986cdc4SMichal Krawczyk if (vectors_nb > RTE_MAX_RXTX_INTR_VEC_ID) { 3836e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 3837e99981afSDavid Marchand "Too many Rx interrupts requested, maximum number: %d", 38386986cdc4SMichal Krawczyk RTE_MAX_RXTX_INTR_VEC_ID); 38396986cdc4SMichal Krawczyk rc = -ENOTSUP; 38406986cdc4SMichal Krawczyk goto enable_intr; 38416986cdc4SMichal Krawczyk } 38426986cdc4SMichal Krawczyk 3843d61138d4SHarman Kalra /* Allocate the vector list */ 3844d61138d4SHarman Kalra if (rte_intr_vec_list_alloc(intr_handle, "intr_vec", 3845d61138d4SHarman Kalra dev->data->nb_rx_queues)) { 3846e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 3847e99981afSDavid Marchand "Failed to allocate interrupt vector for %d queues", 38486986cdc4SMichal Krawczyk dev->data->nb_rx_queues); 38496986cdc4SMichal Krawczyk rc = -ENOMEM; 38506986cdc4SMichal Krawczyk goto enable_intr; 38516986cdc4SMichal Krawczyk } 38526986cdc4SMichal Krawczyk 38536986cdc4SMichal Krawczyk rc = rte_intr_efd_enable(intr_handle, vectors_nb); 38546986cdc4SMichal Krawczyk if (rc != 0) 38556986cdc4SMichal Krawczyk goto free_intr_vec; 38566986cdc4SMichal Krawczyk 38576986cdc4SMichal Krawczyk if (!rte_intr_allow_others(intr_handle)) { 3858e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 3859e99981afSDavid Marchand "Not enough interrupts available to use both ENA Admin and Rx interrupts"); 38606986cdc4SMichal Krawczyk goto disable_intr_efd; 38616986cdc4SMichal Krawczyk } 38626986cdc4SMichal Krawczyk 38636986cdc4SMichal Krawczyk for (i = 0; i < vectors_nb; ++i) 3864d61138d4SHarman Kalra if (rte_intr_vec_list_index_set(intr_handle, i, 3865d61138d4SHarman Kalra RTE_INTR_VEC_RXTX_OFFSET + i)) 3866d61138d4SHarman Kalra goto disable_intr_efd; 38676986cdc4SMichal Krawczyk 38686986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 38696986cdc4SMichal Krawczyk return 0; 38706986cdc4SMichal Krawczyk 38716986cdc4SMichal Krawczyk disable_intr_efd: 38726986cdc4SMichal Krawczyk rte_intr_efd_disable(intr_handle); 38736986cdc4SMichal Krawczyk free_intr_vec: 3874d61138d4SHarman Kalra rte_intr_vec_list_free(intr_handle); 38756986cdc4SMichal Krawczyk enable_intr: 38766986cdc4SMichal Krawczyk rte_intr_enable(intr_handle); 38776986cdc4SMichal Krawczyk return rc; 38786986cdc4SMichal Krawczyk } 38796986cdc4SMichal Krawczyk 38806986cdc4SMichal Krawczyk static void ena_rx_queue_intr_set(struct rte_eth_dev *dev, 38816986cdc4SMichal Krawczyk uint16_t queue_id, 38826986cdc4SMichal Krawczyk bool unmask) 38836986cdc4SMichal Krawczyk { 38846986cdc4SMichal Krawczyk struct ena_adapter *adapter = dev->data->dev_private; 38856986cdc4SMichal Krawczyk struct ena_ring *rxq = &adapter->rx_ring[queue_id]; 38866986cdc4SMichal Krawczyk struct ena_eth_io_intr_reg intr_reg; 38876986cdc4SMichal Krawczyk 3888f73f53f7SShai Brandes ena_com_update_intr_reg(&intr_reg, 0, 0, unmask, 1); 38896986cdc4SMichal Krawczyk ena_com_unmask_intr(rxq->ena_com_io_cq, &intr_reg); 38906986cdc4SMichal Krawczyk } 38916986cdc4SMichal Krawczyk 38926986cdc4SMichal Krawczyk static int ena_rx_queue_intr_enable(struct rte_eth_dev *dev, 38936986cdc4SMichal Krawczyk uint16_t queue_id) 38946986cdc4SMichal Krawczyk { 38956986cdc4SMichal Krawczyk ena_rx_queue_intr_set(dev, queue_id, true); 38966986cdc4SMichal Krawczyk 38976986cdc4SMichal Krawczyk return 0; 38986986cdc4SMichal Krawczyk } 38996986cdc4SMichal Krawczyk 39006986cdc4SMichal Krawczyk static int ena_rx_queue_intr_disable(struct rte_eth_dev *dev, 39016986cdc4SMichal Krawczyk uint16_t queue_id) 39026986cdc4SMichal Krawczyk { 39036986cdc4SMichal Krawczyk ena_rx_queue_intr_set(dev, queue_id, false); 39046986cdc4SMichal Krawczyk 39056986cdc4SMichal Krawczyk return 0; 39066986cdc4SMichal Krawczyk } 39076986cdc4SMichal Krawczyk 3908b9b05d6fSMichal Krawczyk static int ena_configure_aenq(struct ena_adapter *adapter) 3909b9b05d6fSMichal Krawczyk { 3910b9b05d6fSMichal Krawczyk uint32_t aenq_groups = adapter->all_aenq_groups; 3911b9b05d6fSMichal Krawczyk int rc; 3912b9b05d6fSMichal Krawczyk 3913b9b05d6fSMichal Krawczyk /* All_aenq_groups holds all AENQ functions supported by the device and 3914b9b05d6fSMichal Krawczyk * the HW, so at first we need to be sure the LSC request is valid. 3915b9b05d6fSMichal Krawczyk */ 3916b9b05d6fSMichal Krawczyk if (adapter->edev_data->dev_conf.intr_conf.lsc != 0) { 3917b9b05d6fSMichal Krawczyk if (!(aenq_groups & BIT(ENA_ADMIN_LINK_CHANGE))) { 3918e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 3919e99981afSDavid Marchand "LSC requested, but it's not supported by the AENQ"); 3920b9b05d6fSMichal Krawczyk return -EINVAL; 3921b9b05d6fSMichal Krawczyk } 3922b9b05d6fSMichal Krawczyk } else { 3923b9b05d6fSMichal Krawczyk /* If LSC wasn't enabled by the app, let's enable all supported 3924b9b05d6fSMichal Krawczyk * AENQ procedures except the LSC. 3925b9b05d6fSMichal Krawczyk */ 3926b9b05d6fSMichal Krawczyk aenq_groups &= ~BIT(ENA_ADMIN_LINK_CHANGE); 3927b9b05d6fSMichal Krawczyk } 3928b9b05d6fSMichal Krawczyk 3929b9b05d6fSMichal Krawczyk rc = ena_com_set_aenq_config(&adapter->ena_dev, aenq_groups); 3930b9b05d6fSMichal Krawczyk if (rc != 0) { 3931e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Cannot configure AENQ groups, rc=%d", rc); 3932b9b05d6fSMichal Krawczyk return rc; 3933b9b05d6fSMichal Krawczyk } 3934b9b05d6fSMichal Krawczyk 3935b9b05d6fSMichal Krawczyk adapter->active_aenq_groups = aenq_groups; 3936b9b05d6fSMichal Krawczyk 3937b9b05d6fSMichal Krawczyk return 0; 3938b9b05d6fSMichal Krawczyk } 3939b9b05d6fSMichal Krawczyk 3940e3595539SStanislaw Kardach int ena_mp_indirect_table_set(struct ena_adapter *adapter) 3941e3595539SStanislaw Kardach { 3942e3595539SStanislaw Kardach return ENA_PROXY(adapter, ena_com_indirect_table_set, &adapter->ena_dev); 3943e3595539SStanislaw Kardach } 3944e3595539SStanislaw Kardach 3945e3595539SStanislaw Kardach int ena_mp_indirect_table_get(struct ena_adapter *adapter, 3946e3595539SStanislaw Kardach uint32_t *indirect_table) 3947e3595539SStanislaw Kardach { 3948e3595539SStanislaw Kardach return ENA_PROXY(adapter, ena_com_indirect_table_get, &adapter->ena_dev, 3949e3595539SStanislaw Kardach indirect_table); 3950e3595539SStanislaw Kardach } 3951e3595539SStanislaw Kardach 3952ca148440SMichal Krawczyk /********************************************************************* 3953850e1bb1SMichal Krawczyk * ena_plat_dpdk.h functions implementations 3954850e1bb1SMichal Krawczyk *********************************************************************/ 3955850e1bb1SMichal Krawczyk 3956850e1bb1SMichal Krawczyk const struct rte_memzone * 3957850e1bb1SMichal Krawczyk ena_mem_alloc_coherent(struct rte_eth_dev_data *data, size_t size, 3958850e1bb1SMichal Krawczyk int socket_id, unsigned int alignment, void **virt_addr, 3959850e1bb1SMichal Krawczyk dma_addr_t *phys_addr) 3960850e1bb1SMichal Krawczyk { 3961850e1bb1SMichal Krawczyk char z_name[RTE_MEMZONE_NAMESIZE]; 3962850e1bb1SMichal Krawczyk struct ena_adapter *adapter = data->dev_private; 3963850e1bb1SMichal Krawczyk const struct rte_memzone *memzone; 3964850e1bb1SMichal Krawczyk int rc; 3965850e1bb1SMichal Krawczyk 3966850e1bb1SMichal Krawczyk rc = snprintf(z_name, RTE_MEMZONE_NAMESIZE, "ena_p%d_mz%" PRIu64 "", 3967850e1bb1SMichal Krawczyk data->port_id, adapter->memzone_cnt); 3968850e1bb1SMichal Krawczyk if (rc >= RTE_MEMZONE_NAMESIZE) { 3969e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 3970e99981afSDavid Marchand "Name for the ena_com memzone is too long. Port: %d, mz_num: %" PRIu64, 3971850e1bb1SMichal Krawczyk data->port_id, adapter->memzone_cnt); 3972850e1bb1SMichal Krawczyk goto error; 3973850e1bb1SMichal Krawczyk } 3974850e1bb1SMichal Krawczyk adapter->memzone_cnt++; 3975850e1bb1SMichal Krawczyk 3976850e1bb1SMichal Krawczyk memzone = rte_memzone_reserve_aligned(z_name, size, socket_id, 3977850e1bb1SMichal Krawczyk RTE_MEMZONE_IOVA_CONTIG, alignment); 3978850e1bb1SMichal Krawczyk if (memzone == NULL) { 3979e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to allocate ena_com memzone: %s", 3980850e1bb1SMichal Krawczyk z_name); 3981850e1bb1SMichal Krawczyk goto error; 3982850e1bb1SMichal Krawczyk } 3983850e1bb1SMichal Krawczyk 3984850e1bb1SMichal Krawczyk memset(memzone->addr, 0, size); 3985850e1bb1SMichal Krawczyk *virt_addr = memzone->addr; 3986850e1bb1SMichal Krawczyk *phys_addr = memzone->iova; 3987850e1bb1SMichal Krawczyk 3988850e1bb1SMichal Krawczyk return memzone; 3989850e1bb1SMichal Krawczyk 3990850e1bb1SMichal Krawczyk error: 3991850e1bb1SMichal Krawczyk *virt_addr = NULL; 3992850e1bb1SMichal Krawczyk *phys_addr = 0; 3993850e1bb1SMichal Krawczyk 3994850e1bb1SMichal Krawczyk return NULL; 3995850e1bb1SMichal Krawczyk } 3996850e1bb1SMichal Krawczyk 3997850e1bb1SMichal Krawczyk 3998850e1bb1SMichal Krawczyk /********************************************************************* 3999ca148440SMichal Krawczyk * PMD configuration 4000ca148440SMichal Krawczyk *********************************************************************/ 4001fdf91e0fSJan Blunck static int eth_ena_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 4002fdf91e0fSJan Blunck struct rte_pci_device *pci_dev) 4003fdf91e0fSJan Blunck { 4004fdf91e0fSJan Blunck return rte_eth_dev_pci_generic_probe(pci_dev, 4005fdf91e0fSJan Blunck sizeof(struct ena_adapter), eth_ena_dev_init); 4006fdf91e0fSJan Blunck } 4007fdf91e0fSJan Blunck 4008fdf91e0fSJan Blunck static int eth_ena_pci_remove(struct rte_pci_device *pci_dev) 4009fdf91e0fSJan Blunck { 4010eb0ef49dSMichal Krawczyk return rte_eth_dev_pci_generic_remove(pci_dev, eth_ena_dev_uninit); 4011fdf91e0fSJan Blunck } 4012fdf91e0fSJan Blunck 4013fdf91e0fSJan Blunck static struct rte_pci_driver rte_ena_pmd = { 40141173fca2SJan Medala .id_table = pci_id_ena_map, 401505e0eee0SRafal Kozik .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | 401605e0eee0SRafal Kozik RTE_PCI_DRV_WC_ACTIVATE, 4017fdf91e0fSJan Blunck .probe = eth_ena_pci_probe, 4018fdf91e0fSJan Blunck .remove = eth_ena_pci_remove, 40191173fca2SJan Medala }; 40201173fca2SJan Medala 4021fdf91e0fSJan Blunck RTE_PMD_REGISTER_PCI(net_ena, rte_ena_pmd); 402201f19227SShreyansh Jain RTE_PMD_REGISTER_PCI_TABLE(net_ena, pci_id_ena_map); 402306e81dc9SDavid Marchand RTE_PMD_REGISTER_KMOD_DEP(net_ena, "* igb_uio | uio_pci_generic | vfio-pci"); 40249944919eSMichal Krawczyk RTE_PMD_REGISTER_PARAM_STRING(net_ena, 4025d7918d19SShai Brandes ENA_DEVARG_LLQ_POLICY "=<0|1|2|3> " 4026ca1dfa85SShai Brandes ENA_DEVARG_MISS_TXC_TO "=<uint>" 4027ca1dfa85SShai Brandes ENA_DEVARG_CONTROL_PATH_POLL_INTERVAL "=<0-1000>"); 4028eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(ena_logtype_init, init, NOTICE); 4029eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(ena_logtype_driver, driver, NOTICE); 40300a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_RX 40310a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_rx, rx, DEBUG); 40326f1c9df9SStephen Hemminger #endif 40330a001d69SMichal Krawczyk #ifdef RTE_ETHDEV_DEBUG_TX 40340a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_tx, tx, DEBUG); 40356f1c9df9SStephen Hemminger #endif 40360a001d69SMichal Krawczyk RTE_LOG_REGISTER_SUFFIX(ena_logtype_com, com, WARNING); 40373adcba9aSMichal Krawczyk 40383adcba9aSMichal Krawczyk /****************************************************************************** 40393adcba9aSMichal Krawczyk ******************************** AENQ Handlers ******************************* 40403adcba9aSMichal Krawczyk *****************************************************************************/ 4041ca148440SMichal Krawczyk static void ena_update_on_link_change(void *adapter_data, 4042ca148440SMichal Krawczyk struct ena_admin_aenq_entry *aenq_e) 4043ca148440SMichal Krawczyk { 4044aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 4045aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 4046ca148440SMichal Krawczyk struct ena_admin_aenq_link_change_desc *aenq_link_desc; 4047ca148440SMichal Krawczyk uint32_t status; 4048ca148440SMichal Krawczyk 4049ca148440SMichal Krawczyk aenq_link_desc = (struct ena_admin_aenq_link_change_desc *)aenq_e; 4050ca148440SMichal Krawczyk 4051ca148440SMichal Krawczyk status = get_ena_admin_aenq_link_change_desc_link_status(aenq_link_desc); 4052ca148440SMichal Krawczyk adapter->link_status = status; 4053ca148440SMichal Krawczyk 4054ca148440SMichal Krawczyk ena_link_update(eth_dev, 0); 40555723fbedSFerruh Yigit rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL); 4056ca148440SMichal Krawczyk } 4057ca148440SMichal Krawczyk 4058aab58857SStanislaw Kardach static void ena_notification(void *adapter_data, 4059f01f060cSRafal Kozik struct ena_admin_aenq_entry *aenq_e) 4060f01f060cSRafal Kozik { 4061aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 4062aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 4063f01f060cSRafal Kozik struct ena_admin_ena_hw_hints *hints; 4064f01f060cSRafal Kozik 4065f01f060cSRafal Kozik if (aenq_e->aenq_common_desc.group != ENA_ADMIN_NOTIFICATION) 4066e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, "Invalid AENQ group: %x. Expected: %x", 4067f01f060cSRafal Kozik aenq_e->aenq_common_desc.group, 4068f01f060cSRafal Kozik ENA_ADMIN_NOTIFICATION); 4069f01f060cSRafal Kozik 4070b19f366cSMichal Krawczyk switch (aenq_e->aenq_common_desc.syndrome) { 4071f01f060cSRafal Kozik case ENA_ADMIN_UPDATE_HINTS: 4072f01f060cSRafal Kozik hints = (struct ena_admin_ena_hw_hints *) 4073f01f060cSRafal Kozik (&aenq_e->inline_data_w4); 4074f01f060cSRafal Kozik ena_update_hints(adapter, hints); 4075f01f060cSRafal Kozik break; 4076f01f060cSRafal Kozik default: 4077e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Invalid AENQ notification link state: %d", 4078b19f366cSMichal Krawczyk aenq_e->aenq_common_desc.syndrome); 4079f01f060cSRafal Kozik } 4080f01f060cSRafal Kozik } 4081f01f060cSRafal Kozik 4082d9b8b106SMichal Krawczyk static void ena_keep_alive(void *adapter_data, 4083d9b8b106SMichal Krawczyk __rte_unused struct ena_admin_aenq_entry *aenq_e) 4084d9b8b106SMichal Krawczyk { 4085aab58857SStanislaw Kardach struct rte_eth_dev *eth_dev = adapter_data; 4086aab58857SStanislaw Kardach struct ena_adapter *adapter = eth_dev->data->dev_private; 408794c3e376SRafal Kozik struct ena_admin_aenq_keep_alive_desc *desc; 408894c3e376SRafal Kozik uint64_t rx_drops; 4089e1e73e32SMichal Krawczyk uint64_t tx_drops; 409077d4ed30SShai Brandes uint64_t rx_overruns; 4091d9b8b106SMichal Krawczyk 4092d9b8b106SMichal Krawczyk adapter->timestamp_wd = rte_get_timer_cycles(); 409394c3e376SRafal Kozik 409494c3e376SRafal Kozik desc = (struct ena_admin_aenq_keep_alive_desc *)aenq_e; 409594c3e376SRafal Kozik rx_drops = ((uint64_t)desc->rx_drops_high << 32) | desc->rx_drops_low; 4096e1e73e32SMichal Krawczyk tx_drops = ((uint64_t)desc->tx_drops_high << 32) | desc->tx_drops_low; 409777d4ed30SShai Brandes rx_overruns = ((uint64_t)desc->rx_overruns_high << 32) | desc->rx_overruns_low; 4098e1e73e32SMichal Krawczyk 4099dae29f75SShai Brandes /* 4100dae29f75SShai Brandes * Depending on its acceleration support, the device updates a different statistic when 4101dae29f75SShai Brandes * Rx packet is dropped because there are no available buffers to accommodate it. 4102dae29f75SShai Brandes */ 4103dae29f75SShai Brandes adapter->drv_stats->rx_drops = rx_drops + rx_overruns; 4104e1e73e32SMichal Krawczyk adapter->dev_stats.tx_drops = tx_drops; 4105d9b8b106SMichal Krawczyk } 4106d9b8b106SMichal Krawczyk 41072c0f7536SShai Brandes static void ena_suboptimal_configuration(__rte_unused void *adapter_data, 41082c0f7536SShai Brandes struct ena_admin_aenq_entry *aenq_e) 41092c0f7536SShai Brandes { 41102c0f7536SShai Brandes struct ena_admin_aenq_conf_notifications_desc *desc; 41112c0f7536SShai Brandes int bit, num_bits; 41122c0f7536SShai Brandes 41132c0f7536SShai Brandes desc = (struct ena_admin_aenq_conf_notifications_desc *)aenq_e; 41142c0f7536SShai Brandes num_bits = BITS_PER_TYPE(desc->notifications_bitmap); 41152c0f7536SShai Brandes for (bit = 0; bit < num_bits; bit++) { 41162c0f7536SShai Brandes if (desc->notifications_bitmap & RTE_BIT64(bit)) { 4117e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, 4118e99981afSDavid Marchand "Sub-optimal configuration notification code: %d", bit + 1); 41192c0f7536SShai Brandes } 41202c0f7536SShai Brandes } 41212c0f7536SShai Brandes } 41222c0f7536SShai Brandes 41233adcba9aSMichal Krawczyk /** 41243adcba9aSMichal Krawczyk * This handler will called for unknown event group or unimplemented handlers 41253adcba9aSMichal Krawczyk **/ 41263adcba9aSMichal Krawczyk static void unimplemented_aenq_handler(__rte_unused void *data, 41273adcba9aSMichal Krawczyk __rte_unused struct ena_admin_aenq_entry *aenq_e) 41283adcba9aSMichal Krawczyk { 4129e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 4130e99981afSDavid Marchand "Unknown event was received or event with unimplemented handler"); 41313adcba9aSMichal Krawczyk } 41323adcba9aSMichal Krawczyk 4133ca148440SMichal Krawczyk static struct ena_aenq_handlers aenq_handlers = { 41343adcba9aSMichal Krawczyk .handlers = { 4135ca148440SMichal Krawczyk [ENA_ADMIN_LINK_CHANGE] = ena_update_on_link_change, 4136f01f060cSRafal Kozik [ENA_ADMIN_NOTIFICATION] = ena_notification, 41372c0f7536SShai Brandes [ENA_ADMIN_KEEP_ALIVE] = ena_keep_alive, 41382c0f7536SShai Brandes [ENA_ADMIN_CONF_NOTIFICATIONS] = ena_suboptimal_configuration 41393adcba9aSMichal Krawczyk }, 41403adcba9aSMichal Krawczyk .unimplemented_handler = unimplemented_aenq_handler 41413adcba9aSMichal Krawczyk }; 4142e3595539SStanislaw Kardach 4143e3595539SStanislaw Kardach /********************************************************************* 4144e3595539SStanislaw Kardach * Multi-Process communication request handling (in primary) 4145e3595539SStanislaw Kardach *********************************************************************/ 4146e3595539SStanislaw Kardach static int 4147e3595539SStanislaw Kardach ena_mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer) 4148e3595539SStanislaw Kardach { 4149e3595539SStanislaw Kardach const struct ena_mp_body *req = 4150e3595539SStanislaw Kardach (const struct ena_mp_body *)mp_msg->param; 4151e3595539SStanislaw Kardach struct ena_adapter *adapter; 4152e3595539SStanislaw Kardach struct ena_com_dev *ena_dev; 4153e3595539SStanislaw Kardach struct ena_mp_body *rsp; 4154e3595539SStanislaw Kardach struct rte_mp_msg mp_rsp; 4155e3595539SStanislaw Kardach struct rte_eth_dev *dev; 4156e3595539SStanislaw Kardach int res = 0; 4157e3595539SStanislaw Kardach 4158e3595539SStanislaw Kardach rsp = (struct ena_mp_body *)&mp_rsp.param; 4159e3595539SStanislaw Kardach mp_msg_init(&mp_rsp, req->type, req->port_id); 4160e3595539SStanislaw Kardach 4161e3595539SStanislaw Kardach if (!rte_eth_dev_is_valid_port(req->port_id)) { 4162e3595539SStanislaw Kardach rte_errno = ENODEV; 4163e3595539SStanislaw Kardach res = -rte_errno; 4164e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Unknown port %d in request %d", 4165e3595539SStanislaw Kardach req->port_id, req->type); 4166e3595539SStanislaw Kardach goto end; 4167e3595539SStanislaw Kardach } 4168e3595539SStanislaw Kardach dev = &rte_eth_devices[req->port_id]; 4169e3595539SStanislaw Kardach adapter = dev->data->dev_private; 4170e3595539SStanislaw Kardach ena_dev = &adapter->ena_dev; 4171e3595539SStanislaw Kardach 4172e3595539SStanislaw Kardach switch (req->type) { 4173e3595539SStanislaw Kardach case ENA_MP_DEV_STATS_GET: 4174e3595539SStanislaw Kardach res = ena_com_get_dev_basic_stats(ena_dev, 4175e3595539SStanislaw Kardach &adapter->basic_stats); 4176e3595539SStanislaw Kardach break; 4177e3595539SStanislaw Kardach case ENA_MP_ENI_STATS_GET: 4178e3595539SStanislaw Kardach res = ena_com_get_eni_stats(ena_dev, 417992401abfSShai Brandes (struct ena_admin_eni_stats *)&adapter->metrics_stats); 4180e3595539SStanislaw Kardach break; 4181e3595539SStanislaw Kardach case ENA_MP_MTU_SET: 4182e3595539SStanislaw Kardach res = ena_com_set_dev_mtu(ena_dev, req->args.mtu); 4183e3595539SStanislaw Kardach break; 4184e3595539SStanislaw Kardach case ENA_MP_IND_TBL_GET: 4185e3595539SStanislaw Kardach res = ena_com_indirect_table_get(ena_dev, 4186e3595539SStanislaw Kardach adapter->indirect_table); 4187e3595539SStanislaw Kardach break; 4188e3595539SStanislaw Kardach case ENA_MP_IND_TBL_SET: 4189e3595539SStanislaw Kardach res = ena_com_indirect_table_set(ena_dev); 4190e3595539SStanislaw Kardach break; 419192401abfSShai Brandes case ENA_MP_CUSTOMER_METRICS_GET: 419292401abfSShai Brandes res = ena_com_get_customer_metrics(ena_dev, 419392401abfSShai Brandes (char *)adapter->metrics_stats, 4194980d0ba4SShai Brandes adapter->metrics_num * sizeof(uint64_t)); 419592401abfSShai Brandes break; 4196a73dd098SShai Brandes case ENA_MP_SRD_STATS_GET: 4197a73dd098SShai Brandes res = ena_com_get_ena_srd_info(ena_dev, 4198a73dd098SShai Brandes (struct ena_admin_ena_srd_info *)&adapter->srd_stats); 4199a73dd098SShai Brandes break; 4200e3595539SStanislaw Kardach default: 4201e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Unknown request type %d", req->type); 4202e3595539SStanislaw Kardach res = -EINVAL; 4203e3595539SStanislaw Kardach break; 4204e3595539SStanislaw Kardach } 4205e3595539SStanislaw Kardach 4206e3595539SStanislaw Kardach end: 4207e3595539SStanislaw Kardach /* Save processing result in the reply */ 4208e3595539SStanislaw Kardach rsp->result = res; 4209e3595539SStanislaw Kardach /* Return just IPC processing status */ 4210e3595539SStanislaw Kardach return rte_mp_reply(&mp_rsp, peer); 4211e3595539SStanislaw Kardach } 42121f11149dSShai Brandes 42131f11149dSShai Brandes static bool ena_use_large_llq_hdr(struct ena_adapter *adapter, uint8_t recommended_entry_size) 42141f11149dSShai Brandes { 42151f11149dSShai Brandes if (adapter->llq_header_policy == ENA_LLQ_POLICY_LARGE) { 42161f11149dSShai Brandes return true; 42171f11149dSShai Brandes } else if (adapter->llq_header_policy == ENA_LLQ_POLICY_RECOMMENDED) { 4218e99981afSDavid Marchand PMD_DRV_LOG_LINE(INFO, "Recommended device entry size policy %u", 42191f11149dSShai Brandes recommended_entry_size); 42201f11149dSShai Brandes if (recommended_entry_size == ENA_ADMIN_LIST_ENTRY_SIZE_256B) 42211f11149dSShai Brandes return true; 42221f11149dSShai Brandes } 42231f11149dSShai Brandes return false; 42241f11149dSShai Brandes } 4225