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); 64*ea37523dSAllain Legacy static int avp_dev_start(struct rte_eth_dev *dev); 65*ea37523dSAllain Legacy static void avp_dev_stop(struct rte_eth_dev *dev); 66*ea37523dSAllain Legacy static void avp_dev_close(struct rte_eth_dev *dev); 671a859223SAllain Legacy static void avp_dev_info_get(struct rte_eth_dev *dev, 681a859223SAllain Legacy struct rte_eth_dev_info *dev_info); 691a859223SAllain Legacy static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask); 701a859223SAllain Legacy static int avp_dev_link_update(struct rte_eth_dev *dev, 711a859223SAllain Legacy __rte_unused int wait_to_complete); 728129545eSAllain Legacy static void avp_dev_promiscuous_enable(struct rte_eth_dev *dev); 738129545eSAllain Legacy static void avp_dev_promiscuous_disable(struct rte_eth_dev *dev); 748129545eSAllain Legacy 75cce4367fSAllain Legacy static int avp_dev_rx_queue_setup(struct rte_eth_dev *dev, 76cce4367fSAllain Legacy uint16_t rx_queue_id, 77cce4367fSAllain Legacy uint16_t nb_rx_desc, 78cce4367fSAllain Legacy unsigned int socket_id, 79cce4367fSAllain Legacy const struct rte_eth_rxconf *rx_conf, 80cce4367fSAllain Legacy struct rte_mempool *pool); 811a859223SAllain Legacy 82cce4367fSAllain Legacy static int avp_dev_tx_queue_setup(struct rte_eth_dev *dev, 83cce4367fSAllain Legacy uint16_t tx_queue_id, 84cce4367fSAllain Legacy uint16_t nb_tx_desc, 85cce4367fSAllain Legacy unsigned int socket_id, 86cce4367fSAllain Legacy const struct rte_eth_txconf *tx_conf); 87cce4367fSAllain Legacy 8850db69fdSAllain Legacy static uint16_t avp_recv_scattered_pkts(void *rx_queue, 8950db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 9050db69fdSAllain Legacy uint16_t nb_pkts); 9150db69fdSAllain Legacy 9250db69fdSAllain Legacy static uint16_t avp_recv_pkts(void *rx_queue, 9350db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 9450db69fdSAllain Legacy uint16_t nb_pkts); 95295abce2SAllain Legacy 96295abce2SAllain Legacy static uint16_t avp_xmit_scattered_pkts(void *tx_queue, 97295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 98295abce2SAllain Legacy uint16_t nb_pkts); 99295abce2SAllain Legacy 100295abce2SAllain Legacy static uint16_t avp_xmit_pkts(void *tx_queue, 101295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 102295abce2SAllain Legacy uint16_t nb_pkts); 103295abce2SAllain Legacy 104cce4367fSAllain Legacy static void avp_dev_rx_queue_release(void *rxq); 105cce4367fSAllain Legacy static void avp_dev_tx_queue_release(void *txq); 106295abce2SAllain Legacy 1075a5abe2dSAllain Legacy static void avp_dev_stats_get(struct rte_eth_dev *dev, 1085a5abe2dSAllain Legacy struct rte_eth_stats *stats); 1095a5abe2dSAllain Legacy static void avp_dev_stats_reset(struct rte_eth_dev *dev); 1105a5abe2dSAllain Legacy 111295abce2SAllain Legacy 112908072e9SAllain Legacy #define AVP_DEV_TO_PCI(eth_dev) RTE_DEV_TO_PCI((eth_dev)->device) 113908072e9SAllain Legacy 114908072e9SAllain Legacy 11550db69fdSAllain Legacy #define AVP_MAX_RX_BURST 64 116295abce2SAllain Legacy #define AVP_MAX_TX_BURST 64 117908072e9SAllain Legacy #define AVP_MAX_MAC_ADDRS 1 118908072e9SAllain Legacy #define AVP_MIN_RX_BUFSIZE ETHER_MIN_LEN 119908072e9SAllain Legacy 120908072e9SAllain Legacy 121908072e9SAllain Legacy /* 122908072e9SAllain Legacy * Defines the number of microseconds to wait before checking the response 123908072e9SAllain Legacy * queue for completion. 124908072e9SAllain Legacy */ 125908072e9SAllain Legacy #define AVP_REQUEST_DELAY_USECS (5000) 126908072e9SAllain Legacy 127908072e9SAllain Legacy /* 128908072e9SAllain Legacy * Defines the number times to check the response queue for completion before 129908072e9SAllain Legacy * declaring a timeout. 130908072e9SAllain Legacy */ 131908072e9SAllain Legacy #define AVP_MAX_REQUEST_RETRY (100) 132908072e9SAllain Legacy 133908072e9SAllain Legacy /* Defines the current PCI driver version number */ 134908072e9SAllain Legacy #define AVP_DPDK_DRIVER_VERSION RTE_AVP_CURRENT_GUEST_VERSION 135908072e9SAllain Legacy 136908072e9SAllain Legacy /* 137908072e9SAllain Legacy * The set of PCI devices this driver supports 138908072e9SAllain Legacy */ 139908072e9SAllain Legacy static const struct rte_pci_id pci_id_avp_map[] = { 140908072e9SAllain Legacy { .vendor_id = RTE_AVP_PCI_VENDOR_ID, 141908072e9SAllain Legacy .device_id = RTE_AVP_PCI_DEVICE_ID, 142908072e9SAllain Legacy .subsystem_vendor_id = RTE_AVP_PCI_SUB_VENDOR_ID, 143908072e9SAllain Legacy .subsystem_device_id = RTE_AVP_PCI_SUB_DEVICE_ID, 144908072e9SAllain Legacy .class_id = RTE_CLASS_ANY_ID, 145908072e9SAllain Legacy }, 146908072e9SAllain Legacy 147908072e9SAllain Legacy { .vendor_id = 0, /* sentinel */ 148908072e9SAllain Legacy }, 149908072e9SAllain Legacy }; 150908072e9SAllain Legacy 1511a859223SAllain Legacy /* 1521a859223SAllain Legacy * dev_ops for avp, bare necessities for basic operation 1531a859223SAllain Legacy */ 1541a859223SAllain Legacy static const struct eth_dev_ops avp_eth_dev_ops = { 1551a859223SAllain Legacy .dev_configure = avp_dev_configure, 156*ea37523dSAllain Legacy .dev_start = avp_dev_start, 157*ea37523dSAllain Legacy .dev_stop = avp_dev_stop, 158*ea37523dSAllain Legacy .dev_close = avp_dev_close, 1591a859223SAllain Legacy .dev_infos_get = avp_dev_info_get, 1601a859223SAllain Legacy .vlan_offload_set = avp_vlan_offload_set, 1615a5abe2dSAllain Legacy .stats_get = avp_dev_stats_get, 1625a5abe2dSAllain Legacy .stats_reset = avp_dev_stats_reset, 1631a859223SAllain Legacy .link_update = avp_dev_link_update, 1648129545eSAllain Legacy .promiscuous_enable = avp_dev_promiscuous_enable, 1658129545eSAllain Legacy .promiscuous_disable = avp_dev_promiscuous_disable, 166cce4367fSAllain Legacy .rx_queue_setup = avp_dev_rx_queue_setup, 167cce4367fSAllain Legacy .rx_queue_release = avp_dev_rx_queue_release, 168cce4367fSAllain Legacy .tx_queue_setup = avp_dev_tx_queue_setup, 169cce4367fSAllain Legacy .tx_queue_release = avp_dev_tx_queue_release, 1701a859223SAllain Legacy }; 171908072e9SAllain Legacy 172c0ad5842SAllain Legacy /**@{ AVP device flags */ 173c0ad5842SAllain Legacy #define AVP_F_PROMISC (1 << 1) 174c0ad5842SAllain Legacy #define AVP_F_CONFIGURED (1 << 2) 175c0ad5842SAllain Legacy #define AVP_F_LINKUP (1 << 3) 176c0ad5842SAllain Legacy /**@} */ 177c0ad5842SAllain Legacy 178c0ad5842SAllain Legacy /* Ethernet device validation marker */ 179c0ad5842SAllain Legacy #define AVP_ETHDEV_MAGIC 0x92972862 180c0ad5842SAllain Legacy 181908072e9SAllain Legacy /* 182908072e9SAllain Legacy * Defines the AVP device attributes which are attached to an RTE ethernet 183908072e9SAllain Legacy * device 184908072e9SAllain Legacy */ 185908072e9SAllain Legacy struct avp_dev { 186908072e9SAllain Legacy uint32_t magic; /**< Memory validation marker */ 187908072e9SAllain Legacy uint64_t device_id; /**< Unique system identifier */ 188908072e9SAllain Legacy struct ether_addr ethaddr; /**< Host specified MAC address */ 189908072e9SAllain Legacy struct rte_eth_dev_data *dev_data; 190908072e9SAllain Legacy /**< Back pointer to ethernet device data */ 191908072e9SAllain Legacy volatile uint32_t flags; /**< Device operational flags */ 192908072e9SAllain Legacy uint8_t port_id; /**< Ethernet port identifier */ 193908072e9SAllain Legacy struct rte_mempool *pool; /**< pkt mbuf mempool */ 194908072e9SAllain Legacy unsigned int guest_mbuf_size; /**< local pool mbuf size */ 195908072e9SAllain Legacy unsigned int host_mbuf_size; /**< host mbuf size */ 196908072e9SAllain Legacy unsigned int max_rx_pkt_len; /**< maximum receive unit */ 197908072e9SAllain Legacy uint32_t host_features; /**< Supported feature bitmap */ 198908072e9SAllain Legacy uint32_t features; /**< Enabled feature bitmap */ 199908072e9SAllain Legacy unsigned int num_tx_queues; /**< Negotiated number of transmit queues */ 200908072e9SAllain Legacy unsigned int max_tx_queues; /**< Maximum number of transmit queues */ 201908072e9SAllain Legacy unsigned int num_rx_queues; /**< Negotiated number of receive queues */ 202908072e9SAllain Legacy unsigned int max_rx_queues; /**< Maximum number of receive queues */ 203908072e9SAllain Legacy 204908072e9SAllain Legacy struct rte_avp_fifo *tx_q[RTE_AVP_MAX_QUEUES]; /**< TX queue */ 205908072e9SAllain Legacy struct rte_avp_fifo *rx_q[RTE_AVP_MAX_QUEUES]; /**< RX queue */ 206908072e9SAllain Legacy struct rte_avp_fifo *alloc_q[RTE_AVP_MAX_QUEUES]; 207908072e9SAllain Legacy /**< Allocated mbufs queue */ 208908072e9SAllain Legacy struct rte_avp_fifo *free_q[RTE_AVP_MAX_QUEUES]; 209908072e9SAllain Legacy /**< To be freed mbufs queue */ 210908072e9SAllain Legacy 211908072e9SAllain Legacy /* For request & response */ 212908072e9SAllain Legacy struct rte_avp_fifo *req_q; /**< Request queue */ 213908072e9SAllain Legacy struct rte_avp_fifo *resp_q; /**< Response queue */ 214908072e9SAllain Legacy void *host_sync_addr; /**< (host) Req/Resp Mem address */ 215908072e9SAllain Legacy void *sync_addr; /**< Req/Resp Mem address */ 216908072e9SAllain Legacy void *host_mbuf_addr; /**< (host) MBUF pool start address */ 217908072e9SAllain Legacy void *mbuf_addr; /**< MBUF pool start address */ 218908072e9SAllain Legacy } __rte_cache_aligned; 219908072e9SAllain Legacy 220908072e9SAllain Legacy /* RTE ethernet private data */ 221908072e9SAllain Legacy struct avp_adapter { 222908072e9SAllain Legacy struct avp_dev avp; 223908072e9SAllain Legacy } __rte_cache_aligned; 224908072e9SAllain Legacy 225c0ad5842SAllain Legacy 226c0ad5842SAllain Legacy /* 32-bit MMIO register write */ 227c0ad5842SAllain Legacy #define AVP_WRITE32(_value, _addr) rte_write32_relaxed((_value), (_addr)) 228c0ad5842SAllain Legacy 229c0ad5842SAllain Legacy /* 32-bit MMIO register read */ 230c0ad5842SAllain Legacy #define AVP_READ32(_addr) rte_read32_relaxed((_addr)) 231c0ad5842SAllain Legacy 232908072e9SAllain Legacy /* Macro to cast the ethernet device private data to a AVP object */ 233908072e9SAllain Legacy #define AVP_DEV_PRIVATE_TO_HW(adapter) \ 234908072e9SAllain Legacy (&((struct avp_adapter *)adapter)->avp) 235908072e9SAllain Legacy 236908072e9SAllain Legacy /* 237c0ad5842SAllain Legacy * Defines the structure of a AVP device queue for the purpose of handling the 238c0ad5842SAllain Legacy * receive and transmit burst callback functions 239c0ad5842SAllain Legacy */ 240c0ad5842SAllain Legacy struct avp_queue { 241c0ad5842SAllain Legacy struct rte_eth_dev_data *dev_data; 242c0ad5842SAllain Legacy /**< Backpointer to ethernet device data */ 243c0ad5842SAllain Legacy struct avp_dev *avp; /**< Backpointer to AVP device */ 244c0ad5842SAllain Legacy uint16_t queue_id; 245c0ad5842SAllain Legacy /**< Queue identifier used for indexing current queue */ 246c0ad5842SAllain Legacy uint16_t queue_base; 247c0ad5842SAllain Legacy /**< Base queue identifier for queue servicing */ 248c0ad5842SAllain Legacy uint16_t queue_limit; 249c0ad5842SAllain Legacy /**< Maximum queue identifier for queue servicing */ 250c0ad5842SAllain Legacy 251c0ad5842SAllain Legacy uint64_t packets; 252c0ad5842SAllain Legacy uint64_t bytes; 253c0ad5842SAllain Legacy uint64_t errors; 254c0ad5842SAllain Legacy }; 255c0ad5842SAllain Legacy 2561a859223SAllain Legacy /* send a request and wait for a response 2571a859223SAllain Legacy * 2581a859223SAllain Legacy * @warning must be called while holding the avp->lock spinlock. 2591a859223SAllain Legacy */ 2601a859223SAllain Legacy static int 2611a859223SAllain Legacy avp_dev_process_request(struct avp_dev *avp, struct rte_avp_request *request) 2621a859223SAllain Legacy { 2631a859223SAllain Legacy unsigned int retry = AVP_MAX_REQUEST_RETRY; 2641a859223SAllain Legacy void *resp_addr = NULL; 2651a859223SAllain Legacy unsigned int count; 2661a859223SAllain Legacy int ret; 2671a859223SAllain Legacy 2681a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Sending request %u to host\n", request->req_id); 2691a859223SAllain Legacy 2701a859223SAllain Legacy request->result = -ENOTSUP; 2711a859223SAllain Legacy 2721a859223SAllain Legacy /* Discard any stale responses before starting a new request */ 2731a859223SAllain Legacy while (avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1)) 2741a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Discarding stale response\n"); 2751a859223SAllain Legacy 2761a859223SAllain Legacy rte_memcpy(avp->sync_addr, request, sizeof(*request)); 2771a859223SAllain Legacy count = avp_fifo_put(avp->req_q, &avp->host_sync_addr, 1); 2781a859223SAllain Legacy if (count < 1) { 2791a859223SAllain Legacy PMD_DRV_LOG(ERR, "Cannot send request %u to host\n", 2801a859223SAllain Legacy request->req_id); 2811a859223SAllain Legacy ret = -EBUSY; 2821a859223SAllain Legacy goto done; 2831a859223SAllain Legacy } 2841a859223SAllain Legacy 2851a859223SAllain Legacy while (retry--) { 2861a859223SAllain Legacy /* wait for a response */ 2871a859223SAllain Legacy usleep(AVP_REQUEST_DELAY_USECS); 2881a859223SAllain Legacy 2891a859223SAllain Legacy count = avp_fifo_count(avp->resp_q); 2901a859223SAllain Legacy if (count >= 1) { 2911a859223SAllain Legacy /* response received */ 2921a859223SAllain Legacy break; 2931a859223SAllain Legacy } 2941a859223SAllain Legacy 2951a859223SAllain Legacy if ((count < 1) && (retry == 0)) { 2961a859223SAllain Legacy PMD_DRV_LOG(ERR, "Timeout while waiting for a response for %u\n", 2971a859223SAllain Legacy request->req_id); 2981a859223SAllain Legacy ret = -ETIME; 2991a859223SAllain Legacy goto done; 3001a859223SAllain Legacy } 3011a859223SAllain Legacy } 3021a859223SAllain Legacy 3031a859223SAllain Legacy /* retrieve the response */ 3041a859223SAllain Legacy count = avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1); 3051a859223SAllain Legacy if ((count != 1) || (resp_addr != avp->host_sync_addr)) { 3061a859223SAllain Legacy PMD_DRV_LOG(ERR, "Invalid response from host, count=%u resp=%p host_sync_addr=%p\n", 3071a859223SAllain Legacy count, resp_addr, avp->host_sync_addr); 3081a859223SAllain Legacy ret = -ENODATA; 3091a859223SAllain Legacy goto done; 3101a859223SAllain Legacy } 3111a859223SAllain Legacy 3121a859223SAllain Legacy /* copy to user buffer */ 3131a859223SAllain Legacy rte_memcpy(request, avp->sync_addr, sizeof(*request)); 3141a859223SAllain Legacy ret = 0; 3151a859223SAllain Legacy 3161a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Result %d received for request %u\n", 3171a859223SAllain Legacy request->result, request->req_id); 3181a859223SAllain Legacy 3191a859223SAllain Legacy done: 3201a859223SAllain Legacy return ret; 3211a859223SAllain Legacy } 3221a859223SAllain Legacy 3231a859223SAllain Legacy static int 324*ea37523dSAllain Legacy avp_dev_ctrl_set_link_state(struct rte_eth_dev *eth_dev, unsigned int state) 325*ea37523dSAllain Legacy { 326*ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 327*ea37523dSAllain Legacy struct rte_avp_request request; 328*ea37523dSAllain Legacy int ret; 329*ea37523dSAllain Legacy 330*ea37523dSAllain Legacy /* setup a link state change request */ 331*ea37523dSAllain Legacy memset(&request, 0, sizeof(request)); 332*ea37523dSAllain Legacy request.req_id = RTE_AVP_REQ_CFG_NETWORK_IF; 333*ea37523dSAllain Legacy request.if_up = state; 334*ea37523dSAllain Legacy 335*ea37523dSAllain Legacy ret = avp_dev_process_request(avp, &request); 336*ea37523dSAllain Legacy 337*ea37523dSAllain Legacy return ret == 0 ? request.result : ret; 338*ea37523dSAllain Legacy } 339*ea37523dSAllain Legacy 340*ea37523dSAllain Legacy static int 3411a859223SAllain Legacy avp_dev_ctrl_set_config(struct rte_eth_dev *eth_dev, 3421a859223SAllain Legacy struct rte_avp_device_config *config) 3431a859223SAllain Legacy { 3441a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 3451a859223SAllain Legacy struct rte_avp_request request; 3461a859223SAllain Legacy int ret; 3471a859223SAllain Legacy 3481a859223SAllain Legacy /* setup a configure request */ 3491a859223SAllain Legacy memset(&request, 0, sizeof(request)); 3501a859223SAllain Legacy request.req_id = RTE_AVP_REQ_CFG_DEVICE; 3511a859223SAllain Legacy memcpy(&request.config, config, sizeof(request.config)); 3521a859223SAllain Legacy 3531a859223SAllain Legacy ret = avp_dev_process_request(avp, &request); 3541a859223SAllain Legacy 3551a859223SAllain Legacy return ret == 0 ? request.result : ret; 3561a859223SAllain Legacy } 3571a859223SAllain Legacy 358*ea37523dSAllain Legacy static int 359*ea37523dSAllain Legacy avp_dev_ctrl_shutdown(struct rte_eth_dev *eth_dev) 360*ea37523dSAllain Legacy { 361*ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 362*ea37523dSAllain Legacy struct rte_avp_request request; 363*ea37523dSAllain Legacy int ret; 364*ea37523dSAllain Legacy 365*ea37523dSAllain Legacy /* setup a shutdown request */ 366*ea37523dSAllain Legacy memset(&request, 0, sizeof(request)); 367*ea37523dSAllain Legacy request.req_id = RTE_AVP_REQ_SHUTDOWN_DEVICE; 368*ea37523dSAllain Legacy 369*ea37523dSAllain Legacy ret = avp_dev_process_request(avp, &request); 370*ea37523dSAllain Legacy 371*ea37523dSAllain Legacy return ret == 0 ? request.result : ret; 372*ea37523dSAllain Legacy } 373*ea37523dSAllain Legacy 37450db69fdSAllain Legacy /* translate from host mbuf virtual address to guest virtual address */ 37550db69fdSAllain Legacy static inline void * 37650db69fdSAllain Legacy avp_dev_translate_buffer(struct avp_dev *avp, void *host_mbuf_address) 37750db69fdSAllain Legacy { 37850db69fdSAllain Legacy return RTE_PTR_ADD(RTE_PTR_SUB(host_mbuf_address, 37950db69fdSAllain Legacy (uintptr_t)avp->host_mbuf_addr), 38050db69fdSAllain Legacy (uintptr_t)avp->mbuf_addr); 38150db69fdSAllain Legacy } 38250db69fdSAllain Legacy 383c0ad5842SAllain Legacy /* translate from host physical address to guest virtual address */ 384c0ad5842SAllain Legacy static void * 385c0ad5842SAllain Legacy avp_dev_translate_address(struct rte_eth_dev *eth_dev, 386c0ad5842SAllain Legacy phys_addr_t host_phys_addr) 387c0ad5842SAllain Legacy { 388c0ad5842SAllain Legacy struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev); 389c0ad5842SAllain Legacy struct rte_mem_resource *resource; 390c0ad5842SAllain Legacy struct rte_avp_memmap_info *info; 391c0ad5842SAllain Legacy struct rte_avp_memmap *map; 392c0ad5842SAllain Legacy off_t offset; 393c0ad5842SAllain Legacy void *addr; 394c0ad5842SAllain Legacy unsigned int i; 395c0ad5842SAllain Legacy 396c0ad5842SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_MEMORY_BAR].addr; 397c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[RTE_AVP_PCI_MEMMAP_BAR]; 398c0ad5842SAllain Legacy info = (struct rte_avp_memmap_info *)resource->addr; 399c0ad5842SAllain Legacy 400c0ad5842SAllain Legacy offset = 0; 401c0ad5842SAllain Legacy for (i = 0; i < info->nb_maps; i++) { 402c0ad5842SAllain Legacy /* search all segments looking for a matching address */ 403c0ad5842SAllain Legacy map = &info->maps[i]; 404c0ad5842SAllain Legacy 405c0ad5842SAllain Legacy if ((host_phys_addr >= map->phys_addr) && 406c0ad5842SAllain Legacy (host_phys_addr < (map->phys_addr + map->length))) { 407c0ad5842SAllain Legacy /* address is within this segment */ 408c0ad5842SAllain Legacy offset += (host_phys_addr - map->phys_addr); 409c0ad5842SAllain Legacy addr = RTE_PTR_ADD(addr, offset); 410c0ad5842SAllain Legacy 411c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "Translating host physical 0x%" PRIx64 " to guest virtual 0x%p\n", 412c0ad5842SAllain Legacy host_phys_addr, addr); 413c0ad5842SAllain Legacy 414c0ad5842SAllain Legacy return addr; 415c0ad5842SAllain Legacy } 416c0ad5842SAllain Legacy offset += map->length; 417c0ad5842SAllain Legacy } 418c0ad5842SAllain Legacy 419c0ad5842SAllain Legacy return NULL; 420c0ad5842SAllain Legacy } 421c0ad5842SAllain Legacy 422c0ad5842SAllain Legacy /* verify that the incoming device version is compatible with our version */ 423c0ad5842SAllain Legacy static int 424c0ad5842SAllain Legacy avp_dev_version_check(uint32_t version) 425c0ad5842SAllain Legacy { 426c0ad5842SAllain Legacy uint32_t driver = RTE_AVP_STRIP_MINOR_VERSION(AVP_DPDK_DRIVER_VERSION); 427c0ad5842SAllain Legacy uint32_t device = RTE_AVP_STRIP_MINOR_VERSION(version); 428c0ad5842SAllain Legacy 429c0ad5842SAllain Legacy if (device <= driver) { 430c0ad5842SAllain Legacy /* the host driver version is less than or equal to ours */ 431c0ad5842SAllain Legacy return 0; 432c0ad5842SAllain Legacy } 433c0ad5842SAllain Legacy 434c0ad5842SAllain Legacy return 1; 435c0ad5842SAllain Legacy } 436c0ad5842SAllain Legacy 437c0ad5842SAllain Legacy /* verify that memory regions have expected version and validation markers */ 438c0ad5842SAllain Legacy static int 439c0ad5842SAllain Legacy avp_dev_check_regions(struct rte_eth_dev *eth_dev) 440c0ad5842SAllain Legacy { 441c0ad5842SAllain Legacy struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev); 442c0ad5842SAllain Legacy struct rte_avp_memmap_info *memmap; 443c0ad5842SAllain Legacy struct rte_avp_device_info *info; 444c0ad5842SAllain Legacy struct rte_mem_resource *resource; 445c0ad5842SAllain Legacy unsigned int i; 446c0ad5842SAllain Legacy 447c0ad5842SAllain Legacy /* Dump resource info for debug */ 448c0ad5842SAllain Legacy for (i = 0; i < PCI_MAX_RESOURCE; i++) { 449c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[i]; 450c0ad5842SAllain Legacy if ((resource->phys_addr == 0) || (resource->len == 0)) 451c0ad5842SAllain Legacy continue; 452c0ad5842SAllain Legacy 453c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "resource[%u]: phys=0x%" PRIx64 " len=%" PRIu64 " addr=%p\n", 454c0ad5842SAllain Legacy i, resource->phys_addr, 455c0ad5842SAllain Legacy resource->len, resource->addr); 456c0ad5842SAllain Legacy 457c0ad5842SAllain Legacy switch (i) { 458c0ad5842SAllain Legacy case RTE_AVP_PCI_MEMMAP_BAR: 459c0ad5842SAllain Legacy memmap = (struct rte_avp_memmap_info *)resource->addr; 460c0ad5842SAllain Legacy if ((memmap->magic != RTE_AVP_MEMMAP_MAGIC) || 461c0ad5842SAllain Legacy (memmap->version != RTE_AVP_MEMMAP_VERSION)) { 462c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid memmap magic 0x%08x and version %u\n", 463c0ad5842SAllain Legacy memmap->magic, memmap->version); 464c0ad5842SAllain Legacy return -EINVAL; 465c0ad5842SAllain Legacy } 466c0ad5842SAllain Legacy break; 467c0ad5842SAllain Legacy 468c0ad5842SAllain Legacy case RTE_AVP_PCI_DEVICE_BAR: 469c0ad5842SAllain Legacy info = (struct rte_avp_device_info *)resource->addr; 470c0ad5842SAllain Legacy if ((info->magic != RTE_AVP_DEVICE_MAGIC) || 471c0ad5842SAllain Legacy avp_dev_version_check(info->version)) { 472c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid device info magic 0x%08x or version 0x%08x > 0x%08x\n", 473c0ad5842SAllain Legacy info->magic, info->version, 474c0ad5842SAllain Legacy AVP_DPDK_DRIVER_VERSION); 475c0ad5842SAllain Legacy return -EINVAL; 476c0ad5842SAllain Legacy } 477c0ad5842SAllain Legacy break; 478c0ad5842SAllain Legacy 479c0ad5842SAllain Legacy case RTE_AVP_PCI_MEMORY_BAR: 480c0ad5842SAllain Legacy case RTE_AVP_PCI_MMIO_BAR: 481c0ad5842SAllain Legacy if (resource->addr == NULL) { 482c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Missing address space for BAR%u\n", 483c0ad5842SAllain Legacy i); 484c0ad5842SAllain Legacy return -EINVAL; 485c0ad5842SAllain Legacy } 486c0ad5842SAllain Legacy break; 487c0ad5842SAllain Legacy 488c0ad5842SAllain Legacy case RTE_AVP_PCI_MSIX_BAR: 489c0ad5842SAllain Legacy default: 490c0ad5842SAllain Legacy /* no validation required */ 491c0ad5842SAllain Legacy break; 492c0ad5842SAllain Legacy } 493c0ad5842SAllain Legacy } 494c0ad5842SAllain Legacy 495c0ad5842SAllain Legacy return 0; 496c0ad5842SAllain Legacy } 497c0ad5842SAllain Legacy 4981a859223SAllain Legacy static void 499cce4367fSAllain Legacy _avp_set_rx_queue_mappings(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) 500cce4367fSAllain Legacy { 501cce4367fSAllain Legacy struct avp_dev *avp = 502cce4367fSAllain Legacy AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 503cce4367fSAllain Legacy struct avp_queue *rxq; 504cce4367fSAllain Legacy uint16_t queue_count; 505cce4367fSAllain Legacy uint16_t remainder; 506cce4367fSAllain Legacy 507cce4367fSAllain Legacy rxq = (struct avp_queue *)eth_dev->data->rx_queues[rx_queue_id]; 508cce4367fSAllain Legacy 509cce4367fSAllain Legacy /* 510cce4367fSAllain Legacy * Must map all AVP fifos as evenly as possible between the configured 511cce4367fSAllain Legacy * device queues. Each device queue will service a subset of the AVP 512cce4367fSAllain Legacy * fifos. If there is an odd number of device queues the first set of 513cce4367fSAllain Legacy * device queues will get the extra AVP fifos. 514cce4367fSAllain Legacy */ 515cce4367fSAllain Legacy queue_count = avp->num_rx_queues / eth_dev->data->nb_rx_queues; 516cce4367fSAllain Legacy remainder = avp->num_rx_queues % eth_dev->data->nb_rx_queues; 517cce4367fSAllain Legacy if (rx_queue_id < remainder) { 518cce4367fSAllain Legacy /* these queues must service one extra FIFO */ 519cce4367fSAllain Legacy rxq->queue_base = rx_queue_id * (queue_count + 1); 520cce4367fSAllain Legacy rxq->queue_limit = rxq->queue_base + (queue_count + 1) - 1; 521cce4367fSAllain Legacy } else { 522cce4367fSAllain Legacy /* these queues service the regular number of FIFO */ 523cce4367fSAllain Legacy rxq->queue_base = ((remainder * (queue_count + 1)) + 524cce4367fSAllain Legacy ((rx_queue_id - remainder) * queue_count)); 525cce4367fSAllain Legacy rxq->queue_limit = rxq->queue_base + queue_count - 1; 526cce4367fSAllain Legacy } 527cce4367fSAllain Legacy 528cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "rxq %u at %p base %u limit %u\n", 529cce4367fSAllain Legacy rx_queue_id, rxq, rxq->queue_base, rxq->queue_limit); 530cce4367fSAllain Legacy 531cce4367fSAllain Legacy rxq->queue_id = rxq->queue_base; 532cce4367fSAllain Legacy } 533cce4367fSAllain Legacy 534cce4367fSAllain Legacy static void 5351a859223SAllain Legacy _avp_set_queue_counts(struct rte_eth_dev *eth_dev) 5361a859223SAllain Legacy { 5371a859223SAllain Legacy struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev); 5381a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 5391a859223SAllain Legacy struct rte_avp_device_info *host_info; 5401a859223SAllain Legacy void *addr; 5411a859223SAllain Legacy 5421a859223SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr; 5431a859223SAllain Legacy host_info = (struct rte_avp_device_info *)addr; 5441a859223SAllain Legacy 5451a859223SAllain Legacy /* 5461a859223SAllain Legacy * the transmit direction is not negotiated beyond respecting the max 5471a859223SAllain Legacy * number of queues because the host can handle arbitrary guest tx 5481a859223SAllain Legacy * queues (host rx queues). 5491a859223SAllain Legacy */ 5501a859223SAllain Legacy avp->num_tx_queues = eth_dev->data->nb_tx_queues; 5511a859223SAllain Legacy 5521a859223SAllain Legacy /* 5531a859223SAllain Legacy * the receive direction is more restrictive. The host requires a 5541a859223SAllain Legacy * minimum number of guest rx queues (host tx queues) therefore 5551a859223SAllain Legacy * negotiate a value that is at least as large as the host minimum 5561a859223SAllain Legacy * requirement. If the host and guest values are not identical then a 5571a859223SAllain Legacy * mapping will be established in the receive_queue_setup function. 5581a859223SAllain Legacy */ 5591a859223SAllain Legacy avp->num_rx_queues = RTE_MAX(host_info->min_rx_queues, 5601a859223SAllain Legacy eth_dev->data->nb_rx_queues); 5611a859223SAllain Legacy 5621a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Requesting %u Tx and %u Rx queues from host\n", 5631a859223SAllain Legacy avp->num_tx_queues, avp->num_rx_queues); 5641a859223SAllain Legacy } 5651a859223SAllain Legacy 566c0ad5842SAllain Legacy /* 567c0ad5842SAllain Legacy * create a AVP device using the supplied device info by first translating it 568c0ad5842SAllain Legacy * to guest address space(s). 569c0ad5842SAllain Legacy */ 570c0ad5842SAllain Legacy static int 571c0ad5842SAllain Legacy avp_dev_create(struct rte_pci_device *pci_dev, 572c0ad5842SAllain Legacy struct rte_eth_dev *eth_dev) 573c0ad5842SAllain Legacy { 574c0ad5842SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 575c0ad5842SAllain Legacy struct rte_avp_device_info *host_info; 576c0ad5842SAllain Legacy struct rte_mem_resource *resource; 577c0ad5842SAllain Legacy unsigned int i; 578c0ad5842SAllain Legacy 579c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR]; 580c0ad5842SAllain Legacy if (resource->addr == NULL) { 581c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "BAR%u is not mapped\n", 582c0ad5842SAllain Legacy RTE_AVP_PCI_DEVICE_BAR); 583c0ad5842SAllain Legacy return -EFAULT; 584c0ad5842SAllain Legacy } 585c0ad5842SAllain Legacy host_info = (struct rte_avp_device_info *)resource->addr; 586c0ad5842SAllain Legacy 587c0ad5842SAllain Legacy if ((host_info->magic != RTE_AVP_DEVICE_MAGIC) || 588c0ad5842SAllain Legacy avp_dev_version_check(host_info->version)) { 589c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid AVP PCI device, magic 0x%08x version 0x%08x > 0x%08x\n", 590c0ad5842SAllain Legacy host_info->magic, host_info->version, 591c0ad5842SAllain Legacy AVP_DPDK_DRIVER_VERSION); 592c0ad5842SAllain Legacy return -EINVAL; 593c0ad5842SAllain Legacy } 594c0ad5842SAllain Legacy 595c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host device is v%u.%u.%u\n", 596c0ad5842SAllain Legacy RTE_AVP_GET_RELEASE_VERSION(host_info->version), 597c0ad5842SAllain Legacy RTE_AVP_GET_MAJOR_VERSION(host_info->version), 598c0ad5842SAllain Legacy RTE_AVP_GET_MINOR_VERSION(host_info->version)); 599c0ad5842SAllain Legacy 600c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u TX queue(s)\n", 601c0ad5842SAllain Legacy host_info->min_tx_queues, host_info->max_tx_queues); 602c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u RX queue(s)\n", 603c0ad5842SAllain Legacy host_info->min_rx_queues, host_info->max_rx_queues); 604c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports features 0x%08x\n", 605c0ad5842SAllain Legacy host_info->features); 606c0ad5842SAllain Legacy 607c0ad5842SAllain Legacy if (avp->magic != AVP_ETHDEV_MAGIC) { 608c0ad5842SAllain Legacy /* 609c0ad5842SAllain Legacy * First time initialization (i.e., not during a VM 610c0ad5842SAllain Legacy * migration) 611c0ad5842SAllain Legacy */ 612c0ad5842SAllain Legacy memset(avp, 0, sizeof(*avp)); 613c0ad5842SAllain Legacy avp->magic = AVP_ETHDEV_MAGIC; 614c0ad5842SAllain Legacy avp->dev_data = eth_dev->data; 615c0ad5842SAllain Legacy avp->port_id = eth_dev->data->port_id; 616c0ad5842SAllain Legacy avp->host_mbuf_size = host_info->mbuf_size; 617c0ad5842SAllain Legacy avp->host_features = host_info->features; 618c0ad5842SAllain Legacy memcpy(&avp->ethaddr.addr_bytes[0], 619c0ad5842SAllain Legacy host_info->ethaddr, ETHER_ADDR_LEN); 620c0ad5842SAllain Legacy /* adjust max values to not exceed our max */ 621c0ad5842SAllain Legacy avp->max_tx_queues = 622c0ad5842SAllain Legacy RTE_MIN(host_info->max_tx_queues, RTE_AVP_MAX_QUEUES); 623c0ad5842SAllain Legacy avp->max_rx_queues = 624c0ad5842SAllain Legacy RTE_MIN(host_info->max_rx_queues, RTE_AVP_MAX_QUEUES); 625c0ad5842SAllain Legacy } else { 626c0ad5842SAllain Legacy /* Re-attaching during migration */ 627c0ad5842SAllain Legacy 628c0ad5842SAllain Legacy /* TODO... requires validation of host values */ 629c0ad5842SAllain Legacy if ((host_info->features & avp->features) != avp->features) { 630c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "AVP host features mismatched; 0x%08x, host=0x%08x\n", 631c0ad5842SAllain Legacy avp->features, host_info->features); 632c0ad5842SAllain Legacy /* this should not be possible; continue for now */ 633c0ad5842SAllain Legacy } 634c0ad5842SAllain Legacy } 635c0ad5842SAllain Legacy 636c0ad5842SAllain Legacy /* the device id is allowed to change over migrations */ 637c0ad5842SAllain Legacy avp->device_id = host_info->device_id; 638c0ad5842SAllain Legacy 639c0ad5842SAllain Legacy /* translate incoming host addresses to guest address space */ 640c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host tx queue at 0x%" PRIx64 "\n", 641c0ad5842SAllain Legacy host_info->tx_phys); 642c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host alloc queue at 0x%" PRIx64 "\n", 643c0ad5842SAllain Legacy host_info->alloc_phys); 644c0ad5842SAllain Legacy for (i = 0; i < avp->max_tx_queues; i++) { 645c0ad5842SAllain Legacy avp->tx_q[i] = avp_dev_translate_address(eth_dev, 646c0ad5842SAllain Legacy host_info->tx_phys + (i * host_info->tx_size)); 647c0ad5842SAllain Legacy 648c0ad5842SAllain Legacy avp->alloc_q[i] = avp_dev_translate_address(eth_dev, 649c0ad5842SAllain Legacy host_info->alloc_phys + (i * host_info->alloc_size)); 650c0ad5842SAllain Legacy } 651c0ad5842SAllain Legacy 652c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host rx queue at 0x%" PRIx64 "\n", 653c0ad5842SAllain Legacy host_info->rx_phys); 654c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host free queue at 0x%" PRIx64 "\n", 655c0ad5842SAllain Legacy host_info->free_phys); 656c0ad5842SAllain Legacy for (i = 0; i < avp->max_rx_queues; i++) { 657c0ad5842SAllain Legacy avp->rx_q[i] = avp_dev_translate_address(eth_dev, 658c0ad5842SAllain Legacy host_info->rx_phys + (i * host_info->rx_size)); 659c0ad5842SAllain Legacy avp->free_q[i] = avp_dev_translate_address(eth_dev, 660c0ad5842SAllain Legacy host_info->free_phys + (i * host_info->free_size)); 661c0ad5842SAllain Legacy } 662c0ad5842SAllain Legacy 663c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host request queue at 0x%" PRIx64 "\n", 664c0ad5842SAllain Legacy host_info->req_phys); 665c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host response queue at 0x%" PRIx64 "\n", 666c0ad5842SAllain Legacy host_info->resp_phys); 667c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host sync address at 0x%" PRIx64 "\n", 668c0ad5842SAllain Legacy host_info->sync_phys); 669c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host mbuf address at 0x%" PRIx64 "\n", 670c0ad5842SAllain Legacy host_info->mbuf_phys); 671c0ad5842SAllain Legacy avp->req_q = avp_dev_translate_address(eth_dev, host_info->req_phys); 672c0ad5842SAllain Legacy avp->resp_q = avp_dev_translate_address(eth_dev, host_info->resp_phys); 673c0ad5842SAllain Legacy avp->sync_addr = 674c0ad5842SAllain Legacy avp_dev_translate_address(eth_dev, host_info->sync_phys); 675c0ad5842SAllain Legacy avp->mbuf_addr = 676c0ad5842SAllain Legacy avp_dev_translate_address(eth_dev, host_info->mbuf_phys); 677c0ad5842SAllain Legacy 678c0ad5842SAllain Legacy /* 679c0ad5842SAllain Legacy * store the host mbuf virtual address so that we can calculate 680c0ad5842SAllain Legacy * relative offsets for each mbuf as they are processed 681c0ad5842SAllain Legacy */ 682c0ad5842SAllain Legacy avp->host_mbuf_addr = host_info->mbuf_va; 683c0ad5842SAllain Legacy avp->host_sync_addr = host_info->sync_va; 684c0ad5842SAllain Legacy 685c0ad5842SAllain Legacy /* 686c0ad5842SAllain Legacy * store the maximum packet length that is supported by the host. 687c0ad5842SAllain Legacy */ 688c0ad5842SAllain Legacy avp->max_rx_pkt_len = host_info->max_rx_pkt_len; 689c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host max receive packet length is %u\n", 690c0ad5842SAllain Legacy host_info->max_rx_pkt_len); 691c0ad5842SAllain Legacy 692c0ad5842SAllain Legacy return 0; 693c0ad5842SAllain Legacy } 694c0ad5842SAllain Legacy 695c0ad5842SAllain Legacy /* 696908072e9SAllain Legacy * This function is based on probe() function in avp_pci.c 697908072e9SAllain Legacy * It returns 0 on success. 698908072e9SAllain Legacy */ 699908072e9SAllain Legacy static int 700908072e9SAllain Legacy eth_avp_dev_init(struct rte_eth_dev *eth_dev) 701908072e9SAllain Legacy { 702c0ad5842SAllain Legacy struct avp_dev *avp = 703c0ad5842SAllain Legacy AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 704908072e9SAllain Legacy struct rte_pci_device *pci_dev; 705c0ad5842SAllain Legacy int ret; 706908072e9SAllain Legacy 707908072e9SAllain Legacy pci_dev = AVP_DEV_TO_PCI(eth_dev); 7081a859223SAllain Legacy eth_dev->dev_ops = &avp_eth_dev_ops; 70950db69fdSAllain Legacy eth_dev->rx_pkt_burst = &avp_recv_pkts; 710295abce2SAllain Legacy eth_dev->tx_pkt_burst = &avp_xmit_pkts; 711908072e9SAllain Legacy 712908072e9SAllain Legacy if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 713908072e9SAllain Legacy /* 714908072e9SAllain Legacy * no setup required on secondary processes. All data is saved 715908072e9SAllain Legacy * in dev_private by the primary process. All resource should 716908072e9SAllain Legacy * be mapped to the same virtual address so all pointers should 717908072e9SAllain Legacy * be valid. 718908072e9SAllain Legacy */ 71950db69fdSAllain Legacy if (eth_dev->data->scattered_rx) { 72050db69fdSAllain Legacy PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n"); 72150db69fdSAllain Legacy eth_dev->rx_pkt_burst = avp_recv_scattered_pkts; 722295abce2SAllain Legacy eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts; 72350db69fdSAllain Legacy } 724908072e9SAllain Legacy return 0; 725908072e9SAllain Legacy } 726908072e9SAllain Legacy 727908072e9SAllain Legacy rte_eth_copy_pci_info(eth_dev, pci_dev); 728908072e9SAllain Legacy 729908072e9SAllain Legacy eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE; 730908072e9SAllain Legacy 731c0ad5842SAllain Legacy /* Check BAR resources */ 732c0ad5842SAllain Legacy ret = avp_dev_check_regions(eth_dev); 733c0ad5842SAllain Legacy if (ret < 0) { 734c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to validate BAR resources, ret=%d\n", 735c0ad5842SAllain Legacy ret); 736c0ad5842SAllain Legacy return ret; 737c0ad5842SAllain Legacy } 738c0ad5842SAllain Legacy 739c0ad5842SAllain Legacy /* Handle each subtype */ 740c0ad5842SAllain Legacy ret = avp_dev_create(pci_dev, eth_dev); 741c0ad5842SAllain Legacy if (ret < 0) { 742c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to create device, ret=%d\n", ret); 743c0ad5842SAllain Legacy return ret; 744c0ad5842SAllain Legacy } 745c0ad5842SAllain Legacy 746c0ad5842SAllain Legacy /* Allocate memory for storing MAC addresses */ 747c0ad5842SAllain Legacy eth_dev->data->mac_addrs = rte_zmalloc("avp_ethdev", ETHER_ADDR_LEN, 0); 748c0ad5842SAllain Legacy if (eth_dev->data->mac_addrs == NULL) { 749c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses\n", 750c0ad5842SAllain Legacy ETHER_ADDR_LEN); 751c0ad5842SAllain Legacy return -ENOMEM; 752c0ad5842SAllain Legacy } 753c0ad5842SAllain Legacy 754c0ad5842SAllain Legacy /* Get a mac from device config */ 755c0ad5842SAllain Legacy ether_addr_copy(&avp->ethaddr, ð_dev->data->mac_addrs[0]); 756c0ad5842SAllain Legacy 757908072e9SAllain Legacy return 0; 758908072e9SAllain Legacy } 759908072e9SAllain Legacy 760908072e9SAllain Legacy static int 761908072e9SAllain Legacy eth_avp_dev_uninit(struct rte_eth_dev *eth_dev) 762908072e9SAllain Legacy { 763908072e9SAllain Legacy if (rte_eal_process_type() != RTE_PROC_PRIMARY) 764908072e9SAllain Legacy return -EPERM; 765908072e9SAllain Legacy 766908072e9SAllain Legacy if (eth_dev->data == NULL) 767908072e9SAllain Legacy return 0; 768908072e9SAllain Legacy 769c0ad5842SAllain Legacy if (eth_dev->data->mac_addrs != NULL) { 770c0ad5842SAllain Legacy rte_free(eth_dev->data->mac_addrs); 771c0ad5842SAllain Legacy eth_dev->data->mac_addrs = NULL; 772c0ad5842SAllain Legacy } 773c0ad5842SAllain Legacy 774908072e9SAllain Legacy return 0; 775908072e9SAllain Legacy } 776908072e9SAllain Legacy 777908072e9SAllain Legacy 778908072e9SAllain Legacy static struct eth_driver rte_avp_pmd = { 779908072e9SAllain Legacy { 780908072e9SAllain Legacy .id_table = pci_id_avp_map, 781908072e9SAllain Legacy .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 782908072e9SAllain Legacy .probe = rte_eth_dev_pci_probe, 783908072e9SAllain Legacy .remove = rte_eth_dev_pci_remove, 784908072e9SAllain Legacy }, 785908072e9SAllain Legacy .eth_dev_init = eth_avp_dev_init, 786908072e9SAllain Legacy .eth_dev_uninit = eth_avp_dev_uninit, 787908072e9SAllain Legacy .dev_private_size = sizeof(struct avp_adapter), 788908072e9SAllain Legacy }; 789908072e9SAllain Legacy 7901a859223SAllain Legacy static int 79150db69fdSAllain Legacy avp_dev_enable_scattered(struct rte_eth_dev *eth_dev, 79250db69fdSAllain Legacy struct avp_dev *avp) 79350db69fdSAllain Legacy { 79450db69fdSAllain Legacy unsigned int max_rx_pkt_len; 79550db69fdSAllain Legacy 79650db69fdSAllain Legacy max_rx_pkt_len = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len; 79750db69fdSAllain Legacy 79850db69fdSAllain Legacy if ((max_rx_pkt_len > avp->guest_mbuf_size) || 79950db69fdSAllain Legacy (max_rx_pkt_len > avp->host_mbuf_size)) { 80050db69fdSAllain Legacy /* 80150db69fdSAllain Legacy * If the guest MTU is greater than either the host or guest 80250db69fdSAllain Legacy * buffers then chained mbufs have to be enabled in the TX 80350db69fdSAllain Legacy * direction. It is assumed that the application will not need 80450db69fdSAllain Legacy * to send packets larger than their max_rx_pkt_len (MRU). 80550db69fdSAllain Legacy */ 80650db69fdSAllain Legacy return 1; 80750db69fdSAllain Legacy } 80850db69fdSAllain Legacy 80950db69fdSAllain Legacy if ((avp->max_rx_pkt_len > avp->guest_mbuf_size) || 81050db69fdSAllain Legacy (avp->max_rx_pkt_len > avp->host_mbuf_size)) { 81150db69fdSAllain Legacy /* 81250db69fdSAllain Legacy * If the host MRU is greater than its own mbuf size or the 81350db69fdSAllain Legacy * guest mbuf size then chained mbufs have to be enabled in the 81450db69fdSAllain Legacy * RX direction. 81550db69fdSAllain Legacy */ 81650db69fdSAllain Legacy return 1; 81750db69fdSAllain Legacy } 81850db69fdSAllain Legacy 81950db69fdSAllain Legacy return 0; 82050db69fdSAllain Legacy } 82150db69fdSAllain Legacy 82250db69fdSAllain Legacy static int 823cce4367fSAllain Legacy avp_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 824cce4367fSAllain Legacy uint16_t rx_queue_id, 825cce4367fSAllain Legacy uint16_t nb_rx_desc, 826cce4367fSAllain Legacy unsigned int socket_id, 827cce4367fSAllain Legacy const struct rte_eth_rxconf *rx_conf, 828cce4367fSAllain Legacy struct rte_mempool *pool) 829cce4367fSAllain Legacy { 830cce4367fSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 831cce4367fSAllain Legacy struct rte_pktmbuf_pool_private *mbp_priv; 832cce4367fSAllain Legacy struct avp_queue *rxq; 833cce4367fSAllain Legacy 834cce4367fSAllain Legacy if (rx_queue_id >= eth_dev->data->nb_rx_queues) { 835cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "RX queue id is out of range: rx_queue_id=%u, nb_rx_queues=%u\n", 836cce4367fSAllain Legacy rx_queue_id, eth_dev->data->nb_rx_queues); 837cce4367fSAllain Legacy return -EINVAL; 838cce4367fSAllain Legacy } 839cce4367fSAllain Legacy 840cce4367fSAllain Legacy /* Save mbuf pool pointer */ 841cce4367fSAllain Legacy avp->pool = pool; 842cce4367fSAllain Legacy 843cce4367fSAllain Legacy /* Save the local mbuf size */ 844cce4367fSAllain Legacy mbp_priv = rte_mempool_get_priv(pool); 845cce4367fSAllain Legacy avp->guest_mbuf_size = (uint16_t)(mbp_priv->mbuf_data_room_size); 846cce4367fSAllain Legacy avp->guest_mbuf_size -= RTE_PKTMBUF_HEADROOM; 847cce4367fSAllain Legacy 84850db69fdSAllain Legacy if (avp_dev_enable_scattered(eth_dev, avp)) { 84950db69fdSAllain Legacy if (!eth_dev->data->scattered_rx) { 85050db69fdSAllain Legacy PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n"); 85150db69fdSAllain Legacy eth_dev->data->scattered_rx = 1; 85250db69fdSAllain Legacy eth_dev->rx_pkt_burst = avp_recv_scattered_pkts; 853295abce2SAllain Legacy eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts; 85450db69fdSAllain Legacy } 85550db69fdSAllain Legacy } 85650db69fdSAllain Legacy 857cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "AVP max_rx_pkt_len=(%u,%u) mbuf_size=(%u,%u)\n", 858cce4367fSAllain Legacy avp->max_rx_pkt_len, 859cce4367fSAllain Legacy eth_dev->data->dev_conf.rxmode.max_rx_pkt_len, 860cce4367fSAllain Legacy avp->host_mbuf_size, 861cce4367fSAllain Legacy avp->guest_mbuf_size); 862cce4367fSAllain Legacy 863cce4367fSAllain Legacy /* allocate a queue object */ 864cce4367fSAllain Legacy rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct avp_queue), 865cce4367fSAllain Legacy RTE_CACHE_LINE_SIZE, socket_id); 866cce4367fSAllain Legacy if (rxq == NULL) { 867cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate new Rx queue object\n"); 868cce4367fSAllain Legacy return -ENOMEM; 869cce4367fSAllain Legacy } 870cce4367fSAllain Legacy 871cce4367fSAllain Legacy /* save back pointers to AVP and Ethernet devices */ 872cce4367fSAllain Legacy rxq->avp = avp; 873cce4367fSAllain Legacy rxq->dev_data = eth_dev->data; 874cce4367fSAllain Legacy eth_dev->data->rx_queues[rx_queue_id] = (void *)rxq; 875cce4367fSAllain Legacy 876cce4367fSAllain Legacy /* setup the queue receive mapping for the current queue. */ 877cce4367fSAllain Legacy _avp_set_rx_queue_mappings(eth_dev, rx_queue_id); 878cce4367fSAllain Legacy 879cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "Rx queue %u setup at %p\n", rx_queue_id, rxq); 880cce4367fSAllain Legacy 881cce4367fSAllain Legacy (void)nb_rx_desc; 882cce4367fSAllain Legacy (void)rx_conf; 883cce4367fSAllain Legacy return 0; 884cce4367fSAllain Legacy } 885cce4367fSAllain Legacy 886cce4367fSAllain Legacy static int 887cce4367fSAllain Legacy avp_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, 888cce4367fSAllain Legacy uint16_t tx_queue_id, 889cce4367fSAllain Legacy uint16_t nb_tx_desc, 890cce4367fSAllain Legacy unsigned int socket_id, 891cce4367fSAllain Legacy const struct rte_eth_txconf *tx_conf) 892cce4367fSAllain Legacy { 893cce4367fSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 894cce4367fSAllain Legacy struct avp_queue *txq; 895cce4367fSAllain Legacy 896cce4367fSAllain Legacy if (tx_queue_id >= eth_dev->data->nb_tx_queues) { 897cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "TX queue id is out of range: tx_queue_id=%u, nb_tx_queues=%u\n", 898cce4367fSAllain Legacy tx_queue_id, eth_dev->data->nb_tx_queues); 899cce4367fSAllain Legacy return -EINVAL; 900cce4367fSAllain Legacy } 901cce4367fSAllain Legacy 902cce4367fSAllain Legacy /* allocate a queue object */ 903cce4367fSAllain Legacy txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct avp_queue), 904cce4367fSAllain Legacy RTE_CACHE_LINE_SIZE, socket_id); 905cce4367fSAllain Legacy if (txq == NULL) { 906cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate new Tx queue object\n"); 907cce4367fSAllain Legacy return -ENOMEM; 908cce4367fSAllain Legacy } 909cce4367fSAllain Legacy 910cce4367fSAllain Legacy /* only the configured set of transmit queues are used */ 911cce4367fSAllain Legacy txq->queue_id = tx_queue_id; 912cce4367fSAllain Legacy txq->queue_base = tx_queue_id; 913cce4367fSAllain Legacy txq->queue_limit = tx_queue_id; 914cce4367fSAllain Legacy 915cce4367fSAllain Legacy /* save back pointers to AVP and Ethernet devices */ 916cce4367fSAllain Legacy txq->avp = avp; 917cce4367fSAllain Legacy txq->dev_data = eth_dev->data; 918cce4367fSAllain Legacy eth_dev->data->tx_queues[tx_queue_id] = (void *)txq; 919cce4367fSAllain Legacy 920cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "Tx queue %u setup at %p\n", tx_queue_id, txq); 921cce4367fSAllain Legacy 922cce4367fSAllain Legacy (void)nb_tx_desc; 923cce4367fSAllain Legacy (void)tx_conf; 924cce4367fSAllain Legacy return 0; 925cce4367fSAllain Legacy } 926cce4367fSAllain Legacy 92750db69fdSAllain Legacy static inline int 92850db69fdSAllain Legacy _avp_cmp_ether_addr(struct ether_addr *a, struct ether_addr *b) 92950db69fdSAllain Legacy { 93050db69fdSAllain Legacy uint16_t *_a = (uint16_t *)&a->addr_bytes[0]; 93150db69fdSAllain Legacy uint16_t *_b = (uint16_t *)&b->addr_bytes[0]; 93250db69fdSAllain Legacy return (_a[0] ^ _b[0]) | (_a[1] ^ _b[1]) | (_a[2] ^ _b[2]); 93350db69fdSAllain Legacy } 93450db69fdSAllain Legacy 93550db69fdSAllain Legacy static inline int 93650db69fdSAllain Legacy _avp_mac_filter(struct avp_dev *avp, struct rte_mbuf *m) 93750db69fdSAllain Legacy { 93850db69fdSAllain Legacy struct ether_hdr *eth = rte_pktmbuf_mtod(m, struct ether_hdr *); 93950db69fdSAllain Legacy 94050db69fdSAllain Legacy if (likely(_avp_cmp_ether_addr(&avp->ethaddr, ð->d_addr) == 0)) { 94150db69fdSAllain Legacy /* allow all packets destined to our address */ 94250db69fdSAllain Legacy return 0; 94350db69fdSAllain Legacy } 94450db69fdSAllain Legacy 94550db69fdSAllain Legacy if (likely(is_broadcast_ether_addr(ð->d_addr))) { 94650db69fdSAllain Legacy /* allow all broadcast packets */ 94750db69fdSAllain Legacy return 0; 94850db69fdSAllain Legacy } 94950db69fdSAllain Legacy 95050db69fdSAllain Legacy if (likely(is_multicast_ether_addr(ð->d_addr))) { 95150db69fdSAllain Legacy /* allow all multicast packets */ 95250db69fdSAllain Legacy return 0; 95350db69fdSAllain Legacy } 95450db69fdSAllain Legacy 95550db69fdSAllain Legacy if (avp->flags & AVP_F_PROMISC) { 95650db69fdSAllain Legacy /* allow all packets when in promiscuous mode */ 95750db69fdSAllain Legacy return 0; 95850db69fdSAllain Legacy } 95950db69fdSAllain Legacy 96050db69fdSAllain Legacy return -1; 96150db69fdSAllain Legacy } 96250db69fdSAllain Legacy 96350db69fdSAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS 96450db69fdSAllain Legacy static inline void 96550db69fdSAllain Legacy __avp_dev_buffer_sanity_check(struct avp_dev *avp, struct rte_avp_desc *buf) 96650db69fdSAllain Legacy { 96750db69fdSAllain Legacy struct rte_avp_desc *first_buf; 96850db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 96950db69fdSAllain Legacy unsigned int pkt_len; 97050db69fdSAllain Legacy unsigned int nb_segs; 97150db69fdSAllain Legacy void *pkt_data; 97250db69fdSAllain Legacy unsigned int i; 97350db69fdSAllain Legacy 97450db69fdSAllain Legacy first_buf = avp_dev_translate_buffer(avp, buf); 97550db69fdSAllain Legacy 97650db69fdSAllain Legacy i = 0; 97750db69fdSAllain Legacy pkt_len = 0; 97850db69fdSAllain Legacy nb_segs = first_buf->nb_segs; 97950db69fdSAllain Legacy do { 98050db69fdSAllain Legacy /* Adjust pointers for guest addressing */ 98150db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 98250db69fdSAllain Legacy if (pkt_buf == NULL) 98350db69fdSAllain Legacy rte_panic("bad buffer: segment %u has an invalid address %p\n", 98450db69fdSAllain Legacy i, buf); 98550db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 98650db69fdSAllain Legacy if (pkt_data == NULL) 98750db69fdSAllain Legacy rte_panic("bad buffer: segment %u has a NULL data pointer\n", 98850db69fdSAllain Legacy i); 98950db69fdSAllain Legacy if (pkt_buf->data_len == 0) 99050db69fdSAllain Legacy rte_panic("bad buffer: segment %u has 0 data length\n", 99150db69fdSAllain Legacy i); 99250db69fdSAllain Legacy pkt_len += pkt_buf->data_len; 99350db69fdSAllain Legacy nb_segs--; 99450db69fdSAllain Legacy i++; 99550db69fdSAllain Legacy 99650db69fdSAllain Legacy } while (nb_segs && (buf = pkt_buf->next) != NULL); 99750db69fdSAllain Legacy 99850db69fdSAllain Legacy if (nb_segs != 0) 99950db69fdSAllain Legacy rte_panic("bad buffer: expected %u segments found %u\n", 100050db69fdSAllain Legacy first_buf->nb_segs, (first_buf->nb_segs - nb_segs)); 100150db69fdSAllain Legacy if (pkt_len != first_buf->pkt_len) 100250db69fdSAllain Legacy rte_panic("bad buffer: expected length %u found %u\n", 100350db69fdSAllain Legacy first_buf->pkt_len, pkt_len); 100450db69fdSAllain Legacy } 100550db69fdSAllain Legacy 100650db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) \ 100750db69fdSAllain Legacy __avp_dev_buffer_sanity_check((a), (b)) 100850db69fdSAllain Legacy 100950db69fdSAllain Legacy #else /* RTE_LIBRTE_AVP_DEBUG_BUFFERS */ 101050db69fdSAllain Legacy 101150db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) do {} while (0) 101250db69fdSAllain Legacy 101350db69fdSAllain Legacy #endif 101450db69fdSAllain Legacy 101550db69fdSAllain Legacy /* 101650db69fdSAllain Legacy * Copy a host buffer chain to a set of mbufs. This function assumes that 101750db69fdSAllain Legacy * there exactly the required number of mbufs to copy all source bytes. 101850db69fdSAllain Legacy */ 101950db69fdSAllain Legacy static inline struct rte_mbuf * 102050db69fdSAllain Legacy avp_dev_copy_from_buffers(struct avp_dev *avp, 102150db69fdSAllain Legacy struct rte_avp_desc *buf, 102250db69fdSAllain Legacy struct rte_mbuf **mbufs, 102350db69fdSAllain Legacy unsigned int count) 102450db69fdSAllain Legacy { 102550db69fdSAllain Legacy struct rte_mbuf *m_previous = NULL; 102650db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 102750db69fdSAllain Legacy unsigned int total_length = 0; 102850db69fdSAllain Legacy unsigned int copy_length; 102950db69fdSAllain Legacy unsigned int src_offset; 103050db69fdSAllain Legacy struct rte_mbuf *m; 103150db69fdSAllain Legacy uint16_t ol_flags; 103250db69fdSAllain Legacy uint16_t vlan_tci; 103350db69fdSAllain Legacy void *pkt_data; 103450db69fdSAllain Legacy unsigned int i; 103550db69fdSAllain Legacy 103650db69fdSAllain Legacy avp_dev_buffer_sanity_check(avp, buf); 103750db69fdSAllain Legacy 103850db69fdSAllain Legacy /* setup the first source buffer */ 103950db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 104050db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 104150db69fdSAllain Legacy total_length = pkt_buf->pkt_len; 104250db69fdSAllain Legacy src_offset = 0; 104350db69fdSAllain Legacy 104450db69fdSAllain Legacy if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) { 104550db69fdSAllain Legacy ol_flags = PKT_RX_VLAN_PKT; 104650db69fdSAllain Legacy vlan_tci = pkt_buf->vlan_tci; 104750db69fdSAllain Legacy } else { 104850db69fdSAllain Legacy ol_flags = 0; 104950db69fdSAllain Legacy vlan_tci = 0; 105050db69fdSAllain Legacy } 105150db69fdSAllain Legacy 105250db69fdSAllain Legacy for (i = 0; (i < count) && (buf != NULL); i++) { 105350db69fdSAllain Legacy /* fill each destination buffer */ 105450db69fdSAllain Legacy m = mbufs[i]; 105550db69fdSAllain Legacy 105650db69fdSAllain Legacy if (m_previous != NULL) 105750db69fdSAllain Legacy m_previous->next = m; 105850db69fdSAllain Legacy 105950db69fdSAllain Legacy m_previous = m; 106050db69fdSAllain Legacy 106150db69fdSAllain Legacy do { 106250db69fdSAllain Legacy /* 106350db69fdSAllain Legacy * Copy as many source buffers as will fit in the 106450db69fdSAllain Legacy * destination buffer. 106550db69fdSAllain Legacy */ 106650db69fdSAllain Legacy copy_length = RTE_MIN((avp->guest_mbuf_size - 106750db69fdSAllain Legacy rte_pktmbuf_data_len(m)), 106850db69fdSAllain Legacy (pkt_buf->data_len - 106950db69fdSAllain Legacy src_offset)); 107050db69fdSAllain Legacy rte_memcpy(RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *), 107150db69fdSAllain Legacy rte_pktmbuf_data_len(m)), 107250db69fdSAllain Legacy RTE_PTR_ADD(pkt_data, src_offset), 107350db69fdSAllain Legacy copy_length); 107450db69fdSAllain Legacy rte_pktmbuf_data_len(m) += copy_length; 107550db69fdSAllain Legacy src_offset += copy_length; 107650db69fdSAllain Legacy 107750db69fdSAllain Legacy if (likely(src_offset == pkt_buf->data_len)) { 107850db69fdSAllain Legacy /* need a new source buffer */ 107950db69fdSAllain Legacy buf = pkt_buf->next; 108050db69fdSAllain Legacy if (buf != NULL) { 108150db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer( 108250db69fdSAllain Legacy avp, buf); 108350db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer( 108450db69fdSAllain Legacy avp, pkt_buf->data); 108550db69fdSAllain Legacy src_offset = 0; 108650db69fdSAllain Legacy } 108750db69fdSAllain Legacy } 108850db69fdSAllain Legacy 108950db69fdSAllain Legacy if (unlikely(rte_pktmbuf_data_len(m) == 109050db69fdSAllain Legacy avp->guest_mbuf_size)) { 109150db69fdSAllain Legacy /* need a new destination mbuf */ 109250db69fdSAllain Legacy break; 109350db69fdSAllain Legacy } 109450db69fdSAllain Legacy 109550db69fdSAllain Legacy } while (buf != NULL); 109650db69fdSAllain Legacy } 109750db69fdSAllain Legacy 109850db69fdSAllain Legacy m = mbufs[0]; 109950db69fdSAllain Legacy m->ol_flags = ol_flags; 110050db69fdSAllain Legacy m->nb_segs = count; 110150db69fdSAllain Legacy rte_pktmbuf_pkt_len(m) = total_length; 110250db69fdSAllain Legacy m->vlan_tci = vlan_tci; 110350db69fdSAllain Legacy 110450db69fdSAllain Legacy __rte_mbuf_sanity_check(m, 1); 110550db69fdSAllain Legacy 110650db69fdSAllain Legacy return m; 110750db69fdSAllain Legacy } 110850db69fdSAllain Legacy 110950db69fdSAllain Legacy static uint16_t 111050db69fdSAllain Legacy avp_recv_scattered_pkts(void *rx_queue, 111150db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 111250db69fdSAllain Legacy uint16_t nb_pkts) 111350db69fdSAllain Legacy { 111450db69fdSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 111550db69fdSAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST]; 111650db69fdSAllain Legacy struct rte_mbuf *mbufs[RTE_AVP_MAX_MBUF_SEGMENTS]; 111750db69fdSAllain Legacy struct avp_dev *avp = rxq->avp; 111850db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 111950db69fdSAllain Legacy struct rte_avp_fifo *free_q; 112050db69fdSAllain Legacy struct rte_avp_fifo *rx_q; 112150db69fdSAllain Legacy struct rte_avp_desc *buf; 112250db69fdSAllain Legacy unsigned int count, avail, n; 112350db69fdSAllain Legacy unsigned int guest_mbuf_size; 112450db69fdSAllain Legacy struct rte_mbuf *m; 112550db69fdSAllain Legacy unsigned int required; 112650db69fdSAllain Legacy unsigned int buf_len; 112750db69fdSAllain Legacy unsigned int port_id; 112850db69fdSAllain Legacy unsigned int i; 112950db69fdSAllain Legacy 113050db69fdSAllain Legacy guest_mbuf_size = avp->guest_mbuf_size; 113150db69fdSAllain Legacy port_id = avp->port_id; 113250db69fdSAllain Legacy rx_q = avp->rx_q[rxq->queue_id]; 113350db69fdSAllain Legacy free_q = avp->free_q[rxq->queue_id]; 113450db69fdSAllain Legacy 113550db69fdSAllain Legacy /* setup next queue to service */ 113650db69fdSAllain Legacy rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ? 113750db69fdSAllain Legacy (rxq->queue_id + 1) : rxq->queue_base; 113850db69fdSAllain Legacy 113950db69fdSAllain Legacy /* determine how many slots are available in the free queue */ 114050db69fdSAllain Legacy count = avp_fifo_free_count(free_q); 114150db69fdSAllain Legacy 114250db69fdSAllain Legacy /* determine how many packets are available in the rx queue */ 114350db69fdSAllain Legacy avail = avp_fifo_count(rx_q); 114450db69fdSAllain Legacy 114550db69fdSAllain Legacy /* determine how many packets can be received */ 114650db69fdSAllain Legacy count = RTE_MIN(count, avail); 114750db69fdSAllain Legacy count = RTE_MIN(count, nb_pkts); 114850db69fdSAllain Legacy count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST); 114950db69fdSAllain Legacy 115050db69fdSAllain Legacy if (unlikely(count == 0)) { 115150db69fdSAllain Legacy /* no free buffers, or no buffers on the rx queue */ 115250db69fdSAllain Legacy return 0; 115350db69fdSAllain Legacy } 115450db69fdSAllain Legacy 115550db69fdSAllain Legacy /* retrieve pending packets */ 115650db69fdSAllain Legacy n = avp_fifo_get(rx_q, (void **)&avp_bufs, count); 115750db69fdSAllain Legacy PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n", 115850db69fdSAllain Legacy count, rx_q); 115950db69fdSAllain Legacy 116050db69fdSAllain Legacy count = 0; 116150db69fdSAllain Legacy for (i = 0; i < n; i++) { 116250db69fdSAllain Legacy /* prefetch next entry while processing current one */ 116350db69fdSAllain Legacy if (i + 1 < n) { 116450db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 116550db69fdSAllain Legacy avp_bufs[i + 1]); 116650db69fdSAllain Legacy rte_prefetch0(pkt_buf); 116750db69fdSAllain Legacy } 116850db69fdSAllain Legacy buf = avp_bufs[i]; 116950db69fdSAllain Legacy 117050db69fdSAllain Legacy /* Peek into the first buffer to determine the total length */ 117150db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 117250db69fdSAllain Legacy buf_len = pkt_buf->pkt_len; 117350db69fdSAllain Legacy 117450db69fdSAllain Legacy /* Allocate enough mbufs to receive the entire packet */ 117550db69fdSAllain Legacy required = (buf_len + guest_mbuf_size - 1) / guest_mbuf_size; 117650db69fdSAllain Legacy if (rte_pktmbuf_alloc_bulk(avp->pool, mbufs, required)) { 117750db69fdSAllain Legacy rxq->dev_data->rx_mbuf_alloc_failed++; 117850db69fdSAllain Legacy continue; 117950db69fdSAllain Legacy } 118050db69fdSAllain Legacy 118150db69fdSAllain Legacy /* Copy the data from the buffers to our mbufs */ 118250db69fdSAllain Legacy m = avp_dev_copy_from_buffers(avp, buf, mbufs, required); 118350db69fdSAllain Legacy 118450db69fdSAllain Legacy /* finalize mbuf */ 118550db69fdSAllain Legacy m->port = port_id; 118650db69fdSAllain Legacy 118750db69fdSAllain Legacy if (_avp_mac_filter(avp, m) != 0) { 118850db69fdSAllain Legacy /* silently discard packets not destined to our MAC */ 118950db69fdSAllain Legacy rte_pktmbuf_free(m); 119050db69fdSAllain Legacy continue; 119150db69fdSAllain Legacy } 119250db69fdSAllain Legacy 119350db69fdSAllain Legacy /* return new mbuf to caller */ 119450db69fdSAllain Legacy rx_pkts[count++] = m; 119550db69fdSAllain Legacy rxq->bytes += buf_len; 119650db69fdSAllain Legacy } 119750db69fdSAllain Legacy 119850db69fdSAllain Legacy rxq->packets += count; 119950db69fdSAllain Legacy 120050db69fdSAllain Legacy /* return the buffers to the free queue */ 120150db69fdSAllain Legacy avp_fifo_put(free_q, (void **)&avp_bufs[0], n); 120250db69fdSAllain Legacy 120350db69fdSAllain Legacy return count; 120450db69fdSAllain Legacy } 120550db69fdSAllain Legacy 120650db69fdSAllain Legacy 120750db69fdSAllain Legacy static uint16_t 120850db69fdSAllain Legacy avp_recv_pkts(void *rx_queue, 120950db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 121050db69fdSAllain Legacy uint16_t nb_pkts) 121150db69fdSAllain Legacy { 121250db69fdSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 121350db69fdSAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST]; 121450db69fdSAllain Legacy struct avp_dev *avp = rxq->avp; 121550db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 121650db69fdSAllain Legacy struct rte_avp_fifo *free_q; 121750db69fdSAllain Legacy struct rte_avp_fifo *rx_q; 121850db69fdSAllain Legacy unsigned int count, avail, n; 121950db69fdSAllain Legacy unsigned int pkt_len; 122050db69fdSAllain Legacy struct rte_mbuf *m; 122150db69fdSAllain Legacy char *pkt_data; 122250db69fdSAllain Legacy unsigned int i; 122350db69fdSAllain Legacy 122450db69fdSAllain Legacy rx_q = avp->rx_q[rxq->queue_id]; 122550db69fdSAllain Legacy free_q = avp->free_q[rxq->queue_id]; 122650db69fdSAllain Legacy 122750db69fdSAllain Legacy /* setup next queue to service */ 122850db69fdSAllain Legacy rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ? 122950db69fdSAllain Legacy (rxq->queue_id + 1) : rxq->queue_base; 123050db69fdSAllain Legacy 123150db69fdSAllain Legacy /* determine how many slots are available in the free queue */ 123250db69fdSAllain Legacy count = avp_fifo_free_count(free_q); 123350db69fdSAllain Legacy 123450db69fdSAllain Legacy /* determine how many packets are available in the rx queue */ 123550db69fdSAllain Legacy avail = avp_fifo_count(rx_q); 123650db69fdSAllain Legacy 123750db69fdSAllain Legacy /* determine how many packets can be received */ 123850db69fdSAllain Legacy count = RTE_MIN(count, avail); 123950db69fdSAllain Legacy count = RTE_MIN(count, nb_pkts); 124050db69fdSAllain Legacy count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST); 124150db69fdSAllain Legacy 124250db69fdSAllain Legacy if (unlikely(count == 0)) { 124350db69fdSAllain Legacy /* no free buffers, or no buffers on the rx queue */ 124450db69fdSAllain Legacy return 0; 124550db69fdSAllain Legacy } 124650db69fdSAllain Legacy 124750db69fdSAllain Legacy /* retrieve pending packets */ 124850db69fdSAllain Legacy n = avp_fifo_get(rx_q, (void **)&avp_bufs, count); 124950db69fdSAllain Legacy PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n", 125050db69fdSAllain Legacy count, rx_q); 125150db69fdSAllain Legacy 125250db69fdSAllain Legacy count = 0; 125350db69fdSAllain Legacy for (i = 0; i < n; i++) { 125450db69fdSAllain Legacy /* prefetch next entry while processing current one */ 125550db69fdSAllain Legacy if (i < n - 1) { 125650db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 125750db69fdSAllain Legacy avp_bufs[i + 1]); 125850db69fdSAllain Legacy rte_prefetch0(pkt_buf); 125950db69fdSAllain Legacy } 126050db69fdSAllain Legacy 126150db69fdSAllain Legacy /* Adjust host pointers for guest addressing */ 126250db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]); 126350db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 126450db69fdSAllain Legacy pkt_len = pkt_buf->pkt_len; 126550db69fdSAllain Legacy 126650db69fdSAllain Legacy if (unlikely((pkt_len > avp->guest_mbuf_size) || 126750db69fdSAllain Legacy (pkt_buf->nb_segs > 1))) { 126850db69fdSAllain Legacy /* 126950db69fdSAllain Legacy * application should be using the scattered receive 127050db69fdSAllain Legacy * function 127150db69fdSAllain Legacy */ 127250db69fdSAllain Legacy rxq->errors++; 127350db69fdSAllain Legacy continue; 127450db69fdSAllain Legacy } 127550db69fdSAllain Legacy 127650db69fdSAllain Legacy /* process each packet to be transmitted */ 127750db69fdSAllain Legacy m = rte_pktmbuf_alloc(avp->pool); 127850db69fdSAllain Legacy if (unlikely(m == NULL)) { 127950db69fdSAllain Legacy rxq->dev_data->rx_mbuf_alloc_failed++; 128050db69fdSAllain Legacy continue; 128150db69fdSAllain Legacy } 128250db69fdSAllain Legacy 128350db69fdSAllain Legacy /* copy data out of the host buffer to our buffer */ 128450db69fdSAllain Legacy m->data_off = RTE_PKTMBUF_HEADROOM; 128550db69fdSAllain Legacy rte_memcpy(rte_pktmbuf_mtod(m, void *), pkt_data, pkt_len); 128650db69fdSAllain Legacy 128750db69fdSAllain Legacy /* initialize the local mbuf */ 128850db69fdSAllain Legacy rte_pktmbuf_data_len(m) = pkt_len; 128950db69fdSAllain Legacy rte_pktmbuf_pkt_len(m) = pkt_len; 129050db69fdSAllain Legacy m->port = avp->port_id; 129150db69fdSAllain Legacy 129250db69fdSAllain Legacy if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) { 129350db69fdSAllain Legacy m->ol_flags = PKT_RX_VLAN_PKT; 129450db69fdSAllain Legacy m->vlan_tci = pkt_buf->vlan_tci; 129550db69fdSAllain Legacy } 129650db69fdSAllain Legacy 129750db69fdSAllain Legacy if (_avp_mac_filter(avp, m) != 0) { 129850db69fdSAllain Legacy /* silently discard packets not destined to our MAC */ 129950db69fdSAllain Legacy rte_pktmbuf_free(m); 130050db69fdSAllain Legacy continue; 130150db69fdSAllain Legacy } 130250db69fdSAllain Legacy 130350db69fdSAllain Legacy /* return new mbuf to caller */ 130450db69fdSAllain Legacy rx_pkts[count++] = m; 130550db69fdSAllain Legacy rxq->bytes += pkt_len; 130650db69fdSAllain Legacy } 130750db69fdSAllain Legacy 130850db69fdSAllain Legacy rxq->packets += count; 130950db69fdSAllain Legacy 131050db69fdSAllain Legacy /* return the buffers to the free queue */ 131150db69fdSAllain Legacy avp_fifo_put(free_q, (void **)&avp_bufs[0], n); 131250db69fdSAllain Legacy 131350db69fdSAllain Legacy return count; 131450db69fdSAllain Legacy } 131550db69fdSAllain Legacy 1316295abce2SAllain Legacy /* 1317295abce2SAllain Legacy * Copy a chained mbuf to a set of host buffers. This function assumes that 1318295abce2SAllain Legacy * there are sufficient destination buffers to contain the entire source 1319295abce2SAllain Legacy * packet. 1320295abce2SAllain Legacy */ 1321295abce2SAllain Legacy static inline uint16_t 1322295abce2SAllain Legacy avp_dev_copy_to_buffers(struct avp_dev *avp, 1323295abce2SAllain Legacy struct rte_mbuf *mbuf, 1324295abce2SAllain Legacy struct rte_avp_desc **buffers, 1325295abce2SAllain Legacy unsigned int count) 1326295abce2SAllain Legacy { 1327295abce2SAllain Legacy struct rte_avp_desc *previous_buf = NULL; 1328295abce2SAllain Legacy struct rte_avp_desc *first_buf = NULL; 1329295abce2SAllain Legacy struct rte_avp_desc *pkt_buf; 1330295abce2SAllain Legacy struct rte_avp_desc *buf; 1331295abce2SAllain Legacy size_t total_length; 1332295abce2SAllain Legacy struct rte_mbuf *m; 1333295abce2SAllain Legacy size_t copy_length; 1334295abce2SAllain Legacy size_t src_offset; 1335295abce2SAllain Legacy char *pkt_data; 1336295abce2SAllain Legacy unsigned int i; 1337295abce2SAllain Legacy 1338295abce2SAllain Legacy __rte_mbuf_sanity_check(mbuf, 1); 1339295abce2SAllain Legacy 1340295abce2SAllain Legacy m = mbuf; 1341295abce2SAllain Legacy src_offset = 0; 1342295abce2SAllain Legacy total_length = rte_pktmbuf_pkt_len(m); 1343295abce2SAllain Legacy for (i = 0; (i < count) && (m != NULL); i++) { 1344295abce2SAllain Legacy /* fill each destination buffer */ 1345295abce2SAllain Legacy buf = buffers[i]; 1346295abce2SAllain Legacy 1347295abce2SAllain Legacy if (i < count - 1) { 1348295abce2SAllain Legacy /* prefetch next entry while processing this one */ 1349295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buffers[i + 1]); 1350295abce2SAllain Legacy rte_prefetch0(pkt_buf); 1351295abce2SAllain Legacy } 1352295abce2SAllain Legacy 1353295abce2SAllain Legacy /* Adjust pointers for guest addressing */ 1354295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 1355295abce2SAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 1356295abce2SAllain Legacy 1357295abce2SAllain Legacy /* setup the buffer chain */ 1358295abce2SAllain Legacy if (previous_buf != NULL) 1359295abce2SAllain Legacy previous_buf->next = buf; 1360295abce2SAllain Legacy else 1361295abce2SAllain Legacy first_buf = pkt_buf; 1362295abce2SAllain Legacy 1363295abce2SAllain Legacy previous_buf = pkt_buf; 1364295abce2SAllain Legacy 1365295abce2SAllain Legacy do { 1366295abce2SAllain Legacy /* 1367295abce2SAllain Legacy * copy as many source mbuf segments as will fit in the 1368295abce2SAllain Legacy * destination buffer. 1369295abce2SAllain Legacy */ 1370295abce2SAllain Legacy copy_length = RTE_MIN((avp->host_mbuf_size - 1371295abce2SAllain Legacy pkt_buf->data_len), 1372295abce2SAllain Legacy (rte_pktmbuf_data_len(m) - 1373295abce2SAllain Legacy src_offset)); 1374295abce2SAllain Legacy rte_memcpy(RTE_PTR_ADD(pkt_data, pkt_buf->data_len), 1375295abce2SAllain Legacy RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *), 1376295abce2SAllain Legacy src_offset), 1377295abce2SAllain Legacy copy_length); 1378295abce2SAllain Legacy pkt_buf->data_len += copy_length; 1379295abce2SAllain Legacy src_offset += copy_length; 1380295abce2SAllain Legacy 1381295abce2SAllain Legacy if (likely(src_offset == rte_pktmbuf_data_len(m))) { 1382295abce2SAllain Legacy /* need a new source buffer */ 1383295abce2SAllain Legacy m = m->next; 1384295abce2SAllain Legacy src_offset = 0; 1385295abce2SAllain Legacy } 1386295abce2SAllain Legacy 1387295abce2SAllain Legacy if (unlikely(pkt_buf->data_len == 1388295abce2SAllain Legacy avp->host_mbuf_size)) { 1389295abce2SAllain Legacy /* need a new destination buffer */ 1390295abce2SAllain Legacy break; 1391295abce2SAllain Legacy } 1392295abce2SAllain Legacy 1393295abce2SAllain Legacy } while (m != NULL); 1394295abce2SAllain Legacy } 1395295abce2SAllain Legacy 1396295abce2SAllain Legacy first_buf->nb_segs = count; 1397295abce2SAllain Legacy first_buf->pkt_len = total_length; 1398295abce2SAllain Legacy 1399295abce2SAllain Legacy if (mbuf->ol_flags & PKT_TX_VLAN_PKT) { 1400295abce2SAllain Legacy first_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT; 1401295abce2SAllain Legacy first_buf->vlan_tci = mbuf->vlan_tci; 1402295abce2SAllain Legacy } 1403295abce2SAllain Legacy 1404295abce2SAllain Legacy avp_dev_buffer_sanity_check(avp, buffers[0]); 1405295abce2SAllain Legacy 1406295abce2SAllain Legacy return total_length; 1407295abce2SAllain Legacy } 1408295abce2SAllain Legacy 1409295abce2SAllain Legacy 1410295abce2SAllain Legacy static uint16_t 1411295abce2SAllain Legacy avp_xmit_scattered_pkts(void *tx_queue, 1412295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 1413295abce2SAllain Legacy uint16_t nb_pkts) 1414295abce2SAllain Legacy { 1415295abce2SAllain Legacy struct rte_avp_desc *avp_bufs[(AVP_MAX_TX_BURST * 1416295abce2SAllain Legacy RTE_AVP_MAX_MBUF_SEGMENTS)]; 1417295abce2SAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 1418295abce2SAllain Legacy struct rte_avp_desc *tx_bufs[AVP_MAX_TX_BURST]; 1419295abce2SAllain Legacy struct avp_dev *avp = txq->avp; 1420295abce2SAllain Legacy struct rte_avp_fifo *alloc_q; 1421295abce2SAllain Legacy struct rte_avp_fifo *tx_q; 1422295abce2SAllain Legacy unsigned int count, avail, n; 1423295abce2SAllain Legacy unsigned int orig_nb_pkts; 1424295abce2SAllain Legacy struct rte_mbuf *m; 1425295abce2SAllain Legacy unsigned int required; 1426295abce2SAllain Legacy unsigned int segments; 1427295abce2SAllain Legacy unsigned int tx_bytes; 1428295abce2SAllain Legacy unsigned int i; 1429295abce2SAllain Legacy 1430295abce2SAllain Legacy orig_nb_pkts = nb_pkts; 1431295abce2SAllain Legacy tx_q = avp->tx_q[txq->queue_id]; 1432295abce2SAllain Legacy alloc_q = avp->alloc_q[txq->queue_id]; 1433295abce2SAllain Legacy 1434295abce2SAllain Legacy /* limit the number of transmitted packets to the max burst size */ 1435295abce2SAllain Legacy if (unlikely(nb_pkts > AVP_MAX_TX_BURST)) 1436295abce2SAllain Legacy nb_pkts = AVP_MAX_TX_BURST; 1437295abce2SAllain Legacy 1438295abce2SAllain Legacy /* determine how many buffers are available to copy into */ 1439295abce2SAllain Legacy avail = avp_fifo_count(alloc_q); 1440295abce2SAllain Legacy if (unlikely(avail > (AVP_MAX_TX_BURST * 1441295abce2SAllain Legacy RTE_AVP_MAX_MBUF_SEGMENTS))) 1442295abce2SAllain Legacy avail = AVP_MAX_TX_BURST * RTE_AVP_MAX_MBUF_SEGMENTS; 1443295abce2SAllain Legacy 1444295abce2SAllain Legacy /* determine how many slots are available in the transmit queue */ 1445295abce2SAllain Legacy count = avp_fifo_free_count(tx_q); 1446295abce2SAllain Legacy 1447295abce2SAllain Legacy /* determine how many packets can be sent */ 1448295abce2SAllain Legacy nb_pkts = RTE_MIN(count, nb_pkts); 1449295abce2SAllain Legacy 1450295abce2SAllain Legacy /* determine how many packets will fit in the available buffers */ 1451295abce2SAllain Legacy count = 0; 1452295abce2SAllain Legacy segments = 0; 1453295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) { 1454295abce2SAllain Legacy m = tx_pkts[i]; 1455295abce2SAllain Legacy if (likely(i < (unsigned int)nb_pkts - 1)) { 1456295abce2SAllain Legacy /* prefetch next entry while processing this one */ 1457295abce2SAllain Legacy rte_prefetch0(tx_pkts[i + 1]); 1458295abce2SAllain Legacy } 1459295abce2SAllain Legacy required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) / 1460295abce2SAllain Legacy avp->host_mbuf_size; 1461295abce2SAllain Legacy 1462295abce2SAllain Legacy if (unlikely((required == 0) || 1463295abce2SAllain Legacy (required > RTE_AVP_MAX_MBUF_SEGMENTS))) 1464295abce2SAllain Legacy break; 1465295abce2SAllain Legacy else if (unlikely(required + segments > avail)) 1466295abce2SAllain Legacy break; 1467295abce2SAllain Legacy segments += required; 1468295abce2SAllain Legacy count++; 1469295abce2SAllain Legacy } 1470295abce2SAllain Legacy nb_pkts = count; 1471295abce2SAllain Legacy 1472295abce2SAllain Legacy if (unlikely(nb_pkts == 0)) { 1473295abce2SAllain Legacy /* no available buffers, or no space on the tx queue */ 1474295abce2SAllain Legacy txq->errors += orig_nb_pkts; 1475295abce2SAllain Legacy return 0; 1476295abce2SAllain Legacy } 1477295abce2SAllain Legacy 1478295abce2SAllain Legacy PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n", 1479295abce2SAllain Legacy nb_pkts, tx_q); 1480295abce2SAllain Legacy 1481295abce2SAllain Legacy /* retrieve sufficient send buffers */ 1482295abce2SAllain Legacy n = avp_fifo_get(alloc_q, (void **)&avp_bufs, segments); 1483295abce2SAllain Legacy if (unlikely(n != segments)) { 1484295abce2SAllain Legacy PMD_TX_LOG(DEBUG, "Failed to allocate buffers " 1485295abce2SAllain Legacy "n=%u, segments=%u, orig=%u\n", 1486295abce2SAllain Legacy n, segments, orig_nb_pkts); 1487295abce2SAllain Legacy txq->errors += orig_nb_pkts; 1488295abce2SAllain Legacy return 0; 1489295abce2SAllain Legacy } 1490295abce2SAllain Legacy 1491295abce2SAllain Legacy tx_bytes = 0; 1492295abce2SAllain Legacy count = 0; 1493295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) { 1494295abce2SAllain Legacy /* process each packet to be transmitted */ 1495295abce2SAllain Legacy m = tx_pkts[i]; 1496295abce2SAllain Legacy 1497295abce2SAllain Legacy /* determine how many buffers are required for this packet */ 1498295abce2SAllain Legacy required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) / 1499295abce2SAllain Legacy avp->host_mbuf_size; 1500295abce2SAllain Legacy 1501295abce2SAllain Legacy tx_bytes += avp_dev_copy_to_buffers(avp, m, 1502295abce2SAllain Legacy &avp_bufs[count], required); 1503295abce2SAllain Legacy tx_bufs[i] = avp_bufs[count]; 1504295abce2SAllain Legacy count += required; 1505295abce2SAllain Legacy 1506295abce2SAllain Legacy /* free the original mbuf */ 1507295abce2SAllain Legacy rte_pktmbuf_free(m); 1508295abce2SAllain Legacy } 1509295abce2SAllain Legacy 1510295abce2SAllain Legacy txq->packets += nb_pkts; 1511295abce2SAllain Legacy txq->bytes += tx_bytes; 1512295abce2SAllain Legacy 1513295abce2SAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS 1514295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) 1515295abce2SAllain Legacy avp_dev_buffer_sanity_check(avp, tx_bufs[i]); 1516295abce2SAllain Legacy #endif 1517295abce2SAllain Legacy 1518295abce2SAllain Legacy /* send the packets */ 1519295abce2SAllain Legacy n = avp_fifo_put(tx_q, (void **)&tx_bufs[0], nb_pkts); 1520295abce2SAllain Legacy if (unlikely(n != orig_nb_pkts)) 1521295abce2SAllain Legacy txq->errors += (orig_nb_pkts - n); 1522295abce2SAllain Legacy 1523295abce2SAllain Legacy return n; 1524295abce2SAllain Legacy } 1525295abce2SAllain Legacy 1526295abce2SAllain Legacy 1527295abce2SAllain Legacy static uint16_t 1528295abce2SAllain Legacy avp_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) 1529295abce2SAllain Legacy { 1530295abce2SAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 1531295abce2SAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_TX_BURST]; 1532295abce2SAllain Legacy struct avp_dev *avp = txq->avp; 1533295abce2SAllain Legacy struct rte_avp_desc *pkt_buf; 1534295abce2SAllain Legacy struct rte_avp_fifo *alloc_q; 1535295abce2SAllain Legacy struct rte_avp_fifo *tx_q; 1536295abce2SAllain Legacy unsigned int count, avail, n; 1537295abce2SAllain Legacy struct rte_mbuf *m; 1538295abce2SAllain Legacy unsigned int pkt_len; 1539295abce2SAllain Legacy unsigned int tx_bytes; 1540295abce2SAllain Legacy char *pkt_data; 1541295abce2SAllain Legacy unsigned int i; 1542295abce2SAllain Legacy 1543295abce2SAllain Legacy tx_q = avp->tx_q[txq->queue_id]; 1544295abce2SAllain Legacy alloc_q = avp->alloc_q[txq->queue_id]; 1545295abce2SAllain Legacy 1546295abce2SAllain Legacy /* limit the number of transmitted packets to the max burst size */ 1547295abce2SAllain Legacy if (unlikely(nb_pkts > AVP_MAX_TX_BURST)) 1548295abce2SAllain Legacy nb_pkts = AVP_MAX_TX_BURST; 1549295abce2SAllain Legacy 1550295abce2SAllain Legacy /* determine how many buffers are available to copy into */ 1551295abce2SAllain Legacy avail = avp_fifo_count(alloc_q); 1552295abce2SAllain Legacy 1553295abce2SAllain Legacy /* determine how many slots are available in the transmit queue */ 1554295abce2SAllain Legacy count = avp_fifo_free_count(tx_q); 1555295abce2SAllain Legacy 1556295abce2SAllain Legacy /* determine how many packets can be sent */ 1557295abce2SAllain Legacy count = RTE_MIN(count, avail); 1558295abce2SAllain Legacy count = RTE_MIN(count, nb_pkts); 1559295abce2SAllain Legacy 1560295abce2SAllain Legacy if (unlikely(count == 0)) { 1561295abce2SAllain Legacy /* no available buffers, or no space on the tx queue */ 1562295abce2SAllain Legacy txq->errors += nb_pkts; 1563295abce2SAllain Legacy return 0; 1564295abce2SAllain Legacy } 1565295abce2SAllain Legacy 1566295abce2SAllain Legacy PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n", 1567295abce2SAllain Legacy count, tx_q); 1568295abce2SAllain Legacy 1569295abce2SAllain Legacy /* retrieve sufficient send buffers */ 1570295abce2SAllain Legacy n = avp_fifo_get(alloc_q, (void **)&avp_bufs, count); 1571295abce2SAllain Legacy if (unlikely(n != count)) { 1572295abce2SAllain Legacy txq->errors++; 1573295abce2SAllain Legacy return 0; 1574295abce2SAllain Legacy } 1575295abce2SAllain Legacy 1576295abce2SAllain Legacy tx_bytes = 0; 1577295abce2SAllain Legacy for (i = 0; i < count; i++) { 1578295abce2SAllain Legacy /* prefetch next entry while processing the current one */ 1579295abce2SAllain Legacy if (i < count - 1) { 1580295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 1581295abce2SAllain Legacy avp_bufs[i + 1]); 1582295abce2SAllain Legacy rte_prefetch0(pkt_buf); 1583295abce2SAllain Legacy } 1584295abce2SAllain Legacy 1585295abce2SAllain Legacy /* process each packet to be transmitted */ 1586295abce2SAllain Legacy m = tx_pkts[i]; 1587295abce2SAllain Legacy 1588295abce2SAllain Legacy /* Adjust pointers for guest addressing */ 1589295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]); 1590295abce2SAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 1591295abce2SAllain Legacy pkt_len = rte_pktmbuf_pkt_len(m); 1592295abce2SAllain Legacy 1593295abce2SAllain Legacy if (unlikely((pkt_len > avp->guest_mbuf_size) || 1594295abce2SAllain Legacy (pkt_len > avp->host_mbuf_size))) { 1595295abce2SAllain Legacy /* 1596295abce2SAllain Legacy * application should be using the scattered transmit 1597295abce2SAllain Legacy * function; send it truncated to avoid the performance 1598295abce2SAllain Legacy * hit of having to manage returning the already 1599295abce2SAllain Legacy * allocated buffer to the free list. This should not 1600295abce2SAllain Legacy * happen since the application should have set the 1601295abce2SAllain Legacy * max_rx_pkt_len based on its MTU and it should be 1602295abce2SAllain Legacy * policing its own packet sizes. 1603295abce2SAllain Legacy */ 1604295abce2SAllain Legacy txq->errors++; 1605295abce2SAllain Legacy pkt_len = RTE_MIN(avp->guest_mbuf_size, 1606295abce2SAllain Legacy avp->host_mbuf_size); 1607295abce2SAllain Legacy } 1608295abce2SAllain Legacy 1609295abce2SAllain Legacy /* copy data out of our mbuf and into the AVP buffer */ 1610295abce2SAllain Legacy rte_memcpy(pkt_data, rte_pktmbuf_mtod(m, void *), pkt_len); 1611295abce2SAllain Legacy pkt_buf->pkt_len = pkt_len; 1612295abce2SAllain Legacy pkt_buf->data_len = pkt_len; 1613295abce2SAllain Legacy pkt_buf->nb_segs = 1; 1614295abce2SAllain Legacy pkt_buf->next = NULL; 1615295abce2SAllain Legacy 1616295abce2SAllain Legacy if (m->ol_flags & PKT_TX_VLAN_PKT) { 1617295abce2SAllain Legacy pkt_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT; 1618295abce2SAllain Legacy pkt_buf->vlan_tci = m->vlan_tci; 1619295abce2SAllain Legacy } 1620295abce2SAllain Legacy 1621295abce2SAllain Legacy tx_bytes += pkt_len; 1622295abce2SAllain Legacy 1623295abce2SAllain Legacy /* free the original mbuf */ 1624295abce2SAllain Legacy rte_pktmbuf_free(m); 1625295abce2SAllain Legacy } 1626295abce2SAllain Legacy 1627295abce2SAllain Legacy txq->packets += count; 1628295abce2SAllain Legacy txq->bytes += tx_bytes; 1629295abce2SAllain Legacy 1630295abce2SAllain Legacy /* send the packets */ 1631295abce2SAllain Legacy n = avp_fifo_put(tx_q, (void **)&avp_bufs[0], count); 1632295abce2SAllain Legacy 1633295abce2SAllain Legacy return n; 1634295abce2SAllain Legacy } 1635295abce2SAllain Legacy 1636cce4367fSAllain Legacy static void 1637cce4367fSAllain Legacy avp_dev_rx_queue_release(void *rx_queue) 1638cce4367fSAllain Legacy { 1639cce4367fSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 1640cce4367fSAllain Legacy struct avp_dev *avp = rxq->avp; 1641cce4367fSAllain Legacy struct rte_eth_dev_data *data = avp->dev_data; 1642cce4367fSAllain Legacy unsigned int i; 1643cce4367fSAllain Legacy 1644cce4367fSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 1645cce4367fSAllain Legacy if (data->rx_queues[i] == rxq) 1646cce4367fSAllain Legacy data->rx_queues[i] = NULL; 1647cce4367fSAllain Legacy } 1648cce4367fSAllain Legacy } 1649cce4367fSAllain Legacy 1650cce4367fSAllain Legacy static void 1651cce4367fSAllain Legacy avp_dev_tx_queue_release(void *tx_queue) 1652cce4367fSAllain Legacy { 1653cce4367fSAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 1654cce4367fSAllain Legacy struct avp_dev *avp = txq->avp; 1655cce4367fSAllain Legacy struct rte_eth_dev_data *data = avp->dev_data; 1656cce4367fSAllain Legacy unsigned int i; 1657cce4367fSAllain Legacy 1658cce4367fSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 1659cce4367fSAllain Legacy if (data->tx_queues[i] == txq) 1660cce4367fSAllain Legacy data->tx_queues[i] = NULL; 1661cce4367fSAllain Legacy } 1662cce4367fSAllain Legacy } 1663cce4367fSAllain Legacy 1664cce4367fSAllain Legacy static int 16651a859223SAllain Legacy avp_dev_configure(struct rte_eth_dev *eth_dev) 16661a859223SAllain Legacy { 16671a859223SAllain Legacy struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev); 16681a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 16691a859223SAllain Legacy struct rte_avp_device_info *host_info; 16701a859223SAllain Legacy struct rte_avp_device_config config; 16711a859223SAllain Legacy int mask = 0; 16721a859223SAllain Legacy void *addr; 16731a859223SAllain Legacy int ret; 16741a859223SAllain Legacy 16751a859223SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr; 16761a859223SAllain Legacy host_info = (struct rte_avp_device_info *)addr; 16771a859223SAllain Legacy 16781a859223SAllain Legacy /* Setup required number of queues */ 16791a859223SAllain Legacy _avp_set_queue_counts(eth_dev); 16801a859223SAllain Legacy 16811a859223SAllain Legacy mask = (ETH_VLAN_STRIP_MASK | 16821a859223SAllain Legacy ETH_VLAN_FILTER_MASK | 16831a859223SAllain Legacy ETH_VLAN_EXTEND_MASK); 16841a859223SAllain Legacy avp_vlan_offload_set(eth_dev, mask); 16851a859223SAllain Legacy 16861a859223SAllain Legacy /* update device config */ 16871a859223SAllain Legacy memset(&config, 0, sizeof(config)); 16881a859223SAllain Legacy config.device_id = host_info->device_id; 16891a859223SAllain Legacy config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK; 16901a859223SAllain Legacy config.driver_version = AVP_DPDK_DRIVER_VERSION; 16911a859223SAllain Legacy config.features = avp->features; 16921a859223SAllain Legacy config.num_tx_queues = avp->num_tx_queues; 16931a859223SAllain Legacy config.num_rx_queues = avp->num_rx_queues; 16941a859223SAllain Legacy 16951a859223SAllain Legacy ret = avp_dev_ctrl_set_config(eth_dev, &config); 16961a859223SAllain Legacy if (ret < 0) { 16971a859223SAllain Legacy PMD_DRV_LOG(ERR, "Config request failed by host, ret=%d\n", 16981a859223SAllain Legacy ret); 16991a859223SAllain Legacy goto unlock; 17001a859223SAllain Legacy } 17011a859223SAllain Legacy 17021a859223SAllain Legacy avp->flags |= AVP_F_CONFIGURED; 17031a859223SAllain Legacy ret = 0; 17041a859223SAllain Legacy 17051a859223SAllain Legacy unlock: 17061a859223SAllain Legacy return ret; 17071a859223SAllain Legacy } 17081a859223SAllain Legacy 1709*ea37523dSAllain Legacy static int 1710*ea37523dSAllain Legacy avp_dev_start(struct rte_eth_dev *eth_dev) 1711*ea37523dSAllain Legacy { 1712*ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 1713*ea37523dSAllain Legacy int ret; 1714*ea37523dSAllain Legacy 1715*ea37523dSAllain Legacy /* disable features that we do not support */ 1716*ea37523dSAllain Legacy eth_dev->data->dev_conf.rxmode.hw_ip_checksum = 0; 1717*ea37523dSAllain Legacy eth_dev->data->dev_conf.rxmode.hw_vlan_filter = 0; 1718*ea37523dSAllain Legacy eth_dev->data->dev_conf.rxmode.hw_vlan_extend = 0; 1719*ea37523dSAllain Legacy eth_dev->data->dev_conf.rxmode.hw_strip_crc = 0; 1720*ea37523dSAllain Legacy 1721*ea37523dSAllain Legacy /* update link state */ 1722*ea37523dSAllain Legacy ret = avp_dev_ctrl_set_link_state(eth_dev, 1); 1723*ea37523dSAllain Legacy if (ret < 0) { 1724*ea37523dSAllain Legacy PMD_DRV_LOG(ERR, "Link state change failed by host, ret=%d\n", 1725*ea37523dSAllain Legacy ret); 1726*ea37523dSAllain Legacy goto unlock; 1727*ea37523dSAllain Legacy } 1728*ea37523dSAllain Legacy 1729*ea37523dSAllain Legacy /* remember current link state */ 1730*ea37523dSAllain Legacy avp->flags |= AVP_F_LINKUP; 1731*ea37523dSAllain Legacy 1732*ea37523dSAllain Legacy ret = 0; 1733*ea37523dSAllain Legacy 1734*ea37523dSAllain Legacy unlock: 1735*ea37523dSAllain Legacy return ret; 1736*ea37523dSAllain Legacy } 1737*ea37523dSAllain Legacy 1738*ea37523dSAllain Legacy static void 1739*ea37523dSAllain Legacy avp_dev_stop(struct rte_eth_dev *eth_dev) 1740*ea37523dSAllain Legacy { 1741*ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 1742*ea37523dSAllain Legacy int ret; 1743*ea37523dSAllain Legacy 1744*ea37523dSAllain Legacy avp->flags &= ~AVP_F_LINKUP; 1745*ea37523dSAllain Legacy 1746*ea37523dSAllain Legacy /* update link state */ 1747*ea37523dSAllain Legacy ret = avp_dev_ctrl_set_link_state(eth_dev, 0); 1748*ea37523dSAllain Legacy if (ret < 0) { 1749*ea37523dSAllain Legacy PMD_DRV_LOG(ERR, "Link state change failed by host, ret=%d\n", 1750*ea37523dSAllain Legacy ret); 1751*ea37523dSAllain Legacy } 1752*ea37523dSAllain Legacy } 1753*ea37523dSAllain Legacy 1754*ea37523dSAllain Legacy static void 1755*ea37523dSAllain Legacy avp_dev_close(struct rte_eth_dev *eth_dev) 1756*ea37523dSAllain Legacy { 1757*ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 1758*ea37523dSAllain Legacy int ret; 1759*ea37523dSAllain Legacy 1760*ea37523dSAllain Legacy /* remember current link state */ 1761*ea37523dSAllain Legacy avp->flags &= ~AVP_F_LINKUP; 1762*ea37523dSAllain Legacy avp->flags &= ~AVP_F_CONFIGURED; 1763*ea37523dSAllain Legacy 1764*ea37523dSAllain Legacy /* update device state */ 1765*ea37523dSAllain Legacy ret = avp_dev_ctrl_shutdown(eth_dev); 1766*ea37523dSAllain Legacy if (ret < 0) { 1767*ea37523dSAllain Legacy PMD_DRV_LOG(ERR, "Device shutdown failed by host, ret=%d\n", 1768*ea37523dSAllain Legacy ret); 1769*ea37523dSAllain Legacy /* continue */ 1770*ea37523dSAllain Legacy } 1771*ea37523dSAllain Legacy } 17721a859223SAllain Legacy 17731a859223SAllain Legacy static int 17741a859223SAllain Legacy avp_dev_link_update(struct rte_eth_dev *eth_dev, 17751a859223SAllain Legacy __rte_unused int wait_to_complete) 17761a859223SAllain Legacy { 17771a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 17781a859223SAllain Legacy struct rte_eth_link *link = ð_dev->data->dev_link; 17791a859223SAllain Legacy 17801a859223SAllain Legacy link->link_speed = ETH_SPEED_NUM_10G; 17811a859223SAllain Legacy link->link_duplex = ETH_LINK_FULL_DUPLEX; 17821a859223SAllain Legacy link->link_status = !!(avp->flags & AVP_F_LINKUP); 17831a859223SAllain Legacy 17841a859223SAllain Legacy return -1; 17851a859223SAllain Legacy } 17861a859223SAllain Legacy 17878129545eSAllain Legacy static void 17888129545eSAllain Legacy avp_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 17898129545eSAllain Legacy { 17908129545eSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 17918129545eSAllain Legacy 17928129545eSAllain Legacy if ((avp->flags & AVP_F_PROMISC) == 0) { 17938129545eSAllain Legacy avp->flags |= AVP_F_PROMISC; 17948129545eSAllain Legacy PMD_DRV_LOG(DEBUG, "Promiscuous mode enabled on %u\n", 17958129545eSAllain Legacy eth_dev->data->port_id); 17968129545eSAllain Legacy } 17978129545eSAllain Legacy } 17988129545eSAllain Legacy 17998129545eSAllain Legacy static void 18008129545eSAllain Legacy avp_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 18018129545eSAllain Legacy { 18028129545eSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 18038129545eSAllain Legacy 18048129545eSAllain Legacy if ((avp->flags & AVP_F_PROMISC) != 0) { 18058129545eSAllain Legacy avp->flags &= ~AVP_F_PROMISC; 18068129545eSAllain Legacy PMD_DRV_LOG(DEBUG, "Promiscuous mode disabled on %u\n", 18078129545eSAllain Legacy eth_dev->data->port_id); 18088129545eSAllain Legacy } 18098129545eSAllain Legacy } 18101a859223SAllain Legacy 18111a859223SAllain Legacy static void 18121a859223SAllain Legacy avp_dev_info_get(struct rte_eth_dev *eth_dev, 18131a859223SAllain Legacy struct rte_eth_dev_info *dev_info) 18141a859223SAllain Legacy { 18151a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 18161a859223SAllain Legacy 18171a859223SAllain Legacy dev_info->driver_name = "rte_avp_pmd"; 18181a859223SAllain Legacy dev_info->pci_dev = RTE_DEV_TO_PCI(eth_dev->device); 18191a859223SAllain Legacy dev_info->max_rx_queues = avp->max_rx_queues; 18201a859223SAllain Legacy dev_info->max_tx_queues = avp->max_tx_queues; 18211a859223SAllain Legacy dev_info->min_rx_bufsize = AVP_MIN_RX_BUFSIZE; 18221a859223SAllain Legacy dev_info->max_rx_pktlen = avp->max_rx_pkt_len; 18231a859223SAllain Legacy dev_info->max_mac_addrs = AVP_MAX_MAC_ADDRS; 18241a859223SAllain Legacy if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) { 18251a859223SAllain Legacy dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP; 18261a859223SAllain Legacy dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT; 18271a859223SAllain Legacy } 18281a859223SAllain Legacy } 18291a859223SAllain Legacy 18301a859223SAllain Legacy static void 18311a859223SAllain Legacy avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) 18321a859223SAllain Legacy { 18331a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 18341a859223SAllain Legacy 18351a859223SAllain Legacy if (mask & ETH_VLAN_STRIP_MASK) { 18361a859223SAllain Legacy if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) { 18371a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip) 18381a859223SAllain Legacy avp->features |= RTE_AVP_FEATURE_VLAN_OFFLOAD; 18391a859223SAllain Legacy else 18401a859223SAllain Legacy avp->features &= ~RTE_AVP_FEATURE_VLAN_OFFLOAD; 18411a859223SAllain Legacy } else { 18421a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN strip offload not supported\n"); 18431a859223SAllain Legacy } 18441a859223SAllain Legacy } 18451a859223SAllain Legacy 18461a859223SAllain Legacy if (mask & ETH_VLAN_FILTER_MASK) { 18471a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_filter) 18481a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN filter offload not supported\n"); 18491a859223SAllain Legacy } 18501a859223SAllain Legacy 18511a859223SAllain Legacy if (mask & ETH_VLAN_EXTEND_MASK) { 18521a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend) 18531a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n"); 18541a859223SAllain Legacy } 18551a859223SAllain Legacy } 18561a859223SAllain Legacy 18575a5abe2dSAllain Legacy static void 18585a5abe2dSAllain Legacy avp_dev_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats) 18595a5abe2dSAllain Legacy { 18605a5abe2dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 18615a5abe2dSAllain Legacy unsigned int i; 18625a5abe2dSAllain Legacy 18635a5abe2dSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 18645a5abe2dSAllain Legacy struct avp_queue *rxq = avp->dev_data->rx_queues[i]; 18655a5abe2dSAllain Legacy 18665a5abe2dSAllain Legacy if (rxq) { 18675a5abe2dSAllain Legacy stats->ipackets += rxq->packets; 18685a5abe2dSAllain Legacy stats->ibytes += rxq->bytes; 18695a5abe2dSAllain Legacy stats->ierrors += rxq->errors; 18705a5abe2dSAllain Legacy 18715a5abe2dSAllain Legacy stats->q_ipackets[i] += rxq->packets; 18725a5abe2dSAllain Legacy stats->q_ibytes[i] += rxq->bytes; 18735a5abe2dSAllain Legacy stats->q_errors[i] += rxq->errors; 18745a5abe2dSAllain Legacy } 18755a5abe2dSAllain Legacy } 18765a5abe2dSAllain Legacy 18775a5abe2dSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 18785a5abe2dSAllain Legacy struct avp_queue *txq = avp->dev_data->tx_queues[i]; 18795a5abe2dSAllain Legacy 18805a5abe2dSAllain Legacy if (txq) { 18815a5abe2dSAllain Legacy stats->opackets += txq->packets; 18825a5abe2dSAllain Legacy stats->obytes += txq->bytes; 18835a5abe2dSAllain Legacy stats->oerrors += txq->errors; 18845a5abe2dSAllain Legacy 18855a5abe2dSAllain Legacy stats->q_opackets[i] += txq->packets; 18865a5abe2dSAllain Legacy stats->q_obytes[i] += txq->bytes; 18875a5abe2dSAllain Legacy stats->q_errors[i] += txq->errors; 18885a5abe2dSAllain Legacy } 18895a5abe2dSAllain Legacy } 18905a5abe2dSAllain Legacy } 18915a5abe2dSAllain Legacy 18925a5abe2dSAllain Legacy static void 18935a5abe2dSAllain Legacy avp_dev_stats_reset(struct rte_eth_dev *eth_dev) 18945a5abe2dSAllain Legacy { 18955a5abe2dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 18965a5abe2dSAllain Legacy unsigned int i; 18975a5abe2dSAllain Legacy 18985a5abe2dSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 18995a5abe2dSAllain Legacy struct avp_queue *rxq = avp->dev_data->rx_queues[i]; 19005a5abe2dSAllain Legacy 19015a5abe2dSAllain Legacy if (rxq) { 19025a5abe2dSAllain Legacy rxq->bytes = 0; 19035a5abe2dSAllain Legacy rxq->packets = 0; 19045a5abe2dSAllain Legacy rxq->errors = 0; 19055a5abe2dSAllain Legacy } 19065a5abe2dSAllain Legacy } 19075a5abe2dSAllain Legacy 19085a5abe2dSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 19095a5abe2dSAllain Legacy struct avp_queue *txq = avp->dev_data->tx_queues[i]; 19105a5abe2dSAllain Legacy 19115a5abe2dSAllain Legacy if (txq) { 19125a5abe2dSAllain Legacy txq->bytes = 0; 19135a5abe2dSAllain Legacy txq->packets = 0; 19145a5abe2dSAllain Legacy txq->errors = 0; 19155a5abe2dSAllain Legacy } 19165a5abe2dSAllain Legacy } 19175a5abe2dSAllain Legacy } 19185a5abe2dSAllain Legacy 1919908072e9SAllain Legacy RTE_PMD_REGISTER_PCI(net_avp, rte_avp_pmd.pci_drv); 1920908072e9SAllain Legacy RTE_PMD_REGISTER_PCI_TABLE(net_avp, pci_id_avp_map); 1921