150da8b0dSAllain Legacy /* SPDX-License-Identifier: BSD-3-Clause 250da8b0dSAllain Legacy * Copyright(c) 2013-2017 Wind River Systems, Inc. 3908072e9SAllain Legacy */ 4908072e9SAllain Legacy 5908072e9SAllain Legacy #include <stdint.h> 6908072e9SAllain Legacy #include <string.h> 7908072e9SAllain Legacy #include <stdio.h> 8908072e9SAllain Legacy #include <errno.h> 9908072e9SAllain Legacy #include <unistd.h> 10908072e9SAllain Legacy 11df96fd0dSBruce Richardson #include <ethdev_driver.h> 12df96fd0dSBruce Richardson #include <ethdev_pci.h> 13908072e9SAllain Legacy #include <rte_memcpy.h> 14908072e9SAllain Legacy #include <rte_string_fns.h> 15908072e9SAllain Legacy #include <rte_malloc.h> 16908072e9SAllain Legacy #include <rte_atomic.h> 17908072e9SAllain Legacy #include <rte_branch_prediction.h> 18908072e9SAllain Legacy #include <rte_pci.h> 191f37cb2bSDavid Marchand #include <bus_pci_driver.h> 20908072e9SAllain Legacy #include <rte_ether.h> 21908072e9SAllain Legacy #include <rte_common.h> 22908072e9SAllain Legacy #include <rte_cycles.h> 2382e140b8SAllain Legacy #include <rte_spinlock.h> 24908072e9SAllain Legacy #include <rte_byteorder.h> 251acb7f54SDavid Marchand #include <dev_driver.h> 26908072e9SAllain Legacy #include <rte_memory.h> 27908072e9SAllain Legacy #include <rte_eal.h> 28c0ad5842SAllain Legacy #include <rte_io.h> 29908072e9SAllain Legacy 30908072e9SAllain Legacy #include "rte_avp_common.h" 31908072e9SAllain Legacy #include "rte_avp_fifo.h" 32908072e9SAllain Legacy 33908072e9SAllain Legacy #include "avp_logs.h" 34908072e9SAllain Legacy 3582e140b8SAllain Legacy static int avp_dev_create(struct rte_pci_device *pci_dev, 3682e140b8SAllain Legacy struct rte_eth_dev *eth_dev); 37908072e9SAllain Legacy 381a859223SAllain Legacy static int avp_dev_configure(struct rte_eth_dev *dev); 39ea37523dSAllain Legacy static int avp_dev_start(struct rte_eth_dev *dev); 4062024eb8SIvan Ilchenko static int avp_dev_stop(struct rte_eth_dev *dev); 41b142387bSThomas Monjalon static int avp_dev_close(struct rte_eth_dev *dev); 42bdad90d1SIvan Ilchenko static int avp_dev_info_get(struct rte_eth_dev *dev, 431a859223SAllain Legacy struct rte_eth_dev_info *dev_info); 44289ba0c0SDavid Harton static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask); 45dd2c630aSFerruh Yigit static int avp_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); 469039c812SAndrew Rybchenko static int avp_dev_promiscuous_enable(struct rte_eth_dev *dev); 479039c812SAndrew Rybchenko static int avp_dev_promiscuous_disable(struct rte_eth_dev *dev); 488129545eSAllain Legacy 49cce4367fSAllain Legacy static int avp_dev_rx_queue_setup(struct rte_eth_dev *dev, 50cce4367fSAllain Legacy uint16_t rx_queue_id, 51cce4367fSAllain Legacy uint16_t nb_rx_desc, 52cce4367fSAllain Legacy unsigned int socket_id, 53cce4367fSAllain Legacy const struct rte_eth_rxconf *rx_conf, 54cce4367fSAllain Legacy struct rte_mempool *pool); 551a859223SAllain Legacy 56cce4367fSAllain Legacy static int avp_dev_tx_queue_setup(struct rte_eth_dev *dev, 57cce4367fSAllain Legacy uint16_t tx_queue_id, 58cce4367fSAllain Legacy uint16_t nb_tx_desc, 59cce4367fSAllain Legacy unsigned int socket_id, 60cce4367fSAllain Legacy const struct rte_eth_txconf *tx_conf); 61cce4367fSAllain Legacy 6250db69fdSAllain Legacy static uint16_t avp_recv_scattered_pkts(void *rx_queue, 6350db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 6450db69fdSAllain Legacy uint16_t nb_pkts); 6550db69fdSAllain Legacy 6650db69fdSAllain Legacy static uint16_t avp_recv_pkts(void *rx_queue, 6750db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 6850db69fdSAllain Legacy uint16_t nb_pkts); 69295abce2SAllain Legacy 70295abce2SAllain Legacy static uint16_t avp_xmit_scattered_pkts(void *tx_queue, 71295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 72295abce2SAllain Legacy uint16_t nb_pkts); 73295abce2SAllain Legacy 74295abce2SAllain Legacy static uint16_t avp_xmit_pkts(void *tx_queue, 75295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 76295abce2SAllain Legacy uint16_t nb_pkts); 77295abce2SAllain Legacy 787483341aSXueming Li static void avp_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 797483341aSXueming Li static void avp_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 80295abce2SAllain Legacy 81d5b0924bSMatan Azrad static int avp_dev_stats_get(struct rte_eth_dev *dev, 825a5abe2dSAllain Legacy struct rte_eth_stats *stats); 839970a9adSIgor Romanov static int avp_dev_stats_reset(struct rte_eth_dev *dev); 845a5abe2dSAllain Legacy 85295abce2SAllain Legacy 8650db69fdSAllain Legacy #define AVP_MAX_RX_BURST 64 87295abce2SAllain Legacy #define AVP_MAX_TX_BURST 64 88908072e9SAllain Legacy #define AVP_MAX_MAC_ADDRS 1 8935b2d13fSOlivier Matz #define AVP_MIN_RX_BUFSIZE RTE_ETHER_MIN_LEN 90908072e9SAllain Legacy 91908072e9SAllain Legacy 92908072e9SAllain Legacy /* 93908072e9SAllain Legacy * Defines the number of microseconds to wait before checking the response 94908072e9SAllain Legacy * queue for completion. 95908072e9SAllain Legacy */ 96908072e9SAllain Legacy #define AVP_REQUEST_DELAY_USECS (5000) 97908072e9SAllain Legacy 98908072e9SAllain Legacy /* 99908072e9SAllain Legacy * Defines the number times to check the response queue for completion before 100908072e9SAllain Legacy * declaring a timeout. 101908072e9SAllain Legacy */ 102908072e9SAllain Legacy #define AVP_MAX_REQUEST_RETRY (100) 103908072e9SAllain Legacy 104908072e9SAllain Legacy /* Defines the current PCI driver version number */ 105908072e9SAllain Legacy #define AVP_DPDK_DRIVER_VERSION RTE_AVP_CURRENT_GUEST_VERSION 106908072e9SAllain Legacy 107908072e9SAllain Legacy /* 108908072e9SAllain Legacy * The set of PCI devices this driver supports 109908072e9SAllain Legacy */ 110908072e9SAllain Legacy static const struct rte_pci_id pci_id_avp_map[] = { 111908072e9SAllain Legacy { .vendor_id = RTE_AVP_PCI_VENDOR_ID, 112908072e9SAllain Legacy .device_id = RTE_AVP_PCI_DEVICE_ID, 113908072e9SAllain Legacy .subsystem_vendor_id = RTE_AVP_PCI_SUB_VENDOR_ID, 114908072e9SAllain Legacy .subsystem_device_id = RTE_AVP_PCI_SUB_DEVICE_ID, 115908072e9SAllain Legacy .class_id = RTE_CLASS_ANY_ID, 116908072e9SAllain Legacy }, 117908072e9SAllain Legacy 118908072e9SAllain Legacy { .vendor_id = 0, /* sentinel */ 119908072e9SAllain Legacy }, 120908072e9SAllain Legacy }; 121908072e9SAllain Legacy 1221a859223SAllain Legacy /* 1231a859223SAllain Legacy * dev_ops for avp, bare necessities for basic operation 1241a859223SAllain Legacy */ 1251a859223SAllain Legacy static const struct eth_dev_ops avp_eth_dev_ops = { 1261a859223SAllain Legacy .dev_configure = avp_dev_configure, 127ea37523dSAllain Legacy .dev_start = avp_dev_start, 128ea37523dSAllain Legacy .dev_stop = avp_dev_stop, 129ea37523dSAllain Legacy .dev_close = avp_dev_close, 1301a859223SAllain Legacy .dev_infos_get = avp_dev_info_get, 1311a859223SAllain Legacy .vlan_offload_set = avp_vlan_offload_set, 1325a5abe2dSAllain Legacy .stats_get = avp_dev_stats_get, 1335a5abe2dSAllain Legacy .stats_reset = avp_dev_stats_reset, 1341a859223SAllain Legacy .link_update = avp_dev_link_update, 1358129545eSAllain Legacy .promiscuous_enable = avp_dev_promiscuous_enable, 1368129545eSAllain Legacy .promiscuous_disable = avp_dev_promiscuous_disable, 137cce4367fSAllain Legacy .rx_queue_setup = avp_dev_rx_queue_setup, 138cce4367fSAllain Legacy .rx_queue_release = avp_dev_rx_queue_release, 139cce4367fSAllain Legacy .tx_queue_setup = avp_dev_tx_queue_setup, 140cce4367fSAllain Legacy .tx_queue_release = avp_dev_tx_queue_release, 1411a859223SAllain Legacy }; 142908072e9SAllain Legacy 143c0ad5842SAllain Legacy /**@{ AVP device flags */ 144c0ad5842SAllain Legacy #define AVP_F_PROMISC (1 << 1) 145c0ad5842SAllain Legacy #define AVP_F_CONFIGURED (1 << 2) 146c0ad5842SAllain Legacy #define AVP_F_LINKUP (1 << 3) 14782e140b8SAllain Legacy #define AVP_F_DETACHED (1 << 4) 148c0ad5842SAllain Legacy /**@} */ 149c0ad5842SAllain Legacy 150c0ad5842SAllain Legacy /* Ethernet device validation marker */ 151c0ad5842SAllain Legacy #define AVP_ETHDEV_MAGIC 0x92972862 152c0ad5842SAllain Legacy 153908072e9SAllain Legacy /* 154908072e9SAllain Legacy * Defines the AVP device attributes which are attached to an RTE ethernet 155908072e9SAllain Legacy * device 156908072e9SAllain Legacy */ 15727595cd8STyler Retzlaff struct __rte_cache_aligned avp_dev { 158908072e9SAllain Legacy uint32_t magic; /**< Memory validation marker */ 159908072e9SAllain Legacy uint64_t device_id; /**< Unique system identifier */ 1606d13ea8eSOlivier Matz struct rte_ether_addr ethaddr; /**< Host specified MAC address */ 161908072e9SAllain Legacy struct rte_eth_dev_data *dev_data; 162908072e9SAllain Legacy /**< Back pointer to ethernet device data */ 163908072e9SAllain Legacy volatile uint32_t flags; /**< Device operational flags */ 164f8244c63SZhiyong Yang uint16_t port_id; /**< Ethernet port identifier */ 165908072e9SAllain Legacy struct rte_mempool *pool; /**< pkt mbuf mempool */ 166908072e9SAllain Legacy unsigned int guest_mbuf_size; /**< local pool mbuf size */ 167908072e9SAllain Legacy unsigned int host_mbuf_size; /**< host mbuf size */ 168908072e9SAllain Legacy unsigned int max_rx_pkt_len; /**< maximum receive unit */ 169908072e9SAllain Legacy uint32_t host_features; /**< Supported feature bitmap */ 170908072e9SAllain Legacy uint32_t features; /**< Enabled feature bitmap */ 171908072e9SAllain Legacy unsigned int num_tx_queues; /**< Negotiated number of transmit queues */ 172908072e9SAllain Legacy unsigned int max_tx_queues; /**< Maximum number of transmit queues */ 173908072e9SAllain Legacy unsigned int num_rx_queues; /**< Negotiated number of receive queues */ 174908072e9SAllain Legacy unsigned int max_rx_queues; /**< Maximum number of receive queues */ 175908072e9SAllain Legacy 176908072e9SAllain Legacy struct rte_avp_fifo *tx_q[RTE_AVP_MAX_QUEUES]; /**< TX queue */ 177908072e9SAllain Legacy struct rte_avp_fifo *rx_q[RTE_AVP_MAX_QUEUES]; /**< RX queue */ 178908072e9SAllain Legacy struct rte_avp_fifo *alloc_q[RTE_AVP_MAX_QUEUES]; 179908072e9SAllain Legacy /**< Allocated mbufs queue */ 180908072e9SAllain Legacy struct rte_avp_fifo *free_q[RTE_AVP_MAX_QUEUES]; 181908072e9SAllain Legacy /**< To be freed mbufs queue */ 182908072e9SAllain Legacy 18382e140b8SAllain Legacy /* mutual exclusion over the 'flag' and 'resp_q/req_q' fields */ 18482e140b8SAllain Legacy rte_spinlock_t lock; 18582e140b8SAllain Legacy 186908072e9SAllain Legacy /* For request & response */ 187908072e9SAllain Legacy struct rte_avp_fifo *req_q; /**< Request queue */ 188908072e9SAllain Legacy struct rte_avp_fifo *resp_q; /**< Response queue */ 189908072e9SAllain Legacy void *host_sync_addr; /**< (host) Req/Resp Mem address */ 190908072e9SAllain Legacy void *sync_addr; /**< Req/Resp Mem address */ 191908072e9SAllain Legacy void *host_mbuf_addr; /**< (host) MBUF pool start address */ 192908072e9SAllain Legacy void *mbuf_addr; /**< MBUF pool start address */ 19327595cd8STyler Retzlaff }; 194908072e9SAllain Legacy 195908072e9SAllain Legacy /* RTE ethernet private data */ 19627595cd8STyler Retzlaff struct __rte_cache_aligned avp_adapter { 197908072e9SAllain Legacy struct avp_dev avp; 19827595cd8STyler Retzlaff }; 199908072e9SAllain Legacy 200c0ad5842SAllain Legacy 201c0ad5842SAllain Legacy /* 32-bit MMIO register write */ 202c0ad5842SAllain Legacy #define AVP_WRITE32(_value, _addr) rte_write32_relaxed((_value), (_addr)) 203c0ad5842SAllain Legacy 204c0ad5842SAllain Legacy /* 32-bit MMIO register read */ 205c0ad5842SAllain Legacy #define AVP_READ32(_addr) rte_read32_relaxed((_addr)) 206c0ad5842SAllain Legacy 207908072e9SAllain Legacy /* Macro to cast the ethernet device private data to a AVP object */ 208908072e9SAllain Legacy #define AVP_DEV_PRIVATE_TO_HW(adapter) \ 209908072e9SAllain Legacy (&((struct avp_adapter *)adapter)->avp) 210908072e9SAllain Legacy 211908072e9SAllain Legacy /* 212c0ad5842SAllain Legacy * Defines the structure of a AVP device queue for the purpose of handling the 213c0ad5842SAllain Legacy * receive and transmit burst callback functions 214c0ad5842SAllain Legacy */ 215c0ad5842SAllain Legacy struct avp_queue { 216c0ad5842SAllain Legacy struct rte_eth_dev_data *dev_data; 217c0ad5842SAllain Legacy /**< Backpointer to ethernet device data */ 218c0ad5842SAllain Legacy struct avp_dev *avp; /**< Backpointer to AVP device */ 219c0ad5842SAllain Legacy uint16_t queue_id; 220c0ad5842SAllain Legacy /**< Queue identifier used for indexing current queue */ 221c0ad5842SAllain Legacy uint16_t queue_base; 222c0ad5842SAllain Legacy /**< Base queue identifier for queue servicing */ 223c0ad5842SAllain Legacy uint16_t queue_limit; 224c0ad5842SAllain Legacy /**< Maximum queue identifier for queue servicing */ 225c0ad5842SAllain Legacy 226c0ad5842SAllain Legacy uint64_t packets; 227c0ad5842SAllain Legacy uint64_t bytes; 228c0ad5842SAllain Legacy uint64_t errors; 229c0ad5842SAllain Legacy }; 230c0ad5842SAllain Legacy 2311a859223SAllain Legacy /* send a request and wait for a response 2321a859223SAllain Legacy * 2331a859223SAllain Legacy * @warning must be called while holding the avp->lock spinlock. 2341a859223SAllain Legacy */ 2351a859223SAllain Legacy static int 2361a859223SAllain Legacy avp_dev_process_request(struct avp_dev *avp, struct rte_avp_request *request) 2371a859223SAllain Legacy { 2381a859223SAllain Legacy unsigned int retry = AVP_MAX_REQUEST_RETRY; 2391a859223SAllain Legacy void *resp_addr = NULL; 2401a859223SAllain Legacy unsigned int count; 2411a859223SAllain Legacy int ret; 2421a859223SAllain Legacy 243*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Sending request %u to host", request->req_id); 2441a859223SAllain Legacy 2451a859223SAllain Legacy request->result = -ENOTSUP; 2461a859223SAllain Legacy 2471a859223SAllain Legacy /* Discard any stale responses before starting a new request */ 2481a859223SAllain Legacy while (avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1)) 249*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Discarding stale response"); 2501a859223SAllain Legacy 2511a859223SAllain Legacy rte_memcpy(avp->sync_addr, request, sizeof(*request)); 2521a859223SAllain Legacy count = avp_fifo_put(avp->req_q, &avp->host_sync_addr, 1); 2531a859223SAllain Legacy if (count < 1) { 254*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Cannot send request %u to host", 2551a859223SAllain Legacy request->req_id); 2561a859223SAllain Legacy ret = -EBUSY; 2571a859223SAllain Legacy goto done; 2581a859223SAllain Legacy } 2591a859223SAllain Legacy 2601a859223SAllain Legacy while (retry--) { 2611a859223SAllain Legacy /* wait for a response */ 2621a859223SAllain Legacy usleep(AVP_REQUEST_DELAY_USECS); 2631a859223SAllain Legacy 2641a859223SAllain Legacy count = avp_fifo_count(avp->resp_q); 2651a859223SAllain Legacy if (count >= 1) { 2661a859223SAllain Legacy /* response received */ 2671a859223SAllain Legacy break; 2681a859223SAllain Legacy } 2691a859223SAllain Legacy 270e6b87501SFerruh Yigit if (retry == 0) { 271*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Timeout while waiting for a response for %u", 2721a859223SAllain Legacy request->req_id); 2731a859223SAllain Legacy ret = -ETIME; 2741a859223SAllain Legacy goto done; 2751a859223SAllain Legacy } 2761a859223SAllain Legacy } 2771a859223SAllain Legacy 2781a859223SAllain Legacy /* retrieve the response */ 2791a859223SAllain Legacy count = avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1); 2801a859223SAllain Legacy if ((count != 1) || (resp_addr != avp->host_sync_addr)) { 281*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Invalid response from host, count=%u resp=%p host_sync_addr=%p", 2821a859223SAllain Legacy count, resp_addr, avp->host_sync_addr); 2831a859223SAllain Legacy ret = -ENODATA; 2841a859223SAllain Legacy goto done; 2851a859223SAllain Legacy } 2861a859223SAllain Legacy 2871a859223SAllain Legacy /* copy to user buffer */ 2881a859223SAllain Legacy rte_memcpy(request, avp->sync_addr, sizeof(*request)); 2891a859223SAllain Legacy ret = 0; 2901a859223SAllain Legacy 291*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Result %d received for request %u", 2921a859223SAllain Legacy request->result, request->req_id); 2931a859223SAllain Legacy 2941a859223SAllain Legacy done: 2951a859223SAllain Legacy return ret; 2961a859223SAllain Legacy } 2971a859223SAllain Legacy 2981a859223SAllain Legacy static int 299ea37523dSAllain Legacy avp_dev_ctrl_set_link_state(struct rte_eth_dev *eth_dev, unsigned int state) 300ea37523dSAllain Legacy { 301ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 302ea37523dSAllain Legacy struct rte_avp_request request; 303ea37523dSAllain Legacy int ret; 304ea37523dSAllain Legacy 305ea37523dSAllain Legacy /* setup a link state change request */ 306ea37523dSAllain Legacy memset(&request, 0, sizeof(request)); 307ea37523dSAllain Legacy request.req_id = RTE_AVP_REQ_CFG_NETWORK_IF; 308ea37523dSAllain Legacy request.if_up = state; 309ea37523dSAllain Legacy 310ea37523dSAllain Legacy ret = avp_dev_process_request(avp, &request); 311ea37523dSAllain Legacy 312ea37523dSAllain Legacy return ret == 0 ? request.result : ret; 313ea37523dSAllain Legacy } 314ea37523dSAllain Legacy 315ea37523dSAllain Legacy static int 3161a859223SAllain Legacy avp_dev_ctrl_set_config(struct rte_eth_dev *eth_dev, 3171a859223SAllain Legacy struct rte_avp_device_config *config) 3181a859223SAllain Legacy { 3191a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 3201a859223SAllain Legacy struct rte_avp_request request; 3211a859223SAllain Legacy int ret; 3221a859223SAllain Legacy 3231a859223SAllain Legacy /* setup a configure request */ 3241a859223SAllain Legacy memset(&request, 0, sizeof(request)); 3251a859223SAllain Legacy request.req_id = RTE_AVP_REQ_CFG_DEVICE; 3261a859223SAllain Legacy memcpy(&request.config, config, sizeof(request.config)); 3271a859223SAllain Legacy 3281a859223SAllain Legacy ret = avp_dev_process_request(avp, &request); 3291a859223SAllain Legacy 3301a859223SAllain Legacy return ret == 0 ? request.result : ret; 3311a859223SAllain Legacy } 3321a859223SAllain Legacy 333ea37523dSAllain Legacy static int 334ea37523dSAllain Legacy avp_dev_ctrl_shutdown(struct rte_eth_dev *eth_dev) 335ea37523dSAllain Legacy { 336ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 337ea37523dSAllain Legacy struct rte_avp_request request; 338ea37523dSAllain Legacy int ret; 339ea37523dSAllain Legacy 340ea37523dSAllain Legacy /* setup a shutdown request */ 341ea37523dSAllain Legacy memset(&request, 0, sizeof(request)); 342ea37523dSAllain Legacy request.req_id = RTE_AVP_REQ_SHUTDOWN_DEVICE; 343ea37523dSAllain Legacy 344ea37523dSAllain Legacy ret = avp_dev_process_request(avp, &request); 345ea37523dSAllain Legacy 346ea37523dSAllain Legacy return ret == 0 ? request.result : ret; 347ea37523dSAllain Legacy } 348ea37523dSAllain Legacy 34950db69fdSAllain Legacy /* translate from host mbuf virtual address to guest virtual address */ 35050db69fdSAllain Legacy static inline void * 35150db69fdSAllain Legacy avp_dev_translate_buffer(struct avp_dev *avp, void *host_mbuf_address) 35250db69fdSAllain Legacy { 35350db69fdSAllain Legacy return RTE_PTR_ADD(RTE_PTR_SUB(host_mbuf_address, 35450db69fdSAllain Legacy (uintptr_t)avp->host_mbuf_addr), 35550db69fdSAllain Legacy (uintptr_t)avp->mbuf_addr); 35650db69fdSAllain Legacy } 35750db69fdSAllain Legacy 358c0ad5842SAllain Legacy /* translate from host physical address to guest virtual address */ 359c0ad5842SAllain Legacy static void * 360c0ad5842SAllain Legacy avp_dev_translate_address(struct rte_eth_dev *eth_dev, 361df6e0a06SSantosh Shukla rte_iova_t host_phys_addr) 362c0ad5842SAllain Legacy { 363c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 364c0ad5842SAllain Legacy struct rte_mem_resource *resource; 365c0ad5842SAllain Legacy struct rte_avp_memmap_info *info; 366c0ad5842SAllain Legacy struct rte_avp_memmap *map; 367c0ad5842SAllain Legacy off_t offset; 368c0ad5842SAllain Legacy void *addr; 369c0ad5842SAllain Legacy unsigned int i; 370c0ad5842SAllain Legacy 371c0ad5842SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_MEMORY_BAR].addr; 372c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[RTE_AVP_PCI_MEMMAP_BAR]; 373c0ad5842SAllain Legacy info = (struct rte_avp_memmap_info *)resource->addr; 374c0ad5842SAllain Legacy 375c0ad5842SAllain Legacy offset = 0; 376c0ad5842SAllain Legacy for (i = 0; i < info->nb_maps; i++) { 377c0ad5842SAllain Legacy /* search all segments looking for a matching address */ 378c0ad5842SAllain Legacy map = &info->maps[i]; 379c0ad5842SAllain Legacy 380c0ad5842SAllain Legacy if ((host_phys_addr >= map->phys_addr) && 381c0ad5842SAllain Legacy (host_phys_addr < (map->phys_addr + map->length))) { 382c0ad5842SAllain Legacy /* address is within this segment */ 383c0ad5842SAllain Legacy offset += (host_phys_addr - map->phys_addr); 3848a70b112SBruce Richardson addr = RTE_PTR_ADD(addr, (uintptr_t)offset); 385c0ad5842SAllain Legacy 386*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Translating host physical 0x%" PRIx64 " to guest virtual 0x%p", 387c0ad5842SAllain Legacy host_phys_addr, addr); 388c0ad5842SAllain Legacy 389c0ad5842SAllain Legacy return addr; 390c0ad5842SAllain Legacy } 391c0ad5842SAllain Legacy offset += map->length; 392c0ad5842SAllain Legacy } 393c0ad5842SAllain Legacy 394c0ad5842SAllain Legacy return NULL; 395c0ad5842SAllain Legacy } 396c0ad5842SAllain Legacy 397c0ad5842SAllain Legacy /* verify that the incoming device version is compatible with our version */ 398c0ad5842SAllain Legacy static int 399c0ad5842SAllain Legacy avp_dev_version_check(uint32_t version) 400c0ad5842SAllain Legacy { 401c0ad5842SAllain Legacy uint32_t driver = RTE_AVP_STRIP_MINOR_VERSION(AVP_DPDK_DRIVER_VERSION); 402c0ad5842SAllain Legacy uint32_t device = RTE_AVP_STRIP_MINOR_VERSION(version); 403c0ad5842SAllain Legacy 404c0ad5842SAllain Legacy if (device <= driver) { 405c0ad5842SAllain Legacy /* the host driver version is less than or equal to ours */ 406c0ad5842SAllain Legacy return 0; 407c0ad5842SAllain Legacy } 408c0ad5842SAllain Legacy 409c0ad5842SAllain Legacy return 1; 410c0ad5842SAllain Legacy } 411c0ad5842SAllain Legacy 412c0ad5842SAllain Legacy /* verify that memory regions have expected version and validation markers */ 413c0ad5842SAllain Legacy static int 414c0ad5842SAllain Legacy avp_dev_check_regions(struct rte_eth_dev *eth_dev) 415c0ad5842SAllain Legacy { 416c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 417c0ad5842SAllain Legacy struct rte_avp_memmap_info *memmap; 418c0ad5842SAllain Legacy struct rte_avp_device_info *info; 419c0ad5842SAllain Legacy struct rte_mem_resource *resource; 420c0ad5842SAllain Legacy unsigned int i; 421c0ad5842SAllain Legacy 422c0ad5842SAllain Legacy /* Dump resource info for debug */ 423c0ad5842SAllain Legacy for (i = 0; i < PCI_MAX_RESOURCE; i++) { 424c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[i]; 425c0ad5842SAllain Legacy if ((resource->phys_addr == 0) || (resource->len == 0)) 426c0ad5842SAllain Legacy continue; 427c0ad5842SAllain Legacy 428*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "resource[%u]: phys=0x%" PRIx64 " len=%" PRIu64 " addr=%p", 429c0ad5842SAllain Legacy i, resource->phys_addr, 430c0ad5842SAllain Legacy resource->len, resource->addr); 431c0ad5842SAllain Legacy 432c0ad5842SAllain Legacy switch (i) { 433c0ad5842SAllain Legacy case RTE_AVP_PCI_MEMMAP_BAR: 434c0ad5842SAllain Legacy memmap = (struct rte_avp_memmap_info *)resource->addr; 435c0ad5842SAllain Legacy if ((memmap->magic != RTE_AVP_MEMMAP_MAGIC) || 436c0ad5842SAllain Legacy (memmap->version != RTE_AVP_MEMMAP_VERSION)) { 437*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Invalid memmap magic 0x%08x and version %u", 438c0ad5842SAllain Legacy memmap->magic, memmap->version); 439c0ad5842SAllain Legacy return -EINVAL; 440c0ad5842SAllain Legacy } 441c0ad5842SAllain Legacy break; 442c0ad5842SAllain Legacy 443c0ad5842SAllain Legacy case RTE_AVP_PCI_DEVICE_BAR: 444c0ad5842SAllain Legacy info = (struct rte_avp_device_info *)resource->addr; 445c0ad5842SAllain Legacy if ((info->magic != RTE_AVP_DEVICE_MAGIC) || 446c0ad5842SAllain Legacy avp_dev_version_check(info->version)) { 447*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Invalid device info magic 0x%08x or version 0x%08x > 0x%08x", 448c0ad5842SAllain Legacy info->magic, info->version, 449c0ad5842SAllain Legacy AVP_DPDK_DRIVER_VERSION); 450c0ad5842SAllain Legacy return -EINVAL; 451c0ad5842SAllain Legacy } 452c0ad5842SAllain Legacy break; 453c0ad5842SAllain Legacy 454c0ad5842SAllain Legacy case RTE_AVP_PCI_MEMORY_BAR: 455c0ad5842SAllain Legacy case RTE_AVP_PCI_MMIO_BAR: 456c0ad5842SAllain Legacy if (resource->addr == NULL) { 457*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Missing address space for BAR%u", 458c0ad5842SAllain Legacy i); 459c0ad5842SAllain Legacy return -EINVAL; 460c0ad5842SAllain Legacy } 461c0ad5842SAllain Legacy break; 462c0ad5842SAllain Legacy 463c0ad5842SAllain Legacy case RTE_AVP_PCI_MSIX_BAR: 464c0ad5842SAllain Legacy default: 465c0ad5842SAllain Legacy /* no validation required */ 466c0ad5842SAllain Legacy break; 467c0ad5842SAllain Legacy } 468c0ad5842SAllain Legacy } 469c0ad5842SAllain Legacy 470c0ad5842SAllain Legacy return 0; 471c0ad5842SAllain Legacy } 472c0ad5842SAllain Legacy 47382e140b8SAllain Legacy static int 47482e140b8SAllain Legacy avp_dev_detach(struct rte_eth_dev *eth_dev) 47582e140b8SAllain Legacy { 47682e140b8SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 47782e140b8SAllain Legacy int ret; 47882e140b8SAllain Legacy 479*e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "Detaching port %u from AVP device 0x%" PRIx64 "", 48082e140b8SAllain Legacy eth_dev->data->port_id, avp->device_id); 48182e140b8SAllain Legacy 48282e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 48382e140b8SAllain Legacy 48482e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 485*e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "port %u already detached", 48682e140b8SAllain Legacy eth_dev->data->port_id); 48782e140b8SAllain Legacy ret = 0; 48882e140b8SAllain Legacy goto unlock; 48982e140b8SAllain Legacy } 49082e140b8SAllain Legacy 49182e140b8SAllain Legacy /* shutdown the device first so the host stops sending us packets. */ 49282e140b8SAllain Legacy ret = avp_dev_ctrl_shutdown(eth_dev); 49382e140b8SAllain Legacy if (ret < 0) { 494*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to send/recv shutdown to host, ret=%d", 49582e140b8SAllain Legacy ret); 49682e140b8SAllain Legacy avp->flags &= ~AVP_F_DETACHED; 49782e140b8SAllain Legacy goto unlock; 49882e140b8SAllain Legacy } 49982e140b8SAllain Legacy 50082e140b8SAllain Legacy avp->flags |= AVP_F_DETACHED; 50182e140b8SAllain Legacy rte_wmb(); 50282e140b8SAllain Legacy 50382e140b8SAllain Legacy /* wait for queues to acknowledge the presence of the detach flag */ 50482e140b8SAllain Legacy rte_delay_ms(1); 50582e140b8SAllain Legacy 50682e140b8SAllain Legacy ret = 0; 50782e140b8SAllain Legacy 50882e140b8SAllain Legacy unlock: 50982e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 51082e140b8SAllain Legacy return ret; 51182e140b8SAllain Legacy } 51282e140b8SAllain Legacy 5131a859223SAllain Legacy static void 514cce4367fSAllain Legacy _avp_set_rx_queue_mappings(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) 515cce4367fSAllain Legacy { 516cce4367fSAllain Legacy struct avp_dev *avp = 517cce4367fSAllain Legacy AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 518cce4367fSAllain Legacy struct avp_queue *rxq; 519cce4367fSAllain Legacy uint16_t queue_count; 520cce4367fSAllain Legacy uint16_t remainder; 521cce4367fSAllain Legacy 522cce4367fSAllain Legacy rxq = (struct avp_queue *)eth_dev->data->rx_queues[rx_queue_id]; 523cce4367fSAllain Legacy 524cce4367fSAllain Legacy /* 525cce4367fSAllain Legacy * Must map all AVP fifos as evenly as possible between the configured 526cce4367fSAllain Legacy * device queues. Each device queue will service a subset of the AVP 527cce4367fSAllain Legacy * fifos. If there is an odd number of device queues the first set of 528cce4367fSAllain Legacy * device queues will get the extra AVP fifos. 529cce4367fSAllain Legacy */ 530cce4367fSAllain Legacy queue_count = avp->num_rx_queues / eth_dev->data->nb_rx_queues; 531cce4367fSAllain Legacy remainder = avp->num_rx_queues % eth_dev->data->nb_rx_queues; 532cce4367fSAllain Legacy if (rx_queue_id < remainder) { 533cce4367fSAllain Legacy /* these queues must service one extra FIFO */ 534cce4367fSAllain Legacy rxq->queue_base = rx_queue_id * (queue_count + 1); 535cce4367fSAllain Legacy rxq->queue_limit = rxq->queue_base + (queue_count + 1) - 1; 536cce4367fSAllain Legacy } else { 537cce4367fSAllain Legacy /* these queues service the regular number of FIFO */ 538cce4367fSAllain Legacy rxq->queue_base = ((remainder * (queue_count + 1)) + 539cce4367fSAllain Legacy ((rx_queue_id - remainder) * queue_count)); 540cce4367fSAllain Legacy rxq->queue_limit = rxq->queue_base + queue_count - 1; 541cce4367fSAllain Legacy } 542cce4367fSAllain Legacy 543*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "rxq %u at %p base %u limit %u", 544cce4367fSAllain Legacy rx_queue_id, rxq, rxq->queue_base, rxq->queue_limit); 545cce4367fSAllain Legacy 546cce4367fSAllain Legacy rxq->queue_id = rxq->queue_base; 547cce4367fSAllain Legacy } 548cce4367fSAllain Legacy 549cce4367fSAllain Legacy static void 5501a859223SAllain Legacy _avp_set_queue_counts(struct rte_eth_dev *eth_dev) 5511a859223SAllain Legacy { 552c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 5531a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 5541a859223SAllain Legacy struct rte_avp_device_info *host_info; 5551a859223SAllain Legacy void *addr; 5561a859223SAllain Legacy 5571a859223SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr; 5581a859223SAllain Legacy host_info = (struct rte_avp_device_info *)addr; 5591a859223SAllain Legacy 5601a859223SAllain Legacy /* 5611a859223SAllain Legacy * the transmit direction is not negotiated beyond respecting the max 5621a859223SAllain Legacy * number of queues because the host can handle arbitrary guest tx 5631a859223SAllain Legacy * queues (host rx queues). 5641a859223SAllain Legacy */ 5651a859223SAllain Legacy avp->num_tx_queues = eth_dev->data->nb_tx_queues; 5661a859223SAllain Legacy 5671a859223SAllain Legacy /* 5681a859223SAllain Legacy * the receive direction is more restrictive. The host requires a 5691a859223SAllain Legacy * minimum number of guest rx queues (host tx queues) therefore 5701a859223SAllain Legacy * negotiate a value that is at least as large as the host minimum 5711a859223SAllain Legacy * requirement. If the host and guest values are not identical then a 5721a859223SAllain Legacy * mapping will be established in the receive_queue_setup function. 5731a859223SAllain Legacy */ 5741a859223SAllain Legacy avp->num_rx_queues = RTE_MAX(host_info->min_rx_queues, 5751a859223SAllain Legacy eth_dev->data->nb_rx_queues); 5761a859223SAllain Legacy 577*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Requesting %u Tx and %u Rx queues from host", 5781a859223SAllain Legacy avp->num_tx_queues, avp->num_rx_queues); 5791a859223SAllain Legacy } 5801a859223SAllain Legacy 58182e140b8SAllain Legacy static int 58282e140b8SAllain Legacy avp_dev_attach(struct rte_eth_dev *eth_dev) 58382e140b8SAllain Legacy { 58482e140b8SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 58582e140b8SAllain Legacy struct rte_avp_device_config config; 58682e140b8SAllain Legacy unsigned int i; 58782e140b8SAllain Legacy int ret; 58882e140b8SAllain Legacy 589*e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "Attaching port %u to AVP device 0x%" PRIx64 "", 59082e140b8SAllain Legacy eth_dev->data->port_id, avp->device_id); 59182e140b8SAllain Legacy 59282e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 59382e140b8SAllain Legacy 59482e140b8SAllain Legacy if (!(avp->flags & AVP_F_DETACHED)) { 595*e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "port %u already attached", 59682e140b8SAllain Legacy eth_dev->data->port_id); 59782e140b8SAllain Legacy ret = 0; 59882e140b8SAllain Legacy goto unlock; 59982e140b8SAllain Legacy } 60082e140b8SAllain Legacy 60182e140b8SAllain Legacy /* 60282e140b8SAllain Legacy * make sure that the detached flag is set prior to reconfiguring the 60382e140b8SAllain Legacy * queues. 60482e140b8SAllain Legacy */ 60582e140b8SAllain Legacy avp->flags |= AVP_F_DETACHED; 60682e140b8SAllain Legacy rte_wmb(); 60782e140b8SAllain Legacy 60882e140b8SAllain Legacy /* 60982e140b8SAllain Legacy * re-run the device create utility which will parse the new host info 61082e140b8SAllain Legacy * and setup the AVP device queue pointers. 61182e140b8SAllain Legacy */ 612c0802544SFerruh Yigit ret = avp_dev_create(RTE_ETH_DEV_TO_PCI(eth_dev), eth_dev); 61382e140b8SAllain Legacy if (ret < 0) { 614*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to re-create AVP device, ret=%d", 61582e140b8SAllain Legacy ret); 61682e140b8SAllain Legacy goto unlock; 61782e140b8SAllain Legacy } 61882e140b8SAllain Legacy 61982e140b8SAllain Legacy if (avp->flags & AVP_F_CONFIGURED) { 62082e140b8SAllain Legacy /* 62182e140b8SAllain Legacy * Update the receive queue mapping to handle cases where the 62282e140b8SAllain Legacy * source and destination hosts have different queue 62382e140b8SAllain Legacy * requirements. As long as the DETACHED flag is asserted the 62482e140b8SAllain Legacy * queue table should not be referenced so it should be safe to 62582e140b8SAllain Legacy * update it. 62682e140b8SAllain Legacy */ 62782e140b8SAllain Legacy _avp_set_queue_counts(eth_dev); 62882e140b8SAllain Legacy for (i = 0; i < eth_dev->data->nb_rx_queues; i++) 62982e140b8SAllain Legacy _avp_set_rx_queue_mappings(eth_dev, i); 63082e140b8SAllain Legacy 63182e140b8SAllain Legacy /* 63282e140b8SAllain Legacy * Update the host with our config details so that it knows the 63382e140b8SAllain Legacy * device is active. 63482e140b8SAllain Legacy */ 63582e140b8SAllain Legacy memset(&config, 0, sizeof(config)); 63682e140b8SAllain Legacy config.device_id = avp->device_id; 63782e140b8SAllain Legacy config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK; 63882e140b8SAllain Legacy config.driver_version = AVP_DPDK_DRIVER_VERSION; 63982e140b8SAllain Legacy config.features = avp->features; 64082e140b8SAllain Legacy config.num_tx_queues = avp->num_tx_queues; 64182e140b8SAllain Legacy config.num_rx_queues = avp->num_rx_queues; 64282e140b8SAllain Legacy config.if_up = !!(avp->flags & AVP_F_LINKUP); 64382e140b8SAllain Legacy 64482e140b8SAllain Legacy ret = avp_dev_ctrl_set_config(eth_dev, &config); 64582e140b8SAllain Legacy if (ret < 0) { 646*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Config request failed by host, ret=%d", 64782e140b8SAllain Legacy ret); 64882e140b8SAllain Legacy goto unlock; 64982e140b8SAllain Legacy } 65082e140b8SAllain Legacy } 65182e140b8SAllain Legacy 65282e140b8SAllain Legacy rte_wmb(); 65382e140b8SAllain Legacy avp->flags &= ~AVP_F_DETACHED; 65482e140b8SAllain Legacy 65582e140b8SAllain Legacy ret = 0; 65682e140b8SAllain Legacy 65782e140b8SAllain Legacy unlock: 65882e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 65982e140b8SAllain Legacy return ret; 66082e140b8SAllain Legacy } 66182e140b8SAllain Legacy 66282e140b8SAllain Legacy static void 663c23a1a30SQi Zhang avp_dev_interrupt_handler(void *data) 66482e140b8SAllain Legacy { 66582e140b8SAllain Legacy struct rte_eth_dev *eth_dev = data; 666c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 66782e140b8SAllain Legacy void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr; 66882e140b8SAllain Legacy uint32_t status, value; 66982e140b8SAllain Legacy int ret; 67082e140b8SAllain Legacy 67182e140b8SAllain Legacy if (registers == NULL) 67282e140b8SAllain Legacy rte_panic("no mapped MMIO register space\n"); 67382e140b8SAllain Legacy 67482e140b8SAllain Legacy /* read the interrupt status register 67582e140b8SAllain Legacy * note: this register clears on read so all raised interrupts must be 67682e140b8SAllain Legacy * handled or remembered for later processing 67782e140b8SAllain Legacy */ 67882e140b8SAllain Legacy status = AVP_READ32( 67982e140b8SAllain Legacy RTE_PTR_ADD(registers, 68082e140b8SAllain Legacy RTE_AVP_INTERRUPT_STATUS_OFFSET)); 68182e140b8SAllain Legacy 682f353fbc5SFerruh Yigit if (status & RTE_AVP_MIGRATION_INTERRUPT_MASK) { 68382e140b8SAllain Legacy /* handle interrupt based on current status */ 68482e140b8SAllain Legacy value = AVP_READ32( 68582e140b8SAllain Legacy RTE_PTR_ADD(registers, 68682e140b8SAllain Legacy RTE_AVP_MIGRATION_STATUS_OFFSET)); 68782e140b8SAllain Legacy switch (value) { 68882e140b8SAllain Legacy case RTE_AVP_MIGRATION_DETACHED: 68982e140b8SAllain Legacy ret = avp_dev_detach(eth_dev); 69082e140b8SAllain Legacy break; 69182e140b8SAllain Legacy case RTE_AVP_MIGRATION_ATTACHED: 69282e140b8SAllain Legacy ret = avp_dev_attach(eth_dev); 69382e140b8SAllain Legacy break; 69482e140b8SAllain Legacy default: 695*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "unexpected migration status, status=%u", 69682e140b8SAllain Legacy value); 69782e140b8SAllain Legacy ret = -EINVAL; 69882e140b8SAllain Legacy } 69982e140b8SAllain Legacy 70082e140b8SAllain Legacy /* acknowledge the request by writing out our current status */ 70182e140b8SAllain Legacy value = (ret == 0 ? value : RTE_AVP_MIGRATION_ERROR); 70282e140b8SAllain Legacy AVP_WRITE32(value, 70382e140b8SAllain Legacy RTE_PTR_ADD(registers, 70482e140b8SAllain Legacy RTE_AVP_MIGRATION_ACK_OFFSET)); 70582e140b8SAllain Legacy 706*e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "AVP migration interrupt handled"); 70782e140b8SAllain Legacy } 70882e140b8SAllain Legacy 70982e140b8SAllain Legacy if (status & ~RTE_AVP_MIGRATION_INTERRUPT_MASK) 710*e99981afSDavid Marchand PMD_DRV_LOG_LINE(WARNING, "AVP unexpected interrupt, status=0x%08x", 71182e140b8SAllain Legacy status); 71282e140b8SAllain Legacy 71382e140b8SAllain Legacy /* re-enable UIO interrupt handling */ 714d61138d4SHarman Kalra ret = rte_intr_ack(pci_dev->intr_handle); 71582e140b8SAllain Legacy if (ret < 0) { 716*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to re-enable UIO interrupts, ret=%d", 71782e140b8SAllain Legacy ret); 71882e140b8SAllain Legacy /* continue */ 71982e140b8SAllain Legacy } 72082e140b8SAllain Legacy } 72182e140b8SAllain Legacy 72282e140b8SAllain Legacy static int 72382e140b8SAllain Legacy avp_dev_enable_interrupts(struct rte_eth_dev *eth_dev) 72482e140b8SAllain Legacy { 725c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 72682e140b8SAllain Legacy void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr; 72782e140b8SAllain Legacy int ret; 72882e140b8SAllain Legacy 72982e140b8SAllain Legacy if (registers == NULL) 73082e140b8SAllain Legacy return -EINVAL; 73182e140b8SAllain Legacy 73282e140b8SAllain Legacy /* enable UIO interrupt handling */ 733d61138d4SHarman Kalra ret = rte_intr_enable(pci_dev->intr_handle); 73482e140b8SAllain Legacy if (ret < 0) { 735*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to enable UIO interrupts, ret=%d", 73682e140b8SAllain Legacy ret); 73782e140b8SAllain Legacy return ret; 73882e140b8SAllain Legacy } 73982e140b8SAllain Legacy 74082e140b8SAllain Legacy /* inform the device that all interrupts are enabled */ 74182e140b8SAllain Legacy AVP_WRITE32(RTE_AVP_APP_INTERRUPTS_MASK, 74282e140b8SAllain Legacy RTE_PTR_ADD(registers, RTE_AVP_INTERRUPT_MASK_OFFSET)); 74382e140b8SAllain Legacy 74482e140b8SAllain Legacy return 0; 74582e140b8SAllain Legacy } 74682e140b8SAllain Legacy 74782e140b8SAllain Legacy static int 74882e140b8SAllain Legacy avp_dev_disable_interrupts(struct rte_eth_dev *eth_dev) 74982e140b8SAllain Legacy { 750c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 75182e140b8SAllain Legacy void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr; 75282e140b8SAllain Legacy int ret; 75382e140b8SAllain Legacy 75482e140b8SAllain Legacy if (registers == NULL) 75582e140b8SAllain Legacy return 0; 75682e140b8SAllain Legacy 75782e140b8SAllain Legacy /* inform the device that all interrupts are disabled */ 75882e140b8SAllain Legacy AVP_WRITE32(RTE_AVP_NO_INTERRUPTS_MASK, 75982e140b8SAllain Legacy RTE_PTR_ADD(registers, RTE_AVP_INTERRUPT_MASK_OFFSET)); 76082e140b8SAllain Legacy 76182e140b8SAllain Legacy /* enable UIO interrupt handling */ 762d61138d4SHarman Kalra ret = rte_intr_disable(pci_dev->intr_handle); 76382e140b8SAllain Legacy if (ret < 0) { 764*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to disable UIO interrupts, ret=%d", 76582e140b8SAllain Legacy ret); 76682e140b8SAllain Legacy return ret; 76782e140b8SAllain Legacy } 76882e140b8SAllain Legacy 76982e140b8SAllain Legacy return 0; 77082e140b8SAllain Legacy } 77182e140b8SAllain Legacy 77282e140b8SAllain Legacy static int 77382e140b8SAllain Legacy avp_dev_setup_interrupts(struct rte_eth_dev *eth_dev) 77482e140b8SAllain Legacy { 775c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 77682e140b8SAllain Legacy int ret; 77782e140b8SAllain Legacy 77882e140b8SAllain Legacy /* register a callback handler with UIO for interrupt notifications */ 779d61138d4SHarman Kalra ret = rte_intr_callback_register(pci_dev->intr_handle, 78082e140b8SAllain Legacy avp_dev_interrupt_handler, 78182e140b8SAllain Legacy (void *)eth_dev); 78282e140b8SAllain Legacy if (ret < 0) { 783*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to register UIO interrupt callback, ret=%d", 78482e140b8SAllain Legacy ret); 78582e140b8SAllain Legacy return ret; 78682e140b8SAllain Legacy } 78782e140b8SAllain Legacy 78882e140b8SAllain Legacy /* enable interrupt processing */ 78982e140b8SAllain Legacy return avp_dev_enable_interrupts(eth_dev); 79082e140b8SAllain Legacy } 79182e140b8SAllain Legacy 79282e140b8SAllain Legacy static int 79382e140b8SAllain Legacy avp_dev_migration_pending(struct rte_eth_dev *eth_dev) 79482e140b8SAllain Legacy { 795c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 79682e140b8SAllain Legacy void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr; 79782e140b8SAllain Legacy uint32_t value; 79882e140b8SAllain Legacy 79982e140b8SAllain Legacy if (registers == NULL) 80082e140b8SAllain Legacy return 0; 80182e140b8SAllain Legacy 80282e140b8SAllain Legacy value = AVP_READ32(RTE_PTR_ADD(registers, 80382e140b8SAllain Legacy RTE_AVP_MIGRATION_STATUS_OFFSET)); 80482e140b8SAllain Legacy if (value == RTE_AVP_MIGRATION_DETACHED) { 80582e140b8SAllain Legacy /* migration is in progress; ack it if we have not already */ 80682e140b8SAllain Legacy AVP_WRITE32(value, 80782e140b8SAllain Legacy RTE_PTR_ADD(registers, 80882e140b8SAllain Legacy RTE_AVP_MIGRATION_ACK_OFFSET)); 80982e140b8SAllain Legacy return 1; 81082e140b8SAllain Legacy } 81182e140b8SAllain Legacy return 0; 81282e140b8SAllain Legacy } 81382e140b8SAllain Legacy 814c0ad5842SAllain Legacy /* 815c0ad5842SAllain Legacy * create a AVP device using the supplied device info by first translating it 816c0ad5842SAllain Legacy * to guest address space(s). 817c0ad5842SAllain Legacy */ 818c0ad5842SAllain Legacy static int 819c0ad5842SAllain Legacy avp_dev_create(struct rte_pci_device *pci_dev, 820c0ad5842SAllain Legacy struct rte_eth_dev *eth_dev) 821c0ad5842SAllain Legacy { 822c0ad5842SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 823c0ad5842SAllain Legacy struct rte_avp_device_info *host_info; 824c0ad5842SAllain Legacy struct rte_mem_resource *resource; 825c0ad5842SAllain Legacy unsigned int i; 826c0ad5842SAllain Legacy 827c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR]; 828c0ad5842SAllain Legacy if (resource->addr == NULL) { 829*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "BAR%u is not mapped", 830c0ad5842SAllain Legacy RTE_AVP_PCI_DEVICE_BAR); 831c0ad5842SAllain Legacy return -EFAULT; 832c0ad5842SAllain Legacy } 833c0ad5842SAllain Legacy host_info = (struct rte_avp_device_info *)resource->addr; 834c0ad5842SAllain Legacy 835c0ad5842SAllain Legacy if ((host_info->magic != RTE_AVP_DEVICE_MAGIC) || 836c0ad5842SAllain Legacy avp_dev_version_check(host_info->version)) { 837*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Invalid AVP PCI device, magic 0x%08x version 0x%08x > 0x%08x", 838c0ad5842SAllain Legacy host_info->magic, host_info->version, 839c0ad5842SAllain Legacy AVP_DPDK_DRIVER_VERSION); 840c0ad5842SAllain Legacy return -EINVAL; 841c0ad5842SAllain Legacy } 842c0ad5842SAllain Legacy 843*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host device is v%u.%u.%u", 844c0ad5842SAllain Legacy RTE_AVP_GET_RELEASE_VERSION(host_info->version), 845c0ad5842SAllain Legacy RTE_AVP_GET_MAJOR_VERSION(host_info->version), 846c0ad5842SAllain Legacy RTE_AVP_GET_MINOR_VERSION(host_info->version)); 847c0ad5842SAllain Legacy 848*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host supports %u to %u TX queue(s)", 849c0ad5842SAllain Legacy host_info->min_tx_queues, host_info->max_tx_queues); 850*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host supports %u to %u RX queue(s)", 851c0ad5842SAllain Legacy host_info->min_rx_queues, host_info->max_rx_queues); 852*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host supports features 0x%08x", 853c0ad5842SAllain Legacy host_info->features); 854c0ad5842SAllain Legacy 855c0ad5842SAllain Legacy if (avp->magic != AVP_ETHDEV_MAGIC) { 856c0ad5842SAllain Legacy /* 857c0ad5842SAllain Legacy * First time initialization (i.e., not during a VM 858c0ad5842SAllain Legacy * migration) 859c0ad5842SAllain Legacy */ 860c0ad5842SAllain Legacy memset(avp, 0, sizeof(*avp)); 861c0ad5842SAllain Legacy avp->magic = AVP_ETHDEV_MAGIC; 862c0ad5842SAllain Legacy avp->dev_data = eth_dev->data; 863c0ad5842SAllain Legacy avp->port_id = eth_dev->data->port_id; 864c0ad5842SAllain Legacy avp->host_mbuf_size = host_info->mbuf_size; 865c0ad5842SAllain Legacy avp->host_features = host_info->features; 86682e140b8SAllain Legacy rte_spinlock_init(&avp->lock); 867c0ad5842SAllain Legacy memcpy(&avp->ethaddr.addr_bytes[0], 86835b2d13fSOlivier Matz host_info->ethaddr, RTE_ETHER_ADDR_LEN); 869c0ad5842SAllain Legacy /* adjust max values to not exceed our max */ 870c0ad5842SAllain Legacy avp->max_tx_queues = 871c0ad5842SAllain Legacy RTE_MIN(host_info->max_tx_queues, RTE_AVP_MAX_QUEUES); 872c0ad5842SAllain Legacy avp->max_rx_queues = 873c0ad5842SAllain Legacy RTE_MIN(host_info->max_rx_queues, RTE_AVP_MAX_QUEUES); 874c0ad5842SAllain Legacy } else { 875c0ad5842SAllain Legacy /* Re-attaching during migration */ 876c0ad5842SAllain Legacy 877c0ad5842SAllain Legacy /* TODO... requires validation of host values */ 878c0ad5842SAllain Legacy if ((host_info->features & avp->features) != avp->features) { 879*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "AVP host features mismatched; 0x%08x, host=0x%08x", 880c0ad5842SAllain Legacy avp->features, host_info->features); 881c0ad5842SAllain Legacy /* this should not be possible; continue for now */ 882c0ad5842SAllain Legacy } 883c0ad5842SAllain Legacy } 884c0ad5842SAllain Legacy 885c0ad5842SAllain Legacy /* the device id is allowed to change over migrations */ 886c0ad5842SAllain Legacy avp->device_id = host_info->device_id; 887c0ad5842SAllain Legacy 888c0ad5842SAllain Legacy /* translate incoming host addresses to guest address space */ 889*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP first host tx queue at 0x%" PRIx64 "", 890c0ad5842SAllain Legacy host_info->tx_phys); 891*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP first host alloc queue at 0x%" PRIx64 "", 892c0ad5842SAllain Legacy host_info->alloc_phys); 893c0ad5842SAllain Legacy for (i = 0; i < avp->max_tx_queues; i++) { 894c0ad5842SAllain Legacy avp->tx_q[i] = avp_dev_translate_address(eth_dev, 895c0ad5842SAllain Legacy host_info->tx_phys + (i * host_info->tx_size)); 896c0ad5842SAllain Legacy 897c0ad5842SAllain Legacy avp->alloc_q[i] = avp_dev_translate_address(eth_dev, 898c0ad5842SAllain Legacy host_info->alloc_phys + (i * host_info->alloc_size)); 899c0ad5842SAllain Legacy } 900c0ad5842SAllain Legacy 901*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP first host rx queue at 0x%" PRIx64 "", 902c0ad5842SAllain Legacy host_info->rx_phys); 903*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP first host free queue at 0x%" PRIx64 "", 904c0ad5842SAllain Legacy host_info->free_phys); 905c0ad5842SAllain Legacy for (i = 0; i < avp->max_rx_queues; i++) { 906c0ad5842SAllain Legacy avp->rx_q[i] = avp_dev_translate_address(eth_dev, 907c0ad5842SAllain Legacy host_info->rx_phys + (i * host_info->rx_size)); 908c0ad5842SAllain Legacy avp->free_q[i] = avp_dev_translate_address(eth_dev, 909c0ad5842SAllain Legacy host_info->free_phys + (i * host_info->free_size)); 910c0ad5842SAllain Legacy } 911c0ad5842SAllain Legacy 912*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host request queue at 0x%" PRIx64 "", 913c0ad5842SAllain Legacy host_info->req_phys); 914*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host response queue at 0x%" PRIx64 "", 915c0ad5842SAllain Legacy host_info->resp_phys); 916*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host sync address at 0x%" PRIx64 "", 917c0ad5842SAllain Legacy host_info->sync_phys); 918*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host mbuf address at 0x%" PRIx64 "", 919c0ad5842SAllain Legacy host_info->mbuf_phys); 920c0ad5842SAllain Legacy avp->req_q = avp_dev_translate_address(eth_dev, host_info->req_phys); 921c0ad5842SAllain Legacy avp->resp_q = avp_dev_translate_address(eth_dev, host_info->resp_phys); 922c0ad5842SAllain Legacy avp->sync_addr = 923c0ad5842SAllain Legacy avp_dev_translate_address(eth_dev, host_info->sync_phys); 924c0ad5842SAllain Legacy avp->mbuf_addr = 925c0ad5842SAllain Legacy avp_dev_translate_address(eth_dev, host_info->mbuf_phys); 926c0ad5842SAllain Legacy 927c0ad5842SAllain Legacy /* 928c0ad5842SAllain Legacy * store the host mbuf virtual address so that we can calculate 929c0ad5842SAllain Legacy * relative offsets for each mbuf as they are processed 930c0ad5842SAllain Legacy */ 931c0ad5842SAllain Legacy avp->host_mbuf_addr = host_info->mbuf_va; 932c0ad5842SAllain Legacy avp->host_sync_addr = host_info->sync_va; 933c0ad5842SAllain Legacy 934c0ad5842SAllain Legacy /* 935c0ad5842SAllain Legacy * store the maximum packet length that is supported by the host. 936c0ad5842SAllain Legacy */ 937c0ad5842SAllain Legacy avp->max_rx_pkt_len = host_info->max_rx_pkt_len; 938*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP host max receive packet length is %u", 939c0ad5842SAllain Legacy host_info->max_rx_pkt_len); 940c0ad5842SAllain Legacy 941c0ad5842SAllain Legacy return 0; 942c0ad5842SAllain Legacy } 943c0ad5842SAllain Legacy 944c0ad5842SAllain Legacy /* 945908072e9SAllain Legacy * This function is based on probe() function in avp_pci.c 946908072e9SAllain Legacy * It returns 0 on success. 947908072e9SAllain Legacy */ 948908072e9SAllain Legacy static int 949908072e9SAllain Legacy eth_avp_dev_init(struct rte_eth_dev *eth_dev) 950908072e9SAllain Legacy { 951c0ad5842SAllain Legacy struct avp_dev *avp = 952c0ad5842SAllain Legacy AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 953908072e9SAllain Legacy struct rte_pci_device *pci_dev; 954c0ad5842SAllain Legacy int ret; 955908072e9SAllain Legacy 956c0802544SFerruh Yigit pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 9571a859223SAllain Legacy eth_dev->dev_ops = &avp_eth_dev_ops; 95850db69fdSAllain Legacy eth_dev->rx_pkt_burst = &avp_recv_pkts; 959295abce2SAllain Legacy eth_dev->tx_pkt_burst = &avp_xmit_pkts; 960908072e9SAllain Legacy 961908072e9SAllain Legacy if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 962908072e9SAllain Legacy /* 963908072e9SAllain Legacy * no setup required on secondary processes. All data is saved 964908072e9SAllain Legacy * in dev_private by the primary process. All resource should 965908072e9SAllain Legacy * be mapped to the same virtual address so all pointers should 966908072e9SAllain Legacy * be valid. 967908072e9SAllain Legacy */ 96850db69fdSAllain Legacy if (eth_dev->data->scattered_rx) { 969*e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "AVP device configured for chained mbufs"); 97050db69fdSAllain Legacy eth_dev->rx_pkt_burst = avp_recv_scattered_pkts; 971295abce2SAllain Legacy eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts; 97250db69fdSAllain Legacy } 973908072e9SAllain Legacy return 0; 974908072e9SAllain Legacy } 975908072e9SAllain Legacy 976908072e9SAllain Legacy rte_eth_copy_pci_info(eth_dev, pci_dev); 977f30e69b4SFerruh Yigit eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 978908072e9SAllain Legacy 97982e140b8SAllain Legacy /* Check current migration status */ 98082e140b8SAllain Legacy if (avp_dev_migration_pending(eth_dev)) { 981*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "VM live migration operation in progress"); 98282e140b8SAllain Legacy return -EBUSY; 98382e140b8SAllain Legacy } 98482e140b8SAllain Legacy 985c0ad5842SAllain Legacy /* Check BAR resources */ 986c0ad5842SAllain Legacy ret = avp_dev_check_regions(eth_dev); 987c0ad5842SAllain Legacy if (ret < 0) { 988*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to validate BAR resources, ret=%d", 989c0ad5842SAllain Legacy ret); 990c0ad5842SAllain Legacy return ret; 991c0ad5842SAllain Legacy } 992c0ad5842SAllain Legacy 99382e140b8SAllain Legacy /* Enable interrupts */ 99482e140b8SAllain Legacy ret = avp_dev_setup_interrupts(eth_dev); 99582e140b8SAllain Legacy if (ret < 0) { 996*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to enable interrupts, ret=%d", ret); 99782e140b8SAllain Legacy return ret; 99882e140b8SAllain Legacy } 99982e140b8SAllain Legacy 1000c0ad5842SAllain Legacy /* Handle each subtype */ 1001c0ad5842SAllain Legacy ret = avp_dev_create(pci_dev, eth_dev); 1002c0ad5842SAllain Legacy if (ret < 0) { 1003*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to create device, ret=%d", ret); 1004c0ad5842SAllain Legacy return ret; 1005c0ad5842SAllain Legacy } 1006c0ad5842SAllain Legacy 1007c0ad5842SAllain Legacy /* Allocate memory for storing MAC addresses */ 100835b2d13fSOlivier Matz eth_dev->data->mac_addrs = rte_zmalloc("avp_ethdev", 100935b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN, 0); 1010c0ad5842SAllain Legacy if (eth_dev->data->mac_addrs == NULL) { 1011*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to allocate %d bytes needed to store MAC addresses", 101235b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN); 1013c0ad5842SAllain Legacy return -ENOMEM; 1014c0ad5842SAllain Legacy } 1015c0ad5842SAllain Legacy 1016c0ad5842SAllain Legacy /* Get a mac from device config */ 1017538da7a1SOlivier Matz rte_ether_addr_copy(&avp->ethaddr, ð_dev->data->mac_addrs[0]); 1018c0ad5842SAllain Legacy 1019908072e9SAllain Legacy return 0; 1020908072e9SAllain Legacy } 1021908072e9SAllain Legacy 1022908072e9SAllain Legacy static int 1023908072e9SAllain Legacy eth_avp_dev_uninit(struct rte_eth_dev *eth_dev) 1024908072e9SAllain Legacy { 1025908072e9SAllain Legacy if (rte_eal_process_type() != RTE_PROC_PRIMARY) 1026908072e9SAllain Legacy return -EPERM; 1027908072e9SAllain Legacy 1028908072e9SAllain Legacy if (eth_dev->data == NULL) 1029908072e9SAllain Legacy return 0; 1030908072e9SAllain Legacy 103115fb42d5SAllain Legacy avp_dev_close(eth_dev); 103282e140b8SAllain Legacy 1033908072e9SAllain Legacy return 0; 1034908072e9SAllain Legacy } 1035908072e9SAllain Legacy 1036fdf91e0fSJan Blunck static int 1037fdf91e0fSJan Blunck eth_avp_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 1038fdf91e0fSJan Blunck struct rte_pci_device *pci_dev) 1039908072e9SAllain Legacy { 104001a98fddSThomas Monjalon return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct avp_adapter), 104101a98fddSThomas Monjalon eth_avp_dev_init); 1042fdf91e0fSJan Blunck } 1043fdf91e0fSJan Blunck 1044fdf91e0fSJan Blunck static int 1045fdf91e0fSJan Blunck eth_avp_pci_remove(struct rte_pci_device *pci_dev) 1046fdf91e0fSJan Blunck { 1047fdf91e0fSJan Blunck return rte_eth_dev_pci_generic_remove(pci_dev, 1048fdf91e0fSJan Blunck eth_avp_dev_uninit); 1049fdf91e0fSJan Blunck } 1050fdf91e0fSJan Blunck 1051fdf91e0fSJan Blunck static struct rte_pci_driver rte_avp_pmd = { 1052908072e9SAllain Legacy .id_table = pci_id_avp_map, 1053908072e9SAllain Legacy .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 1054fdf91e0fSJan Blunck .probe = eth_avp_pci_probe, 1055fdf91e0fSJan Blunck .remove = eth_avp_pci_remove, 1056908072e9SAllain Legacy }; 1057908072e9SAllain Legacy 10581a859223SAllain Legacy static int 105950db69fdSAllain Legacy avp_dev_enable_scattered(struct rte_eth_dev *eth_dev, 106050db69fdSAllain Legacy struct avp_dev *avp) 106150db69fdSAllain Legacy { 10621bb4a528SFerruh Yigit unsigned int max_rx_pktlen; 106350db69fdSAllain Legacy 10641bb4a528SFerruh Yigit max_rx_pktlen = eth_dev->data->mtu + RTE_ETHER_HDR_LEN + 10651bb4a528SFerruh Yigit RTE_ETHER_CRC_LEN; 106650db69fdSAllain Legacy 10671bb4a528SFerruh Yigit if (max_rx_pktlen > avp->guest_mbuf_size || 10681bb4a528SFerruh Yigit max_rx_pktlen > avp->host_mbuf_size) { 106950db69fdSAllain Legacy /* 107050db69fdSAllain Legacy * If the guest MTU is greater than either the host or guest 107150db69fdSAllain Legacy * buffers then chained mbufs have to be enabled in the TX 107250db69fdSAllain Legacy * direction. It is assumed that the application will not need 10731bb4a528SFerruh Yigit * to send packets larger than their MTU. 107450db69fdSAllain Legacy */ 107550db69fdSAllain Legacy return 1; 107650db69fdSAllain Legacy } 107750db69fdSAllain Legacy 107850db69fdSAllain Legacy if ((avp->max_rx_pkt_len > avp->guest_mbuf_size) || 107950db69fdSAllain Legacy (avp->max_rx_pkt_len > avp->host_mbuf_size)) { 108050db69fdSAllain Legacy /* 108150db69fdSAllain Legacy * If the host MRU is greater than its own mbuf size or the 108250db69fdSAllain Legacy * guest mbuf size then chained mbufs have to be enabled in the 108350db69fdSAllain Legacy * RX direction. 108450db69fdSAllain Legacy */ 108550db69fdSAllain Legacy return 1; 108650db69fdSAllain Legacy } 108750db69fdSAllain Legacy 108850db69fdSAllain Legacy return 0; 108950db69fdSAllain Legacy } 109050db69fdSAllain Legacy 109150db69fdSAllain Legacy static int 1092cce4367fSAllain Legacy avp_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 1093cce4367fSAllain Legacy uint16_t rx_queue_id, 1094cce4367fSAllain Legacy uint16_t nb_rx_desc, 1095cce4367fSAllain Legacy unsigned int socket_id, 1096cce4367fSAllain Legacy const struct rte_eth_rxconf *rx_conf, 1097cce4367fSAllain Legacy struct rte_mempool *pool) 1098cce4367fSAllain Legacy { 1099cce4367fSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 1100cce4367fSAllain Legacy struct rte_pktmbuf_pool_private *mbp_priv; 1101cce4367fSAllain Legacy struct avp_queue *rxq; 1102cce4367fSAllain Legacy 1103cce4367fSAllain Legacy if (rx_queue_id >= eth_dev->data->nb_rx_queues) { 1104*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "RX queue id is out of range: rx_queue_id=%u, nb_rx_queues=%u", 1105cce4367fSAllain Legacy rx_queue_id, eth_dev->data->nb_rx_queues); 1106cce4367fSAllain Legacy return -EINVAL; 1107cce4367fSAllain Legacy } 1108cce4367fSAllain Legacy 1109cce4367fSAllain Legacy /* Save mbuf pool pointer */ 1110cce4367fSAllain Legacy avp->pool = pool; 1111cce4367fSAllain Legacy 1112cce4367fSAllain Legacy /* Save the local mbuf size */ 1113cce4367fSAllain Legacy mbp_priv = rte_mempool_get_priv(pool); 1114cce4367fSAllain Legacy avp->guest_mbuf_size = (uint16_t)(mbp_priv->mbuf_data_room_size); 1115cce4367fSAllain Legacy avp->guest_mbuf_size -= RTE_PKTMBUF_HEADROOM; 1116cce4367fSAllain Legacy 111750db69fdSAllain Legacy if (avp_dev_enable_scattered(eth_dev, avp)) { 111850db69fdSAllain Legacy if (!eth_dev->data->scattered_rx) { 1119*e99981afSDavid Marchand PMD_DRV_LOG_LINE(NOTICE, "AVP device configured for chained mbufs"); 112050db69fdSAllain Legacy eth_dev->data->scattered_rx = 1; 112150db69fdSAllain Legacy eth_dev->rx_pkt_burst = avp_recv_scattered_pkts; 1122295abce2SAllain Legacy eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts; 112350db69fdSAllain Legacy } 112450db69fdSAllain Legacy } 112550db69fdSAllain Legacy 1126*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "AVP max_rx_pkt_len=(%u,%u) mbuf_size=(%u,%u)", 1127cce4367fSAllain Legacy avp->max_rx_pkt_len, 11281bb4a528SFerruh Yigit eth_dev->data->mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN, 1129cce4367fSAllain Legacy avp->host_mbuf_size, 1130cce4367fSAllain Legacy avp->guest_mbuf_size); 1131cce4367fSAllain Legacy 1132cce4367fSAllain Legacy /* allocate a queue object */ 1133cce4367fSAllain Legacy rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct avp_queue), 1134cce4367fSAllain Legacy RTE_CACHE_LINE_SIZE, socket_id); 1135cce4367fSAllain Legacy if (rxq == NULL) { 1136*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to allocate new Rx queue object"); 1137cce4367fSAllain Legacy return -ENOMEM; 1138cce4367fSAllain Legacy } 1139cce4367fSAllain Legacy 1140cce4367fSAllain Legacy /* save back pointers to AVP and Ethernet devices */ 1141cce4367fSAllain Legacy rxq->avp = avp; 1142cce4367fSAllain Legacy rxq->dev_data = eth_dev->data; 1143cce4367fSAllain Legacy eth_dev->data->rx_queues[rx_queue_id] = (void *)rxq; 1144cce4367fSAllain Legacy 1145cce4367fSAllain Legacy /* setup the queue receive mapping for the current queue. */ 1146cce4367fSAllain Legacy _avp_set_rx_queue_mappings(eth_dev, rx_queue_id); 1147cce4367fSAllain Legacy 1148*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Rx queue %u setup at %p", rx_queue_id, rxq); 1149cce4367fSAllain Legacy 1150cce4367fSAllain Legacy (void)nb_rx_desc; 1151cce4367fSAllain Legacy (void)rx_conf; 1152cce4367fSAllain Legacy return 0; 1153cce4367fSAllain Legacy } 1154cce4367fSAllain Legacy 1155cce4367fSAllain Legacy static int 1156cce4367fSAllain Legacy avp_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, 1157cce4367fSAllain Legacy uint16_t tx_queue_id, 1158cce4367fSAllain Legacy uint16_t nb_tx_desc, 1159cce4367fSAllain Legacy unsigned int socket_id, 1160cce4367fSAllain Legacy const struct rte_eth_txconf *tx_conf) 1161cce4367fSAllain Legacy { 1162cce4367fSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 1163cce4367fSAllain Legacy struct avp_queue *txq; 1164cce4367fSAllain Legacy 1165cce4367fSAllain Legacy if (tx_queue_id >= eth_dev->data->nb_tx_queues) { 1166*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "TX queue id is out of range: tx_queue_id=%u, nb_tx_queues=%u", 1167cce4367fSAllain Legacy tx_queue_id, eth_dev->data->nb_tx_queues); 1168cce4367fSAllain Legacy return -EINVAL; 1169cce4367fSAllain Legacy } 1170cce4367fSAllain Legacy 1171cce4367fSAllain Legacy /* allocate a queue object */ 1172cce4367fSAllain Legacy txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct avp_queue), 1173cce4367fSAllain Legacy RTE_CACHE_LINE_SIZE, socket_id); 1174cce4367fSAllain Legacy if (txq == NULL) { 1175*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to allocate new Tx queue object"); 1176cce4367fSAllain Legacy return -ENOMEM; 1177cce4367fSAllain Legacy } 1178cce4367fSAllain Legacy 1179cce4367fSAllain Legacy /* only the configured set of transmit queues are used */ 1180cce4367fSAllain Legacy txq->queue_id = tx_queue_id; 1181cce4367fSAllain Legacy txq->queue_base = tx_queue_id; 1182cce4367fSAllain Legacy txq->queue_limit = tx_queue_id; 1183cce4367fSAllain Legacy 1184cce4367fSAllain Legacy /* save back pointers to AVP and Ethernet devices */ 1185cce4367fSAllain Legacy txq->avp = avp; 1186cce4367fSAllain Legacy txq->dev_data = eth_dev->data; 1187cce4367fSAllain Legacy eth_dev->data->tx_queues[tx_queue_id] = (void *)txq; 1188cce4367fSAllain Legacy 1189*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Tx queue %u setup at %p", tx_queue_id, txq); 1190cce4367fSAllain Legacy 1191cce4367fSAllain Legacy (void)nb_tx_desc; 1192cce4367fSAllain Legacy (void)tx_conf; 1193cce4367fSAllain Legacy return 0; 1194cce4367fSAllain Legacy } 1195cce4367fSAllain Legacy 119650db69fdSAllain Legacy static inline int 11976d13ea8eSOlivier Matz _avp_cmp_ether_addr(struct rte_ether_addr *a, struct rte_ether_addr *b) 119850db69fdSAllain Legacy { 119950db69fdSAllain Legacy uint16_t *_a = (uint16_t *)&a->addr_bytes[0]; 120050db69fdSAllain Legacy uint16_t *_b = (uint16_t *)&b->addr_bytes[0]; 120150db69fdSAllain Legacy return (_a[0] ^ _b[0]) | (_a[1] ^ _b[1]) | (_a[2] ^ _b[2]); 120250db69fdSAllain Legacy } 120350db69fdSAllain Legacy 120450db69fdSAllain Legacy static inline int 120550db69fdSAllain Legacy _avp_mac_filter(struct avp_dev *avp, struct rte_mbuf *m) 120650db69fdSAllain Legacy { 12076d13ea8eSOlivier Matz struct rte_ether_hdr *eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); 120850db69fdSAllain Legacy 120904d43857SDmitry Kozlyuk if (likely(_avp_cmp_ether_addr(&avp->ethaddr, ð->dst_addr) == 0)) { 121050db69fdSAllain Legacy /* allow all packets destined to our address */ 121150db69fdSAllain Legacy return 0; 121250db69fdSAllain Legacy } 121350db69fdSAllain Legacy 121404d43857SDmitry Kozlyuk if (likely(rte_is_broadcast_ether_addr(ð->dst_addr))) { 121550db69fdSAllain Legacy /* allow all broadcast packets */ 121650db69fdSAllain Legacy return 0; 121750db69fdSAllain Legacy } 121850db69fdSAllain Legacy 121904d43857SDmitry Kozlyuk if (likely(rte_is_multicast_ether_addr(ð->dst_addr))) { 122050db69fdSAllain Legacy /* allow all multicast packets */ 122150db69fdSAllain Legacy return 0; 122250db69fdSAllain Legacy } 122350db69fdSAllain Legacy 122450db69fdSAllain Legacy if (avp->flags & AVP_F_PROMISC) { 122550db69fdSAllain Legacy /* allow all packets when in promiscuous mode */ 122650db69fdSAllain Legacy return 0; 122750db69fdSAllain Legacy } 122850db69fdSAllain Legacy 122950db69fdSAllain Legacy return -1; 123050db69fdSAllain Legacy } 123150db69fdSAllain Legacy 123250db69fdSAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS 123350db69fdSAllain Legacy static inline void 123450db69fdSAllain Legacy __avp_dev_buffer_sanity_check(struct avp_dev *avp, struct rte_avp_desc *buf) 123550db69fdSAllain Legacy { 123650db69fdSAllain Legacy struct rte_avp_desc *first_buf; 123750db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 123850db69fdSAllain Legacy unsigned int pkt_len; 123950db69fdSAllain Legacy unsigned int nb_segs; 124050db69fdSAllain Legacy void *pkt_data; 124150db69fdSAllain Legacy unsigned int i; 124250db69fdSAllain Legacy 124350db69fdSAllain Legacy first_buf = avp_dev_translate_buffer(avp, buf); 124450db69fdSAllain Legacy 124550db69fdSAllain Legacy i = 0; 124650db69fdSAllain Legacy pkt_len = 0; 124750db69fdSAllain Legacy nb_segs = first_buf->nb_segs; 124850db69fdSAllain Legacy do { 124950db69fdSAllain Legacy /* Adjust pointers for guest addressing */ 125050db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 125150db69fdSAllain Legacy if (pkt_buf == NULL) 125250db69fdSAllain Legacy rte_panic("bad buffer: segment %u has an invalid address %p\n", 125350db69fdSAllain Legacy i, buf); 125450db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 125550db69fdSAllain Legacy if (pkt_data == NULL) 125650db69fdSAllain Legacy rte_panic("bad buffer: segment %u has a NULL data pointer\n", 125750db69fdSAllain Legacy i); 125850db69fdSAllain Legacy if (pkt_buf->data_len == 0) 125950db69fdSAllain Legacy rte_panic("bad buffer: segment %u has 0 data length\n", 126050db69fdSAllain Legacy i); 126150db69fdSAllain Legacy pkt_len += pkt_buf->data_len; 126250db69fdSAllain Legacy nb_segs--; 126350db69fdSAllain Legacy i++; 126450db69fdSAllain Legacy 126550db69fdSAllain Legacy } while (nb_segs && (buf = pkt_buf->next) != NULL); 126650db69fdSAllain Legacy 126750db69fdSAllain Legacy if (nb_segs != 0) 126850db69fdSAllain Legacy rte_panic("bad buffer: expected %u segments found %u\n", 126950db69fdSAllain Legacy first_buf->nb_segs, (first_buf->nb_segs - nb_segs)); 127050db69fdSAllain Legacy if (pkt_len != first_buf->pkt_len) 127150db69fdSAllain Legacy rte_panic("bad buffer: expected length %u found %u\n", 127250db69fdSAllain Legacy first_buf->pkt_len, pkt_len); 127350db69fdSAllain Legacy } 127450db69fdSAllain Legacy 127550db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) \ 127650db69fdSAllain Legacy __avp_dev_buffer_sanity_check((a), (b)) 127750db69fdSAllain Legacy 127850db69fdSAllain Legacy #else /* RTE_LIBRTE_AVP_DEBUG_BUFFERS */ 127950db69fdSAllain Legacy 128050db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) do {} while (0) 128150db69fdSAllain Legacy 128250db69fdSAllain Legacy #endif 128350db69fdSAllain Legacy 128450db69fdSAllain Legacy /* 128550db69fdSAllain Legacy * Copy a host buffer chain to a set of mbufs. This function assumes that 128650db69fdSAllain Legacy * there exactly the required number of mbufs to copy all source bytes. 128750db69fdSAllain Legacy */ 128850db69fdSAllain Legacy static inline struct rte_mbuf * 128950db69fdSAllain Legacy avp_dev_copy_from_buffers(struct avp_dev *avp, 129050db69fdSAllain Legacy struct rte_avp_desc *buf, 129150db69fdSAllain Legacy struct rte_mbuf **mbufs, 129250db69fdSAllain Legacy unsigned int count) 129350db69fdSAllain Legacy { 129450db69fdSAllain Legacy struct rte_mbuf *m_previous = NULL; 129550db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 129650db69fdSAllain Legacy unsigned int total_length = 0; 129750db69fdSAllain Legacy unsigned int copy_length; 129850db69fdSAllain Legacy unsigned int src_offset; 129950db69fdSAllain Legacy struct rte_mbuf *m; 130050db69fdSAllain Legacy uint16_t ol_flags; 130150db69fdSAllain Legacy uint16_t vlan_tci; 130250db69fdSAllain Legacy void *pkt_data; 130350db69fdSAllain Legacy unsigned int i; 130450db69fdSAllain Legacy 130550db69fdSAllain Legacy avp_dev_buffer_sanity_check(avp, buf); 130650db69fdSAllain Legacy 130750db69fdSAllain Legacy /* setup the first source buffer */ 130850db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 130950db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 131050db69fdSAllain Legacy total_length = pkt_buf->pkt_len; 131150db69fdSAllain Legacy src_offset = 0; 131250db69fdSAllain Legacy 131350db69fdSAllain Legacy if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) { 1314daa02b5cSOlivier Matz ol_flags = RTE_MBUF_F_RX_VLAN; 131550db69fdSAllain Legacy vlan_tci = pkt_buf->vlan_tci; 131650db69fdSAllain Legacy } else { 131750db69fdSAllain Legacy ol_flags = 0; 131850db69fdSAllain Legacy vlan_tci = 0; 131950db69fdSAllain Legacy } 132050db69fdSAllain Legacy 132150db69fdSAllain Legacy for (i = 0; (i < count) && (buf != NULL); i++) { 132250db69fdSAllain Legacy /* fill each destination buffer */ 132350db69fdSAllain Legacy m = mbufs[i]; 132450db69fdSAllain Legacy 132550db69fdSAllain Legacy if (m_previous != NULL) 132650db69fdSAllain Legacy m_previous->next = m; 132750db69fdSAllain Legacy 132850db69fdSAllain Legacy m_previous = m; 132950db69fdSAllain Legacy 133050db69fdSAllain Legacy do { 133150db69fdSAllain Legacy /* 133250db69fdSAllain Legacy * Copy as many source buffers as will fit in the 133350db69fdSAllain Legacy * destination buffer. 133450db69fdSAllain Legacy */ 133550db69fdSAllain Legacy copy_length = RTE_MIN((avp->guest_mbuf_size - 133650db69fdSAllain Legacy rte_pktmbuf_data_len(m)), 133750db69fdSAllain Legacy (pkt_buf->data_len - 133850db69fdSAllain Legacy src_offset)); 133950db69fdSAllain Legacy rte_memcpy(RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *), 134050db69fdSAllain Legacy rte_pktmbuf_data_len(m)), 134150db69fdSAllain Legacy RTE_PTR_ADD(pkt_data, src_offset), 134250db69fdSAllain Legacy copy_length); 134350db69fdSAllain Legacy rte_pktmbuf_data_len(m) += copy_length; 134450db69fdSAllain Legacy src_offset += copy_length; 134550db69fdSAllain Legacy 134650db69fdSAllain Legacy if (likely(src_offset == pkt_buf->data_len)) { 134750db69fdSAllain Legacy /* need a new source buffer */ 134850db69fdSAllain Legacy buf = pkt_buf->next; 134950db69fdSAllain Legacy if (buf != NULL) { 135050db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer( 135150db69fdSAllain Legacy avp, buf); 135250db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer( 135350db69fdSAllain Legacy avp, pkt_buf->data); 135450db69fdSAllain Legacy src_offset = 0; 135550db69fdSAllain Legacy } 135650db69fdSAllain Legacy } 135750db69fdSAllain Legacy 135850db69fdSAllain Legacy if (unlikely(rte_pktmbuf_data_len(m) == 135950db69fdSAllain Legacy avp->guest_mbuf_size)) { 136050db69fdSAllain Legacy /* need a new destination mbuf */ 136150db69fdSAllain Legacy break; 136250db69fdSAllain Legacy } 136350db69fdSAllain Legacy 136450db69fdSAllain Legacy } while (buf != NULL); 136550db69fdSAllain Legacy } 136650db69fdSAllain Legacy 136750db69fdSAllain Legacy m = mbufs[0]; 136850db69fdSAllain Legacy m->ol_flags = ol_flags; 136950db69fdSAllain Legacy m->nb_segs = count; 137050db69fdSAllain Legacy rte_pktmbuf_pkt_len(m) = total_length; 137150db69fdSAllain Legacy m->vlan_tci = vlan_tci; 137250db69fdSAllain Legacy 137350db69fdSAllain Legacy __rte_mbuf_sanity_check(m, 1); 137450db69fdSAllain Legacy 137550db69fdSAllain Legacy return m; 137650db69fdSAllain Legacy } 137750db69fdSAllain Legacy 137850db69fdSAllain Legacy static uint16_t 137950db69fdSAllain Legacy avp_recv_scattered_pkts(void *rx_queue, 138050db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 138150db69fdSAllain Legacy uint16_t nb_pkts) 138250db69fdSAllain Legacy { 138350db69fdSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 138450db69fdSAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST]; 138550db69fdSAllain Legacy struct rte_mbuf *mbufs[RTE_AVP_MAX_MBUF_SEGMENTS]; 138650db69fdSAllain Legacy struct avp_dev *avp = rxq->avp; 138750db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 138850db69fdSAllain Legacy struct rte_avp_fifo *free_q; 138950db69fdSAllain Legacy struct rte_avp_fifo *rx_q; 139050db69fdSAllain Legacy struct rte_avp_desc *buf; 139150db69fdSAllain Legacy unsigned int count, avail, n; 139250db69fdSAllain Legacy unsigned int guest_mbuf_size; 139350db69fdSAllain Legacy struct rte_mbuf *m; 139450db69fdSAllain Legacy unsigned int required; 139550db69fdSAllain Legacy unsigned int buf_len; 139650db69fdSAllain Legacy unsigned int port_id; 139750db69fdSAllain Legacy unsigned int i; 139850db69fdSAllain Legacy 139982e140b8SAllain Legacy if (unlikely(avp->flags & AVP_F_DETACHED)) { 140082e140b8SAllain Legacy /* VM live migration in progress */ 140182e140b8SAllain Legacy return 0; 140282e140b8SAllain Legacy } 140382e140b8SAllain Legacy 140450db69fdSAllain Legacy guest_mbuf_size = avp->guest_mbuf_size; 140550db69fdSAllain Legacy port_id = avp->port_id; 140650db69fdSAllain Legacy rx_q = avp->rx_q[rxq->queue_id]; 140750db69fdSAllain Legacy free_q = avp->free_q[rxq->queue_id]; 140850db69fdSAllain Legacy 140950db69fdSAllain Legacy /* setup next queue to service */ 141050db69fdSAllain Legacy rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ? 141150db69fdSAllain Legacy (rxq->queue_id + 1) : rxq->queue_base; 141250db69fdSAllain Legacy 141350db69fdSAllain Legacy /* determine how many slots are available in the free queue */ 141450db69fdSAllain Legacy count = avp_fifo_free_count(free_q); 141550db69fdSAllain Legacy 141650db69fdSAllain Legacy /* determine how many packets are available in the rx queue */ 141750db69fdSAllain Legacy avail = avp_fifo_count(rx_q); 141850db69fdSAllain Legacy 141950db69fdSAllain Legacy /* determine how many packets can be received */ 142050db69fdSAllain Legacy count = RTE_MIN(count, avail); 142150db69fdSAllain Legacy count = RTE_MIN(count, nb_pkts); 142250db69fdSAllain Legacy count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST); 142350db69fdSAllain Legacy 142450db69fdSAllain Legacy if (unlikely(count == 0)) { 142550db69fdSAllain Legacy /* no free buffers, or no buffers on the rx queue */ 142650db69fdSAllain Legacy return 0; 142750db69fdSAllain Legacy } 142850db69fdSAllain Legacy 142950db69fdSAllain Legacy /* retrieve pending packets */ 143050db69fdSAllain Legacy n = avp_fifo_get(rx_q, (void **)&avp_bufs, count); 1431*e99981afSDavid Marchand PMD_RX_LOG_LINE(DEBUG, "Receiving %u packets from Rx queue at %p", 143250db69fdSAllain Legacy count, rx_q); 143350db69fdSAllain Legacy 143450db69fdSAllain Legacy count = 0; 143550db69fdSAllain Legacy for (i = 0; i < n; i++) { 143650db69fdSAllain Legacy /* prefetch next entry while processing current one */ 143750db69fdSAllain Legacy if (i + 1 < n) { 143850db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 143950db69fdSAllain Legacy avp_bufs[i + 1]); 144050db69fdSAllain Legacy rte_prefetch0(pkt_buf); 144150db69fdSAllain Legacy } 144250db69fdSAllain Legacy buf = avp_bufs[i]; 144350db69fdSAllain Legacy 144450db69fdSAllain Legacy /* Peek into the first buffer to determine the total length */ 144550db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 144650db69fdSAllain Legacy buf_len = pkt_buf->pkt_len; 144750db69fdSAllain Legacy 144850db69fdSAllain Legacy /* Allocate enough mbufs to receive the entire packet */ 144950db69fdSAllain Legacy required = (buf_len + guest_mbuf_size - 1) / guest_mbuf_size; 145050db69fdSAllain Legacy if (rte_pktmbuf_alloc_bulk(avp->pool, mbufs, required)) { 145150db69fdSAllain Legacy rxq->dev_data->rx_mbuf_alloc_failed++; 145250db69fdSAllain Legacy continue; 145350db69fdSAllain Legacy } 145450db69fdSAllain Legacy 145550db69fdSAllain Legacy /* Copy the data from the buffers to our mbufs */ 145650db69fdSAllain Legacy m = avp_dev_copy_from_buffers(avp, buf, mbufs, required); 145750db69fdSAllain Legacy 145850db69fdSAllain Legacy /* finalize mbuf */ 145950db69fdSAllain Legacy m->port = port_id; 146050db69fdSAllain Legacy 146150db69fdSAllain Legacy if (_avp_mac_filter(avp, m) != 0) { 146250db69fdSAllain Legacy /* silently discard packets not destined to our MAC */ 146350db69fdSAllain Legacy rte_pktmbuf_free(m); 146450db69fdSAllain Legacy continue; 146550db69fdSAllain Legacy } 146650db69fdSAllain Legacy 146750db69fdSAllain Legacy /* return new mbuf to caller */ 146850db69fdSAllain Legacy rx_pkts[count++] = m; 146950db69fdSAllain Legacy rxq->bytes += buf_len; 147050db69fdSAllain Legacy } 147150db69fdSAllain Legacy 147250db69fdSAllain Legacy rxq->packets += count; 147350db69fdSAllain Legacy 147450db69fdSAllain Legacy /* return the buffers to the free queue */ 147550db69fdSAllain Legacy avp_fifo_put(free_q, (void **)&avp_bufs[0], n); 147650db69fdSAllain Legacy 147750db69fdSAllain Legacy return count; 147850db69fdSAllain Legacy } 147950db69fdSAllain Legacy 148050db69fdSAllain Legacy 148150db69fdSAllain Legacy static uint16_t 148250db69fdSAllain Legacy avp_recv_pkts(void *rx_queue, 148350db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 148450db69fdSAllain Legacy uint16_t nb_pkts) 148550db69fdSAllain Legacy { 148650db69fdSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 148750db69fdSAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST]; 148850db69fdSAllain Legacy struct avp_dev *avp = rxq->avp; 148950db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 149050db69fdSAllain Legacy struct rte_avp_fifo *free_q; 149150db69fdSAllain Legacy struct rte_avp_fifo *rx_q; 149250db69fdSAllain Legacy unsigned int count, avail, n; 149350db69fdSAllain Legacy unsigned int pkt_len; 149450db69fdSAllain Legacy struct rte_mbuf *m; 149550db69fdSAllain Legacy char *pkt_data; 149650db69fdSAllain Legacy unsigned int i; 149750db69fdSAllain Legacy 149882e140b8SAllain Legacy if (unlikely(avp->flags & AVP_F_DETACHED)) { 149982e140b8SAllain Legacy /* VM live migration in progress */ 150082e140b8SAllain Legacy return 0; 150182e140b8SAllain Legacy } 150282e140b8SAllain Legacy 150350db69fdSAllain Legacy rx_q = avp->rx_q[rxq->queue_id]; 150450db69fdSAllain Legacy free_q = avp->free_q[rxq->queue_id]; 150550db69fdSAllain Legacy 150650db69fdSAllain Legacy /* setup next queue to service */ 150750db69fdSAllain Legacy rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ? 150850db69fdSAllain Legacy (rxq->queue_id + 1) : rxq->queue_base; 150950db69fdSAllain Legacy 151050db69fdSAllain Legacy /* determine how many slots are available in the free queue */ 151150db69fdSAllain Legacy count = avp_fifo_free_count(free_q); 151250db69fdSAllain Legacy 151350db69fdSAllain Legacy /* determine how many packets are available in the rx queue */ 151450db69fdSAllain Legacy avail = avp_fifo_count(rx_q); 151550db69fdSAllain Legacy 151650db69fdSAllain Legacy /* determine how many packets can be received */ 151750db69fdSAllain Legacy count = RTE_MIN(count, avail); 151850db69fdSAllain Legacy count = RTE_MIN(count, nb_pkts); 151950db69fdSAllain Legacy count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST); 152050db69fdSAllain Legacy 152150db69fdSAllain Legacy if (unlikely(count == 0)) { 152250db69fdSAllain Legacy /* no free buffers, or no buffers on the rx queue */ 152350db69fdSAllain Legacy return 0; 152450db69fdSAllain Legacy } 152550db69fdSAllain Legacy 152650db69fdSAllain Legacy /* retrieve pending packets */ 152750db69fdSAllain Legacy n = avp_fifo_get(rx_q, (void **)&avp_bufs, count); 1528*e99981afSDavid Marchand PMD_RX_LOG_LINE(DEBUG, "Receiving %u packets from Rx queue at %p", 152950db69fdSAllain Legacy count, rx_q); 153050db69fdSAllain Legacy 153150db69fdSAllain Legacy count = 0; 153250db69fdSAllain Legacy for (i = 0; i < n; i++) { 153350db69fdSAllain Legacy /* prefetch next entry while processing current one */ 153450db69fdSAllain Legacy if (i < n - 1) { 153550db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 153650db69fdSAllain Legacy avp_bufs[i + 1]); 153750db69fdSAllain Legacy rte_prefetch0(pkt_buf); 153850db69fdSAllain Legacy } 153950db69fdSAllain Legacy 154050db69fdSAllain Legacy /* Adjust host pointers for guest addressing */ 154150db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]); 154250db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 154350db69fdSAllain Legacy pkt_len = pkt_buf->pkt_len; 154450db69fdSAllain Legacy 154550db69fdSAllain Legacy if (unlikely((pkt_len > avp->guest_mbuf_size) || 154650db69fdSAllain Legacy (pkt_buf->nb_segs > 1))) { 154750db69fdSAllain Legacy /* 154850db69fdSAllain Legacy * application should be using the scattered receive 154950db69fdSAllain Legacy * function 155050db69fdSAllain Legacy */ 155150db69fdSAllain Legacy rxq->errors++; 155250db69fdSAllain Legacy continue; 155350db69fdSAllain Legacy } 155450db69fdSAllain Legacy 155550db69fdSAllain Legacy /* process each packet to be transmitted */ 155650db69fdSAllain Legacy m = rte_pktmbuf_alloc(avp->pool); 155750db69fdSAllain Legacy if (unlikely(m == NULL)) { 155850db69fdSAllain Legacy rxq->dev_data->rx_mbuf_alloc_failed++; 155950db69fdSAllain Legacy continue; 156050db69fdSAllain Legacy } 156150db69fdSAllain Legacy 156250db69fdSAllain Legacy /* copy data out of the host buffer to our buffer */ 156350db69fdSAllain Legacy m->data_off = RTE_PKTMBUF_HEADROOM; 156450db69fdSAllain Legacy rte_memcpy(rte_pktmbuf_mtod(m, void *), pkt_data, pkt_len); 156550db69fdSAllain Legacy 156650db69fdSAllain Legacy /* initialize the local mbuf */ 156750db69fdSAllain Legacy rte_pktmbuf_data_len(m) = pkt_len; 156850db69fdSAllain Legacy rte_pktmbuf_pkt_len(m) = pkt_len; 156950db69fdSAllain Legacy m->port = avp->port_id; 157050db69fdSAllain Legacy 157150db69fdSAllain Legacy if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) { 1572daa02b5cSOlivier Matz m->ol_flags = RTE_MBUF_F_RX_VLAN; 157350db69fdSAllain Legacy m->vlan_tci = pkt_buf->vlan_tci; 157450db69fdSAllain Legacy } 157550db69fdSAllain Legacy 157650db69fdSAllain Legacy if (_avp_mac_filter(avp, m) != 0) { 157750db69fdSAllain Legacy /* silently discard packets not destined to our MAC */ 157850db69fdSAllain Legacy rte_pktmbuf_free(m); 157950db69fdSAllain Legacy continue; 158050db69fdSAllain Legacy } 158150db69fdSAllain Legacy 158250db69fdSAllain Legacy /* return new mbuf to caller */ 158350db69fdSAllain Legacy rx_pkts[count++] = m; 158450db69fdSAllain Legacy rxq->bytes += pkt_len; 158550db69fdSAllain Legacy } 158650db69fdSAllain Legacy 158750db69fdSAllain Legacy rxq->packets += count; 158850db69fdSAllain Legacy 158950db69fdSAllain Legacy /* return the buffers to the free queue */ 159050db69fdSAllain Legacy avp_fifo_put(free_q, (void **)&avp_bufs[0], n); 159150db69fdSAllain Legacy 159250db69fdSAllain Legacy return count; 159350db69fdSAllain Legacy } 159450db69fdSAllain Legacy 1595295abce2SAllain Legacy /* 1596295abce2SAllain Legacy * Copy a chained mbuf to a set of host buffers. This function assumes that 1597295abce2SAllain Legacy * there are sufficient destination buffers to contain the entire source 1598295abce2SAllain Legacy * packet. 1599295abce2SAllain Legacy */ 1600295abce2SAllain Legacy static inline uint16_t 1601295abce2SAllain Legacy avp_dev_copy_to_buffers(struct avp_dev *avp, 1602295abce2SAllain Legacy struct rte_mbuf *mbuf, 1603295abce2SAllain Legacy struct rte_avp_desc **buffers, 1604295abce2SAllain Legacy unsigned int count) 1605295abce2SAllain Legacy { 1606295abce2SAllain Legacy struct rte_avp_desc *previous_buf = NULL; 1607295abce2SAllain Legacy struct rte_avp_desc *first_buf = NULL; 1608295abce2SAllain Legacy struct rte_avp_desc *pkt_buf; 1609295abce2SAllain Legacy struct rte_avp_desc *buf; 1610295abce2SAllain Legacy size_t total_length; 1611295abce2SAllain Legacy struct rte_mbuf *m; 1612295abce2SAllain Legacy size_t copy_length; 1613295abce2SAllain Legacy size_t src_offset; 1614295abce2SAllain Legacy char *pkt_data; 1615295abce2SAllain Legacy unsigned int i; 1616295abce2SAllain Legacy 1617295abce2SAllain Legacy __rte_mbuf_sanity_check(mbuf, 1); 1618295abce2SAllain Legacy 1619295abce2SAllain Legacy m = mbuf; 1620295abce2SAllain Legacy src_offset = 0; 1621295abce2SAllain Legacy total_length = rte_pktmbuf_pkt_len(m); 1622295abce2SAllain Legacy for (i = 0; (i < count) && (m != NULL); i++) { 1623295abce2SAllain Legacy /* fill each destination buffer */ 1624295abce2SAllain Legacy buf = buffers[i]; 1625295abce2SAllain Legacy 1626295abce2SAllain Legacy if (i < count - 1) { 1627295abce2SAllain Legacy /* prefetch next entry while processing this one */ 1628295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buffers[i + 1]); 1629295abce2SAllain Legacy rte_prefetch0(pkt_buf); 1630295abce2SAllain Legacy } 1631295abce2SAllain Legacy 1632295abce2SAllain Legacy /* Adjust pointers for guest addressing */ 1633295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 1634295abce2SAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 1635295abce2SAllain Legacy 1636295abce2SAllain Legacy /* setup the buffer chain */ 1637295abce2SAllain Legacy if (previous_buf != NULL) 1638295abce2SAllain Legacy previous_buf->next = buf; 1639295abce2SAllain Legacy else 1640295abce2SAllain Legacy first_buf = pkt_buf; 1641295abce2SAllain Legacy 1642295abce2SAllain Legacy previous_buf = pkt_buf; 1643295abce2SAllain Legacy 1644295abce2SAllain Legacy do { 1645295abce2SAllain Legacy /* 1646295abce2SAllain Legacy * copy as many source mbuf segments as will fit in the 1647295abce2SAllain Legacy * destination buffer. 1648295abce2SAllain Legacy */ 1649295abce2SAllain Legacy copy_length = RTE_MIN((avp->host_mbuf_size - 1650295abce2SAllain Legacy pkt_buf->data_len), 1651295abce2SAllain Legacy (rte_pktmbuf_data_len(m) - 1652295abce2SAllain Legacy src_offset)); 1653295abce2SAllain Legacy rte_memcpy(RTE_PTR_ADD(pkt_data, pkt_buf->data_len), 1654295abce2SAllain Legacy RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *), 1655295abce2SAllain Legacy src_offset), 1656295abce2SAllain Legacy copy_length); 1657295abce2SAllain Legacy pkt_buf->data_len += copy_length; 1658295abce2SAllain Legacy src_offset += copy_length; 1659295abce2SAllain Legacy 1660295abce2SAllain Legacy if (likely(src_offset == rte_pktmbuf_data_len(m))) { 1661295abce2SAllain Legacy /* need a new source buffer */ 1662295abce2SAllain Legacy m = m->next; 1663295abce2SAllain Legacy src_offset = 0; 1664295abce2SAllain Legacy } 1665295abce2SAllain Legacy 1666295abce2SAllain Legacy if (unlikely(pkt_buf->data_len == 1667295abce2SAllain Legacy avp->host_mbuf_size)) { 1668295abce2SAllain Legacy /* need a new destination buffer */ 1669295abce2SAllain Legacy break; 1670295abce2SAllain Legacy } 1671295abce2SAllain Legacy 1672295abce2SAllain Legacy } while (m != NULL); 1673295abce2SAllain Legacy } 1674295abce2SAllain Legacy 1675295abce2SAllain Legacy first_buf->nb_segs = count; 1676295abce2SAllain Legacy first_buf->pkt_len = total_length; 1677295abce2SAllain Legacy 1678daa02b5cSOlivier Matz if (mbuf->ol_flags & RTE_MBUF_F_TX_VLAN) { 1679295abce2SAllain Legacy first_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT; 1680295abce2SAllain Legacy first_buf->vlan_tci = mbuf->vlan_tci; 1681295abce2SAllain Legacy } 1682295abce2SAllain Legacy 1683295abce2SAllain Legacy avp_dev_buffer_sanity_check(avp, buffers[0]); 1684295abce2SAllain Legacy 1685295abce2SAllain Legacy return total_length; 1686295abce2SAllain Legacy } 1687295abce2SAllain Legacy 1688295abce2SAllain Legacy 1689295abce2SAllain Legacy static uint16_t 1690295abce2SAllain Legacy avp_xmit_scattered_pkts(void *tx_queue, 1691295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 1692295abce2SAllain Legacy uint16_t nb_pkts) 1693295abce2SAllain Legacy { 1694295abce2SAllain Legacy struct rte_avp_desc *avp_bufs[(AVP_MAX_TX_BURST * 1695ec87d3b2SKevin Traynor RTE_AVP_MAX_MBUF_SEGMENTS)] = {}; 1696295abce2SAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 1697295abce2SAllain Legacy struct rte_avp_desc *tx_bufs[AVP_MAX_TX_BURST]; 1698295abce2SAllain Legacy struct avp_dev *avp = txq->avp; 1699295abce2SAllain Legacy struct rte_avp_fifo *alloc_q; 1700295abce2SAllain Legacy struct rte_avp_fifo *tx_q; 1701295abce2SAllain Legacy unsigned int count, avail, n; 1702295abce2SAllain Legacy unsigned int orig_nb_pkts; 1703295abce2SAllain Legacy struct rte_mbuf *m; 1704295abce2SAllain Legacy unsigned int required; 1705295abce2SAllain Legacy unsigned int segments; 1706295abce2SAllain Legacy unsigned int tx_bytes; 1707295abce2SAllain Legacy unsigned int i; 1708295abce2SAllain Legacy 1709295abce2SAllain Legacy orig_nb_pkts = nb_pkts; 171082e140b8SAllain Legacy if (unlikely(avp->flags & AVP_F_DETACHED)) { 171182e140b8SAllain Legacy /* VM live migration in progress */ 171282e140b8SAllain Legacy /* TODO ... buffer for X packets then drop? */ 171382e140b8SAllain Legacy txq->errors += nb_pkts; 171482e140b8SAllain Legacy return 0; 171582e140b8SAllain Legacy } 171682e140b8SAllain Legacy 1717295abce2SAllain Legacy tx_q = avp->tx_q[txq->queue_id]; 1718295abce2SAllain Legacy alloc_q = avp->alloc_q[txq->queue_id]; 1719295abce2SAllain Legacy 1720295abce2SAllain Legacy /* limit the number of transmitted packets to the max burst size */ 1721295abce2SAllain Legacy if (unlikely(nb_pkts > AVP_MAX_TX_BURST)) 1722295abce2SAllain Legacy nb_pkts = AVP_MAX_TX_BURST; 1723295abce2SAllain Legacy 1724295abce2SAllain Legacy /* determine how many buffers are available to copy into */ 1725295abce2SAllain Legacy avail = avp_fifo_count(alloc_q); 1726295abce2SAllain Legacy if (unlikely(avail > (AVP_MAX_TX_BURST * 1727295abce2SAllain Legacy RTE_AVP_MAX_MBUF_SEGMENTS))) 1728295abce2SAllain Legacy avail = AVP_MAX_TX_BURST * RTE_AVP_MAX_MBUF_SEGMENTS; 1729295abce2SAllain Legacy 1730295abce2SAllain Legacy /* determine how many slots are available in the transmit queue */ 1731295abce2SAllain Legacy count = avp_fifo_free_count(tx_q); 1732295abce2SAllain Legacy 1733295abce2SAllain Legacy /* determine how many packets can be sent */ 1734295abce2SAllain Legacy nb_pkts = RTE_MIN(count, nb_pkts); 1735295abce2SAllain Legacy 1736295abce2SAllain Legacy /* determine how many packets will fit in the available buffers */ 1737295abce2SAllain Legacy count = 0; 1738295abce2SAllain Legacy segments = 0; 1739295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) { 1740295abce2SAllain Legacy m = tx_pkts[i]; 1741295abce2SAllain Legacy if (likely(i < (unsigned int)nb_pkts - 1)) { 1742295abce2SAllain Legacy /* prefetch next entry while processing this one */ 1743295abce2SAllain Legacy rte_prefetch0(tx_pkts[i + 1]); 1744295abce2SAllain Legacy } 1745295abce2SAllain Legacy required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) / 1746295abce2SAllain Legacy avp->host_mbuf_size; 1747295abce2SAllain Legacy 1748295abce2SAllain Legacy if (unlikely((required == 0) || 1749295abce2SAllain Legacy (required > RTE_AVP_MAX_MBUF_SEGMENTS))) 1750295abce2SAllain Legacy break; 1751295abce2SAllain Legacy else if (unlikely(required + segments > avail)) 1752295abce2SAllain Legacy break; 1753295abce2SAllain Legacy segments += required; 1754295abce2SAllain Legacy count++; 1755295abce2SAllain Legacy } 1756295abce2SAllain Legacy nb_pkts = count; 1757295abce2SAllain Legacy 1758295abce2SAllain Legacy if (unlikely(nb_pkts == 0)) { 1759295abce2SAllain Legacy /* no available buffers, or no space on the tx queue */ 1760295abce2SAllain Legacy txq->errors += orig_nb_pkts; 1761295abce2SAllain Legacy return 0; 1762295abce2SAllain Legacy } 1763295abce2SAllain Legacy 1764*e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, "Sending %u packets on Tx queue at %p", 1765295abce2SAllain Legacy nb_pkts, tx_q); 1766295abce2SAllain Legacy 1767295abce2SAllain Legacy /* retrieve sufficient send buffers */ 1768295abce2SAllain Legacy n = avp_fifo_get(alloc_q, (void **)&avp_bufs, segments); 1769295abce2SAllain Legacy if (unlikely(n != segments)) { 1770*e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, "Failed to allocate buffers n=%u, segments=%u, orig=%u", 1771295abce2SAllain Legacy n, segments, orig_nb_pkts); 1772295abce2SAllain Legacy txq->errors += orig_nb_pkts; 1773295abce2SAllain Legacy return 0; 1774295abce2SAllain Legacy } 1775295abce2SAllain Legacy 1776295abce2SAllain Legacy tx_bytes = 0; 1777295abce2SAllain Legacy count = 0; 1778295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) { 1779295abce2SAllain Legacy /* process each packet to be transmitted */ 1780295abce2SAllain Legacy m = tx_pkts[i]; 1781295abce2SAllain Legacy 1782295abce2SAllain Legacy /* determine how many buffers are required for this packet */ 1783295abce2SAllain Legacy required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) / 1784295abce2SAllain Legacy avp->host_mbuf_size; 1785295abce2SAllain Legacy 1786295abce2SAllain Legacy tx_bytes += avp_dev_copy_to_buffers(avp, m, 1787295abce2SAllain Legacy &avp_bufs[count], required); 1788295abce2SAllain Legacy tx_bufs[i] = avp_bufs[count]; 1789295abce2SAllain Legacy count += required; 1790295abce2SAllain Legacy 1791295abce2SAllain Legacy /* free the original mbuf */ 1792295abce2SAllain Legacy rte_pktmbuf_free(m); 1793295abce2SAllain Legacy } 1794295abce2SAllain Legacy 1795295abce2SAllain Legacy txq->packets += nb_pkts; 1796295abce2SAllain Legacy txq->bytes += tx_bytes; 1797295abce2SAllain Legacy 1798295abce2SAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS 1799295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) 1800295abce2SAllain Legacy avp_dev_buffer_sanity_check(avp, tx_bufs[i]); 1801295abce2SAllain Legacy #endif 1802295abce2SAllain Legacy 1803295abce2SAllain Legacy /* send the packets */ 1804295abce2SAllain Legacy n = avp_fifo_put(tx_q, (void **)&tx_bufs[0], nb_pkts); 1805295abce2SAllain Legacy if (unlikely(n != orig_nb_pkts)) 1806295abce2SAllain Legacy txq->errors += (orig_nb_pkts - n); 1807295abce2SAllain Legacy 1808295abce2SAllain Legacy return n; 1809295abce2SAllain Legacy } 1810295abce2SAllain Legacy 1811295abce2SAllain Legacy 1812295abce2SAllain Legacy static uint16_t 1813295abce2SAllain Legacy avp_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) 1814295abce2SAllain Legacy { 1815295abce2SAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 1816295abce2SAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_TX_BURST]; 1817295abce2SAllain Legacy struct avp_dev *avp = txq->avp; 1818295abce2SAllain Legacy struct rte_avp_desc *pkt_buf; 1819295abce2SAllain Legacy struct rte_avp_fifo *alloc_q; 1820295abce2SAllain Legacy struct rte_avp_fifo *tx_q; 1821295abce2SAllain Legacy unsigned int count, avail, n; 1822295abce2SAllain Legacy struct rte_mbuf *m; 1823295abce2SAllain Legacy unsigned int pkt_len; 1824295abce2SAllain Legacy unsigned int tx_bytes; 1825295abce2SAllain Legacy char *pkt_data; 1826295abce2SAllain Legacy unsigned int i; 1827295abce2SAllain Legacy 182882e140b8SAllain Legacy if (unlikely(avp->flags & AVP_F_DETACHED)) { 182982e140b8SAllain Legacy /* VM live migration in progress */ 183082e140b8SAllain Legacy /* TODO ... buffer for X packets then drop?! */ 183182e140b8SAllain Legacy txq->errors++; 183282e140b8SAllain Legacy return 0; 183382e140b8SAllain Legacy } 183482e140b8SAllain Legacy 1835295abce2SAllain Legacy tx_q = avp->tx_q[txq->queue_id]; 1836295abce2SAllain Legacy alloc_q = avp->alloc_q[txq->queue_id]; 1837295abce2SAllain Legacy 1838295abce2SAllain Legacy /* limit the number of transmitted packets to the max burst size */ 1839295abce2SAllain Legacy if (unlikely(nb_pkts > AVP_MAX_TX_BURST)) 1840295abce2SAllain Legacy nb_pkts = AVP_MAX_TX_BURST; 1841295abce2SAllain Legacy 1842295abce2SAllain Legacy /* determine how many buffers are available to copy into */ 1843295abce2SAllain Legacy avail = avp_fifo_count(alloc_q); 1844295abce2SAllain Legacy 1845295abce2SAllain Legacy /* determine how many slots are available in the transmit queue */ 1846295abce2SAllain Legacy count = avp_fifo_free_count(tx_q); 1847295abce2SAllain Legacy 1848295abce2SAllain Legacy /* determine how many packets can be sent */ 1849295abce2SAllain Legacy count = RTE_MIN(count, avail); 1850295abce2SAllain Legacy count = RTE_MIN(count, nb_pkts); 1851295abce2SAllain Legacy 1852295abce2SAllain Legacy if (unlikely(count == 0)) { 1853295abce2SAllain Legacy /* no available buffers, or no space on the tx queue */ 1854295abce2SAllain Legacy txq->errors += nb_pkts; 1855295abce2SAllain Legacy return 0; 1856295abce2SAllain Legacy } 1857295abce2SAllain Legacy 1858*e99981afSDavid Marchand PMD_TX_LOG_LINE(DEBUG, "Sending %u packets on Tx queue at %p", 1859295abce2SAllain Legacy count, tx_q); 1860295abce2SAllain Legacy 1861295abce2SAllain Legacy /* retrieve sufficient send buffers */ 1862295abce2SAllain Legacy n = avp_fifo_get(alloc_q, (void **)&avp_bufs, count); 1863295abce2SAllain Legacy if (unlikely(n != count)) { 1864295abce2SAllain Legacy txq->errors++; 1865295abce2SAllain Legacy return 0; 1866295abce2SAllain Legacy } 1867295abce2SAllain Legacy 1868295abce2SAllain Legacy tx_bytes = 0; 1869295abce2SAllain Legacy for (i = 0; i < count; i++) { 1870295abce2SAllain Legacy /* prefetch next entry while processing the current one */ 1871295abce2SAllain Legacy if (i < count - 1) { 1872295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 1873295abce2SAllain Legacy avp_bufs[i + 1]); 1874295abce2SAllain Legacy rte_prefetch0(pkt_buf); 1875295abce2SAllain Legacy } 1876295abce2SAllain Legacy 1877295abce2SAllain Legacy /* process each packet to be transmitted */ 1878295abce2SAllain Legacy m = tx_pkts[i]; 1879295abce2SAllain Legacy 1880295abce2SAllain Legacy /* Adjust pointers for guest addressing */ 1881295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]); 1882295abce2SAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 1883295abce2SAllain Legacy pkt_len = rte_pktmbuf_pkt_len(m); 1884295abce2SAllain Legacy 1885295abce2SAllain Legacy if (unlikely((pkt_len > avp->guest_mbuf_size) || 1886295abce2SAllain Legacy (pkt_len > avp->host_mbuf_size))) { 1887295abce2SAllain Legacy /* 1888295abce2SAllain Legacy * application should be using the scattered transmit 1889295abce2SAllain Legacy * function; send it truncated to avoid the performance 1890295abce2SAllain Legacy * hit of having to manage returning the already 1891295abce2SAllain Legacy * allocated buffer to the free list. This should not 18921bb4a528SFerruh Yigit * happen since the application should have not send 18931bb4a528SFerruh Yigit * packages larger than its MTU and it should be 1894295abce2SAllain Legacy * policing its own packet sizes. 1895295abce2SAllain Legacy */ 1896295abce2SAllain Legacy txq->errors++; 1897295abce2SAllain Legacy pkt_len = RTE_MIN(avp->guest_mbuf_size, 1898295abce2SAllain Legacy avp->host_mbuf_size); 1899295abce2SAllain Legacy } 1900295abce2SAllain Legacy 1901295abce2SAllain Legacy /* copy data out of our mbuf and into the AVP buffer */ 1902295abce2SAllain Legacy rte_memcpy(pkt_data, rte_pktmbuf_mtod(m, void *), pkt_len); 1903295abce2SAllain Legacy pkt_buf->pkt_len = pkt_len; 1904295abce2SAllain Legacy pkt_buf->data_len = pkt_len; 1905295abce2SAllain Legacy pkt_buf->nb_segs = 1; 1906295abce2SAllain Legacy pkt_buf->next = NULL; 1907295abce2SAllain Legacy 1908daa02b5cSOlivier Matz if (m->ol_flags & RTE_MBUF_F_TX_VLAN) { 1909295abce2SAllain Legacy pkt_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT; 1910295abce2SAllain Legacy pkt_buf->vlan_tci = m->vlan_tci; 1911295abce2SAllain Legacy } 1912295abce2SAllain Legacy 1913295abce2SAllain Legacy tx_bytes += pkt_len; 1914295abce2SAllain Legacy 1915295abce2SAllain Legacy /* free the original mbuf */ 1916295abce2SAllain Legacy rte_pktmbuf_free(m); 1917295abce2SAllain Legacy } 1918295abce2SAllain Legacy 1919295abce2SAllain Legacy txq->packets += count; 1920295abce2SAllain Legacy txq->bytes += tx_bytes; 1921295abce2SAllain Legacy 1922295abce2SAllain Legacy /* send the packets */ 1923295abce2SAllain Legacy n = avp_fifo_put(tx_q, (void **)&avp_bufs[0], count); 1924295abce2SAllain Legacy 1925295abce2SAllain Legacy return n; 1926295abce2SAllain Legacy } 1927295abce2SAllain Legacy 1928cce4367fSAllain Legacy static void 19297483341aSXueming Li avp_dev_rx_queue_release(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) 1930cce4367fSAllain Legacy { 19317483341aSXueming Li if (eth_dev->data->rx_queues[rx_queue_id] != NULL) { 19327483341aSXueming Li rte_free(eth_dev->data->rx_queues[rx_queue_id]); 19337483341aSXueming Li eth_dev->data->rx_queues[rx_queue_id] = NULL; 1934cce4367fSAllain Legacy } 193515fb42d5SAllain Legacy } 193615fb42d5SAllain Legacy 193715fb42d5SAllain Legacy static void 193815fb42d5SAllain Legacy avp_dev_rx_queue_release_all(struct rte_eth_dev *eth_dev) 193915fb42d5SAllain Legacy { 194015fb42d5SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 194115fb42d5SAllain Legacy struct rte_eth_dev_data *data = avp->dev_data; 194215fb42d5SAllain Legacy unsigned int i; 194315fb42d5SAllain Legacy 194415fb42d5SAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 194515fb42d5SAllain Legacy if (data->rx_queues[i]) { 194615fb42d5SAllain Legacy rte_free(data->rx_queues[i]); 194715fb42d5SAllain Legacy data->rx_queues[i] = NULL; 194815fb42d5SAllain Legacy } 194915fb42d5SAllain Legacy } 195015fb42d5SAllain Legacy } 1951cce4367fSAllain Legacy 1952cce4367fSAllain Legacy static void 19537483341aSXueming Li avp_dev_tx_queue_release(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id) 1954cce4367fSAllain Legacy { 19557483341aSXueming Li if (eth_dev->data->tx_queues[tx_queue_id] != NULL) { 19567483341aSXueming Li rte_free(eth_dev->data->tx_queues[tx_queue_id]); 19577483341aSXueming Li eth_dev->data->tx_queues[tx_queue_id] = NULL; 1958cce4367fSAllain Legacy } 195915fb42d5SAllain Legacy } 196015fb42d5SAllain Legacy 196115fb42d5SAllain Legacy static void 196215fb42d5SAllain Legacy avp_dev_tx_queue_release_all(struct rte_eth_dev *eth_dev) 196315fb42d5SAllain Legacy { 196415fb42d5SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 196515fb42d5SAllain Legacy struct rte_eth_dev_data *data = avp->dev_data; 196615fb42d5SAllain Legacy unsigned int i; 196715fb42d5SAllain Legacy 196815fb42d5SAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 196915fb42d5SAllain Legacy if (data->tx_queues[i]) { 197015fb42d5SAllain Legacy rte_free(data->tx_queues[i]); 197115fb42d5SAllain Legacy data->tx_queues[i] = NULL; 197215fb42d5SAllain Legacy } 197315fb42d5SAllain Legacy } 197415fb42d5SAllain Legacy } 1975cce4367fSAllain Legacy 1976cce4367fSAllain Legacy static int 19771a859223SAllain Legacy avp_dev_configure(struct rte_eth_dev *eth_dev) 19781a859223SAllain Legacy { 1979c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 19801a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 19811a859223SAllain Legacy struct rte_avp_device_info *host_info; 19821a859223SAllain Legacy struct rte_avp_device_config config; 19831a859223SAllain Legacy int mask = 0; 19841a859223SAllain Legacy void *addr; 19851a859223SAllain Legacy int ret; 19861a859223SAllain Legacy 198782e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 198882e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 1989*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Operation not supported during VM live migration"); 199082e140b8SAllain Legacy ret = -ENOTSUP; 199182e140b8SAllain Legacy goto unlock; 199282e140b8SAllain Legacy } 199382e140b8SAllain Legacy 19941a859223SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr; 19951a859223SAllain Legacy host_info = (struct rte_avp_device_info *)addr; 19961a859223SAllain Legacy 19971a859223SAllain Legacy /* Setup required number of queues */ 19981a859223SAllain Legacy _avp_set_queue_counts(eth_dev); 19991a859223SAllain Legacy 2000295968d1SFerruh Yigit mask = (RTE_ETH_VLAN_STRIP_MASK | 2001295968d1SFerruh Yigit RTE_ETH_VLAN_FILTER_MASK | 2002295968d1SFerruh Yigit RTE_ETH_VLAN_EXTEND_MASK); 2003289ba0c0SDavid Harton ret = avp_vlan_offload_set(eth_dev, mask); 2004289ba0c0SDavid Harton if (ret < 0) { 2005*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "VLAN offload set failed by host, ret=%d", 2006289ba0c0SDavid Harton ret); 2007289ba0c0SDavid Harton goto unlock; 2008289ba0c0SDavid Harton } 20091a859223SAllain Legacy 20101a859223SAllain Legacy /* update device config */ 20111a859223SAllain Legacy memset(&config, 0, sizeof(config)); 20121a859223SAllain Legacy config.device_id = host_info->device_id; 20131a859223SAllain Legacy config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK; 20141a859223SAllain Legacy config.driver_version = AVP_DPDK_DRIVER_VERSION; 20151a859223SAllain Legacy config.features = avp->features; 20161a859223SAllain Legacy config.num_tx_queues = avp->num_tx_queues; 20171a859223SAllain Legacy config.num_rx_queues = avp->num_rx_queues; 20181a859223SAllain Legacy 20191a859223SAllain Legacy ret = avp_dev_ctrl_set_config(eth_dev, &config); 20201a859223SAllain Legacy if (ret < 0) { 2021*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Config request failed by host, ret=%d", 20221a859223SAllain Legacy ret); 20231a859223SAllain Legacy goto unlock; 20241a859223SAllain Legacy } 20251a859223SAllain Legacy 20261a859223SAllain Legacy avp->flags |= AVP_F_CONFIGURED; 20271a859223SAllain Legacy ret = 0; 20281a859223SAllain Legacy 20291a859223SAllain Legacy unlock: 203082e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 20311a859223SAllain Legacy return ret; 20321a859223SAllain Legacy } 20331a859223SAllain Legacy 2034ea37523dSAllain Legacy static int 2035ea37523dSAllain Legacy avp_dev_start(struct rte_eth_dev *eth_dev) 2036ea37523dSAllain Legacy { 2037ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 203868601507SJie Hai uint16_t i; 2039ea37523dSAllain Legacy int ret; 2040ea37523dSAllain Legacy 204182e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 204282e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 2043*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Operation not supported during VM live migration"); 204482e140b8SAllain Legacy ret = -ENOTSUP; 204582e140b8SAllain Legacy goto unlock; 204682e140b8SAllain Legacy } 204782e140b8SAllain Legacy 2048ea37523dSAllain Legacy /* update link state */ 2049ea37523dSAllain Legacy ret = avp_dev_ctrl_set_link_state(eth_dev, 1); 2050ea37523dSAllain Legacy if (ret < 0) { 2051*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Link state change failed by host, ret=%d", 2052ea37523dSAllain Legacy ret); 2053ea37523dSAllain Legacy goto unlock; 2054ea37523dSAllain Legacy } 2055ea37523dSAllain Legacy 2056ea37523dSAllain Legacy /* remember current link state */ 2057ea37523dSAllain Legacy avp->flags |= AVP_F_LINKUP; 2058ea37523dSAllain Legacy 205968601507SJie Hai for (i = 0; i < avp->num_rx_queues; i++) 206068601507SJie Hai eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 206168601507SJie Hai for (i = 0; i < avp->num_tx_queues; i++) 206268601507SJie Hai eth_dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 206368601507SJie Hai 2064ea37523dSAllain Legacy ret = 0; 2065ea37523dSAllain Legacy 2066ea37523dSAllain Legacy unlock: 206782e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 2068ea37523dSAllain Legacy return ret; 2069ea37523dSAllain Legacy } 2070ea37523dSAllain Legacy 207162024eb8SIvan Ilchenko static int 2072ea37523dSAllain Legacy avp_dev_stop(struct rte_eth_dev *eth_dev) 2073ea37523dSAllain Legacy { 2074ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 207568601507SJie Hai uint16_t i; 2076ea37523dSAllain Legacy int ret; 2077ea37523dSAllain Legacy 207882e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 207982e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 2080*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Operation not supported during VM live migration"); 208162024eb8SIvan Ilchenko ret = -ENOTSUP; 208282e140b8SAllain Legacy goto unlock; 208382e140b8SAllain Legacy } 208482e140b8SAllain Legacy 208582e140b8SAllain Legacy /* remember current link state */ 2086ea37523dSAllain Legacy avp->flags &= ~AVP_F_LINKUP; 2087ea37523dSAllain Legacy 2088ea37523dSAllain Legacy /* update link state */ 2089ea37523dSAllain Legacy ret = avp_dev_ctrl_set_link_state(eth_dev, 0); 2090ea37523dSAllain Legacy if (ret < 0) { 2091*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Link state change failed by host, ret=%d", 2092ea37523dSAllain Legacy ret); 2093ea37523dSAllain Legacy } 209482e140b8SAllain Legacy 209568601507SJie Hai for (i = 0; i < avp->num_rx_queues; i++) 209668601507SJie Hai eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 209768601507SJie Hai for (i = 0; i < avp->num_tx_queues; i++) 209868601507SJie Hai eth_dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 209968601507SJie Hai 210082e140b8SAllain Legacy unlock: 210182e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 210262024eb8SIvan Ilchenko return ret; 2103ea37523dSAllain Legacy } 2104ea37523dSAllain Legacy 2105b142387bSThomas Monjalon static int 2106ea37523dSAllain Legacy avp_dev_close(struct rte_eth_dev *eth_dev) 2107ea37523dSAllain Legacy { 2108ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 2109ea37523dSAllain Legacy int ret; 2110ea37523dSAllain Legacy 211130410493SThomas Monjalon if (rte_eal_process_type() != RTE_PROC_PRIMARY) 211230410493SThomas Monjalon return 0; 211330410493SThomas Monjalon 211482e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 211582e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 2116*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Operation not supported during VM live migration"); 211782e140b8SAllain Legacy goto unlock; 211882e140b8SAllain Legacy } 211982e140b8SAllain Legacy 2120ea37523dSAllain Legacy /* remember current link state */ 2121ea37523dSAllain Legacy avp->flags &= ~AVP_F_LINKUP; 2122ea37523dSAllain Legacy avp->flags &= ~AVP_F_CONFIGURED; 2123ea37523dSAllain Legacy 212482e140b8SAllain Legacy ret = avp_dev_disable_interrupts(eth_dev); 212582e140b8SAllain Legacy if (ret < 0) { 2126*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Failed to disable interrupts"); 212782e140b8SAllain Legacy /* continue */ 212882e140b8SAllain Legacy } 212982e140b8SAllain Legacy 2130ea37523dSAllain Legacy /* update device state */ 2131ea37523dSAllain Legacy ret = avp_dev_ctrl_shutdown(eth_dev); 2132ea37523dSAllain Legacy if (ret < 0) { 2133*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "Device shutdown failed by host, ret=%d", 2134ea37523dSAllain Legacy ret); 2135ea37523dSAllain Legacy /* continue */ 2136ea37523dSAllain Legacy } 213782e140b8SAllain Legacy 213815fb42d5SAllain Legacy /* release dynamic storage for rx/tx queues */ 213915fb42d5SAllain Legacy avp_dev_rx_queue_release_all(eth_dev); 214015fb42d5SAllain Legacy avp_dev_tx_queue_release_all(eth_dev); 214115fb42d5SAllain Legacy 214282e140b8SAllain Legacy unlock: 214382e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 2144b142387bSThomas Monjalon return 0; 2145ea37523dSAllain Legacy } 21461a859223SAllain Legacy 21471a859223SAllain Legacy static int 21481a859223SAllain Legacy avp_dev_link_update(struct rte_eth_dev *eth_dev, 21491a859223SAllain Legacy __rte_unused int wait_to_complete) 21501a859223SAllain Legacy { 21511a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 21521a859223SAllain Legacy struct rte_eth_link *link = ð_dev->data->dev_link; 21531a859223SAllain Legacy 2154295968d1SFerruh Yigit link->link_speed = RTE_ETH_SPEED_NUM_10G; 2155295968d1SFerruh Yigit link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 21561a859223SAllain Legacy link->link_status = !!(avp->flags & AVP_F_LINKUP); 21571a859223SAllain Legacy 21581a859223SAllain Legacy return -1; 21591a859223SAllain Legacy } 21601a859223SAllain Legacy 21619039c812SAndrew Rybchenko static int 21628129545eSAllain Legacy avp_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 21638129545eSAllain Legacy { 21648129545eSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 21658129545eSAllain Legacy 216682e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 21678129545eSAllain Legacy if ((avp->flags & AVP_F_PROMISC) == 0) { 21688129545eSAllain Legacy avp->flags |= AVP_F_PROMISC; 2169*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Promiscuous mode enabled on %u", 21708129545eSAllain Legacy eth_dev->data->port_id); 21718129545eSAllain Legacy } 217282e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 21739039c812SAndrew Rybchenko 21749039c812SAndrew Rybchenko return 0; 21758129545eSAllain Legacy } 21768129545eSAllain Legacy 21779039c812SAndrew Rybchenko static int 21788129545eSAllain Legacy avp_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 21798129545eSAllain Legacy { 21808129545eSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 21818129545eSAllain Legacy 218282e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 21838129545eSAllain Legacy if ((avp->flags & AVP_F_PROMISC) != 0) { 21848129545eSAllain Legacy avp->flags &= ~AVP_F_PROMISC; 2185*e99981afSDavid Marchand PMD_DRV_LOG_LINE(DEBUG, "Promiscuous mode disabled on %u", 21868129545eSAllain Legacy eth_dev->data->port_id); 21878129545eSAllain Legacy } 218882e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 21899039c812SAndrew Rybchenko 21909039c812SAndrew Rybchenko return 0; 21918129545eSAllain Legacy } 21921a859223SAllain Legacy 2193bdad90d1SIvan Ilchenko static int 21941a859223SAllain Legacy avp_dev_info_get(struct rte_eth_dev *eth_dev, 21951a859223SAllain Legacy struct rte_eth_dev_info *dev_info) 21961a859223SAllain Legacy { 21971a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 21981a859223SAllain Legacy 21991a859223SAllain Legacy dev_info->max_rx_queues = avp->max_rx_queues; 22001a859223SAllain Legacy dev_info->max_tx_queues = avp->max_tx_queues; 22011a859223SAllain Legacy dev_info->min_rx_bufsize = AVP_MIN_RX_BUFSIZE; 22021a859223SAllain Legacy dev_info->max_rx_pktlen = avp->max_rx_pkt_len; 22031a859223SAllain Legacy dev_info->max_mac_addrs = AVP_MAX_MAC_ADDRS; 22041a859223SAllain Legacy if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) { 2205295968d1SFerruh Yigit dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP; 2206295968d1SFerruh Yigit dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT; 22071a859223SAllain Legacy } 2208bdad90d1SIvan Ilchenko 2209bdad90d1SIvan Ilchenko return 0; 22101a859223SAllain Legacy } 22111a859223SAllain Legacy 2212289ba0c0SDavid Harton static int 22131a859223SAllain Legacy avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) 22141a859223SAllain Legacy { 22151a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 2216462b66d8SAllain Legacy struct rte_eth_conf *dev_conf = ð_dev->data->dev_conf; 2217462b66d8SAllain Legacy uint64_t offloads = dev_conf->rxmode.offloads; 22181a859223SAllain Legacy 2219295968d1SFerruh Yigit if (mask & RTE_ETH_VLAN_STRIP_MASK) { 22201a859223SAllain Legacy if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) { 2221295968d1SFerruh Yigit if (offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) 22221a859223SAllain Legacy avp->features |= RTE_AVP_FEATURE_VLAN_OFFLOAD; 22231a859223SAllain Legacy else 22241a859223SAllain Legacy avp->features &= ~RTE_AVP_FEATURE_VLAN_OFFLOAD; 22251a859223SAllain Legacy } else { 2226*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "VLAN strip offload not supported"); 22271a859223SAllain Legacy } 22281a859223SAllain Legacy } 22291a859223SAllain Legacy 2230295968d1SFerruh Yigit if (mask & RTE_ETH_VLAN_FILTER_MASK) { 2231295968d1SFerruh Yigit if (offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) 2232*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "VLAN filter offload not supported"); 22331a859223SAllain Legacy } 22341a859223SAllain Legacy 2235295968d1SFerruh Yigit if (mask & RTE_ETH_VLAN_EXTEND_MASK) { 2236295968d1SFerruh Yigit if (offloads & RTE_ETH_RX_OFFLOAD_VLAN_EXTEND) 2237*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "VLAN extend offload not supported"); 22381a859223SAllain Legacy } 2239289ba0c0SDavid Harton 2240289ba0c0SDavid Harton return 0; 22411a859223SAllain Legacy } 22421a859223SAllain Legacy 2243d5b0924bSMatan Azrad static int 22445a5abe2dSAllain Legacy avp_dev_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats) 22455a5abe2dSAllain Legacy { 22465a5abe2dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 22475a5abe2dSAllain Legacy unsigned int i; 22485a5abe2dSAllain Legacy 22495a5abe2dSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 22505a5abe2dSAllain Legacy struct avp_queue *rxq = avp->dev_data->rx_queues[i]; 22515a5abe2dSAllain Legacy 22525a5abe2dSAllain Legacy if (rxq) { 22535a5abe2dSAllain Legacy stats->ipackets += rxq->packets; 22545a5abe2dSAllain Legacy stats->ibytes += rxq->bytes; 22555a5abe2dSAllain Legacy stats->ierrors += rxq->errors; 22565a5abe2dSAllain Legacy 22575a5abe2dSAllain Legacy stats->q_ipackets[i] += rxq->packets; 22585a5abe2dSAllain Legacy stats->q_ibytes[i] += rxq->bytes; 22595a5abe2dSAllain Legacy stats->q_errors[i] += rxq->errors; 22605a5abe2dSAllain Legacy } 22615a5abe2dSAllain Legacy } 22625a5abe2dSAllain Legacy 22635a5abe2dSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 22645a5abe2dSAllain Legacy struct avp_queue *txq = avp->dev_data->tx_queues[i]; 22655a5abe2dSAllain Legacy 22665a5abe2dSAllain Legacy if (txq) { 22675a5abe2dSAllain Legacy stats->opackets += txq->packets; 22685a5abe2dSAllain Legacy stats->obytes += txq->bytes; 22695a5abe2dSAllain Legacy stats->oerrors += txq->errors; 22705a5abe2dSAllain Legacy 22715a5abe2dSAllain Legacy stats->q_opackets[i] += txq->packets; 22725a5abe2dSAllain Legacy stats->q_obytes[i] += txq->bytes; 22735a5abe2dSAllain Legacy } 22745a5abe2dSAllain Legacy } 2275d5b0924bSMatan Azrad 2276d5b0924bSMatan Azrad return 0; 22775a5abe2dSAllain Legacy } 22785a5abe2dSAllain Legacy 22799970a9adSIgor Romanov static int 22805a5abe2dSAllain Legacy avp_dev_stats_reset(struct rte_eth_dev *eth_dev) 22815a5abe2dSAllain Legacy { 22825a5abe2dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 22835a5abe2dSAllain Legacy unsigned int i; 22845a5abe2dSAllain Legacy 22855a5abe2dSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 22865a5abe2dSAllain Legacy struct avp_queue *rxq = avp->dev_data->rx_queues[i]; 22875a5abe2dSAllain Legacy 22885a5abe2dSAllain Legacy if (rxq) { 22895a5abe2dSAllain Legacy rxq->bytes = 0; 22905a5abe2dSAllain Legacy rxq->packets = 0; 22915a5abe2dSAllain Legacy rxq->errors = 0; 22925a5abe2dSAllain Legacy } 22935a5abe2dSAllain Legacy } 22945a5abe2dSAllain Legacy 22955a5abe2dSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 22965a5abe2dSAllain Legacy struct avp_queue *txq = avp->dev_data->tx_queues[i]; 22975a5abe2dSAllain Legacy 22985a5abe2dSAllain Legacy if (txq) { 22995a5abe2dSAllain Legacy txq->bytes = 0; 23005a5abe2dSAllain Legacy txq->packets = 0; 23015a5abe2dSAllain Legacy txq->errors = 0; 23025a5abe2dSAllain Legacy } 23035a5abe2dSAllain Legacy } 23049970a9adSIgor Romanov 23059970a9adSIgor Romanov return 0; 23065a5abe2dSAllain Legacy } 23075a5abe2dSAllain Legacy 2308fdf91e0fSJan Blunck RTE_PMD_REGISTER_PCI(net_avp, rte_avp_pmd); 2309908072e9SAllain Legacy RTE_PMD_REGISTER_PCI_TABLE(net_avp, pci_id_avp_map); 2310eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(avp_logtype_driver, driver, NOTICE); 2311