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 39ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 40fdf91e0fSJan Blunck #include <rte_ethdev_pci.h> 41908072e9SAllain Legacy #include <rte_memcpy.h> 42908072e9SAllain Legacy #include <rte_string_fns.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> 47c752998bSGaetan Rivet #include <rte_bus_pci.h> 48908072e9SAllain Legacy #include <rte_ether.h> 49908072e9SAllain Legacy #include <rte_common.h> 50908072e9SAllain Legacy #include <rte_cycles.h> 5182e140b8SAllain Legacy #include <rte_spinlock.h> 52908072e9SAllain Legacy #include <rte_byteorder.h> 53908072e9SAllain Legacy #include <rte_dev.h> 54908072e9SAllain Legacy #include <rte_memory.h> 55908072e9SAllain Legacy #include <rte_eal.h> 56c0ad5842SAllain Legacy #include <rte_io.h> 57908072e9SAllain Legacy 58908072e9SAllain Legacy #include "rte_avp_common.h" 59908072e9SAllain Legacy #include "rte_avp_fifo.h" 60908072e9SAllain Legacy 61908072e9SAllain Legacy #include "avp_logs.h" 62908072e9SAllain Legacy 63e6b790c0SStephen Hemminger int avp_logtype_driver; 64908072e9SAllain Legacy 6582e140b8SAllain Legacy static int avp_dev_create(struct rte_pci_device *pci_dev, 6682e140b8SAllain Legacy struct rte_eth_dev *eth_dev); 67908072e9SAllain Legacy 681a859223SAllain Legacy static int avp_dev_configure(struct rte_eth_dev *dev); 69ea37523dSAllain Legacy static int avp_dev_start(struct rte_eth_dev *dev); 70ea37523dSAllain Legacy static void avp_dev_stop(struct rte_eth_dev *dev); 71ea37523dSAllain Legacy static void avp_dev_close(struct rte_eth_dev *dev); 721a859223SAllain Legacy static void avp_dev_info_get(struct rte_eth_dev *dev, 731a859223SAllain Legacy struct rte_eth_dev_info *dev_info); 74289ba0c0SDavid Harton static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask); 75dd2c630aSFerruh Yigit static int avp_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); 768129545eSAllain Legacy static void avp_dev_promiscuous_enable(struct rte_eth_dev *dev); 778129545eSAllain Legacy static void avp_dev_promiscuous_disable(struct rte_eth_dev *dev); 788129545eSAllain Legacy 79cce4367fSAllain Legacy static int avp_dev_rx_queue_setup(struct rte_eth_dev *dev, 80cce4367fSAllain Legacy uint16_t rx_queue_id, 81cce4367fSAllain Legacy uint16_t nb_rx_desc, 82cce4367fSAllain Legacy unsigned int socket_id, 83cce4367fSAllain Legacy const struct rte_eth_rxconf *rx_conf, 84cce4367fSAllain Legacy struct rte_mempool *pool); 851a859223SAllain Legacy 86cce4367fSAllain Legacy static int avp_dev_tx_queue_setup(struct rte_eth_dev *dev, 87cce4367fSAllain Legacy uint16_t tx_queue_id, 88cce4367fSAllain Legacy uint16_t nb_tx_desc, 89cce4367fSAllain Legacy unsigned int socket_id, 90cce4367fSAllain Legacy const struct rte_eth_txconf *tx_conf); 91cce4367fSAllain Legacy 9250db69fdSAllain Legacy static uint16_t avp_recv_scattered_pkts(void *rx_queue, 9350db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 9450db69fdSAllain Legacy uint16_t nb_pkts); 9550db69fdSAllain Legacy 9650db69fdSAllain Legacy static uint16_t avp_recv_pkts(void *rx_queue, 9750db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 9850db69fdSAllain Legacy uint16_t nb_pkts); 99295abce2SAllain Legacy 100295abce2SAllain Legacy static uint16_t avp_xmit_scattered_pkts(void *tx_queue, 101295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 102295abce2SAllain Legacy uint16_t nb_pkts); 103295abce2SAllain Legacy 104295abce2SAllain Legacy static uint16_t avp_xmit_pkts(void *tx_queue, 105295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 106295abce2SAllain Legacy uint16_t nb_pkts); 107295abce2SAllain Legacy 108cce4367fSAllain Legacy static void avp_dev_rx_queue_release(void *rxq); 109cce4367fSAllain Legacy static void avp_dev_tx_queue_release(void *txq); 110295abce2SAllain Legacy 111d5b0924bSMatan Azrad static int avp_dev_stats_get(struct rte_eth_dev *dev, 1125a5abe2dSAllain Legacy struct rte_eth_stats *stats); 1135a5abe2dSAllain Legacy static void avp_dev_stats_reset(struct rte_eth_dev *dev); 1145a5abe2dSAllain Legacy 115295abce2SAllain Legacy 11650db69fdSAllain Legacy #define AVP_MAX_RX_BURST 64 117295abce2SAllain Legacy #define AVP_MAX_TX_BURST 64 118908072e9SAllain Legacy #define AVP_MAX_MAC_ADDRS 1 119908072e9SAllain Legacy #define AVP_MIN_RX_BUFSIZE ETHER_MIN_LEN 120908072e9SAllain Legacy 121908072e9SAllain Legacy 122908072e9SAllain Legacy /* 123908072e9SAllain Legacy * Defines the number of microseconds to wait before checking the response 124908072e9SAllain Legacy * queue for completion. 125908072e9SAllain Legacy */ 126908072e9SAllain Legacy #define AVP_REQUEST_DELAY_USECS (5000) 127908072e9SAllain Legacy 128908072e9SAllain Legacy /* 129908072e9SAllain Legacy * Defines the number times to check the response queue for completion before 130908072e9SAllain Legacy * declaring a timeout. 131908072e9SAllain Legacy */ 132908072e9SAllain Legacy #define AVP_MAX_REQUEST_RETRY (100) 133908072e9SAllain Legacy 134908072e9SAllain Legacy /* Defines the current PCI driver version number */ 135908072e9SAllain Legacy #define AVP_DPDK_DRIVER_VERSION RTE_AVP_CURRENT_GUEST_VERSION 136908072e9SAllain Legacy 137908072e9SAllain Legacy /* 138908072e9SAllain Legacy * The set of PCI devices this driver supports 139908072e9SAllain Legacy */ 140908072e9SAllain Legacy static const struct rte_pci_id pci_id_avp_map[] = { 141908072e9SAllain Legacy { .vendor_id = RTE_AVP_PCI_VENDOR_ID, 142908072e9SAllain Legacy .device_id = RTE_AVP_PCI_DEVICE_ID, 143908072e9SAllain Legacy .subsystem_vendor_id = RTE_AVP_PCI_SUB_VENDOR_ID, 144908072e9SAllain Legacy .subsystem_device_id = RTE_AVP_PCI_SUB_DEVICE_ID, 145908072e9SAllain Legacy .class_id = RTE_CLASS_ANY_ID, 146908072e9SAllain Legacy }, 147908072e9SAllain Legacy 148908072e9SAllain Legacy { .vendor_id = 0, /* sentinel */ 149908072e9SAllain Legacy }, 150908072e9SAllain Legacy }; 151908072e9SAllain Legacy 1521a859223SAllain Legacy /* 1531a859223SAllain Legacy * dev_ops for avp, bare necessities for basic operation 1541a859223SAllain Legacy */ 1551a859223SAllain Legacy static const struct eth_dev_ops avp_eth_dev_ops = { 1561a859223SAllain Legacy .dev_configure = avp_dev_configure, 157ea37523dSAllain Legacy .dev_start = avp_dev_start, 158ea37523dSAllain Legacy .dev_stop = avp_dev_stop, 159ea37523dSAllain Legacy .dev_close = avp_dev_close, 1601a859223SAllain Legacy .dev_infos_get = avp_dev_info_get, 1611a859223SAllain Legacy .vlan_offload_set = avp_vlan_offload_set, 1625a5abe2dSAllain Legacy .stats_get = avp_dev_stats_get, 1635a5abe2dSAllain Legacy .stats_reset = avp_dev_stats_reset, 1641a859223SAllain Legacy .link_update = avp_dev_link_update, 1658129545eSAllain Legacy .promiscuous_enable = avp_dev_promiscuous_enable, 1668129545eSAllain Legacy .promiscuous_disable = avp_dev_promiscuous_disable, 167cce4367fSAllain Legacy .rx_queue_setup = avp_dev_rx_queue_setup, 168cce4367fSAllain Legacy .rx_queue_release = avp_dev_rx_queue_release, 169cce4367fSAllain Legacy .tx_queue_setup = avp_dev_tx_queue_setup, 170cce4367fSAllain Legacy .tx_queue_release = avp_dev_tx_queue_release, 1711a859223SAllain Legacy }; 172908072e9SAllain Legacy 173c0ad5842SAllain Legacy /**@{ AVP device flags */ 174c0ad5842SAllain Legacy #define AVP_F_PROMISC (1 << 1) 175c0ad5842SAllain Legacy #define AVP_F_CONFIGURED (1 << 2) 176c0ad5842SAllain Legacy #define AVP_F_LINKUP (1 << 3) 17782e140b8SAllain Legacy #define AVP_F_DETACHED (1 << 4) 178c0ad5842SAllain Legacy /**@} */ 179c0ad5842SAllain Legacy 180c0ad5842SAllain Legacy /* Ethernet device validation marker */ 181c0ad5842SAllain Legacy #define AVP_ETHDEV_MAGIC 0x92972862 182c0ad5842SAllain Legacy 183908072e9SAllain Legacy /* 184908072e9SAllain Legacy * Defines the AVP device attributes which are attached to an RTE ethernet 185908072e9SAllain Legacy * device 186908072e9SAllain Legacy */ 187908072e9SAllain Legacy struct avp_dev { 188908072e9SAllain Legacy uint32_t magic; /**< Memory validation marker */ 189908072e9SAllain Legacy uint64_t device_id; /**< Unique system identifier */ 190908072e9SAllain Legacy struct ether_addr ethaddr; /**< Host specified MAC address */ 191908072e9SAllain Legacy struct rte_eth_dev_data *dev_data; 192908072e9SAllain Legacy /**< Back pointer to ethernet device data */ 193908072e9SAllain Legacy volatile uint32_t flags; /**< Device operational flags */ 194f8244c63SZhiyong Yang uint16_t port_id; /**< Ethernet port identifier */ 195908072e9SAllain Legacy struct rte_mempool *pool; /**< pkt mbuf mempool */ 196908072e9SAllain Legacy unsigned int guest_mbuf_size; /**< local pool mbuf size */ 197908072e9SAllain Legacy unsigned int host_mbuf_size; /**< host mbuf size */ 198908072e9SAllain Legacy unsigned int max_rx_pkt_len; /**< maximum receive unit */ 199908072e9SAllain Legacy uint32_t host_features; /**< Supported feature bitmap */ 200908072e9SAllain Legacy uint32_t features; /**< Enabled feature bitmap */ 201908072e9SAllain Legacy unsigned int num_tx_queues; /**< Negotiated number of transmit queues */ 202908072e9SAllain Legacy unsigned int max_tx_queues; /**< Maximum number of transmit queues */ 203908072e9SAllain Legacy unsigned int num_rx_queues; /**< Negotiated number of receive queues */ 204908072e9SAllain Legacy unsigned int max_rx_queues; /**< Maximum number of receive queues */ 205908072e9SAllain Legacy 206908072e9SAllain Legacy struct rte_avp_fifo *tx_q[RTE_AVP_MAX_QUEUES]; /**< TX queue */ 207908072e9SAllain Legacy struct rte_avp_fifo *rx_q[RTE_AVP_MAX_QUEUES]; /**< RX queue */ 208908072e9SAllain Legacy struct rte_avp_fifo *alloc_q[RTE_AVP_MAX_QUEUES]; 209908072e9SAllain Legacy /**< Allocated mbufs queue */ 210908072e9SAllain Legacy struct rte_avp_fifo *free_q[RTE_AVP_MAX_QUEUES]; 211908072e9SAllain Legacy /**< To be freed mbufs queue */ 212908072e9SAllain Legacy 21382e140b8SAllain Legacy /* mutual exclusion over the 'flag' and 'resp_q/req_q' fields */ 21482e140b8SAllain Legacy rte_spinlock_t lock; 21582e140b8SAllain Legacy 216908072e9SAllain Legacy /* For request & response */ 217908072e9SAllain Legacy struct rte_avp_fifo *req_q; /**< Request queue */ 218908072e9SAllain Legacy struct rte_avp_fifo *resp_q; /**< Response queue */ 219908072e9SAllain Legacy void *host_sync_addr; /**< (host) Req/Resp Mem address */ 220908072e9SAllain Legacy void *sync_addr; /**< Req/Resp Mem address */ 221908072e9SAllain Legacy void *host_mbuf_addr; /**< (host) MBUF pool start address */ 222908072e9SAllain Legacy void *mbuf_addr; /**< MBUF pool start address */ 223908072e9SAllain Legacy } __rte_cache_aligned; 224908072e9SAllain Legacy 225908072e9SAllain Legacy /* RTE ethernet private data */ 226908072e9SAllain Legacy struct avp_adapter { 227908072e9SAllain Legacy struct avp_dev avp; 228908072e9SAllain Legacy } __rte_cache_aligned; 229908072e9SAllain Legacy 230c0ad5842SAllain Legacy 231c0ad5842SAllain Legacy /* 32-bit MMIO register write */ 232c0ad5842SAllain Legacy #define AVP_WRITE32(_value, _addr) rte_write32_relaxed((_value), (_addr)) 233c0ad5842SAllain Legacy 234c0ad5842SAllain Legacy /* 32-bit MMIO register read */ 235c0ad5842SAllain Legacy #define AVP_READ32(_addr) rte_read32_relaxed((_addr)) 236c0ad5842SAllain Legacy 237908072e9SAllain Legacy /* Macro to cast the ethernet device private data to a AVP object */ 238908072e9SAllain Legacy #define AVP_DEV_PRIVATE_TO_HW(adapter) \ 239908072e9SAllain Legacy (&((struct avp_adapter *)adapter)->avp) 240908072e9SAllain Legacy 241908072e9SAllain Legacy /* 242c0ad5842SAllain Legacy * Defines the structure of a AVP device queue for the purpose of handling the 243c0ad5842SAllain Legacy * receive and transmit burst callback functions 244c0ad5842SAllain Legacy */ 245c0ad5842SAllain Legacy struct avp_queue { 246c0ad5842SAllain Legacy struct rte_eth_dev_data *dev_data; 247c0ad5842SAllain Legacy /**< Backpointer to ethernet device data */ 248c0ad5842SAllain Legacy struct avp_dev *avp; /**< Backpointer to AVP device */ 249c0ad5842SAllain Legacy uint16_t queue_id; 250c0ad5842SAllain Legacy /**< Queue identifier used for indexing current queue */ 251c0ad5842SAllain Legacy uint16_t queue_base; 252c0ad5842SAllain Legacy /**< Base queue identifier for queue servicing */ 253c0ad5842SAllain Legacy uint16_t queue_limit; 254c0ad5842SAllain Legacy /**< Maximum queue identifier for queue servicing */ 255c0ad5842SAllain Legacy 256c0ad5842SAllain Legacy uint64_t packets; 257c0ad5842SAllain Legacy uint64_t bytes; 258c0ad5842SAllain Legacy uint64_t errors; 259c0ad5842SAllain Legacy }; 260c0ad5842SAllain Legacy 2611a859223SAllain Legacy /* send a request and wait for a response 2621a859223SAllain Legacy * 2631a859223SAllain Legacy * @warning must be called while holding the avp->lock spinlock. 2641a859223SAllain Legacy */ 2651a859223SAllain Legacy static int 2661a859223SAllain Legacy avp_dev_process_request(struct avp_dev *avp, struct rte_avp_request *request) 2671a859223SAllain Legacy { 2681a859223SAllain Legacy unsigned int retry = AVP_MAX_REQUEST_RETRY; 2691a859223SAllain Legacy void *resp_addr = NULL; 2701a859223SAllain Legacy unsigned int count; 2711a859223SAllain Legacy int ret; 2721a859223SAllain Legacy 2731a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Sending request %u to host\n", request->req_id); 2741a859223SAllain Legacy 2751a859223SAllain Legacy request->result = -ENOTSUP; 2761a859223SAllain Legacy 2771a859223SAllain Legacy /* Discard any stale responses before starting a new request */ 2781a859223SAllain Legacy while (avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1)) 2791a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Discarding stale response\n"); 2801a859223SAllain Legacy 2811a859223SAllain Legacy rte_memcpy(avp->sync_addr, request, sizeof(*request)); 2821a859223SAllain Legacy count = avp_fifo_put(avp->req_q, &avp->host_sync_addr, 1); 2831a859223SAllain Legacy if (count < 1) { 2841a859223SAllain Legacy PMD_DRV_LOG(ERR, "Cannot send request %u to host\n", 2851a859223SAllain Legacy request->req_id); 2861a859223SAllain Legacy ret = -EBUSY; 2871a859223SAllain Legacy goto done; 2881a859223SAllain Legacy } 2891a859223SAllain Legacy 2901a859223SAllain Legacy while (retry--) { 2911a859223SAllain Legacy /* wait for a response */ 2921a859223SAllain Legacy usleep(AVP_REQUEST_DELAY_USECS); 2931a859223SAllain Legacy 2941a859223SAllain Legacy count = avp_fifo_count(avp->resp_q); 2951a859223SAllain Legacy if (count >= 1) { 2961a859223SAllain Legacy /* response received */ 2971a859223SAllain Legacy break; 2981a859223SAllain Legacy } 2991a859223SAllain Legacy 3001a859223SAllain Legacy if ((count < 1) && (retry == 0)) { 3011a859223SAllain Legacy PMD_DRV_LOG(ERR, "Timeout while waiting for a response for %u\n", 3021a859223SAllain Legacy request->req_id); 3031a859223SAllain Legacy ret = -ETIME; 3041a859223SAllain Legacy goto done; 3051a859223SAllain Legacy } 3061a859223SAllain Legacy } 3071a859223SAllain Legacy 3081a859223SAllain Legacy /* retrieve the response */ 3091a859223SAllain Legacy count = avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1); 3101a859223SAllain Legacy if ((count != 1) || (resp_addr != avp->host_sync_addr)) { 3111a859223SAllain Legacy PMD_DRV_LOG(ERR, "Invalid response from host, count=%u resp=%p host_sync_addr=%p\n", 3121a859223SAllain Legacy count, resp_addr, avp->host_sync_addr); 3131a859223SAllain Legacy ret = -ENODATA; 3141a859223SAllain Legacy goto done; 3151a859223SAllain Legacy } 3161a859223SAllain Legacy 3171a859223SAllain Legacy /* copy to user buffer */ 3181a859223SAllain Legacy rte_memcpy(request, avp->sync_addr, sizeof(*request)); 3191a859223SAllain Legacy ret = 0; 3201a859223SAllain Legacy 3211a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Result %d received for request %u\n", 3221a859223SAllain Legacy request->result, request->req_id); 3231a859223SAllain Legacy 3241a859223SAllain Legacy done: 3251a859223SAllain Legacy return ret; 3261a859223SAllain Legacy } 3271a859223SAllain Legacy 3281a859223SAllain Legacy static int 329ea37523dSAllain Legacy avp_dev_ctrl_set_link_state(struct rte_eth_dev *eth_dev, unsigned int state) 330ea37523dSAllain Legacy { 331ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 332ea37523dSAllain Legacy struct rte_avp_request request; 333ea37523dSAllain Legacy int ret; 334ea37523dSAllain Legacy 335ea37523dSAllain Legacy /* setup a link state change request */ 336ea37523dSAllain Legacy memset(&request, 0, sizeof(request)); 337ea37523dSAllain Legacy request.req_id = RTE_AVP_REQ_CFG_NETWORK_IF; 338ea37523dSAllain Legacy request.if_up = state; 339ea37523dSAllain Legacy 340ea37523dSAllain Legacy ret = avp_dev_process_request(avp, &request); 341ea37523dSAllain Legacy 342ea37523dSAllain Legacy return ret == 0 ? request.result : ret; 343ea37523dSAllain Legacy } 344ea37523dSAllain Legacy 345ea37523dSAllain Legacy static int 3461a859223SAllain Legacy avp_dev_ctrl_set_config(struct rte_eth_dev *eth_dev, 3471a859223SAllain Legacy struct rte_avp_device_config *config) 3481a859223SAllain Legacy { 3491a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 3501a859223SAllain Legacy struct rte_avp_request request; 3511a859223SAllain Legacy int ret; 3521a859223SAllain Legacy 3531a859223SAllain Legacy /* setup a configure request */ 3541a859223SAllain Legacy memset(&request, 0, sizeof(request)); 3551a859223SAllain Legacy request.req_id = RTE_AVP_REQ_CFG_DEVICE; 3561a859223SAllain Legacy memcpy(&request.config, config, sizeof(request.config)); 3571a859223SAllain Legacy 3581a859223SAllain Legacy ret = avp_dev_process_request(avp, &request); 3591a859223SAllain Legacy 3601a859223SAllain Legacy return ret == 0 ? request.result : ret; 3611a859223SAllain Legacy } 3621a859223SAllain Legacy 363ea37523dSAllain Legacy static int 364ea37523dSAllain Legacy avp_dev_ctrl_shutdown(struct rte_eth_dev *eth_dev) 365ea37523dSAllain Legacy { 366ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 367ea37523dSAllain Legacy struct rte_avp_request request; 368ea37523dSAllain Legacy int ret; 369ea37523dSAllain Legacy 370ea37523dSAllain Legacy /* setup a shutdown request */ 371ea37523dSAllain Legacy memset(&request, 0, sizeof(request)); 372ea37523dSAllain Legacy request.req_id = RTE_AVP_REQ_SHUTDOWN_DEVICE; 373ea37523dSAllain Legacy 374ea37523dSAllain Legacy ret = avp_dev_process_request(avp, &request); 375ea37523dSAllain Legacy 376ea37523dSAllain Legacy return ret == 0 ? request.result : ret; 377ea37523dSAllain Legacy } 378ea37523dSAllain Legacy 37950db69fdSAllain Legacy /* translate from host mbuf virtual address to guest virtual address */ 38050db69fdSAllain Legacy static inline void * 38150db69fdSAllain Legacy avp_dev_translate_buffer(struct avp_dev *avp, void *host_mbuf_address) 38250db69fdSAllain Legacy { 38350db69fdSAllain Legacy return RTE_PTR_ADD(RTE_PTR_SUB(host_mbuf_address, 38450db69fdSAllain Legacy (uintptr_t)avp->host_mbuf_addr), 38550db69fdSAllain Legacy (uintptr_t)avp->mbuf_addr); 38650db69fdSAllain Legacy } 38750db69fdSAllain Legacy 388c0ad5842SAllain Legacy /* translate from host physical address to guest virtual address */ 389c0ad5842SAllain Legacy static void * 390c0ad5842SAllain Legacy avp_dev_translate_address(struct rte_eth_dev *eth_dev, 391df6e0a06SSantosh Shukla rte_iova_t host_phys_addr) 392c0ad5842SAllain Legacy { 393c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 394c0ad5842SAllain Legacy struct rte_mem_resource *resource; 395c0ad5842SAllain Legacy struct rte_avp_memmap_info *info; 396c0ad5842SAllain Legacy struct rte_avp_memmap *map; 397c0ad5842SAllain Legacy off_t offset; 398c0ad5842SAllain Legacy void *addr; 399c0ad5842SAllain Legacy unsigned int i; 400c0ad5842SAllain Legacy 401c0ad5842SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_MEMORY_BAR].addr; 402c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[RTE_AVP_PCI_MEMMAP_BAR]; 403c0ad5842SAllain Legacy info = (struct rte_avp_memmap_info *)resource->addr; 404c0ad5842SAllain Legacy 405c0ad5842SAllain Legacy offset = 0; 406c0ad5842SAllain Legacy for (i = 0; i < info->nb_maps; i++) { 407c0ad5842SAllain Legacy /* search all segments looking for a matching address */ 408c0ad5842SAllain Legacy map = &info->maps[i]; 409c0ad5842SAllain Legacy 410c0ad5842SAllain Legacy if ((host_phys_addr >= map->phys_addr) && 411c0ad5842SAllain Legacy (host_phys_addr < (map->phys_addr + map->length))) { 412c0ad5842SAllain Legacy /* address is within this segment */ 413c0ad5842SAllain Legacy offset += (host_phys_addr - map->phys_addr); 414c0ad5842SAllain Legacy addr = RTE_PTR_ADD(addr, offset); 415c0ad5842SAllain Legacy 416c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "Translating host physical 0x%" PRIx64 " to guest virtual 0x%p\n", 417c0ad5842SAllain Legacy host_phys_addr, addr); 418c0ad5842SAllain Legacy 419c0ad5842SAllain Legacy return addr; 420c0ad5842SAllain Legacy } 421c0ad5842SAllain Legacy offset += map->length; 422c0ad5842SAllain Legacy } 423c0ad5842SAllain Legacy 424c0ad5842SAllain Legacy return NULL; 425c0ad5842SAllain Legacy } 426c0ad5842SAllain Legacy 427c0ad5842SAllain Legacy /* verify that the incoming device version is compatible with our version */ 428c0ad5842SAllain Legacy static int 429c0ad5842SAllain Legacy avp_dev_version_check(uint32_t version) 430c0ad5842SAllain Legacy { 431c0ad5842SAllain Legacy uint32_t driver = RTE_AVP_STRIP_MINOR_VERSION(AVP_DPDK_DRIVER_VERSION); 432c0ad5842SAllain Legacy uint32_t device = RTE_AVP_STRIP_MINOR_VERSION(version); 433c0ad5842SAllain Legacy 434c0ad5842SAllain Legacy if (device <= driver) { 435c0ad5842SAllain Legacy /* the host driver version is less than or equal to ours */ 436c0ad5842SAllain Legacy return 0; 437c0ad5842SAllain Legacy } 438c0ad5842SAllain Legacy 439c0ad5842SAllain Legacy return 1; 440c0ad5842SAllain Legacy } 441c0ad5842SAllain Legacy 442c0ad5842SAllain Legacy /* verify that memory regions have expected version and validation markers */ 443c0ad5842SAllain Legacy static int 444c0ad5842SAllain Legacy avp_dev_check_regions(struct rte_eth_dev *eth_dev) 445c0ad5842SAllain Legacy { 446c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 447c0ad5842SAllain Legacy struct rte_avp_memmap_info *memmap; 448c0ad5842SAllain Legacy struct rte_avp_device_info *info; 449c0ad5842SAllain Legacy struct rte_mem_resource *resource; 450c0ad5842SAllain Legacy unsigned int i; 451c0ad5842SAllain Legacy 452c0ad5842SAllain Legacy /* Dump resource info for debug */ 453c0ad5842SAllain Legacy for (i = 0; i < PCI_MAX_RESOURCE; i++) { 454c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[i]; 455c0ad5842SAllain Legacy if ((resource->phys_addr == 0) || (resource->len == 0)) 456c0ad5842SAllain Legacy continue; 457c0ad5842SAllain Legacy 458c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "resource[%u]: phys=0x%" PRIx64 " len=%" PRIu64 " addr=%p\n", 459c0ad5842SAllain Legacy i, resource->phys_addr, 460c0ad5842SAllain Legacy resource->len, resource->addr); 461c0ad5842SAllain Legacy 462c0ad5842SAllain Legacy switch (i) { 463c0ad5842SAllain Legacy case RTE_AVP_PCI_MEMMAP_BAR: 464c0ad5842SAllain Legacy memmap = (struct rte_avp_memmap_info *)resource->addr; 465c0ad5842SAllain Legacy if ((memmap->magic != RTE_AVP_MEMMAP_MAGIC) || 466c0ad5842SAllain Legacy (memmap->version != RTE_AVP_MEMMAP_VERSION)) { 467c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid memmap magic 0x%08x and version %u\n", 468c0ad5842SAllain Legacy memmap->magic, memmap->version); 469c0ad5842SAllain Legacy return -EINVAL; 470c0ad5842SAllain Legacy } 471c0ad5842SAllain Legacy break; 472c0ad5842SAllain Legacy 473c0ad5842SAllain Legacy case RTE_AVP_PCI_DEVICE_BAR: 474c0ad5842SAllain Legacy info = (struct rte_avp_device_info *)resource->addr; 475c0ad5842SAllain Legacy if ((info->magic != RTE_AVP_DEVICE_MAGIC) || 476c0ad5842SAllain Legacy avp_dev_version_check(info->version)) { 477c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid device info magic 0x%08x or version 0x%08x > 0x%08x\n", 478c0ad5842SAllain Legacy info->magic, info->version, 479c0ad5842SAllain Legacy AVP_DPDK_DRIVER_VERSION); 480c0ad5842SAllain Legacy return -EINVAL; 481c0ad5842SAllain Legacy } 482c0ad5842SAllain Legacy break; 483c0ad5842SAllain Legacy 484c0ad5842SAllain Legacy case RTE_AVP_PCI_MEMORY_BAR: 485c0ad5842SAllain Legacy case RTE_AVP_PCI_MMIO_BAR: 486c0ad5842SAllain Legacy if (resource->addr == NULL) { 487c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Missing address space for BAR%u\n", 488c0ad5842SAllain Legacy i); 489c0ad5842SAllain Legacy return -EINVAL; 490c0ad5842SAllain Legacy } 491c0ad5842SAllain Legacy break; 492c0ad5842SAllain Legacy 493c0ad5842SAllain Legacy case RTE_AVP_PCI_MSIX_BAR: 494c0ad5842SAllain Legacy default: 495c0ad5842SAllain Legacy /* no validation required */ 496c0ad5842SAllain Legacy break; 497c0ad5842SAllain Legacy } 498c0ad5842SAllain Legacy } 499c0ad5842SAllain Legacy 500c0ad5842SAllain Legacy return 0; 501c0ad5842SAllain Legacy } 502c0ad5842SAllain Legacy 50382e140b8SAllain Legacy static int 50482e140b8SAllain Legacy avp_dev_detach(struct rte_eth_dev *eth_dev) 50582e140b8SAllain Legacy { 50682e140b8SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 50782e140b8SAllain Legacy int ret; 50882e140b8SAllain Legacy 50982e140b8SAllain Legacy PMD_DRV_LOG(NOTICE, "Detaching port %u from AVP device 0x%" PRIx64 "\n", 51082e140b8SAllain Legacy eth_dev->data->port_id, avp->device_id); 51182e140b8SAllain Legacy 51282e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 51382e140b8SAllain Legacy 51482e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 51582e140b8SAllain Legacy PMD_DRV_LOG(NOTICE, "port %u already detached\n", 51682e140b8SAllain Legacy eth_dev->data->port_id); 51782e140b8SAllain Legacy ret = 0; 51882e140b8SAllain Legacy goto unlock; 51982e140b8SAllain Legacy } 52082e140b8SAllain Legacy 52182e140b8SAllain Legacy /* shutdown the device first so the host stops sending us packets. */ 52282e140b8SAllain Legacy ret = avp_dev_ctrl_shutdown(eth_dev); 52382e140b8SAllain Legacy if (ret < 0) { 52482e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to send/recv shutdown to host, ret=%d\n", 52582e140b8SAllain Legacy ret); 52682e140b8SAllain Legacy avp->flags &= ~AVP_F_DETACHED; 52782e140b8SAllain Legacy goto unlock; 52882e140b8SAllain Legacy } 52982e140b8SAllain Legacy 53082e140b8SAllain Legacy avp->flags |= AVP_F_DETACHED; 53182e140b8SAllain Legacy rte_wmb(); 53282e140b8SAllain Legacy 53382e140b8SAllain Legacy /* wait for queues to acknowledge the presence of the detach flag */ 53482e140b8SAllain Legacy rte_delay_ms(1); 53582e140b8SAllain Legacy 53682e140b8SAllain Legacy ret = 0; 53782e140b8SAllain Legacy 53882e140b8SAllain Legacy unlock: 53982e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 54082e140b8SAllain Legacy return ret; 54182e140b8SAllain Legacy } 54282e140b8SAllain Legacy 5431a859223SAllain Legacy static void 544cce4367fSAllain Legacy _avp_set_rx_queue_mappings(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) 545cce4367fSAllain Legacy { 546cce4367fSAllain Legacy struct avp_dev *avp = 547cce4367fSAllain Legacy AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 548cce4367fSAllain Legacy struct avp_queue *rxq; 549cce4367fSAllain Legacy uint16_t queue_count; 550cce4367fSAllain Legacy uint16_t remainder; 551cce4367fSAllain Legacy 552cce4367fSAllain Legacy rxq = (struct avp_queue *)eth_dev->data->rx_queues[rx_queue_id]; 553cce4367fSAllain Legacy 554cce4367fSAllain Legacy /* 555cce4367fSAllain Legacy * Must map all AVP fifos as evenly as possible between the configured 556cce4367fSAllain Legacy * device queues. Each device queue will service a subset of the AVP 557cce4367fSAllain Legacy * fifos. If there is an odd number of device queues the first set of 558cce4367fSAllain Legacy * device queues will get the extra AVP fifos. 559cce4367fSAllain Legacy */ 560cce4367fSAllain Legacy queue_count = avp->num_rx_queues / eth_dev->data->nb_rx_queues; 561cce4367fSAllain Legacy remainder = avp->num_rx_queues % eth_dev->data->nb_rx_queues; 562cce4367fSAllain Legacy if (rx_queue_id < remainder) { 563cce4367fSAllain Legacy /* these queues must service one extra FIFO */ 564cce4367fSAllain Legacy rxq->queue_base = rx_queue_id * (queue_count + 1); 565cce4367fSAllain Legacy rxq->queue_limit = rxq->queue_base + (queue_count + 1) - 1; 566cce4367fSAllain Legacy } else { 567cce4367fSAllain Legacy /* these queues service the regular number of FIFO */ 568cce4367fSAllain Legacy rxq->queue_base = ((remainder * (queue_count + 1)) + 569cce4367fSAllain Legacy ((rx_queue_id - remainder) * queue_count)); 570cce4367fSAllain Legacy rxq->queue_limit = rxq->queue_base + queue_count - 1; 571cce4367fSAllain Legacy } 572cce4367fSAllain Legacy 573cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "rxq %u at %p base %u limit %u\n", 574cce4367fSAllain Legacy rx_queue_id, rxq, rxq->queue_base, rxq->queue_limit); 575cce4367fSAllain Legacy 576cce4367fSAllain Legacy rxq->queue_id = rxq->queue_base; 577cce4367fSAllain Legacy } 578cce4367fSAllain Legacy 579cce4367fSAllain Legacy static void 5801a859223SAllain Legacy _avp_set_queue_counts(struct rte_eth_dev *eth_dev) 5811a859223SAllain Legacy { 582c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 5831a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 5841a859223SAllain Legacy struct rte_avp_device_info *host_info; 5851a859223SAllain Legacy void *addr; 5861a859223SAllain Legacy 5871a859223SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr; 5881a859223SAllain Legacy host_info = (struct rte_avp_device_info *)addr; 5891a859223SAllain Legacy 5901a859223SAllain Legacy /* 5911a859223SAllain Legacy * the transmit direction is not negotiated beyond respecting the max 5921a859223SAllain Legacy * number of queues because the host can handle arbitrary guest tx 5931a859223SAllain Legacy * queues (host rx queues). 5941a859223SAllain Legacy */ 5951a859223SAllain Legacy avp->num_tx_queues = eth_dev->data->nb_tx_queues; 5961a859223SAllain Legacy 5971a859223SAllain Legacy /* 5981a859223SAllain Legacy * the receive direction is more restrictive. The host requires a 5991a859223SAllain Legacy * minimum number of guest rx queues (host tx queues) therefore 6001a859223SAllain Legacy * negotiate a value that is at least as large as the host minimum 6011a859223SAllain Legacy * requirement. If the host and guest values are not identical then a 6021a859223SAllain Legacy * mapping will be established in the receive_queue_setup function. 6031a859223SAllain Legacy */ 6041a859223SAllain Legacy avp->num_rx_queues = RTE_MAX(host_info->min_rx_queues, 6051a859223SAllain Legacy eth_dev->data->nb_rx_queues); 6061a859223SAllain Legacy 6071a859223SAllain Legacy PMD_DRV_LOG(DEBUG, "Requesting %u Tx and %u Rx queues from host\n", 6081a859223SAllain Legacy avp->num_tx_queues, avp->num_rx_queues); 6091a859223SAllain Legacy } 6101a859223SAllain Legacy 61182e140b8SAllain Legacy static int 61282e140b8SAllain Legacy avp_dev_attach(struct rte_eth_dev *eth_dev) 61382e140b8SAllain Legacy { 61482e140b8SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 61582e140b8SAllain Legacy struct rte_avp_device_config config; 61682e140b8SAllain Legacy unsigned int i; 61782e140b8SAllain Legacy int ret; 61882e140b8SAllain Legacy 61982e140b8SAllain Legacy PMD_DRV_LOG(NOTICE, "Attaching port %u to AVP device 0x%" PRIx64 "\n", 62082e140b8SAllain Legacy eth_dev->data->port_id, avp->device_id); 62182e140b8SAllain Legacy 62282e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 62382e140b8SAllain Legacy 62482e140b8SAllain Legacy if (!(avp->flags & AVP_F_DETACHED)) { 62582e140b8SAllain Legacy PMD_DRV_LOG(NOTICE, "port %u already attached\n", 62682e140b8SAllain Legacy eth_dev->data->port_id); 62782e140b8SAllain Legacy ret = 0; 62882e140b8SAllain Legacy goto unlock; 62982e140b8SAllain Legacy } 63082e140b8SAllain Legacy 63182e140b8SAllain Legacy /* 63282e140b8SAllain Legacy * make sure that the detached flag is set prior to reconfiguring the 63382e140b8SAllain Legacy * queues. 63482e140b8SAllain Legacy */ 63582e140b8SAllain Legacy avp->flags |= AVP_F_DETACHED; 63682e140b8SAllain Legacy rte_wmb(); 63782e140b8SAllain Legacy 63882e140b8SAllain Legacy /* 63982e140b8SAllain Legacy * re-run the device create utility which will parse the new host info 64082e140b8SAllain Legacy * and setup the AVP device queue pointers. 64182e140b8SAllain Legacy */ 642c0802544SFerruh Yigit ret = avp_dev_create(RTE_ETH_DEV_TO_PCI(eth_dev), eth_dev); 64382e140b8SAllain Legacy if (ret < 0) { 64482e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to re-create AVP device, ret=%d\n", 64582e140b8SAllain Legacy ret); 64682e140b8SAllain Legacy goto unlock; 64782e140b8SAllain Legacy } 64882e140b8SAllain Legacy 64982e140b8SAllain Legacy if (avp->flags & AVP_F_CONFIGURED) { 65082e140b8SAllain Legacy /* 65182e140b8SAllain Legacy * Update the receive queue mapping to handle cases where the 65282e140b8SAllain Legacy * source and destination hosts have different queue 65382e140b8SAllain Legacy * requirements. As long as the DETACHED flag is asserted the 65482e140b8SAllain Legacy * queue table should not be referenced so it should be safe to 65582e140b8SAllain Legacy * update it. 65682e140b8SAllain Legacy */ 65782e140b8SAllain Legacy _avp_set_queue_counts(eth_dev); 65882e140b8SAllain Legacy for (i = 0; i < eth_dev->data->nb_rx_queues; i++) 65982e140b8SAllain Legacy _avp_set_rx_queue_mappings(eth_dev, i); 66082e140b8SAllain Legacy 66182e140b8SAllain Legacy /* 66282e140b8SAllain Legacy * Update the host with our config details so that it knows the 66382e140b8SAllain Legacy * device is active. 66482e140b8SAllain Legacy */ 66582e140b8SAllain Legacy memset(&config, 0, sizeof(config)); 66682e140b8SAllain Legacy config.device_id = avp->device_id; 66782e140b8SAllain Legacy config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK; 66882e140b8SAllain Legacy config.driver_version = AVP_DPDK_DRIVER_VERSION; 66982e140b8SAllain Legacy config.features = avp->features; 67082e140b8SAllain Legacy config.num_tx_queues = avp->num_tx_queues; 67182e140b8SAllain Legacy config.num_rx_queues = avp->num_rx_queues; 67282e140b8SAllain Legacy config.if_up = !!(avp->flags & AVP_F_LINKUP); 67382e140b8SAllain Legacy 67482e140b8SAllain Legacy ret = avp_dev_ctrl_set_config(eth_dev, &config); 67582e140b8SAllain Legacy if (ret < 0) { 67682e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Config request failed by host, ret=%d\n", 67782e140b8SAllain Legacy ret); 67882e140b8SAllain Legacy goto unlock; 67982e140b8SAllain Legacy } 68082e140b8SAllain Legacy } 68182e140b8SAllain Legacy 68282e140b8SAllain Legacy rte_wmb(); 68382e140b8SAllain Legacy avp->flags &= ~AVP_F_DETACHED; 68482e140b8SAllain Legacy 68582e140b8SAllain Legacy ret = 0; 68682e140b8SAllain Legacy 68782e140b8SAllain Legacy unlock: 68882e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 68982e140b8SAllain Legacy return ret; 69082e140b8SAllain Legacy } 69182e140b8SAllain Legacy 69282e140b8SAllain Legacy static void 693c23a1a30SQi Zhang avp_dev_interrupt_handler(void *data) 69482e140b8SAllain Legacy { 69582e140b8SAllain Legacy struct rte_eth_dev *eth_dev = data; 696c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 69782e140b8SAllain Legacy void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr; 69882e140b8SAllain Legacy uint32_t status, value; 69982e140b8SAllain Legacy int ret; 70082e140b8SAllain Legacy 70182e140b8SAllain Legacy if (registers == NULL) 70282e140b8SAllain Legacy rte_panic("no mapped MMIO register space\n"); 70382e140b8SAllain Legacy 70482e140b8SAllain Legacy /* read the interrupt status register 70582e140b8SAllain Legacy * note: this register clears on read so all raised interrupts must be 70682e140b8SAllain Legacy * handled or remembered for later processing 70782e140b8SAllain Legacy */ 70882e140b8SAllain Legacy status = AVP_READ32( 70982e140b8SAllain Legacy RTE_PTR_ADD(registers, 71082e140b8SAllain Legacy RTE_AVP_INTERRUPT_STATUS_OFFSET)); 71182e140b8SAllain Legacy 712f353fbc5SFerruh Yigit if (status & RTE_AVP_MIGRATION_INTERRUPT_MASK) { 71382e140b8SAllain Legacy /* handle interrupt based on current status */ 71482e140b8SAllain Legacy value = AVP_READ32( 71582e140b8SAllain Legacy RTE_PTR_ADD(registers, 71682e140b8SAllain Legacy RTE_AVP_MIGRATION_STATUS_OFFSET)); 71782e140b8SAllain Legacy switch (value) { 71882e140b8SAllain Legacy case RTE_AVP_MIGRATION_DETACHED: 71982e140b8SAllain Legacy ret = avp_dev_detach(eth_dev); 72082e140b8SAllain Legacy break; 72182e140b8SAllain Legacy case RTE_AVP_MIGRATION_ATTACHED: 72282e140b8SAllain Legacy ret = avp_dev_attach(eth_dev); 72382e140b8SAllain Legacy break; 72482e140b8SAllain Legacy default: 72582e140b8SAllain Legacy PMD_DRV_LOG(ERR, "unexpected migration status, status=%u\n", 72682e140b8SAllain Legacy value); 72782e140b8SAllain Legacy ret = -EINVAL; 72882e140b8SAllain Legacy } 72982e140b8SAllain Legacy 73082e140b8SAllain Legacy /* acknowledge the request by writing out our current status */ 73182e140b8SAllain Legacy value = (ret == 0 ? value : RTE_AVP_MIGRATION_ERROR); 73282e140b8SAllain Legacy AVP_WRITE32(value, 73382e140b8SAllain Legacy RTE_PTR_ADD(registers, 73482e140b8SAllain Legacy RTE_AVP_MIGRATION_ACK_OFFSET)); 73582e140b8SAllain Legacy 73682e140b8SAllain Legacy PMD_DRV_LOG(NOTICE, "AVP migration interrupt handled\n"); 73782e140b8SAllain Legacy } 73882e140b8SAllain Legacy 73982e140b8SAllain Legacy if (status & ~RTE_AVP_MIGRATION_INTERRUPT_MASK) 74082e140b8SAllain Legacy PMD_DRV_LOG(WARNING, "AVP unexpected interrupt, status=0x%08x\n", 74182e140b8SAllain Legacy status); 74282e140b8SAllain Legacy 74382e140b8SAllain Legacy /* re-enable UIO interrupt handling */ 744c23a1a30SQi Zhang ret = rte_intr_enable(&pci_dev->intr_handle); 74582e140b8SAllain Legacy if (ret < 0) { 74682e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to re-enable UIO interrupts, ret=%d\n", 74782e140b8SAllain Legacy ret); 74882e140b8SAllain Legacy /* continue */ 74982e140b8SAllain Legacy } 75082e140b8SAllain Legacy } 75182e140b8SAllain Legacy 75282e140b8SAllain Legacy static int 75382e140b8SAllain Legacy avp_dev_enable_interrupts(struct rte_eth_dev *eth_dev) 75482e140b8SAllain Legacy { 755c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 75682e140b8SAllain Legacy void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr; 75782e140b8SAllain Legacy int ret; 75882e140b8SAllain Legacy 75982e140b8SAllain Legacy if (registers == NULL) 76082e140b8SAllain Legacy return -EINVAL; 76182e140b8SAllain Legacy 76282e140b8SAllain Legacy /* enable UIO interrupt handling */ 76382e140b8SAllain Legacy ret = rte_intr_enable(&pci_dev->intr_handle); 76482e140b8SAllain Legacy if (ret < 0) { 76582e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to enable UIO interrupts, ret=%d\n", 76682e140b8SAllain Legacy ret); 76782e140b8SAllain Legacy return ret; 76882e140b8SAllain Legacy } 76982e140b8SAllain Legacy 77082e140b8SAllain Legacy /* inform the device that all interrupts are enabled */ 77182e140b8SAllain Legacy AVP_WRITE32(RTE_AVP_APP_INTERRUPTS_MASK, 77282e140b8SAllain Legacy RTE_PTR_ADD(registers, RTE_AVP_INTERRUPT_MASK_OFFSET)); 77382e140b8SAllain Legacy 77482e140b8SAllain Legacy return 0; 77582e140b8SAllain Legacy } 77682e140b8SAllain Legacy 77782e140b8SAllain Legacy static int 77882e140b8SAllain Legacy avp_dev_disable_interrupts(struct rte_eth_dev *eth_dev) 77982e140b8SAllain Legacy { 780c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 78182e140b8SAllain Legacy void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr; 78282e140b8SAllain Legacy int ret; 78382e140b8SAllain Legacy 78482e140b8SAllain Legacy if (registers == NULL) 78582e140b8SAllain Legacy return 0; 78682e140b8SAllain Legacy 78782e140b8SAllain Legacy /* inform the device that all interrupts are disabled */ 78882e140b8SAllain Legacy AVP_WRITE32(RTE_AVP_NO_INTERRUPTS_MASK, 78982e140b8SAllain Legacy RTE_PTR_ADD(registers, RTE_AVP_INTERRUPT_MASK_OFFSET)); 79082e140b8SAllain Legacy 79182e140b8SAllain Legacy /* enable UIO interrupt handling */ 79282e140b8SAllain Legacy ret = rte_intr_disable(&pci_dev->intr_handle); 79382e140b8SAllain Legacy if (ret < 0) { 79482e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to disable UIO interrupts, ret=%d\n", 79582e140b8SAllain Legacy ret); 79682e140b8SAllain Legacy return ret; 79782e140b8SAllain Legacy } 79882e140b8SAllain Legacy 79982e140b8SAllain Legacy return 0; 80082e140b8SAllain Legacy } 80182e140b8SAllain Legacy 80282e140b8SAllain Legacy static int 80382e140b8SAllain Legacy avp_dev_setup_interrupts(struct rte_eth_dev *eth_dev) 80482e140b8SAllain Legacy { 805c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 80682e140b8SAllain Legacy int ret; 80782e140b8SAllain Legacy 80882e140b8SAllain Legacy /* register a callback handler with UIO for interrupt notifications */ 80982e140b8SAllain Legacy ret = rte_intr_callback_register(&pci_dev->intr_handle, 81082e140b8SAllain Legacy avp_dev_interrupt_handler, 81182e140b8SAllain Legacy (void *)eth_dev); 81282e140b8SAllain Legacy if (ret < 0) { 81382e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to register UIO interrupt callback, ret=%d\n", 81482e140b8SAllain Legacy ret); 81582e140b8SAllain Legacy return ret; 81682e140b8SAllain Legacy } 81782e140b8SAllain Legacy 81882e140b8SAllain Legacy /* enable interrupt processing */ 81982e140b8SAllain Legacy return avp_dev_enable_interrupts(eth_dev); 82082e140b8SAllain Legacy } 82182e140b8SAllain Legacy 82282e140b8SAllain Legacy static int 82382e140b8SAllain Legacy avp_dev_migration_pending(struct rte_eth_dev *eth_dev) 82482e140b8SAllain Legacy { 825c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 82682e140b8SAllain Legacy void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr; 82782e140b8SAllain Legacy uint32_t value; 82882e140b8SAllain Legacy 82982e140b8SAllain Legacy if (registers == NULL) 83082e140b8SAllain Legacy return 0; 83182e140b8SAllain Legacy 83282e140b8SAllain Legacy value = AVP_READ32(RTE_PTR_ADD(registers, 83382e140b8SAllain Legacy RTE_AVP_MIGRATION_STATUS_OFFSET)); 83482e140b8SAllain Legacy if (value == RTE_AVP_MIGRATION_DETACHED) { 83582e140b8SAllain Legacy /* migration is in progress; ack it if we have not already */ 83682e140b8SAllain Legacy AVP_WRITE32(value, 83782e140b8SAllain Legacy RTE_PTR_ADD(registers, 83882e140b8SAllain Legacy RTE_AVP_MIGRATION_ACK_OFFSET)); 83982e140b8SAllain Legacy return 1; 84082e140b8SAllain Legacy } 84182e140b8SAllain Legacy return 0; 84282e140b8SAllain Legacy } 84382e140b8SAllain Legacy 844c0ad5842SAllain Legacy /* 845c0ad5842SAllain Legacy * create a AVP device using the supplied device info by first translating it 846c0ad5842SAllain Legacy * to guest address space(s). 847c0ad5842SAllain Legacy */ 848c0ad5842SAllain Legacy static int 849c0ad5842SAllain Legacy avp_dev_create(struct rte_pci_device *pci_dev, 850c0ad5842SAllain Legacy struct rte_eth_dev *eth_dev) 851c0ad5842SAllain Legacy { 852c0ad5842SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 853c0ad5842SAllain Legacy struct rte_avp_device_info *host_info; 854c0ad5842SAllain Legacy struct rte_mem_resource *resource; 855c0ad5842SAllain Legacy unsigned int i; 856c0ad5842SAllain Legacy 857c0ad5842SAllain Legacy resource = &pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR]; 858c0ad5842SAllain Legacy if (resource->addr == NULL) { 859c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "BAR%u is not mapped\n", 860c0ad5842SAllain Legacy RTE_AVP_PCI_DEVICE_BAR); 861c0ad5842SAllain Legacy return -EFAULT; 862c0ad5842SAllain Legacy } 863c0ad5842SAllain Legacy host_info = (struct rte_avp_device_info *)resource->addr; 864c0ad5842SAllain Legacy 865c0ad5842SAllain Legacy if ((host_info->magic != RTE_AVP_DEVICE_MAGIC) || 866c0ad5842SAllain Legacy avp_dev_version_check(host_info->version)) { 867c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Invalid AVP PCI device, magic 0x%08x version 0x%08x > 0x%08x\n", 868c0ad5842SAllain Legacy host_info->magic, host_info->version, 869c0ad5842SAllain Legacy AVP_DPDK_DRIVER_VERSION); 870c0ad5842SAllain Legacy return -EINVAL; 871c0ad5842SAllain Legacy } 872c0ad5842SAllain Legacy 873c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host device is v%u.%u.%u\n", 874c0ad5842SAllain Legacy RTE_AVP_GET_RELEASE_VERSION(host_info->version), 875c0ad5842SAllain Legacy RTE_AVP_GET_MAJOR_VERSION(host_info->version), 876c0ad5842SAllain Legacy RTE_AVP_GET_MINOR_VERSION(host_info->version)); 877c0ad5842SAllain Legacy 878c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u TX queue(s)\n", 879c0ad5842SAllain Legacy host_info->min_tx_queues, host_info->max_tx_queues); 880c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u RX queue(s)\n", 881c0ad5842SAllain Legacy host_info->min_rx_queues, host_info->max_rx_queues); 882c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host supports features 0x%08x\n", 883c0ad5842SAllain Legacy host_info->features); 884c0ad5842SAllain Legacy 885c0ad5842SAllain Legacy if (avp->magic != AVP_ETHDEV_MAGIC) { 886c0ad5842SAllain Legacy /* 887c0ad5842SAllain Legacy * First time initialization (i.e., not during a VM 888c0ad5842SAllain Legacy * migration) 889c0ad5842SAllain Legacy */ 890c0ad5842SAllain Legacy memset(avp, 0, sizeof(*avp)); 891c0ad5842SAllain Legacy avp->magic = AVP_ETHDEV_MAGIC; 892c0ad5842SAllain Legacy avp->dev_data = eth_dev->data; 893c0ad5842SAllain Legacy avp->port_id = eth_dev->data->port_id; 894c0ad5842SAllain Legacy avp->host_mbuf_size = host_info->mbuf_size; 895c0ad5842SAllain Legacy avp->host_features = host_info->features; 89682e140b8SAllain Legacy rte_spinlock_init(&avp->lock); 897c0ad5842SAllain Legacy memcpy(&avp->ethaddr.addr_bytes[0], 898c0ad5842SAllain Legacy host_info->ethaddr, ETHER_ADDR_LEN); 899c0ad5842SAllain Legacy /* adjust max values to not exceed our max */ 900c0ad5842SAllain Legacy avp->max_tx_queues = 901c0ad5842SAllain Legacy RTE_MIN(host_info->max_tx_queues, RTE_AVP_MAX_QUEUES); 902c0ad5842SAllain Legacy avp->max_rx_queues = 903c0ad5842SAllain Legacy RTE_MIN(host_info->max_rx_queues, RTE_AVP_MAX_QUEUES); 904c0ad5842SAllain Legacy } else { 905c0ad5842SAllain Legacy /* Re-attaching during migration */ 906c0ad5842SAllain Legacy 907c0ad5842SAllain Legacy /* TODO... requires validation of host values */ 908c0ad5842SAllain Legacy if ((host_info->features & avp->features) != avp->features) { 909c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "AVP host features mismatched; 0x%08x, host=0x%08x\n", 910c0ad5842SAllain Legacy avp->features, host_info->features); 911c0ad5842SAllain Legacy /* this should not be possible; continue for now */ 912c0ad5842SAllain Legacy } 913c0ad5842SAllain Legacy } 914c0ad5842SAllain Legacy 915c0ad5842SAllain Legacy /* the device id is allowed to change over migrations */ 916c0ad5842SAllain Legacy avp->device_id = host_info->device_id; 917c0ad5842SAllain Legacy 918c0ad5842SAllain Legacy /* translate incoming host addresses to guest address space */ 919c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host tx queue at 0x%" PRIx64 "\n", 920c0ad5842SAllain Legacy host_info->tx_phys); 921c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host alloc queue at 0x%" PRIx64 "\n", 922c0ad5842SAllain Legacy host_info->alloc_phys); 923c0ad5842SAllain Legacy for (i = 0; i < avp->max_tx_queues; i++) { 924c0ad5842SAllain Legacy avp->tx_q[i] = avp_dev_translate_address(eth_dev, 925c0ad5842SAllain Legacy host_info->tx_phys + (i * host_info->tx_size)); 926c0ad5842SAllain Legacy 927c0ad5842SAllain Legacy avp->alloc_q[i] = avp_dev_translate_address(eth_dev, 928c0ad5842SAllain Legacy host_info->alloc_phys + (i * host_info->alloc_size)); 929c0ad5842SAllain Legacy } 930c0ad5842SAllain Legacy 931c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host rx queue at 0x%" PRIx64 "\n", 932c0ad5842SAllain Legacy host_info->rx_phys); 933c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP first host free queue at 0x%" PRIx64 "\n", 934c0ad5842SAllain Legacy host_info->free_phys); 935c0ad5842SAllain Legacy for (i = 0; i < avp->max_rx_queues; i++) { 936c0ad5842SAllain Legacy avp->rx_q[i] = avp_dev_translate_address(eth_dev, 937c0ad5842SAllain Legacy host_info->rx_phys + (i * host_info->rx_size)); 938c0ad5842SAllain Legacy avp->free_q[i] = avp_dev_translate_address(eth_dev, 939c0ad5842SAllain Legacy host_info->free_phys + (i * host_info->free_size)); 940c0ad5842SAllain Legacy } 941c0ad5842SAllain Legacy 942c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host request queue at 0x%" PRIx64 "\n", 943c0ad5842SAllain Legacy host_info->req_phys); 944c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host response queue at 0x%" PRIx64 "\n", 945c0ad5842SAllain Legacy host_info->resp_phys); 946c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host sync address at 0x%" PRIx64 "\n", 947c0ad5842SAllain Legacy host_info->sync_phys); 948c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host mbuf address at 0x%" PRIx64 "\n", 949c0ad5842SAllain Legacy host_info->mbuf_phys); 950c0ad5842SAllain Legacy avp->req_q = avp_dev_translate_address(eth_dev, host_info->req_phys); 951c0ad5842SAllain Legacy avp->resp_q = avp_dev_translate_address(eth_dev, host_info->resp_phys); 952c0ad5842SAllain Legacy avp->sync_addr = 953c0ad5842SAllain Legacy avp_dev_translate_address(eth_dev, host_info->sync_phys); 954c0ad5842SAllain Legacy avp->mbuf_addr = 955c0ad5842SAllain Legacy avp_dev_translate_address(eth_dev, host_info->mbuf_phys); 956c0ad5842SAllain Legacy 957c0ad5842SAllain Legacy /* 958c0ad5842SAllain Legacy * store the host mbuf virtual address so that we can calculate 959c0ad5842SAllain Legacy * relative offsets for each mbuf as they are processed 960c0ad5842SAllain Legacy */ 961c0ad5842SAllain Legacy avp->host_mbuf_addr = host_info->mbuf_va; 962c0ad5842SAllain Legacy avp->host_sync_addr = host_info->sync_va; 963c0ad5842SAllain Legacy 964c0ad5842SAllain Legacy /* 965c0ad5842SAllain Legacy * store the maximum packet length that is supported by the host. 966c0ad5842SAllain Legacy */ 967c0ad5842SAllain Legacy avp->max_rx_pkt_len = host_info->max_rx_pkt_len; 968c0ad5842SAllain Legacy PMD_DRV_LOG(DEBUG, "AVP host max receive packet length is %u\n", 969c0ad5842SAllain Legacy host_info->max_rx_pkt_len); 970c0ad5842SAllain Legacy 971c0ad5842SAllain Legacy return 0; 972c0ad5842SAllain Legacy } 973c0ad5842SAllain Legacy 974c0ad5842SAllain Legacy /* 975908072e9SAllain Legacy * This function is based on probe() function in avp_pci.c 976908072e9SAllain Legacy * It returns 0 on success. 977908072e9SAllain Legacy */ 978908072e9SAllain Legacy static int 979908072e9SAllain Legacy eth_avp_dev_init(struct rte_eth_dev *eth_dev) 980908072e9SAllain Legacy { 981c0ad5842SAllain Legacy struct avp_dev *avp = 982c0ad5842SAllain Legacy AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 983908072e9SAllain Legacy struct rte_pci_device *pci_dev; 984c0ad5842SAllain Legacy int ret; 985908072e9SAllain Legacy 986c0802544SFerruh Yigit pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 9871a859223SAllain Legacy eth_dev->dev_ops = &avp_eth_dev_ops; 98850db69fdSAllain Legacy eth_dev->rx_pkt_burst = &avp_recv_pkts; 989295abce2SAllain Legacy eth_dev->tx_pkt_burst = &avp_xmit_pkts; 990908072e9SAllain Legacy 991908072e9SAllain Legacy if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 992908072e9SAllain Legacy /* 993908072e9SAllain Legacy * no setup required on secondary processes. All data is saved 994908072e9SAllain Legacy * in dev_private by the primary process. All resource should 995908072e9SAllain Legacy * be mapped to the same virtual address so all pointers should 996908072e9SAllain Legacy * be valid. 997908072e9SAllain Legacy */ 99850db69fdSAllain Legacy if (eth_dev->data->scattered_rx) { 99950db69fdSAllain Legacy PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n"); 100050db69fdSAllain Legacy eth_dev->rx_pkt_burst = avp_recv_scattered_pkts; 1001295abce2SAllain Legacy eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts; 100250db69fdSAllain Legacy } 1003908072e9SAllain Legacy return 0; 1004908072e9SAllain Legacy } 1005908072e9SAllain Legacy 1006908072e9SAllain Legacy rte_eth_copy_pci_info(eth_dev, pci_dev); 1007908072e9SAllain Legacy 100882e140b8SAllain Legacy /* Check current migration status */ 100982e140b8SAllain Legacy if (avp_dev_migration_pending(eth_dev)) { 101082e140b8SAllain Legacy PMD_DRV_LOG(ERR, "VM live migration operation in progress\n"); 101182e140b8SAllain Legacy return -EBUSY; 101282e140b8SAllain Legacy } 101382e140b8SAllain Legacy 1014c0ad5842SAllain Legacy /* Check BAR resources */ 1015c0ad5842SAllain Legacy ret = avp_dev_check_regions(eth_dev); 1016c0ad5842SAllain Legacy if (ret < 0) { 1017c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to validate BAR resources, ret=%d\n", 1018c0ad5842SAllain Legacy ret); 1019c0ad5842SAllain Legacy return ret; 1020c0ad5842SAllain Legacy } 1021c0ad5842SAllain Legacy 102282e140b8SAllain Legacy /* Enable interrupts */ 102382e140b8SAllain Legacy ret = avp_dev_setup_interrupts(eth_dev); 102482e140b8SAllain Legacy if (ret < 0) { 102582e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to enable interrupts, ret=%d\n", ret); 102682e140b8SAllain Legacy return ret; 102782e140b8SAllain Legacy } 102882e140b8SAllain Legacy 1029c0ad5842SAllain Legacy /* Handle each subtype */ 1030c0ad5842SAllain Legacy ret = avp_dev_create(pci_dev, eth_dev); 1031c0ad5842SAllain Legacy if (ret < 0) { 1032c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to create device, ret=%d\n", ret); 1033c0ad5842SAllain Legacy return ret; 1034c0ad5842SAllain Legacy } 1035c0ad5842SAllain Legacy 1036c0ad5842SAllain Legacy /* Allocate memory for storing MAC addresses */ 1037c0ad5842SAllain Legacy eth_dev->data->mac_addrs = rte_zmalloc("avp_ethdev", ETHER_ADDR_LEN, 0); 1038c0ad5842SAllain Legacy if (eth_dev->data->mac_addrs == NULL) { 1039c0ad5842SAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses\n", 1040c0ad5842SAllain Legacy ETHER_ADDR_LEN); 1041c0ad5842SAllain Legacy return -ENOMEM; 1042c0ad5842SAllain Legacy } 1043c0ad5842SAllain Legacy 1044c0ad5842SAllain Legacy /* Get a mac from device config */ 1045c0ad5842SAllain Legacy ether_addr_copy(&avp->ethaddr, ð_dev->data->mac_addrs[0]); 1046c0ad5842SAllain Legacy 1047908072e9SAllain Legacy return 0; 1048908072e9SAllain Legacy } 1049908072e9SAllain Legacy 1050908072e9SAllain Legacy static int 1051908072e9SAllain Legacy eth_avp_dev_uninit(struct rte_eth_dev *eth_dev) 1052908072e9SAllain Legacy { 105382e140b8SAllain Legacy int ret; 105482e140b8SAllain Legacy 1055908072e9SAllain Legacy if (rte_eal_process_type() != RTE_PROC_PRIMARY) 1056908072e9SAllain Legacy return -EPERM; 1057908072e9SAllain Legacy 1058908072e9SAllain Legacy if (eth_dev->data == NULL) 1059908072e9SAllain Legacy return 0; 1060908072e9SAllain Legacy 106182e140b8SAllain Legacy ret = avp_dev_disable_interrupts(eth_dev); 106282e140b8SAllain Legacy if (ret != 0) { 106382e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to disable interrupts, ret=%d\n", ret); 106482e140b8SAllain Legacy return ret; 106582e140b8SAllain Legacy } 106682e140b8SAllain Legacy 1067c0ad5842SAllain Legacy if (eth_dev->data->mac_addrs != NULL) { 1068c0ad5842SAllain Legacy rte_free(eth_dev->data->mac_addrs); 1069c0ad5842SAllain Legacy eth_dev->data->mac_addrs = NULL; 1070c0ad5842SAllain Legacy } 1071c0ad5842SAllain Legacy 1072908072e9SAllain Legacy return 0; 1073908072e9SAllain Legacy } 1074908072e9SAllain Legacy 1075fdf91e0fSJan Blunck static int 1076fdf91e0fSJan Blunck eth_avp_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 1077fdf91e0fSJan Blunck struct rte_pci_device *pci_dev) 1078908072e9SAllain Legacy { 1079fdf91e0fSJan Blunck struct rte_eth_dev *eth_dev; 1080fdf91e0fSJan Blunck int ret; 1081fdf91e0fSJan Blunck 1082fdf91e0fSJan Blunck eth_dev = rte_eth_dev_pci_allocate(pci_dev, 1083fdf91e0fSJan Blunck sizeof(struct avp_adapter)); 1084fdf91e0fSJan Blunck if (eth_dev == NULL) 1085fdf91e0fSJan Blunck return -ENOMEM; 1086fdf91e0fSJan Blunck 1087fdf91e0fSJan Blunck ret = eth_avp_dev_init(eth_dev); 1088fdf91e0fSJan Blunck if (ret) 1089fdf91e0fSJan Blunck rte_eth_dev_pci_release(eth_dev); 1090fdf91e0fSJan Blunck 1091fdf91e0fSJan Blunck return ret; 1092fdf91e0fSJan Blunck } 1093fdf91e0fSJan Blunck 1094fdf91e0fSJan Blunck static int 1095fdf91e0fSJan Blunck eth_avp_pci_remove(struct rte_pci_device *pci_dev) 1096fdf91e0fSJan Blunck { 1097fdf91e0fSJan Blunck return rte_eth_dev_pci_generic_remove(pci_dev, 1098fdf91e0fSJan Blunck eth_avp_dev_uninit); 1099fdf91e0fSJan Blunck } 1100fdf91e0fSJan Blunck 1101fdf91e0fSJan Blunck static struct rte_pci_driver rte_avp_pmd = { 1102908072e9SAllain Legacy .id_table = pci_id_avp_map, 1103908072e9SAllain Legacy .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 1104fdf91e0fSJan Blunck .probe = eth_avp_pci_probe, 1105fdf91e0fSJan Blunck .remove = eth_avp_pci_remove, 1106908072e9SAllain Legacy }; 1107908072e9SAllain Legacy 11081a859223SAllain Legacy static int 110950db69fdSAllain Legacy avp_dev_enable_scattered(struct rte_eth_dev *eth_dev, 111050db69fdSAllain Legacy struct avp_dev *avp) 111150db69fdSAllain Legacy { 111250db69fdSAllain Legacy unsigned int max_rx_pkt_len; 111350db69fdSAllain Legacy 111450db69fdSAllain Legacy max_rx_pkt_len = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len; 111550db69fdSAllain Legacy 111650db69fdSAllain Legacy if ((max_rx_pkt_len > avp->guest_mbuf_size) || 111750db69fdSAllain Legacy (max_rx_pkt_len > avp->host_mbuf_size)) { 111850db69fdSAllain Legacy /* 111950db69fdSAllain Legacy * If the guest MTU is greater than either the host or guest 112050db69fdSAllain Legacy * buffers then chained mbufs have to be enabled in the TX 112150db69fdSAllain Legacy * direction. It is assumed that the application will not need 112250db69fdSAllain Legacy * to send packets larger than their max_rx_pkt_len (MRU). 112350db69fdSAllain Legacy */ 112450db69fdSAllain Legacy return 1; 112550db69fdSAllain Legacy } 112650db69fdSAllain Legacy 112750db69fdSAllain Legacy if ((avp->max_rx_pkt_len > avp->guest_mbuf_size) || 112850db69fdSAllain Legacy (avp->max_rx_pkt_len > avp->host_mbuf_size)) { 112950db69fdSAllain Legacy /* 113050db69fdSAllain Legacy * If the host MRU is greater than its own mbuf size or the 113150db69fdSAllain Legacy * guest mbuf size then chained mbufs have to be enabled in the 113250db69fdSAllain Legacy * RX direction. 113350db69fdSAllain Legacy */ 113450db69fdSAllain Legacy return 1; 113550db69fdSAllain Legacy } 113650db69fdSAllain Legacy 113750db69fdSAllain Legacy return 0; 113850db69fdSAllain Legacy } 113950db69fdSAllain Legacy 114050db69fdSAllain Legacy static int 1141cce4367fSAllain Legacy avp_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 1142cce4367fSAllain Legacy uint16_t rx_queue_id, 1143cce4367fSAllain Legacy uint16_t nb_rx_desc, 1144cce4367fSAllain Legacy unsigned int socket_id, 1145cce4367fSAllain Legacy const struct rte_eth_rxconf *rx_conf, 1146cce4367fSAllain Legacy struct rte_mempool *pool) 1147cce4367fSAllain Legacy { 1148cce4367fSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 1149cce4367fSAllain Legacy struct rte_pktmbuf_pool_private *mbp_priv; 1150cce4367fSAllain Legacy struct avp_queue *rxq; 1151cce4367fSAllain Legacy 1152cce4367fSAllain Legacy if (rx_queue_id >= eth_dev->data->nb_rx_queues) { 1153cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "RX queue id is out of range: rx_queue_id=%u, nb_rx_queues=%u\n", 1154cce4367fSAllain Legacy rx_queue_id, eth_dev->data->nb_rx_queues); 1155cce4367fSAllain Legacy return -EINVAL; 1156cce4367fSAllain Legacy } 1157cce4367fSAllain Legacy 1158cce4367fSAllain Legacy /* Save mbuf pool pointer */ 1159cce4367fSAllain Legacy avp->pool = pool; 1160cce4367fSAllain Legacy 1161cce4367fSAllain Legacy /* Save the local mbuf size */ 1162cce4367fSAllain Legacy mbp_priv = rte_mempool_get_priv(pool); 1163cce4367fSAllain Legacy avp->guest_mbuf_size = (uint16_t)(mbp_priv->mbuf_data_room_size); 1164cce4367fSAllain Legacy avp->guest_mbuf_size -= RTE_PKTMBUF_HEADROOM; 1165cce4367fSAllain Legacy 116650db69fdSAllain Legacy if (avp_dev_enable_scattered(eth_dev, avp)) { 116750db69fdSAllain Legacy if (!eth_dev->data->scattered_rx) { 116850db69fdSAllain Legacy PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n"); 116950db69fdSAllain Legacy eth_dev->data->scattered_rx = 1; 117050db69fdSAllain Legacy eth_dev->rx_pkt_burst = avp_recv_scattered_pkts; 1171295abce2SAllain Legacy eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts; 117250db69fdSAllain Legacy } 117350db69fdSAllain Legacy } 117450db69fdSAllain Legacy 1175cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "AVP max_rx_pkt_len=(%u,%u) mbuf_size=(%u,%u)\n", 1176cce4367fSAllain Legacy avp->max_rx_pkt_len, 1177cce4367fSAllain Legacy eth_dev->data->dev_conf.rxmode.max_rx_pkt_len, 1178cce4367fSAllain Legacy avp->host_mbuf_size, 1179cce4367fSAllain Legacy avp->guest_mbuf_size); 1180cce4367fSAllain Legacy 1181cce4367fSAllain Legacy /* allocate a queue object */ 1182cce4367fSAllain Legacy rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct avp_queue), 1183cce4367fSAllain Legacy RTE_CACHE_LINE_SIZE, socket_id); 1184cce4367fSAllain Legacy if (rxq == NULL) { 1185cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate new Rx queue object\n"); 1186cce4367fSAllain Legacy return -ENOMEM; 1187cce4367fSAllain Legacy } 1188cce4367fSAllain Legacy 1189cce4367fSAllain Legacy /* save back pointers to AVP and Ethernet devices */ 1190cce4367fSAllain Legacy rxq->avp = avp; 1191cce4367fSAllain Legacy rxq->dev_data = eth_dev->data; 1192cce4367fSAllain Legacy eth_dev->data->rx_queues[rx_queue_id] = (void *)rxq; 1193cce4367fSAllain Legacy 1194cce4367fSAllain Legacy /* setup the queue receive mapping for the current queue. */ 1195cce4367fSAllain Legacy _avp_set_rx_queue_mappings(eth_dev, rx_queue_id); 1196cce4367fSAllain Legacy 1197cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "Rx queue %u setup at %p\n", rx_queue_id, rxq); 1198cce4367fSAllain Legacy 1199cce4367fSAllain Legacy (void)nb_rx_desc; 1200cce4367fSAllain Legacy (void)rx_conf; 1201cce4367fSAllain Legacy return 0; 1202cce4367fSAllain Legacy } 1203cce4367fSAllain Legacy 1204cce4367fSAllain Legacy static int 1205cce4367fSAllain Legacy avp_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, 1206cce4367fSAllain Legacy uint16_t tx_queue_id, 1207cce4367fSAllain Legacy uint16_t nb_tx_desc, 1208cce4367fSAllain Legacy unsigned int socket_id, 1209cce4367fSAllain Legacy const struct rte_eth_txconf *tx_conf) 1210cce4367fSAllain Legacy { 1211cce4367fSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 1212cce4367fSAllain Legacy struct avp_queue *txq; 1213cce4367fSAllain Legacy 1214cce4367fSAllain Legacy if (tx_queue_id >= eth_dev->data->nb_tx_queues) { 1215cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "TX queue id is out of range: tx_queue_id=%u, nb_tx_queues=%u\n", 1216cce4367fSAllain Legacy tx_queue_id, eth_dev->data->nb_tx_queues); 1217cce4367fSAllain Legacy return -EINVAL; 1218cce4367fSAllain Legacy } 1219cce4367fSAllain Legacy 1220cce4367fSAllain Legacy /* allocate a queue object */ 1221cce4367fSAllain Legacy txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct avp_queue), 1222cce4367fSAllain Legacy RTE_CACHE_LINE_SIZE, socket_id); 1223cce4367fSAllain Legacy if (txq == NULL) { 1224cce4367fSAllain Legacy PMD_DRV_LOG(ERR, "Failed to allocate new Tx queue object\n"); 1225cce4367fSAllain Legacy return -ENOMEM; 1226cce4367fSAllain Legacy } 1227cce4367fSAllain Legacy 1228cce4367fSAllain Legacy /* only the configured set of transmit queues are used */ 1229cce4367fSAllain Legacy txq->queue_id = tx_queue_id; 1230cce4367fSAllain Legacy txq->queue_base = tx_queue_id; 1231cce4367fSAllain Legacy txq->queue_limit = tx_queue_id; 1232cce4367fSAllain Legacy 1233cce4367fSAllain Legacy /* save back pointers to AVP and Ethernet devices */ 1234cce4367fSAllain Legacy txq->avp = avp; 1235cce4367fSAllain Legacy txq->dev_data = eth_dev->data; 1236cce4367fSAllain Legacy eth_dev->data->tx_queues[tx_queue_id] = (void *)txq; 1237cce4367fSAllain Legacy 1238cce4367fSAllain Legacy PMD_DRV_LOG(DEBUG, "Tx queue %u setup at %p\n", tx_queue_id, txq); 1239cce4367fSAllain Legacy 1240cce4367fSAllain Legacy (void)nb_tx_desc; 1241cce4367fSAllain Legacy (void)tx_conf; 1242cce4367fSAllain Legacy return 0; 1243cce4367fSAllain Legacy } 1244cce4367fSAllain Legacy 124550db69fdSAllain Legacy static inline int 124650db69fdSAllain Legacy _avp_cmp_ether_addr(struct ether_addr *a, struct ether_addr *b) 124750db69fdSAllain Legacy { 124850db69fdSAllain Legacy uint16_t *_a = (uint16_t *)&a->addr_bytes[0]; 124950db69fdSAllain Legacy uint16_t *_b = (uint16_t *)&b->addr_bytes[0]; 125050db69fdSAllain Legacy return (_a[0] ^ _b[0]) | (_a[1] ^ _b[1]) | (_a[2] ^ _b[2]); 125150db69fdSAllain Legacy } 125250db69fdSAllain Legacy 125350db69fdSAllain Legacy static inline int 125450db69fdSAllain Legacy _avp_mac_filter(struct avp_dev *avp, struct rte_mbuf *m) 125550db69fdSAllain Legacy { 125650db69fdSAllain Legacy struct ether_hdr *eth = rte_pktmbuf_mtod(m, struct ether_hdr *); 125750db69fdSAllain Legacy 125850db69fdSAllain Legacy if (likely(_avp_cmp_ether_addr(&avp->ethaddr, ð->d_addr) == 0)) { 125950db69fdSAllain Legacy /* allow all packets destined to our address */ 126050db69fdSAllain Legacy return 0; 126150db69fdSAllain Legacy } 126250db69fdSAllain Legacy 126350db69fdSAllain Legacy if (likely(is_broadcast_ether_addr(ð->d_addr))) { 126450db69fdSAllain Legacy /* allow all broadcast packets */ 126550db69fdSAllain Legacy return 0; 126650db69fdSAllain Legacy } 126750db69fdSAllain Legacy 126850db69fdSAllain Legacy if (likely(is_multicast_ether_addr(ð->d_addr))) { 126950db69fdSAllain Legacy /* allow all multicast packets */ 127050db69fdSAllain Legacy return 0; 127150db69fdSAllain Legacy } 127250db69fdSAllain Legacy 127350db69fdSAllain Legacy if (avp->flags & AVP_F_PROMISC) { 127450db69fdSAllain Legacy /* allow all packets when in promiscuous mode */ 127550db69fdSAllain Legacy return 0; 127650db69fdSAllain Legacy } 127750db69fdSAllain Legacy 127850db69fdSAllain Legacy return -1; 127950db69fdSAllain Legacy } 128050db69fdSAllain Legacy 128150db69fdSAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS 128250db69fdSAllain Legacy static inline void 128350db69fdSAllain Legacy __avp_dev_buffer_sanity_check(struct avp_dev *avp, struct rte_avp_desc *buf) 128450db69fdSAllain Legacy { 128550db69fdSAllain Legacy struct rte_avp_desc *first_buf; 128650db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 128750db69fdSAllain Legacy unsigned int pkt_len; 128850db69fdSAllain Legacy unsigned int nb_segs; 128950db69fdSAllain Legacy void *pkt_data; 129050db69fdSAllain Legacy unsigned int i; 129150db69fdSAllain Legacy 129250db69fdSAllain Legacy first_buf = avp_dev_translate_buffer(avp, buf); 129350db69fdSAllain Legacy 129450db69fdSAllain Legacy i = 0; 129550db69fdSAllain Legacy pkt_len = 0; 129650db69fdSAllain Legacy nb_segs = first_buf->nb_segs; 129750db69fdSAllain Legacy do { 129850db69fdSAllain Legacy /* Adjust pointers for guest addressing */ 129950db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 130050db69fdSAllain Legacy if (pkt_buf == NULL) 130150db69fdSAllain Legacy rte_panic("bad buffer: segment %u has an invalid address %p\n", 130250db69fdSAllain Legacy i, buf); 130350db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 130450db69fdSAllain Legacy if (pkt_data == NULL) 130550db69fdSAllain Legacy rte_panic("bad buffer: segment %u has a NULL data pointer\n", 130650db69fdSAllain Legacy i); 130750db69fdSAllain Legacy if (pkt_buf->data_len == 0) 130850db69fdSAllain Legacy rte_panic("bad buffer: segment %u has 0 data length\n", 130950db69fdSAllain Legacy i); 131050db69fdSAllain Legacy pkt_len += pkt_buf->data_len; 131150db69fdSAllain Legacy nb_segs--; 131250db69fdSAllain Legacy i++; 131350db69fdSAllain Legacy 131450db69fdSAllain Legacy } while (nb_segs && (buf = pkt_buf->next) != NULL); 131550db69fdSAllain Legacy 131650db69fdSAllain Legacy if (nb_segs != 0) 131750db69fdSAllain Legacy rte_panic("bad buffer: expected %u segments found %u\n", 131850db69fdSAllain Legacy first_buf->nb_segs, (first_buf->nb_segs - nb_segs)); 131950db69fdSAllain Legacy if (pkt_len != first_buf->pkt_len) 132050db69fdSAllain Legacy rte_panic("bad buffer: expected length %u found %u\n", 132150db69fdSAllain Legacy first_buf->pkt_len, pkt_len); 132250db69fdSAllain Legacy } 132350db69fdSAllain Legacy 132450db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) \ 132550db69fdSAllain Legacy __avp_dev_buffer_sanity_check((a), (b)) 132650db69fdSAllain Legacy 132750db69fdSAllain Legacy #else /* RTE_LIBRTE_AVP_DEBUG_BUFFERS */ 132850db69fdSAllain Legacy 132950db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) do {} while (0) 133050db69fdSAllain Legacy 133150db69fdSAllain Legacy #endif 133250db69fdSAllain Legacy 133350db69fdSAllain Legacy /* 133450db69fdSAllain Legacy * Copy a host buffer chain to a set of mbufs. This function assumes that 133550db69fdSAllain Legacy * there exactly the required number of mbufs to copy all source bytes. 133650db69fdSAllain Legacy */ 133750db69fdSAllain Legacy static inline struct rte_mbuf * 133850db69fdSAllain Legacy avp_dev_copy_from_buffers(struct avp_dev *avp, 133950db69fdSAllain Legacy struct rte_avp_desc *buf, 134050db69fdSAllain Legacy struct rte_mbuf **mbufs, 134150db69fdSAllain Legacy unsigned int count) 134250db69fdSAllain Legacy { 134350db69fdSAllain Legacy struct rte_mbuf *m_previous = NULL; 134450db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 134550db69fdSAllain Legacy unsigned int total_length = 0; 134650db69fdSAllain Legacy unsigned int copy_length; 134750db69fdSAllain Legacy unsigned int src_offset; 134850db69fdSAllain Legacy struct rte_mbuf *m; 134950db69fdSAllain Legacy uint16_t ol_flags; 135050db69fdSAllain Legacy uint16_t vlan_tci; 135150db69fdSAllain Legacy void *pkt_data; 135250db69fdSAllain Legacy unsigned int i; 135350db69fdSAllain Legacy 135450db69fdSAllain Legacy avp_dev_buffer_sanity_check(avp, buf); 135550db69fdSAllain Legacy 135650db69fdSAllain Legacy /* setup the first source buffer */ 135750db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 135850db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 135950db69fdSAllain Legacy total_length = pkt_buf->pkt_len; 136050db69fdSAllain Legacy src_offset = 0; 136150db69fdSAllain Legacy 136250db69fdSAllain Legacy if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) { 1363380a7aabSOlivier Matz ol_flags = PKT_RX_VLAN; 136450db69fdSAllain Legacy vlan_tci = pkt_buf->vlan_tci; 136550db69fdSAllain Legacy } else { 136650db69fdSAllain Legacy ol_flags = 0; 136750db69fdSAllain Legacy vlan_tci = 0; 136850db69fdSAllain Legacy } 136950db69fdSAllain Legacy 137050db69fdSAllain Legacy for (i = 0; (i < count) && (buf != NULL); i++) { 137150db69fdSAllain Legacy /* fill each destination buffer */ 137250db69fdSAllain Legacy m = mbufs[i]; 137350db69fdSAllain Legacy 137450db69fdSAllain Legacy if (m_previous != NULL) 137550db69fdSAllain Legacy m_previous->next = m; 137650db69fdSAllain Legacy 137750db69fdSAllain Legacy m_previous = m; 137850db69fdSAllain Legacy 137950db69fdSAllain Legacy do { 138050db69fdSAllain Legacy /* 138150db69fdSAllain Legacy * Copy as many source buffers as will fit in the 138250db69fdSAllain Legacy * destination buffer. 138350db69fdSAllain Legacy */ 138450db69fdSAllain Legacy copy_length = RTE_MIN((avp->guest_mbuf_size - 138550db69fdSAllain Legacy rte_pktmbuf_data_len(m)), 138650db69fdSAllain Legacy (pkt_buf->data_len - 138750db69fdSAllain Legacy src_offset)); 138850db69fdSAllain Legacy rte_memcpy(RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *), 138950db69fdSAllain Legacy rte_pktmbuf_data_len(m)), 139050db69fdSAllain Legacy RTE_PTR_ADD(pkt_data, src_offset), 139150db69fdSAllain Legacy copy_length); 139250db69fdSAllain Legacy rte_pktmbuf_data_len(m) += copy_length; 139350db69fdSAllain Legacy src_offset += copy_length; 139450db69fdSAllain Legacy 139550db69fdSAllain Legacy if (likely(src_offset == pkt_buf->data_len)) { 139650db69fdSAllain Legacy /* need a new source buffer */ 139750db69fdSAllain Legacy buf = pkt_buf->next; 139850db69fdSAllain Legacy if (buf != NULL) { 139950db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer( 140050db69fdSAllain Legacy avp, buf); 140150db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer( 140250db69fdSAllain Legacy avp, pkt_buf->data); 140350db69fdSAllain Legacy src_offset = 0; 140450db69fdSAllain Legacy } 140550db69fdSAllain Legacy } 140650db69fdSAllain Legacy 140750db69fdSAllain Legacy if (unlikely(rte_pktmbuf_data_len(m) == 140850db69fdSAllain Legacy avp->guest_mbuf_size)) { 140950db69fdSAllain Legacy /* need a new destination mbuf */ 141050db69fdSAllain Legacy break; 141150db69fdSAllain Legacy } 141250db69fdSAllain Legacy 141350db69fdSAllain Legacy } while (buf != NULL); 141450db69fdSAllain Legacy } 141550db69fdSAllain Legacy 141650db69fdSAllain Legacy m = mbufs[0]; 141750db69fdSAllain Legacy m->ol_flags = ol_flags; 141850db69fdSAllain Legacy m->nb_segs = count; 141950db69fdSAllain Legacy rte_pktmbuf_pkt_len(m) = total_length; 142050db69fdSAllain Legacy m->vlan_tci = vlan_tci; 142150db69fdSAllain Legacy 142250db69fdSAllain Legacy __rte_mbuf_sanity_check(m, 1); 142350db69fdSAllain Legacy 142450db69fdSAllain Legacy return m; 142550db69fdSAllain Legacy } 142650db69fdSAllain Legacy 142750db69fdSAllain Legacy static uint16_t 142850db69fdSAllain Legacy avp_recv_scattered_pkts(void *rx_queue, 142950db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 143050db69fdSAllain Legacy uint16_t nb_pkts) 143150db69fdSAllain Legacy { 143250db69fdSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 143350db69fdSAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST]; 143450db69fdSAllain Legacy struct rte_mbuf *mbufs[RTE_AVP_MAX_MBUF_SEGMENTS]; 143550db69fdSAllain Legacy struct avp_dev *avp = rxq->avp; 143650db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 143750db69fdSAllain Legacy struct rte_avp_fifo *free_q; 143850db69fdSAllain Legacy struct rte_avp_fifo *rx_q; 143950db69fdSAllain Legacy struct rte_avp_desc *buf; 144050db69fdSAllain Legacy unsigned int count, avail, n; 144150db69fdSAllain Legacy unsigned int guest_mbuf_size; 144250db69fdSAllain Legacy struct rte_mbuf *m; 144350db69fdSAllain Legacy unsigned int required; 144450db69fdSAllain Legacy unsigned int buf_len; 144550db69fdSAllain Legacy unsigned int port_id; 144650db69fdSAllain Legacy unsigned int i; 144750db69fdSAllain Legacy 144882e140b8SAllain Legacy if (unlikely(avp->flags & AVP_F_DETACHED)) { 144982e140b8SAllain Legacy /* VM live migration in progress */ 145082e140b8SAllain Legacy return 0; 145182e140b8SAllain Legacy } 145282e140b8SAllain Legacy 145350db69fdSAllain Legacy guest_mbuf_size = avp->guest_mbuf_size; 145450db69fdSAllain Legacy port_id = avp->port_id; 145550db69fdSAllain Legacy rx_q = avp->rx_q[rxq->queue_id]; 145650db69fdSAllain Legacy free_q = avp->free_q[rxq->queue_id]; 145750db69fdSAllain Legacy 145850db69fdSAllain Legacy /* setup next queue to service */ 145950db69fdSAllain Legacy rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ? 146050db69fdSAllain Legacy (rxq->queue_id + 1) : rxq->queue_base; 146150db69fdSAllain Legacy 146250db69fdSAllain Legacy /* determine how many slots are available in the free queue */ 146350db69fdSAllain Legacy count = avp_fifo_free_count(free_q); 146450db69fdSAllain Legacy 146550db69fdSAllain Legacy /* determine how many packets are available in the rx queue */ 146650db69fdSAllain Legacy avail = avp_fifo_count(rx_q); 146750db69fdSAllain Legacy 146850db69fdSAllain Legacy /* determine how many packets can be received */ 146950db69fdSAllain Legacy count = RTE_MIN(count, avail); 147050db69fdSAllain Legacy count = RTE_MIN(count, nb_pkts); 147150db69fdSAllain Legacy count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST); 147250db69fdSAllain Legacy 147350db69fdSAllain Legacy if (unlikely(count == 0)) { 147450db69fdSAllain Legacy /* no free buffers, or no buffers on the rx queue */ 147550db69fdSAllain Legacy return 0; 147650db69fdSAllain Legacy } 147750db69fdSAllain Legacy 147850db69fdSAllain Legacy /* retrieve pending packets */ 147950db69fdSAllain Legacy n = avp_fifo_get(rx_q, (void **)&avp_bufs, count); 148050db69fdSAllain Legacy PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n", 148150db69fdSAllain Legacy count, rx_q); 148250db69fdSAllain Legacy 148350db69fdSAllain Legacy count = 0; 148450db69fdSAllain Legacy for (i = 0; i < n; i++) { 148550db69fdSAllain Legacy /* prefetch next entry while processing current one */ 148650db69fdSAllain Legacy if (i + 1 < n) { 148750db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 148850db69fdSAllain Legacy avp_bufs[i + 1]); 148950db69fdSAllain Legacy rte_prefetch0(pkt_buf); 149050db69fdSAllain Legacy } 149150db69fdSAllain Legacy buf = avp_bufs[i]; 149250db69fdSAllain Legacy 149350db69fdSAllain Legacy /* Peek into the first buffer to determine the total length */ 149450db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 149550db69fdSAllain Legacy buf_len = pkt_buf->pkt_len; 149650db69fdSAllain Legacy 149750db69fdSAllain Legacy /* Allocate enough mbufs to receive the entire packet */ 149850db69fdSAllain Legacy required = (buf_len + guest_mbuf_size - 1) / guest_mbuf_size; 149950db69fdSAllain Legacy if (rte_pktmbuf_alloc_bulk(avp->pool, mbufs, required)) { 150050db69fdSAllain Legacy rxq->dev_data->rx_mbuf_alloc_failed++; 150150db69fdSAllain Legacy continue; 150250db69fdSAllain Legacy } 150350db69fdSAllain Legacy 150450db69fdSAllain Legacy /* Copy the data from the buffers to our mbufs */ 150550db69fdSAllain Legacy m = avp_dev_copy_from_buffers(avp, buf, mbufs, required); 150650db69fdSAllain Legacy 150750db69fdSAllain Legacy /* finalize mbuf */ 150850db69fdSAllain Legacy m->port = port_id; 150950db69fdSAllain Legacy 151050db69fdSAllain Legacy if (_avp_mac_filter(avp, m) != 0) { 151150db69fdSAllain Legacy /* silently discard packets not destined to our MAC */ 151250db69fdSAllain Legacy rte_pktmbuf_free(m); 151350db69fdSAllain Legacy continue; 151450db69fdSAllain Legacy } 151550db69fdSAllain Legacy 151650db69fdSAllain Legacy /* return new mbuf to caller */ 151750db69fdSAllain Legacy rx_pkts[count++] = m; 151850db69fdSAllain Legacy rxq->bytes += buf_len; 151950db69fdSAllain Legacy } 152050db69fdSAllain Legacy 152150db69fdSAllain Legacy rxq->packets += count; 152250db69fdSAllain Legacy 152350db69fdSAllain Legacy /* return the buffers to the free queue */ 152450db69fdSAllain Legacy avp_fifo_put(free_q, (void **)&avp_bufs[0], n); 152550db69fdSAllain Legacy 152650db69fdSAllain Legacy return count; 152750db69fdSAllain Legacy } 152850db69fdSAllain Legacy 152950db69fdSAllain Legacy 153050db69fdSAllain Legacy static uint16_t 153150db69fdSAllain Legacy avp_recv_pkts(void *rx_queue, 153250db69fdSAllain Legacy struct rte_mbuf **rx_pkts, 153350db69fdSAllain Legacy uint16_t nb_pkts) 153450db69fdSAllain Legacy { 153550db69fdSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 153650db69fdSAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST]; 153750db69fdSAllain Legacy struct avp_dev *avp = rxq->avp; 153850db69fdSAllain Legacy struct rte_avp_desc *pkt_buf; 153950db69fdSAllain Legacy struct rte_avp_fifo *free_q; 154050db69fdSAllain Legacy struct rte_avp_fifo *rx_q; 154150db69fdSAllain Legacy unsigned int count, avail, n; 154250db69fdSAllain Legacy unsigned int pkt_len; 154350db69fdSAllain Legacy struct rte_mbuf *m; 154450db69fdSAllain Legacy char *pkt_data; 154550db69fdSAllain Legacy unsigned int i; 154650db69fdSAllain Legacy 154782e140b8SAllain Legacy if (unlikely(avp->flags & AVP_F_DETACHED)) { 154882e140b8SAllain Legacy /* VM live migration in progress */ 154982e140b8SAllain Legacy return 0; 155082e140b8SAllain Legacy } 155182e140b8SAllain Legacy 155250db69fdSAllain Legacy rx_q = avp->rx_q[rxq->queue_id]; 155350db69fdSAllain Legacy free_q = avp->free_q[rxq->queue_id]; 155450db69fdSAllain Legacy 155550db69fdSAllain Legacy /* setup next queue to service */ 155650db69fdSAllain Legacy rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ? 155750db69fdSAllain Legacy (rxq->queue_id + 1) : rxq->queue_base; 155850db69fdSAllain Legacy 155950db69fdSAllain Legacy /* determine how many slots are available in the free queue */ 156050db69fdSAllain Legacy count = avp_fifo_free_count(free_q); 156150db69fdSAllain Legacy 156250db69fdSAllain Legacy /* determine how many packets are available in the rx queue */ 156350db69fdSAllain Legacy avail = avp_fifo_count(rx_q); 156450db69fdSAllain Legacy 156550db69fdSAllain Legacy /* determine how many packets can be received */ 156650db69fdSAllain Legacy count = RTE_MIN(count, avail); 156750db69fdSAllain Legacy count = RTE_MIN(count, nb_pkts); 156850db69fdSAllain Legacy count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST); 156950db69fdSAllain Legacy 157050db69fdSAllain Legacy if (unlikely(count == 0)) { 157150db69fdSAllain Legacy /* no free buffers, or no buffers on the rx queue */ 157250db69fdSAllain Legacy return 0; 157350db69fdSAllain Legacy } 157450db69fdSAllain Legacy 157550db69fdSAllain Legacy /* retrieve pending packets */ 157650db69fdSAllain Legacy n = avp_fifo_get(rx_q, (void **)&avp_bufs, count); 157750db69fdSAllain Legacy PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n", 157850db69fdSAllain Legacy count, rx_q); 157950db69fdSAllain Legacy 158050db69fdSAllain Legacy count = 0; 158150db69fdSAllain Legacy for (i = 0; i < n; i++) { 158250db69fdSAllain Legacy /* prefetch next entry while processing current one */ 158350db69fdSAllain Legacy if (i < n - 1) { 158450db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 158550db69fdSAllain Legacy avp_bufs[i + 1]); 158650db69fdSAllain Legacy rte_prefetch0(pkt_buf); 158750db69fdSAllain Legacy } 158850db69fdSAllain Legacy 158950db69fdSAllain Legacy /* Adjust host pointers for guest addressing */ 159050db69fdSAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]); 159150db69fdSAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 159250db69fdSAllain Legacy pkt_len = pkt_buf->pkt_len; 159350db69fdSAllain Legacy 159450db69fdSAllain Legacy if (unlikely((pkt_len > avp->guest_mbuf_size) || 159550db69fdSAllain Legacy (pkt_buf->nb_segs > 1))) { 159650db69fdSAllain Legacy /* 159750db69fdSAllain Legacy * application should be using the scattered receive 159850db69fdSAllain Legacy * function 159950db69fdSAllain Legacy */ 160050db69fdSAllain Legacy rxq->errors++; 160150db69fdSAllain Legacy continue; 160250db69fdSAllain Legacy } 160350db69fdSAllain Legacy 160450db69fdSAllain Legacy /* process each packet to be transmitted */ 160550db69fdSAllain Legacy m = rte_pktmbuf_alloc(avp->pool); 160650db69fdSAllain Legacy if (unlikely(m == NULL)) { 160750db69fdSAllain Legacy rxq->dev_data->rx_mbuf_alloc_failed++; 160850db69fdSAllain Legacy continue; 160950db69fdSAllain Legacy } 161050db69fdSAllain Legacy 161150db69fdSAllain Legacy /* copy data out of the host buffer to our buffer */ 161250db69fdSAllain Legacy m->data_off = RTE_PKTMBUF_HEADROOM; 161350db69fdSAllain Legacy rte_memcpy(rte_pktmbuf_mtod(m, void *), pkt_data, pkt_len); 161450db69fdSAllain Legacy 161550db69fdSAllain Legacy /* initialize the local mbuf */ 161650db69fdSAllain Legacy rte_pktmbuf_data_len(m) = pkt_len; 161750db69fdSAllain Legacy rte_pktmbuf_pkt_len(m) = pkt_len; 161850db69fdSAllain Legacy m->port = avp->port_id; 161950db69fdSAllain Legacy 162050db69fdSAllain Legacy if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) { 1621380a7aabSOlivier Matz m->ol_flags = PKT_RX_VLAN; 162250db69fdSAllain Legacy m->vlan_tci = pkt_buf->vlan_tci; 162350db69fdSAllain Legacy } 162450db69fdSAllain Legacy 162550db69fdSAllain Legacy if (_avp_mac_filter(avp, m) != 0) { 162650db69fdSAllain Legacy /* silently discard packets not destined to our MAC */ 162750db69fdSAllain Legacy rte_pktmbuf_free(m); 162850db69fdSAllain Legacy continue; 162950db69fdSAllain Legacy } 163050db69fdSAllain Legacy 163150db69fdSAllain Legacy /* return new mbuf to caller */ 163250db69fdSAllain Legacy rx_pkts[count++] = m; 163350db69fdSAllain Legacy rxq->bytes += pkt_len; 163450db69fdSAllain Legacy } 163550db69fdSAllain Legacy 163650db69fdSAllain Legacy rxq->packets += count; 163750db69fdSAllain Legacy 163850db69fdSAllain Legacy /* return the buffers to the free queue */ 163950db69fdSAllain Legacy avp_fifo_put(free_q, (void **)&avp_bufs[0], n); 164050db69fdSAllain Legacy 164150db69fdSAllain Legacy return count; 164250db69fdSAllain Legacy } 164350db69fdSAllain Legacy 1644295abce2SAllain Legacy /* 1645295abce2SAllain Legacy * Copy a chained mbuf to a set of host buffers. This function assumes that 1646295abce2SAllain Legacy * there are sufficient destination buffers to contain the entire source 1647295abce2SAllain Legacy * packet. 1648295abce2SAllain Legacy */ 1649295abce2SAllain Legacy static inline uint16_t 1650295abce2SAllain Legacy avp_dev_copy_to_buffers(struct avp_dev *avp, 1651295abce2SAllain Legacy struct rte_mbuf *mbuf, 1652295abce2SAllain Legacy struct rte_avp_desc **buffers, 1653295abce2SAllain Legacy unsigned int count) 1654295abce2SAllain Legacy { 1655295abce2SAllain Legacy struct rte_avp_desc *previous_buf = NULL; 1656295abce2SAllain Legacy struct rte_avp_desc *first_buf = NULL; 1657295abce2SAllain Legacy struct rte_avp_desc *pkt_buf; 1658295abce2SAllain Legacy struct rte_avp_desc *buf; 1659295abce2SAllain Legacy size_t total_length; 1660295abce2SAllain Legacy struct rte_mbuf *m; 1661295abce2SAllain Legacy size_t copy_length; 1662295abce2SAllain Legacy size_t src_offset; 1663295abce2SAllain Legacy char *pkt_data; 1664295abce2SAllain Legacy unsigned int i; 1665295abce2SAllain Legacy 1666295abce2SAllain Legacy __rte_mbuf_sanity_check(mbuf, 1); 1667295abce2SAllain Legacy 1668295abce2SAllain Legacy m = mbuf; 1669295abce2SAllain Legacy src_offset = 0; 1670295abce2SAllain Legacy total_length = rte_pktmbuf_pkt_len(m); 1671295abce2SAllain Legacy for (i = 0; (i < count) && (m != NULL); i++) { 1672295abce2SAllain Legacy /* fill each destination buffer */ 1673295abce2SAllain Legacy buf = buffers[i]; 1674295abce2SAllain Legacy 1675295abce2SAllain Legacy if (i < count - 1) { 1676295abce2SAllain Legacy /* prefetch next entry while processing this one */ 1677295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buffers[i + 1]); 1678295abce2SAllain Legacy rte_prefetch0(pkt_buf); 1679295abce2SAllain Legacy } 1680295abce2SAllain Legacy 1681295abce2SAllain Legacy /* Adjust pointers for guest addressing */ 1682295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, buf); 1683295abce2SAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 1684295abce2SAllain Legacy 1685295abce2SAllain Legacy /* setup the buffer chain */ 1686295abce2SAllain Legacy if (previous_buf != NULL) 1687295abce2SAllain Legacy previous_buf->next = buf; 1688295abce2SAllain Legacy else 1689295abce2SAllain Legacy first_buf = pkt_buf; 1690295abce2SAllain Legacy 1691295abce2SAllain Legacy previous_buf = pkt_buf; 1692295abce2SAllain Legacy 1693295abce2SAllain Legacy do { 1694295abce2SAllain Legacy /* 1695295abce2SAllain Legacy * copy as many source mbuf segments as will fit in the 1696295abce2SAllain Legacy * destination buffer. 1697295abce2SAllain Legacy */ 1698295abce2SAllain Legacy copy_length = RTE_MIN((avp->host_mbuf_size - 1699295abce2SAllain Legacy pkt_buf->data_len), 1700295abce2SAllain Legacy (rte_pktmbuf_data_len(m) - 1701295abce2SAllain Legacy src_offset)); 1702295abce2SAllain Legacy rte_memcpy(RTE_PTR_ADD(pkt_data, pkt_buf->data_len), 1703295abce2SAllain Legacy RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *), 1704295abce2SAllain Legacy src_offset), 1705295abce2SAllain Legacy copy_length); 1706295abce2SAllain Legacy pkt_buf->data_len += copy_length; 1707295abce2SAllain Legacy src_offset += copy_length; 1708295abce2SAllain Legacy 1709295abce2SAllain Legacy if (likely(src_offset == rte_pktmbuf_data_len(m))) { 1710295abce2SAllain Legacy /* need a new source buffer */ 1711295abce2SAllain Legacy m = m->next; 1712295abce2SAllain Legacy src_offset = 0; 1713295abce2SAllain Legacy } 1714295abce2SAllain Legacy 1715295abce2SAllain Legacy if (unlikely(pkt_buf->data_len == 1716295abce2SAllain Legacy avp->host_mbuf_size)) { 1717295abce2SAllain Legacy /* need a new destination buffer */ 1718295abce2SAllain Legacy break; 1719295abce2SAllain Legacy } 1720295abce2SAllain Legacy 1721295abce2SAllain Legacy } while (m != NULL); 1722295abce2SAllain Legacy } 1723295abce2SAllain Legacy 1724295abce2SAllain Legacy first_buf->nb_segs = count; 1725295abce2SAllain Legacy first_buf->pkt_len = total_length; 1726295abce2SAllain Legacy 1727295abce2SAllain Legacy if (mbuf->ol_flags & PKT_TX_VLAN_PKT) { 1728295abce2SAllain Legacy first_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT; 1729295abce2SAllain Legacy first_buf->vlan_tci = mbuf->vlan_tci; 1730295abce2SAllain Legacy } 1731295abce2SAllain Legacy 1732295abce2SAllain Legacy avp_dev_buffer_sanity_check(avp, buffers[0]); 1733295abce2SAllain Legacy 1734295abce2SAllain Legacy return total_length; 1735295abce2SAllain Legacy } 1736295abce2SAllain Legacy 1737295abce2SAllain Legacy 1738295abce2SAllain Legacy static uint16_t 1739295abce2SAllain Legacy avp_xmit_scattered_pkts(void *tx_queue, 1740295abce2SAllain Legacy struct rte_mbuf **tx_pkts, 1741295abce2SAllain Legacy uint16_t nb_pkts) 1742295abce2SAllain Legacy { 1743295abce2SAllain Legacy struct rte_avp_desc *avp_bufs[(AVP_MAX_TX_BURST * 1744295abce2SAllain Legacy RTE_AVP_MAX_MBUF_SEGMENTS)]; 1745295abce2SAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 1746295abce2SAllain Legacy struct rte_avp_desc *tx_bufs[AVP_MAX_TX_BURST]; 1747295abce2SAllain Legacy struct avp_dev *avp = txq->avp; 1748295abce2SAllain Legacy struct rte_avp_fifo *alloc_q; 1749295abce2SAllain Legacy struct rte_avp_fifo *tx_q; 1750295abce2SAllain Legacy unsigned int count, avail, n; 1751295abce2SAllain Legacy unsigned int orig_nb_pkts; 1752295abce2SAllain Legacy struct rte_mbuf *m; 1753295abce2SAllain Legacy unsigned int required; 1754295abce2SAllain Legacy unsigned int segments; 1755295abce2SAllain Legacy unsigned int tx_bytes; 1756295abce2SAllain Legacy unsigned int i; 1757295abce2SAllain Legacy 1758295abce2SAllain Legacy orig_nb_pkts = nb_pkts; 175982e140b8SAllain Legacy if (unlikely(avp->flags & AVP_F_DETACHED)) { 176082e140b8SAllain Legacy /* VM live migration in progress */ 176182e140b8SAllain Legacy /* TODO ... buffer for X packets then drop? */ 176282e140b8SAllain Legacy txq->errors += nb_pkts; 176382e140b8SAllain Legacy return 0; 176482e140b8SAllain Legacy } 176582e140b8SAllain Legacy 1766295abce2SAllain Legacy tx_q = avp->tx_q[txq->queue_id]; 1767295abce2SAllain Legacy alloc_q = avp->alloc_q[txq->queue_id]; 1768295abce2SAllain Legacy 1769295abce2SAllain Legacy /* limit the number of transmitted packets to the max burst size */ 1770295abce2SAllain Legacy if (unlikely(nb_pkts > AVP_MAX_TX_BURST)) 1771295abce2SAllain Legacy nb_pkts = AVP_MAX_TX_BURST; 1772295abce2SAllain Legacy 1773295abce2SAllain Legacy /* determine how many buffers are available to copy into */ 1774295abce2SAllain Legacy avail = avp_fifo_count(alloc_q); 1775295abce2SAllain Legacy if (unlikely(avail > (AVP_MAX_TX_BURST * 1776295abce2SAllain Legacy RTE_AVP_MAX_MBUF_SEGMENTS))) 1777295abce2SAllain Legacy avail = AVP_MAX_TX_BURST * RTE_AVP_MAX_MBUF_SEGMENTS; 1778295abce2SAllain Legacy 1779295abce2SAllain Legacy /* determine how many slots are available in the transmit queue */ 1780295abce2SAllain Legacy count = avp_fifo_free_count(tx_q); 1781295abce2SAllain Legacy 1782295abce2SAllain Legacy /* determine how many packets can be sent */ 1783295abce2SAllain Legacy nb_pkts = RTE_MIN(count, nb_pkts); 1784295abce2SAllain Legacy 1785295abce2SAllain Legacy /* determine how many packets will fit in the available buffers */ 1786295abce2SAllain Legacy count = 0; 1787295abce2SAllain Legacy segments = 0; 1788295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) { 1789295abce2SAllain Legacy m = tx_pkts[i]; 1790295abce2SAllain Legacy if (likely(i < (unsigned int)nb_pkts - 1)) { 1791295abce2SAllain Legacy /* prefetch next entry while processing this one */ 1792295abce2SAllain Legacy rte_prefetch0(tx_pkts[i + 1]); 1793295abce2SAllain Legacy } 1794295abce2SAllain Legacy required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) / 1795295abce2SAllain Legacy avp->host_mbuf_size; 1796295abce2SAllain Legacy 1797295abce2SAllain Legacy if (unlikely((required == 0) || 1798295abce2SAllain Legacy (required > RTE_AVP_MAX_MBUF_SEGMENTS))) 1799295abce2SAllain Legacy break; 1800295abce2SAllain Legacy else if (unlikely(required + segments > avail)) 1801295abce2SAllain Legacy break; 1802295abce2SAllain Legacy segments += required; 1803295abce2SAllain Legacy count++; 1804295abce2SAllain Legacy } 1805295abce2SAllain Legacy nb_pkts = count; 1806295abce2SAllain Legacy 1807295abce2SAllain Legacy if (unlikely(nb_pkts == 0)) { 1808295abce2SAllain Legacy /* no available buffers, or no space on the tx queue */ 1809295abce2SAllain Legacy txq->errors += orig_nb_pkts; 1810295abce2SAllain Legacy return 0; 1811295abce2SAllain Legacy } 1812295abce2SAllain Legacy 1813295abce2SAllain Legacy PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n", 1814295abce2SAllain Legacy nb_pkts, tx_q); 1815295abce2SAllain Legacy 1816295abce2SAllain Legacy /* retrieve sufficient send buffers */ 1817295abce2SAllain Legacy n = avp_fifo_get(alloc_q, (void **)&avp_bufs, segments); 1818295abce2SAllain Legacy if (unlikely(n != segments)) { 1819295abce2SAllain Legacy PMD_TX_LOG(DEBUG, "Failed to allocate buffers " 1820295abce2SAllain Legacy "n=%u, segments=%u, orig=%u\n", 1821295abce2SAllain Legacy n, segments, orig_nb_pkts); 1822295abce2SAllain Legacy txq->errors += orig_nb_pkts; 1823295abce2SAllain Legacy return 0; 1824295abce2SAllain Legacy } 1825295abce2SAllain Legacy 1826295abce2SAllain Legacy tx_bytes = 0; 1827295abce2SAllain Legacy count = 0; 1828295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) { 1829295abce2SAllain Legacy /* process each packet to be transmitted */ 1830295abce2SAllain Legacy m = tx_pkts[i]; 1831295abce2SAllain Legacy 1832295abce2SAllain Legacy /* determine how many buffers are required for this packet */ 1833295abce2SAllain Legacy required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) / 1834295abce2SAllain Legacy avp->host_mbuf_size; 1835295abce2SAllain Legacy 1836295abce2SAllain Legacy tx_bytes += avp_dev_copy_to_buffers(avp, m, 1837295abce2SAllain Legacy &avp_bufs[count], required); 1838295abce2SAllain Legacy tx_bufs[i] = avp_bufs[count]; 1839295abce2SAllain Legacy count += required; 1840295abce2SAllain Legacy 1841295abce2SAllain Legacy /* free the original mbuf */ 1842295abce2SAllain Legacy rte_pktmbuf_free(m); 1843295abce2SAllain Legacy } 1844295abce2SAllain Legacy 1845295abce2SAllain Legacy txq->packets += nb_pkts; 1846295abce2SAllain Legacy txq->bytes += tx_bytes; 1847295abce2SAllain Legacy 1848295abce2SAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS 1849295abce2SAllain Legacy for (i = 0; i < nb_pkts; i++) 1850295abce2SAllain Legacy avp_dev_buffer_sanity_check(avp, tx_bufs[i]); 1851295abce2SAllain Legacy #endif 1852295abce2SAllain Legacy 1853295abce2SAllain Legacy /* send the packets */ 1854295abce2SAllain Legacy n = avp_fifo_put(tx_q, (void **)&tx_bufs[0], nb_pkts); 1855295abce2SAllain Legacy if (unlikely(n != orig_nb_pkts)) 1856295abce2SAllain Legacy txq->errors += (orig_nb_pkts - n); 1857295abce2SAllain Legacy 1858295abce2SAllain Legacy return n; 1859295abce2SAllain Legacy } 1860295abce2SAllain Legacy 1861295abce2SAllain Legacy 1862295abce2SAllain Legacy static uint16_t 1863295abce2SAllain Legacy avp_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) 1864295abce2SAllain Legacy { 1865295abce2SAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 1866295abce2SAllain Legacy struct rte_avp_desc *avp_bufs[AVP_MAX_TX_BURST]; 1867295abce2SAllain Legacy struct avp_dev *avp = txq->avp; 1868295abce2SAllain Legacy struct rte_avp_desc *pkt_buf; 1869295abce2SAllain Legacy struct rte_avp_fifo *alloc_q; 1870295abce2SAllain Legacy struct rte_avp_fifo *tx_q; 1871295abce2SAllain Legacy unsigned int count, avail, n; 1872295abce2SAllain Legacy struct rte_mbuf *m; 1873295abce2SAllain Legacy unsigned int pkt_len; 1874295abce2SAllain Legacy unsigned int tx_bytes; 1875295abce2SAllain Legacy char *pkt_data; 1876295abce2SAllain Legacy unsigned int i; 1877295abce2SAllain Legacy 187882e140b8SAllain Legacy if (unlikely(avp->flags & AVP_F_DETACHED)) { 187982e140b8SAllain Legacy /* VM live migration in progress */ 188082e140b8SAllain Legacy /* TODO ... buffer for X packets then drop?! */ 188182e140b8SAllain Legacy txq->errors++; 188282e140b8SAllain Legacy return 0; 188382e140b8SAllain Legacy } 188482e140b8SAllain Legacy 1885295abce2SAllain Legacy tx_q = avp->tx_q[txq->queue_id]; 1886295abce2SAllain Legacy alloc_q = avp->alloc_q[txq->queue_id]; 1887295abce2SAllain Legacy 1888295abce2SAllain Legacy /* limit the number of transmitted packets to the max burst size */ 1889295abce2SAllain Legacy if (unlikely(nb_pkts > AVP_MAX_TX_BURST)) 1890295abce2SAllain Legacy nb_pkts = AVP_MAX_TX_BURST; 1891295abce2SAllain Legacy 1892295abce2SAllain Legacy /* determine how many buffers are available to copy into */ 1893295abce2SAllain Legacy avail = avp_fifo_count(alloc_q); 1894295abce2SAllain Legacy 1895295abce2SAllain Legacy /* determine how many slots are available in the transmit queue */ 1896295abce2SAllain Legacy count = avp_fifo_free_count(tx_q); 1897295abce2SAllain Legacy 1898295abce2SAllain Legacy /* determine how many packets can be sent */ 1899295abce2SAllain Legacy count = RTE_MIN(count, avail); 1900295abce2SAllain Legacy count = RTE_MIN(count, nb_pkts); 1901295abce2SAllain Legacy 1902295abce2SAllain Legacy if (unlikely(count == 0)) { 1903295abce2SAllain Legacy /* no available buffers, or no space on the tx queue */ 1904295abce2SAllain Legacy txq->errors += nb_pkts; 1905295abce2SAllain Legacy return 0; 1906295abce2SAllain Legacy } 1907295abce2SAllain Legacy 1908295abce2SAllain Legacy PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n", 1909295abce2SAllain Legacy count, tx_q); 1910295abce2SAllain Legacy 1911295abce2SAllain Legacy /* retrieve sufficient send buffers */ 1912295abce2SAllain Legacy n = avp_fifo_get(alloc_q, (void **)&avp_bufs, count); 1913295abce2SAllain Legacy if (unlikely(n != count)) { 1914295abce2SAllain Legacy txq->errors++; 1915295abce2SAllain Legacy return 0; 1916295abce2SAllain Legacy } 1917295abce2SAllain Legacy 1918295abce2SAllain Legacy tx_bytes = 0; 1919295abce2SAllain Legacy for (i = 0; i < count; i++) { 1920295abce2SAllain Legacy /* prefetch next entry while processing the current one */ 1921295abce2SAllain Legacy if (i < count - 1) { 1922295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, 1923295abce2SAllain Legacy avp_bufs[i + 1]); 1924295abce2SAllain Legacy rte_prefetch0(pkt_buf); 1925295abce2SAllain Legacy } 1926295abce2SAllain Legacy 1927295abce2SAllain Legacy /* process each packet to be transmitted */ 1928295abce2SAllain Legacy m = tx_pkts[i]; 1929295abce2SAllain Legacy 1930295abce2SAllain Legacy /* Adjust pointers for guest addressing */ 1931295abce2SAllain Legacy pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]); 1932295abce2SAllain Legacy pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data); 1933295abce2SAllain Legacy pkt_len = rte_pktmbuf_pkt_len(m); 1934295abce2SAllain Legacy 1935295abce2SAllain Legacy if (unlikely((pkt_len > avp->guest_mbuf_size) || 1936295abce2SAllain Legacy (pkt_len > avp->host_mbuf_size))) { 1937295abce2SAllain Legacy /* 1938295abce2SAllain Legacy * application should be using the scattered transmit 1939295abce2SAllain Legacy * function; send it truncated to avoid the performance 1940295abce2SAllain Legacy * hit of having to manage returning the already 1941295abce2SAllain Legacy * allocated buffer to the free list. This should not 1942295abce2SAllain Legacy * happen since the application should have set the 1943295abce2SAllain Legacy * max_rx_pkt_len based on its MTU and it should be 1944295abce2SAllain Legacy * policing its own packet sizes. 1945295abce2SAllain Legacy */ 1946295abce2SAllain Legacy txq->errors++; 1947295abce2SAllain Legacy pkt_len = RTE_MIN(avp->guest_mbuf_size, 1948295abce2SAllain Legacy avp->host_mbuf_size); 1949295abce2SAllain Legacy } 1950295abce2SAllain Legacy 1951295abce2SAllain Legacy /* copy data out of our mbuf and into the AVP buffer */ 1952295abce2SAllain Legacy rte_memcpy(pkt_data, rte_pktmbuf_mtod(m, void *), pkt_len); 1953295abce2SAllain Legacy pkt_buf->pkt_len = pkt_len; 1954295abce2SAllain Legacy pkt_buf->data_len = pkt_len; 1955295abce2SAllain Legacy pkt_buf->nb_segs = 1; 1956295abce2SAllain Legacy pkt_buf->next = NULL; 1957295abce2SAllain Legacy 1958295abce2SAllain Legacy if (m->ol_flags & PKT_TX_VLAN_PKT) { 1959295abce2SAllain Legacy pkt_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT; 1960295abce2SAllain Legacy pkt_buf->vlan_tci = m->vlan_tci; 1961295abce2SAllain Legacy } 1962295abce2SAllain Legacy 1963295abce2SAllain Legacy tx_bytes += pkt_len; 1964295abce2SAllain Legacy 1965295abce2SAllain Legacy /* free the original mbuf */ 1966295abce2SAllain Legacy rte_pktmbuf_free(m); 1967295abce2SAllain Legacy } 1968295abce2SAllain Legacy 1969295abce2SAllain Legacy txq->packets += count; 1970295abce2SAllain Legacy txq->bytes += tx_bytes; 1971295abce2SAllain Legacy 1972295abce2SAllain Legacy /* send the packets */ 1973295abce2SAllain Legacy n = avp_fifo_put(tx_q, (void **)&avp_bufs[0], count); 1974295abce2SAllain Legacy 1975295abce2SAllain Legacy return n; 1976295abce2SAllain Legacy } 1977295abce2SAllain Legacy 1978cce4367fSAllain Legacy static void 1979cce4367fSAllain Legacy avp_dev_rx_queue_release(void *rx_queue) 1980cce4367fSAllain Legacy { 1981cce4367fSAllain Legacy struct avp_queue *rxq = (struct avp_queue *)rx_queue; 1982cce4367fSAllain Legacy struct avp_dev *avp = rxq->avp; 1983cce4367fSAllain Legacy struct rte_eth_dev_data *data = avp->dev_data; 1984cce4367fSAllain Legacy unsigned int i; 1985cce4367fSAllain Legacy 1986cce4367fSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 1987cce4367fSAllain Legacy if (data->rx_queues[i] == rxq) 1988cce4367fSAllain Legacy data->rx_queues[i] = NULL; 1989cce4367fSAllain Legacy } 1990cce4367fSAllain Legacy } 1991cce4367fSAllain Legacy 1992cce4367fSAllain Legacy static void 1993cce4367fSAllain Legacy avp_dev_tx_queue_release(void *tx_queue) 1994cce4367fSAllain Legacy { 1995cce4367fSAllain Legacy struct avp_queue *txq = (struct avp_queue *)tx_queue; 1996cce4367fSAllain Legacy struct avp_dev *avp = txq->avp; 1997cce4367fSAllain Legacy struct rte_eth_dev_data *data = avp->dev_data; 1998cce4367fSAllain Legacy unsigned int i; 1999cce4367fSAllain Legacy 2000cce4367fSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 2001cce4367fSAllain Legacy if (data->tx_queues[i] == txq) 2002cce4367fSAllain Legacy data->tx_queues[i] = NULL; 2003cce4367fSAllain Legacy } 2004cce4367fSAllain Legacy } 2005cce4367fSAllain Legacy 2006cce4367fSAllain Legacy static int 20071a859223SAllain Legacy avp_dev_configure(struct rte_eth_dev *eth_dev) 20081a859223SAllain Legacy { 2009c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 20101a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 20111a859223SAllain Legacy struct rte_avp_device_info *host_info; 20121a859223SAllain Legacy struct rte_avp_device_config config; 20131a859223SAllain Legacy int mask = 0; 20141a859223SAllain Legacy void *addr; 20151a859223SAllain Legacy int ret; 20161a859223SAllain Legacy 201782e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 201882e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 201982e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Operation not supported during VM live migration\n"); 202082e140b8SAllain Legacy ret = -ENOTSUP; 202182e140b8SAllain Legacy goto unlock; 202282e140b8SAllain Legacy } 202382e140b8SAllain Legacy 20241a859223SAllain Legacy addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr; 20251a859223SAllain Legacy host_info = (struct rte_avp_device_info *)addr; 20261a859223SAllain Legacy 20271a859223SAllain Legacy /* Setup required number of queues */ 20281a859223SAllain Legacy _avp_set_queue_counts(eth_dev); 20291a859223SAllain Legacy 20301a859223SAllain Legacy mask = (ETH_VLAN_STRIP_MASK | 20311a859223SAllain Legacy ETH_VLAN_FILTER_MASK | 20321a859223SAllain Legacy ETH_VLAN_EXTEND_MASK); 2033289ba0c0SDavid Harton ret = avp_vlan_offload_set(eth_dev, mask); 2034289ba0c0SDavid Harton if (ret < 0) { 2035289ba0c0SDavid Harton PMD_DRV_LOG(ERR, "VLAN offload set failed by host, ret=%d\n", 2036289ba0c0SDavid Harton ret); 2037289ba0c0SDavid Harton goto unlock; 2038289ba0c0SDavid Harton } 20391a859223SAllain Legacy 20401a859223SAllain Legacy /* update device config */ 20411a859223SAllain Legacy memset(&config, 0, sizeof(config)); 20421a859223SAllain Legacy config.device_id = host_info->device_id; 20431a859223SAllain Legacy config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK; 20441a859223SAllain Legacy config.driver_version = AVP_DPDK_DRIVER_VERSION; 20451a859223SAllain Legacy config.features = avp->features; 20461a859223SAllain Legacy config.num_tx_queues = avp->num_tx_queues; 20471a859223SAllain Legacy config.num_rx_queues = avp->num_rx_queues; 20481a859223SAllain Legacy 20491a859223SAllain Legacy ret = avp_dev_ctrl_set_config(eth_dev, &config); 20501a859223SAllain Legacy if (ret < 0) { 20511a859223SAllain Legacy PMD_DRV_LOG(ERR, "Config request failed by host, ret=%d\n", 20521a859223SAllain Legacy ret); 20531a859223SAllain Legacy goto unlock; 20541a859223SAllain Legacy } 20551a859223SAllain Legacy 20561a859223SAllain Legacy avp->flags |= AVP_F_CONFIGURED; 20571a859223SAllain Legacy ret = 0; 20581a859223SAllain Legacy 20591a859223SAllain Legacy unlock: 206082e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 20611a859223SAllain Legacy return ret; 20621a859223SAllain Legacy } 20631a859223SAllain Legacy 2064ea37523dSAllain Legacy static int 2065ea37523dSAllain Legacy avp_dev_start(struct rte_eth_dev *eth_dev) 2066ea37523dSAllain Legacy { 2067ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 2068ea37523dSAllain Legacy int ret; 2069ea37523dSAllain Legacy 207082e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 207182e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 207282e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Operation not supported during VM live migration\n"); 207382e140b8SAllain Legacy ret = -ENOTSUP; 207482e140b8SAllain Legacy goto unlock; 207582e140b8SAllain Legacy } 207682e140b8SAllain Legacy 2077ea37523dSAllain Legacy /* disable features that we do not support */ 2078ea37523dSAllain Legacy eth_dev->data->dev_conf.rxmode.hw_ip_checksum = 0; 2079ea37523dSAllain Legacy eth_dev->data->dev_conf.rxmode.hw_vlan_filter = 0; 2080ea37523dSAllain Legacy eth_dev->data->dev_conf.rxmode.hw_vlan_extend = 0; 2081ea37523dSAllain Legacy eth_dev->data->dev_conf.rxmode.hw_strip_crc = 0; 2082ea37523dSAllain Legacy 2083ea37523dSAllain Legacy /* update link state */ 2084ea37523dSAllain Legacy ret = avp_dev_ctrl_set_link_state(eth_dev, 1); 2085ea37523dSAllain Legacy if (ret < 0) { 2086ea37523dSAllain Legacy PMD_DRV_LOG(ERR, "Link state change failed by host, ret=%d\n", 2087ea37523dSAllain Legacy ret); 2088ea37523dSAllain Legacy goto unlock; 2089ea37523dSAllain Legacy } 2090ea37523dSAllain Legacy 2091ea37523dSAllain Legacy /* remember current link state */ 2092ea37523dSAllain Legacy avp->flags |= AVP_F_LINKUP; 2093ea37523dSAllain Legacy 2094ea37523dSAllain Legacy ret = 0; 2095ea37523dSAllain Legacy 2096ea37523dSAllain Legacy unlock: 209782e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 2098ea37523dSAllain Legacy return ret; 2099ea37523dSAllain Legacy } 2100ea37523dSAllain Legacy 2101ea37523dSAllain Legacy static void 2102ea37523dSAllain Legacy avp_dev_stop(struct rte_eth_dev *eth_dev) 2103ea37523dSAllain Legacy { 2104ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 2105ea37523dSAllain Legacy int ret; 2106ea37523dSAllain Legacy 210782e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 210882e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 210982e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Operation not supported during VM live migration\n"); 211082e140b8SAllain Legacy goto unlock; 211182e140b8SAllain Legacy } 211282e140b8SAllain Legacy 211382e140b8SAllain Legacy /* remember current link state */ 2114ea37523dSAllain Legacy avp->flags &= ~AVP_F_LINKUP; 2115ea37523dSAllain Legacy 2116ea37523dSAllain Legacy /* update link state */ 2117ea37523dSAllain Legacy ret = avp_dev_ctrl_set_link_state(eth_dev, 0); 2118ea37523dSAllain Legacy if (ret < 0) { 2119ea37523dSAllain Legacy PMD_DRV_LOG(ERR, "Link state change failed by host, ret=%d\n", 2120ea37523dSAllain Legacy ret); 2121ea37523dSAllain Legacy } 212282e140b8SAllain Legacy 212382e140b8SAllain Legacy unlock: 212482e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 2125ea37523dSAllain Legacy } 2126ea37523dSAllain Legacy 2127ea37523dSAllain Legacy static void 2128ea37523dSAllain Legacy avp_dev_close(struct rte_eth_dev *eth_dev) 2129ea37523dSAllain Legacy { 2130ea37523dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 2131ea37523dSAllain Legacy int ret; 2132ea37523dSAllain Legacy 213382e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 213482e140b8SAllain Legacy if (avp->flags & AVP_F_DETACHED) { 213582e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Operation not supported during VM live migration\n"); 213682e140b8SAllain Legacy goto unlock; 213782e140b8SAllain Legacy } 213882e140b8SAllain Legacy 2139ea37523dSAllain Legacy /* remember current link state */ 2140ea37523dSAllain Legacy avp->flags &= ~AVP_F_LINKUP; 2141ea37523dSAllain Legacy avp->flags &= ~AVP_F_CONFIGURED; 2142ea37523dSAllain Legacy 214382e140b8SAllain Legacy ret = avp_dev_disable_interrupts(eth_dev); 214482e140b8SAllain Legacy if (ret < 0) { 214582e140b8SAllain Legacy PMD_DRV_LOG(ERR, "Failed to disable interrupts\n"); 214682e140b8SAllain Legacy /* continue */ 214782e140b8SAllain Legacy } 214882e140b8SAllain Legacy 2149ea37523dSAllain Legacy /* update device state */ 2150ea37523dSAllain Legacy ret = avp_dev_ctrl_shutdown(eth_dev); 2151ea37523dSAllain Legacy if (ret < 0) { 2152ea37523dSAllain Legacy PMD_DRV_LOG(ERR, "Device shutdown failed by host, ret=%d\n", 2153ea37523dSAllain Legacy ret); 2154ea37523dSAllain Legacy /* continue */ 2155ea37523dSAllain Legacy } 215682e140b8SAllain Legacy 215782e140b8SAllain Legacy unlock: 215882e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 2159ea37523dSAllain Legacy } 21601a859223SAllain Legacy 21611a859223SAllain Legacy static int 21621a859223SAllain Legacy avp_dev_link_update(struct rte_eth_dev *eth_dev, 21631a859223SAllain Legacy __rte_unused int wait_to_complete) 21641a859223SAllain Legacy { 21651a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 21661a859223SAllain Legacy struct rte_eth_link *link = ð_dev->data->dev_link; 21671a859223SAllain Legacy 21681a859223SAllain Legacy link->link_speed = ETH_SPEED_NUM_10G; 21691a859223SAllain Legacy link->link_duplex = ETH_LINK_FULL_DUPLEX; 21701a859223SAllain Legacy link->link_status = !!(avp->flags & AVP_F_LINKUP); 21711a859223SAllain Legacy 21721a859223SAllain Legacy return -1; 21731a859223SAllain Legacy } 21741a859223SAllain Legacy 21758129545eSAllain Legacy static void 21768129545eSAllain Legacy avp_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) 21778129545eSAllain Legacy { 21788129545eSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 21798129545eSAllain Legacy 218082e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 21818129545eSAllain Legacy if ((avp->flags & AVP_F_PROMISC) == 0) { 21828129545eSAllain Legacy avp->flags |= AVP_F_PROMISC; 21838129545eSAllain Legacy PMD_DRV_LOG(DEBUG, "Promiscuous mode enabled on %u\n", 21848129545eSAllain Legacy eth_dev->data->port_id); 21858129545eSAllain Legacy } 218682e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 21878129545eSAllain Legacy } 21888129545eSAllain Legacy 21898129545eSAllain Legacy static void 21908129545eSAllain Legacy avp_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) 21918129545eSAllain Legacy { 21928129545eSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 21938129545eSAllain Legacy 219482e140b8SAllain Legacy rte_spinlock_lock(&avp->lock); 21958129545eSAllain Legacy if ((avp->flags & AVP_F_PROMISC) != 0) { 21968129545eSAllain Legacy avp->flags &= ~AVP_F_PROMISC; 21978129545eSAllain Legacy PMD_DRV_LOG(DEBUG, "Promiscuous mode disabled on %u\n", 21988129545eSAllain Legacy eth_dev->data->port_id); 21998129545eSAllain Legacy } 220082e140b8SAllain Legacy rte_spinlock_unlock(&avp->lock); 22018129545eSAllain Legacy } 22021a859223SAllain Legacy 22031a859223SAllain Legacy static void 22041a859223SAllain Legacy avp_dev_info_get(struct rte_eth_dev *eth_dev, 22051a859223SAllain Legacy struct rte_eth_dev_info *dev_info) 22061a859223SAllain Legacy { 22071a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 22081a859223SAllain Legacy 2209c0802544SFerruh Yigit dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 22101a859223SAllain Legacy dev_info->max_rx_queues = avp->max_rx_queues; 22111a859223SAllain Legacy dev_info->max_tx_queues = avp->max_tx_queues; 22121a859223SAllain Legacy dev_info->min_rx_bufsize = AVP_MIN_RX_BUFSIZE; 22131a859223SAllain Legacy dev_info->max_rx_pktlen = avp->max_rx_pkt_len; 22141a859223SAllain Legacy dev_info->max_mac_addrs = AVP_MAX_MAC_ADDRS; 22151a859223SAllain Legacy if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) { 22161a859223SAllain Legacy dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP; 22171a859223SAllain Legacy dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT; 22181a859223SAllain Legacy } 22191a859223SAllain Legacy } 22201a859223SAllain Legacy 2221289ba0c0SDavid Harton static int 22221a859223SAllain Legacy avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) 22231a859223SAllain Legacy { 22241a859223SAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 22251a859223SAllain Legacy 22261a859223SAllain Legacy if (mask & ETH_VLAN_STRIP_MASK) { 22271a859223SAllain Legacy if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) { 22281a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip) 22291a859223SAllain Legacy avp->features |= RTE_AVP_FEATURE_VLAN_OFFLOAD; 22301a859223SAllain Legacy else 22311a859223SAllain Legacy avp->features &= ~RTE_AVP_FEATURE_VLAN_OFFLOAD; 22321a859223SAllain Legacy } else { 22331a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN strip offload not supported\n"); 22341a859223SAllain Legacy } 22351a859223SAllain Legacy } 22361a859223SAllain Legacy 22371a859223SAllain Legacy if (mask & ETH_VLAN_FILTER_MASK) { 22381a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_filter) 22391a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN filter offload not supported\n"); 22401a859223SAllain Legacy } 22411a859223SAllain Legacy 22421a859223SAllain Legacy if (mask & ETH_VLAN_EXTEND_MASK) { 22431a859223SAllain Legacy if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend) 22441a859223SAllain Legacy PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n"); 22451a859223SAllain Legacy } 2246289ba0c0SDavid Harton 2247289ba0c0SDavid Harton return 0; 22481a859223SAllain Legacy } 22491a859223SAllain Legacy 2250d5b0924bSMatan Azrad static int 22515a5abe2dSAllain Legacy avp_dev_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats) 22525a5abe2dSAllain Legacy { 22535a5abe2dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 22545a5abe2dSAllain Legacy unsigned int i; 22555a5abe2dSAllain Legacy 22565a5abe2dSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 22575a5abe2dSAllain Legacy struct avp_queue *rxq = avp->dev_data->rx_queues[i]; 22585a5abe2dSAllain Legacy 22595a5abe2dSAllain Legacy if (rxq) { 22605a5abe2dSAllain Legacy stats->ipackets += rxq->packets; 22615a5abe2dSAllain Legacy stats->ibytes += rxq->bytes; 22625a5abe2dSAllain Legacy stats->ierrors += rxq->errors; 22635a5abe2dSAllain Legacy 22645a5abe2dSAllain Legacy stats->q_ipackets[i] += rxq->packets; 22655a5abe2dSAllain Legacy stats->q_ibytes[i] += rxq->bytes; 22665a5abe2dSAllain Legacy stats->q_errors[i] += rxq->errors; 22675a5abe2dSAllain Legacy } 22685a5abe2dSAllain Legacy } 22695a5abe2dSAllain Legacy 22705a5abe2dSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 22715a5abe2dSAllain Legacy struct avp_queue *txq = avp->dev_data->tx_queues[i]; 22725a5abe2dSAllain Legacy 22735a5abe2dSAllain Legacy if (txq) { 22745a5abe2dSAllain Legacy stats->opackets += txq->packets; 22755a5abe2dSAllain Legacy stats->obytes += txq->bytes; 22765a5abe2dSAllain Legacy stats->oerrors += txq->errors; 22775a5abe2dSAllain Legacy 22785a5abe2dSAllain Legacy stats->q_opackets[i] += txq->packets; 22795a5abe2dSAllain Legacy stats->q_obytes[i] += txq->bytes; 22805a5abe2dSAllain Legacy stats->q_errors[i] += txq->errors; 22815a5abe2dSAllain Legacy } 22825a5abe2dSAllain Legacy } 2283d5b0924bSMatan Azrad 2284d5b0924bSMatan Azrad return 0; 22855a5abe2dSAllain Legacy } 22865a5abe2dSAllain Legacy 22875a5abe2dSAllain Legacy static void 22885a5abe2dSAllain Legacy avp_dev_stats_reset(struct rte_eth_dev *eth_dev) 22895a5abe2dSAllain Legacy { 22905a5abe2dSAllain Legacy struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 22915a5abe2dSAllain Legacy unsigned int i; 22925a5abe2dSAllain Legacy 22935a5abe2dSAllain Legacy for (i = 0; i < avp->num_rx_queues; i++) { 22945a5abe2dSAllain Legacy struct avp_queue *rxq = avp->dev_data->rx_queues[i]; 22955a5abe2dSAllain Legacy 22965a5abe2dSAllain Legacy if (rxq) { 22975a5abe2dSAllain Legacy rxq->bytes = 0; 22985a5abe2dSAllain Legacy rxq->packets = 0; 22995a5abe2dSAllain Legacy rxq->errors = 0; 23005a5abe2dSAllain Legacy } 23015a5abe2dSAllain Legacy } 23025a5abe2dSAllain Legacy 23035a5abe2dSAllain Legacy for (i = 0; i < avp->num_tx_queues; i++) { 23045a5abe2dSAllain Legacy struct avp_queue *txq = avp->dev_data->tx_queues[i]; 23055a5abe2dSAllain Legacy 23065a5abe2dSAllain Legacy if (txq) { 23075a5abe2dSAllain Legacy txq->bytes = 0; 23085a5abe2dSAllain Legacy txq->packets = 0; 23095a5abe2dSAllain Legacy txq->errors = 0; 23105a5abe2dSAllain Legacy } 23115a5abe2dSAllain Legacy } 23125a5abe2dSAllain Legacy } 23135a5abe2dSAllain Legacy 2314fdf91e0fSJan Blunck RTE_PMD_REGISTER_PCI(net_avp, rte_avp_pmd); 2315908072e9SAllain Legacy RTE_PMD_REGISTER_PCI_TABLE(net_avp, pci_id_avp_map); 2316e6b790c0SStephen Hemminger 2317e6b790c0SStephen Hemminger RTE_INIT(avp_init_log); 2318e6b790c0SStephen Hemminger static void 2319e6b790c0SStephen Hemminger avp_init_log(void) 2320e6b790c0SStephen Hemminger { 2321*bd34cd80SHarry van Haaren avp_logtype_driver = rte_log_register("pmd.net.avp.driver"); 2322e6b790c0SStephen Hemminger if (avp_logtype_driver >= 0) 2323e6b790c0SStephen Hemminger rte_log_set_level(avp_logtype_driver, RTE_LOG_NOTICE); 2324e6b790c0SStephen Hemminger } 2325