1908072e9SAllain Legacy /* 2908072e9SAllain Legacy * BSD LICENSE 3908072e9SAllain Legacy * 4908072e9SAllain Legacy * Copyright (c) 2013-2017, Wind River Systems, Inc. 5908072e9SAllain Legacy * 6908072e9SAllain Legacy * Redistribution and use in source and binary forms, with or without 7908072e9SAllain Legacy * modification, are permitted provided that the following conditions are met: 8908072e9SAllain Legacy * 9908072e9SAllain Legacy * 1) Redistributions of source code must retain the above copyright notice, 10908072e9SAllain Legacy * this list of conditions and the following disclaimer. 11908072e9SAllain Legacy * 12908072e9SAllain Legacy * 2) Redistributions in binary form must reproduce the above copyright notice, 13908072e9SAllain Legacy * this list of conditions and the following disclaimer in the documentation 14908072e9SAllain Legacy * and/or other materials provided with the distribution. 15908072e9SAllain Legacy * 16908072e9SAllain Legacy * 3) Neither the name of Wind River Systems nor the names of its contributors 17908072e9SAllain Legacy * may be used to endorse or promote products derived from this software 18908072e9SAllain Legacy * without specific prior written permission. 19908072e9SAllain Legacy * 20908072e9SAllain Legacy * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21908072e9SAllain Legacy * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22908072e9SAllain Legacy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23908072e9SAllain Legacy * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24908072e9SAllain Legacy * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25908072e9SAllain Legacy * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26908072e9SAllain Legacy * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27908072e9SAllain Legacy * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28908072e9SAllain Legacy * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29908072e9SAllain Legacy * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30908072e9SAllain Legacy * POSSIBILITY OF SUCH DAMAGE. 31908072e9SAllain Legacy */ 32908072e9SAllain Legacy 33908072e9SAllain Legacy #include <stdint.h> 34908072e9SAllain Legacy #include <string.h> 35908072e9SAllain Legacy #include <stdio.h> 36908072e9SAllain Legacy #include <errno.h> 37908072e9SAllain Legacy #include <unistd.h> 38908072e9SAllain Legacy 39908072e9SAllain Legacy #include <rte_ethdev.h> 40908072e9SAllain Legacy #include <rte_memcpy.h> 41908072e9SAllain Legacy #include <rte_string_fns.h> 42908072e9SAllain Legacy #include <rte_memzone.h> 43908072e9SAllain Legacy #include <rte_malloc.h> 44908072e9SAllain Legacy #include <rte_atomic.h> 45908072e9SAllain Legacy #include <rte_branch_prediction.h> 46908072e9SAllain Legacy #include <rte_pci.h> 47908072e9SAllain Legacy #include <rte_ether.h> 48908072e9SAllain Legacy #include <rte_common.h> 49908072e9SAllain Legacy #include <rte_cycles.h> 50908072e9SAllain Legacy #include <rte_byteorder.h> 51908072e9SAllain Legacy #include <rte_dev.h> 52908072e9SAllain Legacy #include <rte_memory.h> 53908072e9SAllain Legacy #include <rte_eal.h> 54c0ad5842SAllain Legacy #include <rte_io.h> 55908072e9SAllain Legacy 56908072e9SAllain Legacy #include "rte_avp_common.h" 57908072e9SAllain Legacy #include "rte_avp_fifo.h" 58908072e9SAllain Legacy 59908072e9SAllain Legacy #include "avp_logs.h" 60908072e9SAllain Legacy 61908072e9SAllain Legacy 62908072e9SAllain Legacy 631a859223SAllain Legacy static int avp_dev_configure(struct rte_eth_dev *dev); 641a859223SAllain Legacy static void avp_dev_info_get(struct rte_eth_dev *dev, 651a859223SAllain Legacy struct rte_eth_dev_info *dev_info); 661a859223SAllain Legacy static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask); 671a859223SAllain Legacy static int avp_dev_link_update(struct rte_eth_dev *dev, 681a859223SAllain Legacy __rte_unused int wait_to_complete); 69*cce4367fSAllain Legacy static int avp_dev_rx_queue_setup(struct rte_eth_dev *dev, 70*cce4367fSAllain Legacy uint16_t rx_queue_id, 71*cce4367fSAllain Legacy uint16_t nb_rx_desc, 72*cce4367fSAllain Legacy unsigned int socket_id, 73*cce4367fSAllain Legacy const struct rte_eth_rxconf *rx_conf, 74*cce4367fSAllain Legacy struct rte_mempool *pool); 751a859223SAllain Legacy 76*cce4367fSAllain Legacy static int avp_dev_tx_queue_setup(struct rte_eth_dev *dev, 77*cce4367fSAllain Legacy uint16_t tx_queue_id, 78*cce4367fSAllain Legacy uint16_t nb_tx_desc, 79*cce4367fSAllain Legacy unsigned int socket_id, 80*cce4367fSAllain Legacy const struct rte_eth_txconf *tx_conf); 81*cce4367fSAllain Legacy 82*cce4367fSAllain Legacy static void avp_dev_rx_queue_release(void *rxq); 83*cce4367fSAllain Legacy static void avp_dev_tx_queue_release(void *txq); 84908072e9SAllain Legacy #define AVP_DEV_TO_PCI(eth_dev) RTE_DEV_TO_PCI((eth_dev)->device) 85908072e9SAllain Legacy 86908072e9SAllain Legacy 87908072e9SAllain Legacy #define AVP_MAX_MAC_ADDRS 1 88908072e9SAllain Legacy #define AVP_MIN_RX_BUFSIZE ETHER_MIN_LEN 89908072e9SAllain Legacy 90908072e9SAllain Legacy 91908072e9SAllain Legacy /* 92908072e9SAllain Legacy * Defines the number of microseconds to wait before checking the response 93908072e9SAllain Legacy * queue for completion. 94908072e9SAllain Legacy */ 95908072e9SAllain Legacy #define AVP_REQUEST_DELAY_USECS (5000) 96908072e9SAllain Legacy 97908072e9SAllain Legacy /* 98908072e9SAllain Legacy * Defines the number times to check the response queue for completion before 99908072e9SAllain Legacy * declaring a timeout. 100908072e9SAllain Legacy */ 101908072e9SAllain Legacy #define AVP_MAX_REQUEST_RETRY (100) 102908072e9SAllain Legacy 103908072e9SAllain Legacy /* Defines the current PCI driver version number */ 104908072e9SAllain Legacy #define AVP_DPDK_DRIVER_VERSION RTE_AVP_CURRENT_GUEST_VERSION 105908072e9SAllain Legacy 106908072e9SAllain Legacy /* 107908072e9SAllain Legacy * The set of PCI devices this driver supports 108908072e9SAllain Legacy */ 109908072e9SAllain Legacy static const struct rte_pci_id pci_id_avp_map[] = { 110908072e9SAllain Legacy { .vendor_id = RTE_AVP_PCI_VENDOR_ID, 111908072e9SAllain Legacy .device_id = RTE_AVP_PCI_DEVICE_ID, 112908072e9SAllain Legacy .subsystem_vendor_id = RTE_AVP_PCI_SUB_VENDOR_ID, 113908072e9SAllain Legacy .subsystem_device_id = RTE_AVP_PCI_SUB_DEVICE_ID, 114908072e9SAllain Legacy .class_id = RTE_CLASS_ANY_ID, 115908072e9SAllain Legacy }, 116908072e9SAllain Legacy 117908072e9SAllain Legacy { .vendor_id = 0, /* sentinel */ 118908072e9SAllain Legacy }, 119908072e9SAllain Legacy }; 120908072e9SAllain Legacy 1211a859223SAllain Legacy /* 1221a859223SAllain Legacy * dev_ops for avp, bare necessities for basic operation 1231a859223SAllain Legacy */ 1241a859223SAllain Legacy static const struct eth_dev_ops avp_eth_dev_ops = { 1251a859223SAllain Legacy .dev_configure = avp_dev_configure, 1261a859223SAllain Legacy .dev_infos_get = avp_dev_info_get, 1271a859223SAllain Legacy .vlan_offload_set = avp_vlan_offload_set, 1281a859223SAllain Legacy .link_update = avp_dev_link_update, 129*cce4367fSAllain Legacy .rx_queue_setup = avp_dev_rx_queue_setup, 130*cce4367fSAllain Legacy .rx_queue_release = avp_dev_rx_queue_release, 131*cce4367fSAllain Legacy .tx_queue_setup = avp_dev_tx_queue_setup, 132*cce4367fSAllain Legacy .tx_queue_release = avp_dev_tx_queue_release, 1331a859223SAllain Legacy }; 134908072e9SAllain Legacy 135c0ad5842SAllain Legacy /**@{ AVP device flags */ 136c0ad5842SAllain Legacy #define AVP_F_PROMISC (1 << 1) 137c0ad5842SAllain Legacy #define AVP_F_CONFIGURED (1 << 2) 138c0ad5842SAllain Legacy #define AVP_F_LINKUP (1 << 3) 139c0ad5842SAllain Legacy /**@} */ 140c0ad5842SAllain Legacy 141c0ad5842SAllain Legacy /* Ethernet device validation marker */ 142c0ad5842SAllain Legacy #define AVP_ETHDEV_MAGIC 0x92972862 143c0ad5842SAllain Legacy 144908072e9SAllain Legacy /* 145908072e9SAllain Legacy * Defines the AVP device attributes which are attached to an RTE ethernet 146908072e9SAllain Legacy * device 147908072e9SAllain Legacy */ 148908072e9SAllain Legacy struct avp_dev { 149908072e9SAllain Legacy uint32_t magic; /**< Memory validation marker */ 150908072e9SAllain Legacy uint64_t device_id; /**< Unique system identifier */ 151908072e9SAllain Legacy struct ether_addr ethaddr; /**< Host specified MAC address */ 152908072e9SAllain Legacy struct rte_eth_dev_data *dev_data; 153908072e9SAllain Legacy /**< Back pointer to ethernet device data */ 154908072e9SAllain Legacy volatile uint32_t flags; /**< Device operational flags */ 155908072e9SAllain Legacy uint8_t port_id; /**< Ethernet port identifier */ 156908072e9SAllain Legacy struct rte_mempool *pool; /**< pkt mbuf mempool */ 157908072e9SAllain Legacy unsigned int guest_mbuf_size; /**< local pool mbuf size */ 158908072e9SAllain Legacy unsigned int host_mbuf_size; /**< host mbuf size */ 159908072e9SAllain Legacy unsigned int max_rx_pkt_len; /**< maximum receive unit */ 160908072e9SAllain Legacy uint32_t host_features; /**< Supported feature bitmap */ 161908072e9SAllain Legacy uint32_t features; /**< Enabled feature bitmap */ 162908072e9SAllain Legacy unsigned int num_tx_queues; /**< Negotiated number of transmit queues */ 163908072e9SAllain Legacy unsigned int max_tx_queues; /**< Maximum number of transmit queues */ 164908072e9SAllain Legacy unsigned int num_rx_queues; /**< Negotiated number of receive queues */ 165908072e9SAllain Legacy unsigned int max_rx_queues; /**< Maximum number of receive queues */ 166908072e9SAllain Legacy 167908072e9SAllain Legacy struct rte_avp_fifo *tx_q[RTE_AVP_MAX_QUEUES]; /**< TX queue */ 168908072e9SAllain Legacy struct rte_avp_fifo *rx_q[RTE_AVP_MAX_QUEUES]; /**< RX queue */ 169908072e9SAllain Legacy struct rte_avp_fifo *alloc_q[RTE_AVP_MAX_QUEUES]; 170908072e9SAllain Legacy /**< Allocated mbufs queue */ 171908072e9SAllain Legacy struct rte_avp_fifo *free_q[RTE_AVP_MAX_QUEUES]; 172908072e9SAllain Legacy /**< To be freed mbufs queue */ 173908072e9SAllain Legacy 174908072e9SAllain Legacy /* For request & response */ 175908072e9SAllain Legacy struct rte_avp_fifo *req_q; /**< Request queue */ 176908072e9SAllain Legacy struct rte_avp_fifo *resp_q; /**< Response queue */ 177908072e9SAllain Legacy void *host_sync_addr; /**< (host) Req/Resp Mem address */ 178908072e9SAllain Legacy void *sync_addr; /**< Req/Resp Mem address */ 179908072e9SAllain Legacy void *host_mbuf_addr; /**< (host) MBUF pool start address */ 180908072e9SAllain Legacy void *mbuf_addr; /**< MBUF pool start address */ 181908072e9SAllain Legacy } __rte_cache_aligned; 182908072e9SAllain Legacy 183908072e9SAllain Legacy /* RTE ethernet private data */ 184908072e9SAllain Legacy struct avp_adapter { 185908072e9SAllain Legacy struct avp_dev avp; 186908072e9SAllain Legacy } __rte_cache_aligned; 187908072e9SAllain Legacy 188c0ad5842SAllain Legacy 189c0ad5842SAllain Legacy /* 32-bit MMIO register write */ 190c0ad5842SAllain Legacy #define AVP_WRITE32(_value, _addr) rte_write32_relaxed((_value), (_addr)) 191c0ad5842SAllain Legacy 192c0ad5842SAllain Legacy /* 32-bit MMIO register read */ 193c0ad5842SAllain Legacy #define AVP_READ32(_addr) rte_read32_relaxed((_addr)) 194c0ad5842SAllain Legacy 195908072e9SAllain Legacy /* Macro to cast the ethernet device private data to a AVP object */ 196908072e9SAllain Legacy #define AVP_DEV_PRIVATE_TO_HW(adapter) \ 197908072e9SAllain Legacy (&((struct avp_adapter *)adapter)->avp) 198908072e9SAllain Legacy 199908072e9SAllain Legacy /* 200c0ad5842SAllain Legacy * Defines the structure of a AVP device queue for the purpose of handling the 201c0ad5842SAllain Legacy * receive and transmit burst callback functions 202c0ad5842SAllain Legacy */ 203c0ad5842SAllain Legacy struct avp_queue { 204c0ad5842SAllain Legacy struct rte_eth_dev_data *dev_data; 205c0ad5842SAllain Legacy /**< Backpointer to ethernet device data */ 206c0ad5842SAllain Legacy struct avp_dev *avp; /**< Backpointer to AVP device */ 207c0ad5842SAllain Legacy uint16_t queue_id; 208c0ad5842SAllain Legacy /**< Queue identifier used for indexing current queue */ 209c0ad5842SAllain Legacy uint16_t queue_base; 210c0ad5842SAllain Legacy /**< Base queue identifier for queue servicing */ 211c0ad5842SAllain Legacy uint16_t queue_limit; 212c0ad5842SAllain Legacy /**< Maximum queue identifier for queue servicing */ 213c0ad5842SAllain Legacy 214c0ad5842SAllain Legacy uint64_t packets; 215c0ad5842SAllain Legacy uint64_t bytes; 216c0ad5842SAllain Legacy uint64_t errors; 217c0ad5842SAllain Legacy }; 218c0ad5842SAllain Legacy 2191a859223SAllain Legacy /* send a request and wait for a response 2201a859223SAllain Legacy * 2211a859223SAllain Legacy * @warning must be called while holding the avp->lock spinlock. 2221a859223SAllain Legacy */ 2231a859223SAllain Legacy static int 2241a859223SAllain Legacy avp_dev_process_request(struct avp_dev *avp, struct rte_avp_request *request) 2251a859223SAllain Legacy { 2261a859223SAllain Legacy unsigned int retry = AVP_MAX_REQUEST_RETRY; 2271a859223SAllain Legacy void *resp_addr = NULL; 2281a859223SAllain Legacy unsigned int count; 2291a859223SAllain Legacy int ret; 2301a859223SAllain Legacy 2311a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Sending request %u to host\n", request->req_id); 2321a859223SAllain Legacy 2331a859223SAllain Legacy request->result = -ENOTSUP; 2341a859223SAllain Legacy 2351a859223SAllain Legacy /* Discard any stale responses before starting a new request */ 2361a859223SAllain Legacy while (avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1)) 2371a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Discarding stale response\n"); 2381a859223SAllain Legacy 2391a859223SAllain Legacy rte_memcpy(avp->sync_addr, request, sizeof(*request)); 2401a859223SAllain Legacy count = avp_fifo_put(avp->req_q, &avp->host_sync_addr, 1); 2411a859223SAllain Legacy if (count < 1) { 2421a859223SAllain Legacy PMD_DRV_LOG(ERR, "Cannot send request %u to host\n", 2431a859223SAllain Legacy request->req_id); 2441a859223SAllain Legacy ret = -EBUSY; 2451a859223SAllain Legacy goto done; 2461a859223SAllain Legacy } 2471a859223SAllain Legacy 2481a859223SAllain Legacy while (retry--) { 2491a859223SAllain Legacy /* wait for a response */ 2501a859223SAllain Legacy usleep(AVP_REQUEST_DELAY_USECS); 2511a859223SAllain Legacy 2521a859223SAllain Legacy count = avp_fifo_count(avp->resp_q); 2531a859223SAllain Legacy if (count >= 1) { 2541a859223SAllain Legacy /* response received */ 2551a859223SAllain Legacy break; 2561a859223SAllain Legacy } 2571a859223SAllain Legacy 2581a859223SAllain Legacy if ((count < 1) && (retry == 0)) { 2591a859223SAllain Legacy PMD_DRV_LOG(ERR, "Timeout while waiting for a response for %u\n", 2601a859223SAllain Legacy request->req_id); 2611a859223SAllain Legacy ret = -ETIME; 2621a859223SAllain Legacy goto done; 2631a859223SAllain Legacy } 2641a859223SAllain Legacy } 2651a859223SAllain Legacy 2661a859223SAllain Legacy /* retrieve the response */ 2671a859223SAllain Legacy count = avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1); 2681a859223SAllain Legacy if ((count != 1) || (resp_addr != avp->host_sync_addr)) { 2691a859223SAllain Legacy PMD_DRV_LOG(ERR, "Invalid response from host, count=%u resp=%p host_sync_addr=%p\n", 2701a859223SAllain Legacy count, resp_addr, avp->host_sync_addr); 2711a859223SAllain Legacy ret = -ENODATA; 2721a859223SAllain Legacy goto done; 2731a859223SAllain Legacy } 2741a859223SAllain Legacy 2751a859223SAllain Legacy /* copy to user buffer */ 2761a859223SAllain Legacy rte_memcpy(request, avp->sync_addr, sizeof(*request)); 2771a859223SAllain Legacy ret = 0; 2781a859223SAllain Legacy 2791a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Result %d received for request %u\n", 2801a859223SAllain Legacy request->result, request->req_id); 2811a859223SAllain Legacy 2821a859223SAllain Legacy done: 2831a859223SAllain Legacy return ret; 2841a859223SAllain Legacy } 2851a859223SAllain Legacy 2861a859223SAllain Legacy static int 2871a859223SAllain Legacy avp_dev_ctrl_set_config(struct rte_eth_dev *eth_dev, 2881a859223SAllain Legacy struct rte_avp_device_config *config) 2891a859223SAllain Legacy { 2901a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 2911a859223SAllain Legacy struct rte_avp_request request; 2921a859223SAllain Legacy int ret; 2931a859223SAllain Legacy 2941a859223SAllain Legacy /* setup a configure request */ 2951a859223SAllain Legacy memset(&request, 0, sizeof(request)); 2961a859223SAllain Legacy request.req_id = RTE_AVP_REQ_CFG_DEVICE; 2971a859223SAllain Legacy memcpy(&request.config, config, sizeof(request.config)); 2981a859223SAllain Legacy 2991a859223SAllain Legacy ret = avp_dev_process_request(avp, &request); 3001a859223SAllain Legacy 3011a859223SAllain Legacy return ret == 0 ? request.result : ret; 3021a859223SAllain Legacy } 3031a859223SAllain Legacy 304c0ad5842SAllain Legacy /* translate from host physical address to guest virtual address */ 305c0ad5842SAllain Legacy static void * 306c0ad5842SAllain Legacy avp_dev_translate_address(struct rte_eth_dev *eth_dev, 307c0ad5842SAllain Legacy phys_addr_t host_phys_addr) 308c0ad5842SAllain Legacy { 309c0ad5842SAllain Legacy struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev); 310c0ad5842SAllain Legacy struct rte_mem_resource *resource; 311c0ad5842SAllain Legacy struct rte_avp_memmap_info *info; 312c0ad5842SAllain Legacy struct rte_avp_memmap *map; 313c0ad5842SAllain Legacy off_t offset; 314c0ad5842SAllain Legacy void *addr; 315c0ad5842SAllain Legacy unsigned int i; 316c0ad5842SAllain Legacy 317c0ad5842SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_MEMORY_BAR].addr; 318c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[RTE_AVP_PCI_MEMMAP_BAR]; 319c0ad5842SAllain Legacy info = (struct rte_avp_memmap_info *)resource->addr; 320c0ad5842SAllain Legacy 321c0ad5842SAllain Legacy offset = 0; 322c0ad5842SAllain Legacy for (i = 0; i < info->nb_maps; i++) { 323c0ad5842SAllain Legacy /* search all segments looking for a matching address */ 324c0ad5842SAllain Legacy map = &info->maps[i]; 325c0ad5842SAllain Legacy 326c0ad5842SAllain Legacy if ((host_phys_addr >= map->phys_addr) && 327c0ad5842SAllain Legacy (host_phys_addr < (map->phys_addr + map->length))) { 328c0ad5842SAllain Legacy /* address is within this segment */ 329c0ad5842SAllain Legacy offset += (host_phys_addr - map->phys_addr); 330c0ad5842SAllain Legacy addr = RTE_PTR_ADD(addr, offset); 331c0ad5842SAllain Legacy 332c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "Translating host physical 0x%" PRIx64 " to guest virtual 0x%p\n", 333c0ad5842SAllain Legacy host_phys_addr, addr); 334c0ad5842SAllain Legacy 335c0ad5842SAllain Legacy return addr; 336c0ad5842SAllain Legacy } 337c0ad5842SAllain Legacy offset += map->length; 338c0ad5842SAllain Legacy } 339c0ad5842SAllain Legacy 340c0ad5842SAllain Legacy return NULL; 341c0ad5842SAllain Legacy } 342c0ad5842SAllain Legacy 343c0ad5842SAllain Legacy /* verify that the incoming device version is compatible with our version */ 344c0ad5842SAllain Legacy static int 345c0ad5842SAllain Legacy avp_dev_version_check(uint32_t version) 346c0ad5842SAllain Legacy { 347c0ad5842SAllain Legacy uint32_t driver = RTE_AVP_STRIP_MINOR_VERSION(AVP_DPDK_DRIVER_VERSION); 348c0ad5842SAllain Legacy uint32_t device = RTE_AVP_STRIP_MINOR_VERSION(version); 349c0ad5842SAllain Legacy 350c0ad5842SAllain Legacy if (device <= driver) { 351c0ad5842SAllain Legacy /* the host driver version is less than or equal to ours */ 352c0ad5842SAllain Legacy return 0; 353c0ad5842SAllain Legacy } 354c0ad5842SAllain Legacy 355c0ad5842SAllain Legacy return 1; 356c0ad5842SAllain Legacy } 357c0ad5842SAllain Legacy 358c0ad5842SAllain Legacy /* verify that memory regions have expected version and validation markers */ 359c0ad5842SAllain Legacy static int 360c0ad5842SAllain Legacy avp_dev_check_regions(struct rte_eth_dev *eth_dev) 361c0ad5842SAllain Legacy { 362c0ad5842SAllain Legacy struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev); 363c0ad5842SAllain Legacy struct rte_avp_memmap_info *memmap; 364c0ad5842SAllain Legacy struct rte_avp_device_info *info; 365c0ad5842SAllain Legacy struct rte_mem_resource *resource; 366c0ad5842SAllain Legacy unsigned int i; 367c0ad5842SAllain Legacy 368c0ad5842SAllain Legacy /* Dump resource info for debug */ 369c0ad5842SAllain Legacy for (i = 0; i < PCI_MAX_RESOURCE; i++) { 370c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[i]; 371c0ad5842SAllain Legacy if ((resource->phys_addr == 0) || (resource->len == 0)) 372c0ad5842SAllain Legacy continue; 373c0ad5842SAllain Legacy 374c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "resource[%u]: phys=0x%" PRIx64 " len=%" PRIu64 " addr=%p\n", 375c0ad5842SAllain Legacy i, resource->phys_addr, 376c0ad5842SAllain Legacy resource->len, resource->addr); 377c0ad5842SAllain Legacy 378c0ad5842SAllain Legacy switch (i) { 379c0ad5842SAllain Legacy case RTE_AVP_PCI_MEMMAP_BAR: 380c0ad5842SAllain Legacy memmap = (struct rte_avp_memmap_info *)resource->addr; 381c0ad5842SAllain Legacy if ((memmap->magic != RTE_AVP_MEMMAP_MAGIC) || 382c0ad5842SAllain Legacy (memmap->version != RTE_AVP_MEMMAP_VERSION)) { 383c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid memmap magic 0x%08x and version %u\n", 384c0ad5842SAllain Legacy memmap->magic, memmap->version); 385c0ad5842SAllain Legacy return -EINVAL; 386c0ad5842SAllain Legacy } 387c0ad5842SAllain Legacy break; 388c0ad5842SAllain Legacy 389c0ad5842SAllain Legacy case RTE_AVP_PCI_DEVICE_BAR: 390c0ad5842SAllain Legacy info = (struct rte_avp_device_info *)resource->addr; 391c0ad5842SAllain Legacy if ((info->magic != RTE_AVP_DEVICE_MAGIC) || 392c0ad5842SAllain Legacy avp_dev_version_check(info->version)) { 393c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid device info magic 0x%08x or version 0x%08x > 0x%08x\n", 394c0ad5842SAllain Legacy info->magic, info->version, 395c0ad5842SAllain Legacy AVP_DPDK_DRIVER_VERSION); 396c0ad5842SAllain Legacy return -EINVAL; 397c0ad5842SAllain Legacy } 398c0ad5842SAllain Legacy break; 399c0ad5842SAllain Legacy 400c0ad5842SAllain Legacy case RTE_AVP_PCI_MEMORY_BAR: 401c0ad5842SAllain Legacy case RTE_AVP_PCI_MMIO_BAR: 402c0ad5842SAllain Legacy if (resource->addr == NULL) { 403c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Missing address space for BAR%u\n", 404c0ad5842SAllain Legacy i); 405c0ad5842SAllain Legacy return -EINVAL; 406c0ad5842SAllain Legacy } 407c0ad5842SAllain Legacy break; 408c0ad5842SAllain Legacy 409c0ad5842SAllain Legacy case RTE_AVP_PCI_MSIX_BAR: 410c0ad5842SAllain Legacy default: 411c0ad5842SAllain Legacy /* no validation required */ 412c0ad5842SAllain Legacy break; 413c0ad5842SAllain Legacy } 414c0ad5842SAllain Legacy } 415c0ad5842SAllain Legacy 416c0ad5842SAllain Legacy return 0; 417c0ad5842SAllain Legacy } 418c0ad5842SAllain Legacy 4191a859223SAllain Legacy static void 420*cce4367fSAllain Legacy _avp_set_rx_queue_mappings(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) 421*cce4367fSAllain Legacy { 422*cce4367fSAllain Legacy struct avp_dev *avp = 423*cce4367fSAllain Legacy AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 424*cce4367fSAllain Legacy struct avp_queue *rxq; 425*cce4367fSAllain Legacy uint16_t queue_count; 426*cce4367fSAllain Legacy uint16_t remainder; 427*cce4367fSAllain Legacy 428*cce4367fSAllain Legacy rxq = (struct avp_queue *)eth_dev->data->rx_queues[rx_queue_id]; 429*cce4367fSAllain Legacy 430*cce4367fSAllain Legacy /* 431*cce4367fSAllain Legacy * Must map all AVP fifos as evenly as possible between the configured 432*cce4367fSAllain Legacy * device queues. Each device queue will service a subset of the AVP 433*cce4367fSAllain Legacy * fifos. If there is an odd number of device queues the first set of 434*cce4367fSAllain Legacy * device queues will get the extra AVP fifos. 435*cce4367fSAllain Legacy */ 436*cce4367fSAllain Legacy queue_count = avp->num_rx_queues / eth_dev->data->nb_rx_queues; 437*cce4367fSAllain Legacy remainder = avp->num_rx_queues % eth_dev->data->nb_rx_queues; 438*cce4367fSAllain Legacy if (rx_queue_id < remainder) { 439*cce4367fSAllain Legacy /* these queues must service one extra FIFO */ 440*cce4367fSAllain Legacy rxq->queue_base = rx_queue_id * (queue_count + 1); 441*cce4367fSAllain Legacy rxq->queue_limit = rxq->queue_base + (queue_count + 1) - 1; 442*cce4367fSAllain Legacy } else { 443*cce4367fSAllain Legacy /* these queues service the regular number of FIFO */ 444*cce4367fSAllain Legacy rxq->queue_base = ((remainder * (queue_count + 1)) + 445*cce4367fSAllain Legacy ((rx_queue_id - remainder) * queue_count)); 446*cce4367fSAllain Legacy rxq->queue_limit = rxq->queue_base + queue_count - 1; 447*cce4367fSAllain Legacy } 448*cce4367fSAllain Legacy 449*cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "rxq %u at %p base %u limit %u\n", 450*cce4367fSAllain Legacy rx_queue_id, rxq, rxq->queue_base, rxq->queue_limit); 451*cce4367fSAllain Legacy 452*cce4367fSAllain Legacy rxq->queue_id = rxq->queue_base; 453*cce4367fSAllain Legacy } 454*cce4367fSAllain Legacy 455*cce4367fSAllain Legacy static void 4561a859223SAllain Legacy _avp_set_queue_counts(struct rte_eth_dev *eth_dev) 4571a859223SAllain Legacy { 4581a859223SAllain Legacy struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev); 4591a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 4601a859223SAllain Legacy struct rte_avp_device_info *host_info; 4611a859223SAllain Legacy void *addr; 4621a859223SAllain Legacy 4631a859223SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr; 4641a859223SAllain Legacy host_info = (struct rte_avp_device_info *)addr; 4651a859223SAllain Legacy 4661a859223SAllain Legacy /* 4671a859223SAllain Legacy * the transmit direction is not negotiated beyond respecting the max 4681a859223SAllain Legacy * number of queues because the host can handle arbitrary guest tx 4691a859223SAllain Legacy * queues (host rx queues). 4701a859223SAllain Legacy */ 4711a859223SAllain Legacy avp->num_tx_queues = eth_dev->data->nb_tx_queues; 4721a859223SAllain Legacy 4731a859223SAllain Legacy /* 4741a859223SAllain Legacy * the receive direction is more restrictive. The host requires a 4751a859223SAllain Legacy * minimum number of guest rx queues (host tx queues) therefore 4761a859223SAllain Legacy * negotiate a value that is at least as large as the host minimum 4771a859223SAllain Legacy * requirement. If the host and guest values are not identical then a 4781a859223SAllain Legacy * mapping will be established in the receive_queue_setup function. 4791a859223SAllain Legacy */ 4801a859223SAllain Legacy avp->num_rx_queues = RTE_MAX(host_info->min_rx_queues, 4811a859223SAllain Legacy eth_dev->data->nb_rx_queues); 4821a859223SAllain Legacy 4831a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Requesting %u Tx and %u Rx queues from host\n", 4841a859223SAllain Legacy avp->num_tx_queues, avp->num_rx_queues); 4851a859223SAllain Legacy } 4861a859223SAllain Legacy 487c0ad5842SAllain Legacy /* 488c0ad5842SAllain Legacy * create a AVP device using the supplied device info by first translating it 489c0ad5842SAllain Legacy * to guest address space(s). 490c0ad5842SAllain Legacy */ 491c0ad5842SAllain Legacy static int 492c0ad5842SAllain Legacy avp_dev_create(struct rte_pci_device *pci_dev, 493c0ad5842SAllain Legacy struct rte_eth_dev *eth_dev) 494c0ad5842SAllain Legacy { 495c0ad5842SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 496c0ad5842SAllain Legacy struct rte_avp_device_info *host_info; 497c0ad5842SAllain Legacy struct rte_mem_resource *resource; 498c0ad5842SAllain Legacy unsigned int i; 499c0ad5842SAllain Legacy 500c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR]; 501c0ad5842SAllain Legacy if (resource->addr == NULL) { 502c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "BAR%u is not mapped\n", 503c0ad5842SAllain Legacy RTE_AVP_PCI_DEVICE_BAR); 504c0ad5842SAllain Legacy return -EFAULT; 505c0ad5842SAllain Legacy } 506c0ad5842SAllain Legacy host_info = (struct rte_avp_device_info *)resource->addr; 507c0ad5842SAllain Legacy 508c0ad5842SAllain Legacy if ((host_info->magic != RTE_AVP_DEVICE_MAGIC) || 509c0ad5842SAllain Legacy avp_dev_version_check(host_info->version)) { 510c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid AVP PCI device, magic 0x%08x version 0x%08x > 0x%08x\n", 511c0ad5842SAllain Legacy host_info->magic, host_info->version, 512c0ad5842SAllain Legacy AVP_DPDK_DRIVER_VERSION); 513c0ad5842SAllain Legacy return -EINVAL; 514c0ad5842SAllain Legacy } 515c0ad5842SAllain Legacy 516c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host device is v%u.%u.%u\n", 517c0ad5842SAllain Legacy RTE_AVP_GET_RELEASE_VERSION(host_info->version), 518c0ad5842SAllain Legacy RTE_AVP_GET_MAJOR_VERSION(host_info->version), 519c0ad5842SAllain Legacy RTE_AVP_GET_MINOR_VERSION(host_info->version)); 520c0ad5842SAllain Legacy 521c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u TX queue(s)\n", 522c0ad5842SAllain Legacy host_info->min_tx_queues, host_info->max_tx_queues); 523c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u RX queue(s)\n", 524c0ad5842SAllain Legacy host_info->min_rx_queues, host_info->max_rx_queues); 525c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports features 0x%08x\n", 526c0ad5842SAllain Legacy host_info->features); 527c0ad5842SAllain Legacy 528c0ad5842SAllain Legacy if (avp->magic != AVP_ETHDEV_MAGIC) { 529c0ad5842SAllain Legacy /* 530c0ad5842SAllain Legacy * First time initialization (i.e., not during a VM 531c0ad5842SAllain Legacy * migration) 532c0ad5842SAllain Legacy */ 533c0ad5842SAllain Legacy memset(avp, 0, sizeof(*avp)); 534c0ad5842SAllain Legacy avp->magic = AVP_ETHDEV_MAGIC; 535c0ad5842SAllain Legacy avp->dev_data = eth_dev->data; 536c0ad5842SAllain Legacy avp->port_id = eth_dev->data->port_id; 537c0ad5842SAllain Legacy avp->host_mbuf_size = host_info->mbuf_size; 538c0ad5842SAllain Legacy avp->host_features = host_info->features; 539c0ad5842SAllain Legacy memcpy(&avp->ethaddr.addr_bytes[0], 540c0ad5842SAllain Legacy host_info->ethaddr, ETHER_ADDR_LEN); 541c0ad5842SAllain Legacy /* adjust max values to not exceed our max */ 542c0ad5842SAllain Legacy avp->max_tx_queues = 543c0ad5842SAllain Legacy RTE_MIN(host_info->max_tx_queues, RTE_AVP_MAX_QUEUES); 544c0ad5842SAllain Legacy avp->max_rx_queues = 545c0ad5842SAllain Legacy RTE_MIN(host_info->max_rx_queues, RTE_AVP_MAX_QUEUES); 546c0ad5842SAllain Legacy } else { 547c0ad5842SAllain Legacy /* Re-attaching during migration */ 548c0ad5842SAllain Legacy 549c0ad5842SAllain Legacy /* TODO... requires validation of host values */ 550c0ad5842SAllain Legacy if ((host_info->features & avp->features) != avp->features) { 551c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "AVP host features mismatched; 0x%08x, host=0x%08x\n", 552c0ad5842SAllain Legacy avp->features, host_info->features); 553c0ad5842SAllain Legacy /* this should not be possible; continue for now */ 554c0ad5842SAllain Legacy } 555c0ad5842SAllain Legacy } 556c0ad5842SAllain Legacy 557c0ad5842SAllain Legacy /* the device id is allowed to change over migrations */ 558c0ad5842SAllain Legacy avp->device_id = host_info->device_id; 559c0ad5842SAllain Legacy 560c0ad5842SAllain Legacy /* translate incoming host addresses to guest address space */ 561c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host tx queue at 0x%" PRIx64 "\n", 562c0ad5842SAllain Legacy host_info->tx_phys); 563c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host alloc queue at 0x%" PRIx64 "\n", 564c0ad5842SAllain Legacy host_info->alloc_phys); 565c0ad5842SAllain Legacy for (i = 0; i < avp->max_tx_queues; i++) { 566c0ad5842SAllain Legacy avp->tx_q[i] = avp_dev_translate_address(eth_dev, 567c0ad5842SAllain Legacy host_info->tx_phys + (i * host_info->tx_size)); 568c0ad5842SAllain Legacy 569c0ad5842SAllain Legacy avp->alloc_q[i] = avp_dev_translate_address(eth_dev, 570c0ad5842SAllain Legacy host_info->alloc_phys + (i * host_info->alloc_size)); 571c0ad5842SAllain Legacy } 572c0ad5842SAllain Legacy 573c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host rx queue at 0x%" PRIx64 "\n", 574c0ad5842SAllain Legacy host_info->rx_phys); 575c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host free queue at 0x%" PRIx64 "\n", 576c0ad5842SAllain Legacy host_info->free_phys); 577c0ad5842SAllain Legacy for (i = 0; i < avp->max_rx_queues; i++) { 578c0ad5842SAllain Legacy avp->rx_q[i] = avp_dev_translate_address(eth_dev, 579c0ad5842SAllain Legacy host_info->rx_phys + (i * host_info->rx_size)); 580c0ad5842SAllain Legacy avp->free_q[i] = avp_dev_translate_address(eth_dev, 581c0ad5842SAllain Legacy host_info->free_phys + (i * host_info->free_size)); 582c0ad5842SAllain Legacy } 583c0ad5842SAllain Legacy 584c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host request queue at 0x%" PRIx64 "\n", 585c0ad5842SAllain Legacy host_info->req_phys); 586c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host response queue at 0x%" PRIx64 "\n", 587c0ad5842SAllain Legacy host_info->resp_phys); 588c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host sync address at 0x%" PRIx64 "\n", 589c0ad5842SAllain Legacy host_info->sync_phys); 590c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host mbuf address at 0x%" PRIx64 "\n", 591c0ad5842SAllain Legacy host_info->mbuf_phys); 592c0ad5842SAllain Legacy avp->req_q = avp_dev_translate_address(eth_dev, host_info->req_phys); 593c0ad5842SAllain Legacy avp->resp_q = avp_dev_translate_address(eth_dev, host_info->resp_phys); 594c0ad5842SAllain Legacy avp->sync_addr = 595c0ad5842SAllain Legacy avp_dev_translate_address(eth_dev, host_info->sync_phys); 596c0ad5842SAllain Legacy avp->mbuf_addr = 597c0ad5842SAllain Legacy avp_dev_translate_address(eth_dev, host_info->mbuf_phys); 598c0ad5842SAllain Legacy 599c0ad5842SAllain Legacy /* 600c0ad5842SAllain Legacy * store the host mbuf virtual address so that we can calculate 601c0ad5842SAllain Legacy * relative offsets for each mbuf as they are processed 602c0ad5842SAllain Legacy */ 603c0ad5842SAllain Legacy avp->host_mbuf_addr = host_info->mbuf_va; 604c0ad5842SAllain Legacy avp->host_sync_addr = host_info->sync_va; 605c0ad5842SAllain Legacy 606c0ad5842SAllain Legacy /* 607c0ad5842SAllain Legacy * store the maximum packet length that is supported by the host. 608c0ad5842SAllain Legacy */ 609c0ad5842SAllain Legacy avp->max_rx_pkt_len = host_info->max_rx_pkt_len; 610c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host max receive packet length is %u\n", 611c0ad5842SAllain Legacy host_info->max_rx_pkt_len); 612c0ad5842SAllain Legacy 613c0ad5842SAllain Legacy return 0; 614c0ad5842SAllain Legacy } 615c0ad5842SAllain Legacy 616c0ad5842SAllain Legacy /* 617908072e9SAllain Legacy * This function is based on probe() function in avp_pci.c 618908072e9SAllain Legacy * It returns 0 on success. 619908072e9SAllain Legacy */ 620908072e9SAllain Legacy static int 621908072e9SAllain Legacy eth_avp_dev_init(struct rte_eth_dev *eth_dev) 622908072e9SAllain Legacy { 623c0ad5842SAllain Legacy struct avp_dev *avp = 624c0ad5842SAllain Legacy AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 625908072e9SAllain Legacy struct rte_pci_device *pci_dev; 626c0ad5842SAllain Legacy int ret; 627908072e9SAllain Legacy 628908072e9SAllain Legacy pci_dev = AVP_DEV_TO_PCI(eth_dev); 6291a859223SAllain Legacy eth_dev->dev_ops = &avp_eth_dev_ops; 630908072e9SAllain Legacy 631908072e9SAllain Legacy if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 632908072e9SAllain Legacy /* 633908072e9SAllain Legacy * no setup required on secondary processes. All data is saved 634908072e9SAllain Legacy * in dev_private by the primary process. All resource should 635908072e9SAllain Legacy * be mapped to the same virtual address so all pointers should 636908072e9SAllain Legacy * be valid. 637908072e9SAllain Legacy */ 638908072e9SAllain Legacy return 0; 639908072e9SAllain Legacy } 640908072e9SAllain Legacy 641908072e9SAllain Legacy rte_eth_copy_pci_info(eth_dev, pci_dev); 642908072e9SAllain Legacy 643908072e9SAllain Legacy eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE; 644908072e9SAllain Legacy 645c0ad5842SAllain Legacy /* Check BAR resources */ 646c0ad5842SAllain Legacy ret = avp_dev_check_regions(eth_dev); 647c0ad5842SAllain Legacy if (ret < 0) { 648c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to validate BAR resources, ret=%d\n", 649c0ad5842SAllain Legacy ret); 650c0ad5842SAllain Legacy return ret; 651c0ad5842SAllain Legacy } 652c0ad5842SAllain Legacy 653c0ad5842SAllain Legacy /* Handle each subtype */ 654c0ad5842SAllain Legacy ret = avp_dev_create(pci_dev, eth_dev); 655c0ad5842SAllain Legacy if (ret < 0) { 656c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to create device, ret=%d\n", ret); 657c0ad5842SAllain Legacy return ret; 658c0ad5842SAllain Legacy } 659c0ad5842SAllain Legacy 660c0ad5842SAllain Legacy /* Allocate memory for storing MAC addresses */ 661c0ad5842SAllain Legacy eth_dev->data->mac_addrs = rte_zmalloc("avp_ethdev", ETHER_ADDR_LEN, 0); 662c0ad5842SAllain Legacy if (eth_dev->data->mac_addrs == NULL) { 663c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses\n", 664c0ad5842SAllain Legacy ETHER_ADDR_LEN); 665c0ad5842SAllain Legacy return -ENOMEM; 666c0ad5842SAllain Legacy } 667c0ad5842SAllain Legacy 668c0ad5842SAllain Legacy /* Get a mac from device config */ 669c0ad5842SAllain Legacy ether_addr_copy(&avp->ethaddr, ð_dev->data->mac_addrs[0]); 670c0ad5842SAllain Legacy 671908072e9SAllain Legacy return 0; 672908072e9SAllain Legacy } 673908072e9SAllain Legacy 674908072e9SAllain Legacy static int 675908072e9SAllain Legacy eth_avp_dev_uninit(struct rte_eth_dev *eth_dev) 676908072e9SAllain Legacy { 677908072e9SAllain Legacy if (rte_eal_process_type() != RTE_PROC_PRIMARY) 678908072e9SAllain Legacy return -EPERM; 679908072e9SAllain Legacy 680908072e9SAllain Legacy if (eth_dev->data == NULL) 681908072e9SAllain Legacy return 0; 682908072e9SAllain Legacy 683c0ad5842SAllain Legacy if (eth_dev->data->mac_addrs != NULL) { 684c0ad5842SAllain Legacy rte_free(eth_dev->data->mac_addrs); 685c0ad5842SAllain Legacy eth_dev->data->mac_addrs = NULL; 686c0ad5842SAllain Legacy } 687c0ad5842SAllain Legacy 688908072e9SAllain Legacy return 0; 689908072e9SAllain Legacy } 690908072e9SAllain Legacy 691908072e9SAllain Legacy 692908072e9SAllain Legacy static struct eth_driver rte_avp_pmd = { 693908072e9SAllain Legacy { 694908072e9SAllain Legacy .id_table = pci_id_avp_map, 695908072e9SAllain Legacy .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 696908072e9SAllain Legacy .probe = rte_eth_dev_pci_probe, 697908072e9SAllain Legacy .remove = rte_eth_dev_pci_remove, 698908072e9SAllain Legacy }, 699908072e9SAllain Legacy .eth_dev_init = eth_avp_dev_init, 700908072e9SAllain Legacy .eth_dev_uninit = eth_avp_dev_uninit, 701908072e9SAllain Legacy .dev_private_size = sizeof(struct avp_adapter), 702908072e9SAllain Legacy }; 703908072e9SAllain Legacy 7041a859223SAllain Legacy static int 705*cce4367fSAllain Legacy avp_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 706*cce4367fSAllain Legacy uint16_t rx_queue_id, 707*cce4367fSAllain Legacy uint16_t nb_rx_desc, 708*cce4367fSAllain Legacy unsigned int socket_id, 709*cce4367fSAllain Legacy const struct rte_eth_rxconf *rx_conf, 710*cce4367fSAllain Legacy struct rte_mempool *pool) 711*cce4367fSAllain Legacy { 712*cce4367fSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 713*cce4367fSAllain Legacy struct rte_pktmbuf_pool_private *mbp_priv; 714*cce4367fSAllain Legacy struct avp_queue *rxq; 715*cce4367fSAllain Legacy 716*cce4367fSAllain Legacy if (rx_queue_id >= eth_dev->data->nb_rx_queues) { 717*cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "RX queue id is out of range: rx_queue_id=%u, nb_rx_queues=%u\n", 718*cce4367fSAllain Legacy rx_queue_id, eth_dev->data->nb_rx_queues); 719*cce4367fSAllain Legacy return -EINVAL; 720*cce4367fSAllain Legacy } 721*cce4367fSAllain Legacy 722*cce4367fSAllain Legacy /* Save mbuf pool pointer */ 723*cce4367fSAllain Legacy avp->pool = pool; 724*cce4367fSAllain Legacy 725*cce4367fSAllain Legacy /* Save the local mbuf size */ 726*cce4367fSAllain Legacy mbp_priv = rte_mempool_get_priv(pool); 727*cce4367fSAllain Legacy avp->guest_mbuf_size = (uint16_t)(mbp_priv->mbuf_data_room_size); 728*cce4367fSAllain Legacy avp->guest_mbuf_size -= RTE_PKTMBUF_HEADROOM; 729*cce4367fSAllain Legacy 730*cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "AVP max_rx_pkt_len=(%u,%u) mbuf_size=(%u,%u)\n", 731*cce4367fSAllain Legacy avp->max_rx_pkt_len, 732*cce4367fSAllain Legacy eth_dev->data->dev_conf.rxmode.max_rx_pkt_len, 733*cce4367fSAllain Legacy avp->host_mbuf_size, 734*cce4367fSAllain Legacy avp->guest_mbuf_size); 735*cce4367fSAllain Legacy 736*cce4367fSAllain Legacy /* allocate a queue object */ 737*cce4367fSAllain Legacy rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct avp_queue), 738*cce4367fSAllain Legacy RTE_CACHE_LINE_SIZE, socket_id); 739*cce4367fSAllain Legacy if (rxq == NULL) { 740*cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate new Rx queue object\n"); 741*cce4367fSAllain Legacy return -ENOMEM; 742*cce4367fSAllain Legacy } 743*cce4367fSAllain Legacy 744*cce4367fSAllain Legacy /* save back pointers to AVP and Ethernet devices */ 745*cce4367fSAllain Legacy rxq->avp = avp; 746*cce4367fSAllain Legacy rxq->dev_data = eth_dev->data; 747*cce4367fSAllain Legacy eth_dev->data->rx_queues[rx_queue_id] = (void *)rxq; 748*cce4367fSAllain Legacy 749*cce4367fSAllain Legacy /* setup the queue receive mapping for the current queue. */ 750*cce4367fSAllain Legacy _avp_set_rx_queue_mappings(eth_dev, rx_queue_id); 751*cce4367fSAllain Legacy 752*cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "Rx queue %u setup at %p\n", rx_queue_id, rxq); 753*cce4367fSAllain Legacy 754*cce4367fSAllain Legacy (void)nb_rx_desc; 755*cce4367fSAllain Legacy (void)rx_conf; 756*cce4367fSAllain Legacy return 0; 757*cce4367fSAllain Legacy } 758*cce4367fSAllain Legacy 759*cce4367fSAllain Legacy static int 760*cce4367fSAllain Legacy avp_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, 761*cce4367fSAllain Legacy uint16_t tx_queue_id, 762*cce4367fSAllain Legacy uint16_t nb_tx_desc, 763*cce4367fSAllain Legacy unsigned int socket_id, 764*cce4367fSAllain Legacy const struct rte_eth_txconf *tx_conf) 765*cce4367fSAllain Legacy { 766*cce4367fSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 767*cce4367fSAllain Legacy struct avp_queue *txq; 768*cce4367fSAllain Legacy 769*cce4367fSAllain Legacy if (tx_queue_id >= eth_dev->data->nb_tx_queues) { 770*cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "TX queue id is out of range: tx_queue_id=%u, nb_tx_queues=%u\n", 771*cce4367fSAllain Legacy tx_queue_id, eth_dev->data->nb_tx_queues); 772*cce4367fSAllain Legacy return -EINVAL; 773*cce4367fSAllain Legacy } 774*cce4367fSAllain Legacy 775*cce4367fSAllain Legacy /* allocate a queue object */ 776*cce4367fSAllain Legacy txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct avp_queue), 777*cce4367fSAllain Legacy RTE_CACHE_LINE_SIZE, socket_id); 778*cce4367fSAllain Legacy if (txq == NULL) { 779*cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate new Tx queue object\n"); 780*cce4367fSAllain Legacy return -ENOMEM; 781*cce4367fSAllain Legacy } 782*cce4367fSAllain Legacy 783*cce4367fSAllain Legacy /* only the configured set of transmit queues are used */ 784*cce4367fSAllain Legacy txq->queue_id = tx_queue_id; 785*cce4367fSAllain Legacy txq->queue_base = tx_queue_id; 786*cce4367fSAllain Legacy txq->queue_limit = tx_queue_id; 787*cce4367fSAllain Legacy 788*cce4367fSAllain Legacy /* save back pointers to AVP and Ethernet devices */ 789*cce4367fSAllain Legacy txq->avp = avp; 790*cce4367fSAllain Legacy txq->dev_data = eth_dev->data; 791*cce4367fSAllain Legacy eth_dev->data->tx_queues[tx_queue_id] = (void *)txq; 792*cce4367fSAllain Legacy 793*cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "Tx queue %u setup at %p\n", tx_queue_id, txq); 794*cce4367fSAllain Legacy 795*cce4367fSAllain Legacy (void)nb_tx_desc; 796*cce4367fSAllain Legacy (void)tx_conf; 797*cce4367fSAllain Legacy return 0; 798*cce4367fSAllain Legacy } 799*cce4367fSAllain Legacy 800*cce4367fSAllain Legacy static void 801*cce4367fSAllain Legacy avp_dev_rx_queue_release(void *rx_queue) 802*cce4367fSAllain Legacy { 803*cce4367fSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 804*cce4367fSAllain Legacy struct avp_dev *avp = rxq->avp; 805*cce4367fSAllain Legacy struct rte_eth_dev_data *data = avp->dev_data; 806*cce4367fSAllain Legacy unsigned int i; 807*cce4367fSAllain Legacy 808*cce4367fSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 809*cce4367fSAllain Legacy if (data->rx_queues[i] == rxq) 810*cce4367fSAllain Legacy data->rx_queues[i] = NULL; 811*cce4367fSAllain Legacy } 812*cce4367fSAllain Legacy } 813*cce4367fSAllain Legacy 814*cce4367fSAllain Legacy static void 815*cce4367fSAllain Legacy avp_dev_tx_queue_release(void *tx_queue) 816*cce4367fSAllain Legacy { 817*cce4367fSAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 818*cce4367fSAllain Legacy struct avp_dev *avp = txq->avp; 819*cce4367fSAllain Legacy struct rte_eth_dev_data *data = avp->dev_data; 820*cce4367fSAllain Legacy unsigned int i; 821*cce4367fSAllain Legacy 822*cce4367fSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 823*cce4367fSAllain Legacy if (data->tx_queues[i] == txq) 824*cce4367fSAllain Legacy data->tx_queues[i] = NULL; 825*cce4367fSAllain Legacy } 826*cce4367fSAllain Legacy } 827*cce4367fSAllain Legacy 828*cce4367fSAllain Legacy static int 8291a859223SAllain Legacy avp_dev_configure(struct rte_eth_dev *eth_dev) 8301a859223SAllain Legacy { 8311a859223SAllain Legacy struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev); 8321a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 8331a859223SAllain Legacy struct rte_avp_device_info *host_info; 8341a859223SAllain Legacy struct rte_avp_device_config config; 8351a859223SAllain Legacy int mask = 0; 8361a859223SAllain Legacy void *addr; 8371a859223SAllain Legacy int ret; 8381a859223SAllain Legacy 8391a859223SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr; 8401a859223SAllain Legacy host_info = (struct rte_avp_device_info *)addr; 8411a859223SAllain Legacy 8421a859223SAllain Legacy /* Setup required number of queues */ 8431a859223SAllain Legacy _avp_set_queue_counts(eth_dev); 8441a859223SAllain Legacy 8451a859223SAllain Legacy mask = (ETH_VLAN_STRIP_MASK | 8461a859223SAllain Legacy ETH_VLAN_FILTER_MASK | 8471a859223SAllain Legacy ETH_VLAN_EXTEND_MASK); 8481a859223SAllain Legacy avp_vlan_offload_set(eth_dev, mask); 8491a859223SAllain Legacy 8501a859223SAllain Legacy /* update device config */ 8511a859223SAllain Legacy memset(&config, 0, sizeof(config)); 8521a859223SAllain Legacy config.device_id = host_info->device_id; 8531a859223SAllain Legacy config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK; 8541a859223SAllain Legacy config.driver_version = AVP_DPDK_DRIVER_VERSION; 8551a859223SAllain Legacy config.features = avp->features; 8561a859223SAllain Legacy config.num_tx_queues = avp->num_tx_queues; 8571a859223SAllain Legacy config.num_rx_queues = avp->num_rx_queues; 8581a859223SAllain Legacy 8591a859223SAllain Legacy ret = avp_dev_ctrl_set_config(eth_dev, &config); 8601a859223SAllain Legacy if (ret < 0) { 8611a859223SAllain Legacy PMD_DRV_LOG(ERR, "Config request failed by host, ret=%d\n", 8621a859223SAllain Legacy ret); 8631a859223SAllain Legacy goto unlock; 8641a859223SAllain Legacy } 8651a859223SAllain Legacy 8661a859223SAllain Legacy avp->flags |= AVP_F_CONFIGURED; 8671a859223SAllain Legacy ret = 0; 8681a859223SAllain Legacy 8691a859223SAllain Legacy unlock: 8701a859223SAllain Legacy return ret; 8711a859223SAllain Legacy } 8721a859223SAllain Legacy 8731a859223SAllain Legacy 8741a859223SAllain Legacy static int 8751a859223SAllain Legacy avp_dev_link_update(struct rte_eth_dev *eth_dev, 8761a859223SAllain Legacy __rte_unused int wait_to_complete) 8771a859223SAllain Legacy { 8781a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 8791a859223SAllain Legacy struct rte_eth_link *link = ð_dev->data->dev_link; 8801a859223SAllain Legacy 8811a859223SAllain Legacy link->link_speed = ETH_SPEED_NUM_10G; 8821a859223SAllain Legacy link->link_duplex = ETH_LINK_FULL_DUPLEX; 8831a859223SAllain Legacy link->link_status = !!(avp->flags & AVP_F_LINKUP); 8841a859223SAllain Legacy 8851a859223SAllain Legacy return -1; 8861a859223SAllain Legacy } 8871a859223SAllain Legacy 8881a859223SAllain Legacy 8891a859223SAllain Legacy static void 8901a859223SAllain Legacy avp_dev_info_get(struct rte_eth_dev *eth_dev, 8911a859223SAllain Legacy struct rte_eth_dev_info *dev_info) 8921a859223SAllain Legacy { 8931a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 8941a859223SAllain Legacy 8951a859223SAllain Legacy dev_info->driver_name = "rte_avp_pmd"; 8961a859223SAllain Legacy dev_info->pci_dev = RTE_DEV_TO_PCI(eth_dev->device); 8971a859223SAllain Legacy dev_info->max_rx_queues = avp->max_rx_queues; 8981a859223SAllain Legacy dev_info->max_tx_queues = avp->max_tx_queues; 8991a859223SAllain Legacy dev_info->min_rx_bufsize = AVP_MIN_RX_BUFSIZE; 9001a859223SAllain Legacy dev_info->max_rx_pktlen = avp->max_rx_pkt_len; 9011a859223SAllain Legacy dev_info->max_mac_addrs = AVP_MAX_MAC_ADDRS; 9021a859223SAllain Legacy if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) { 9031a859223SAllain Legacy dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP; 9041a859223SAllain Legacy dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT; 9051a859223SAllain Legacy } 9061a859223SAllain Legacy } 9071a859223SAllain Legacy 9081a859223SAllain Legacy static void 9091a859223SAllain Legacy avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) 9101a859223SAllain Legacy { 9111a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 9121a859223SAllain Legacy 9131a859223SAllain Legacy if (mask & ETH_VLAN_STRIP_MASK) { 9141a859223SAllain Legacy if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) { 9151a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip) 9161a859223SAllain Legacy avp->features |= RTE_AVP_FEATURE_VLAN_OFFLOAD; 9171a859223SAllain Legacy else 9181a859223SAllain Legacy avp->features &= ~RTE_AVP_FEATURE_VLAN_OFFLOAD; 9191a859223SAllain Legacy } else { 9201a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN strip offload not supported\n"); 9211a859223SAllain Legacy } 9221a859223SAllain Legacy } 9231a859223SAllain Legacy 9241a859223SAllain Legacy if (mask & ETH_VLAN_FILTER_MASK) { 9251a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_filter) 9261a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN filter offload not supported\n"); 9271a859223SAllain Legacy } 9281a859223SAllain Legacy 9291a859223SAllain Legacy if (mask & ETH_VLAN_EXTEND_MASK) { 9301a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend) 9311a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n"); 9321a859223SAllain Legacy } 9331a859223SAllain Legacy } 9341a859223SAllain Legacy 935908072e9SAllain Legacy RTE_PMD_REGISTER_PCI(net_avp, rte_avp_pmd.pci_drv); 936908072e9SAllain Legacy RTE_PMD_REGISTER_PCI_TABLE(net_avp, pci_id_avp_map); 937