xref: /dpdk/drivers/net/avp/avp_ethdev.c (revision 5a5abe2de94b8164eee2ab8f45cb51c42d04dedd)
1908072e9SAllain Legacy /*
2908072e9SAllain Legacy  *   BSD LICENSE
3908072e9SAllain Legacy  *
4908072e9SAllain Legacy  * Copyright (c) 2013-2017, Wind River Systems, Inc.
5908072e9SAllain Legacy  *
6908072e9SAllain Legacy  * Redistribution and use in source and binary forms, with or without
7908072e9SAllain Legacy  * modification, are permitted provided that the following conditions are met:
8908072e9SAllain Legacy  *
9908072e9SAllain Legacy  * 1) Redistributions of source code must retain the above copyright notice,
10908072e9SAllain Legacy  * this list of conditions and the following disclaimer.
11908072e9SAllain Legacy  *
12908072e9SAllain Legacy  * 2) Redistributions in binary form must reproduce the above copyright notice,
13908072e9SAllain Legacy  * this list of conditions and the following disclaimer in the documentation
14908072e9SAllain Legacy  * and/or other materials provided with the distribution.
15908072e9SAllain Legacy  *
16908072e9SAllain Legacy  * 3) Neither the name of Wind River Systems nor the names of its contributors
17908072e9SAllain Legacy  * may be used to endorse or promote products derived from this software
18908072e9SAllain Legacy  * without specific prior written permission.
19908072e9SAllain Legacy  *
20908072e9SAllain Legacy  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21908072e9SAllain Legacy  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22908072e9SAllain Legacy  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23908072e9SAllain Legacy  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24908072e9SAllain Legacy  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25908072e9SAllain Legacy  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26908072e9SAllain Legacy  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27908072e9SAllain Legacy  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28908072e9SAllain Legacy  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29908072e9SAllain Legacy  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30908072e9SAllain Legacy  * POSSIBILITY OF SUCH DAMAGE.
31908072e9SAllain Legacy  */
32908072e9SAllain Legacy 
33908072e9SAllain Legacy #include <stdint.h>
34908072e9SAllain Legacy #include <string.h>
35908072e9SAllain Legacy #include <stdio.h>
36908072e9SAllain Legacy #include <errno.h>
37908072e9SAllain Legacy #include <unistd.h>
38908072e9SAllain Legacy 
39908072e9SAllain Legacy #include <rte_ethdev.h>
40908072e9SAllain Legacy #include <rte_memcpy.h>
41908072e9SAllain Legacy #include <rte_string_fns.h>
42908072e9SAllain Legacy #include <rte_memzone.h>
43908072e9SAllain Legacy #include <rte_malloc.h>
44908072e9SAllain Legacy #include <rte_atomic.h>
45908072e9SAllain Legacy #include <rte_branch_prediction.h>
46908072e9SAllain Legacy #include <rte_pci.h>
47908072e9SAllain Legacy #include <rte_ether.h>
48908072e9SAllain Legacy #include <rte_common.h>
49908072e9SAllain Legacy #include <rte_cycles.h>
50908072e9SAllain Legacy #include <rte_byteorder.h>
51908072e9SAllain Legacy #include <rte_dev.h>
52908072e9SAllain Legacy #include <rte_memory.h>
53908072e9SAllain Legacy #include <rte_eal.h>
54c0ad5842SAllain Legacy #include <rte_io.h>
55908072e9SAllain Legacy 
56908072e9SAllain Legacy #include "rte_avp_common.h"
57908072e9SAllain Legacy #include "rte_avp_fifo.h"
58908072e9SAllain Legacy 
59908072e9SAllain Legacy #include "avp_logs.h"
60908072e9SAllain Legacy 
61908072e9SAllain Legacy 
62908072e9SAllain Legacy 
631a859223SAllain Legacy static int avp_dev_configure(struct rte_eth_dev *dev);
641a859223SAllain Legacy static void avp_dev_info_get(struct rte_eth_dev *dev,
651a859223SAllain Legacy 			     struct rte_eth_dev_info *dev_info);
661a859223SAllain Legacy static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
671a859223SAllain Legacy static int avp_dev_link_update(struct rte_eth_dev *dev,
681a859223SAllain Legacy 			       __rte_unused int wait_to_complete);
69cce4367fSAllain Legacy static int avp_dev_rx_queue_setup(struct rte_eth_dev *dev,
70cce4367fSAllain Legacy 				  uint16_t rx_queue_id,
71cce4367fSAllain Legacy 				  uint16_t nb_rx_desc,
72cce4367fSAllain Legacy 				  unsigned int socket_id,
73cce4367fSAllain Legacy 				  const struct rte_eth_rxconf *rx_conf,
74cce4367fSAllain Legacy 				  struct rte_mempool *pool);
751a859223SAllain Legacy 
76cce4367fSAllain Legacy static int avp_dev_tx_queue_setup(struct rte_eth_dev *dev,
77cce4367fSAllain Legacy 				  uint16_t tx_queue_id,
78cce4367fSAllain Legacy 				  uint16_t nb_tx_desc,
79cce4367fSAllain Legacy 				  unsigned int socket_id,
80cce4367fSAllain Legacy 				  const struct rte_eth_txconf *tx_conf);
81cce4367fSAllain Legacy 
8250db69fdSAllain Legacy static uint16_t avp_recv_scattered_pkts(void *rx_queue,
8350db69fdSAllain Legacy 					struct rte_mbuf **rx_pkts,
8450db69fdSAllain Legacy 					uint16_t nb_pkts);
8550db69fdSAllain Legacy 
8650db69fdSAllain Legacy static uint16_t avp_recv_pkts(void *rx_queue,
8750db69fdSAllain Legacy 			      struct rte_mbuf **rx_pkts,
8850db69fdSAllain Legacy 			      uint16_t nb_pkts);
89295abce2SAllain Legacy 
90295abce2SAllain Legacy static uint16_t avp_xmit_scattered_pkts(void *tx_queue,
91295abce2SAllain Legacy 					struct rte_mbuf **tx_pkts,
92295abce2SAllain Legacy 					uint16_t nb_pkts);
93295abce2SAllain Legacy 
94295abce2SAllain Legacy static uint16_t avp_xmit_pkts(void *tx_queue,
95295abce2SAllain Legacy 			      struct rte_mbuf **tx_pkts,
96295abce2SAllain Legacy 			      uint16_t nb_pkts);
97295abce2SAllain Legacy 
98cce4367fSAllain Legacy static void avp_dev_rx_queue_release(void *rxq);
99cce4367fSAllain Legacy static void avp_dev_tx_queue_release(void *txq);
100295abce2SAllain Legacy 
101*5a5abe2dSAllain Legacy static void avp_dev_stats_get(struct rte_eth_dev *dev,
102*5a5abe2dSAllain Legacy 			      struct rte_eth_stats *stats);
103*5a5abe2dSAllain Legacy static void avp_dev_stats_reset(struct rte_eth_dev *dev);
104*5a5abe2dSAllain Legacy 
105295abce2SAllain Legacy 
106908072e9SAllain Legacy #define AVP_DEV_TO_PCI(eth_dev) RTE_DEV_TO_PCI((eth_dev)->device)
107908072e9SAllain Legacy 
108908072e9SAllain Legacy 
10950db69fdSAllain Legacy #define AVP_MAX_RX_BURST 64
110295abce2SAllain Legacy #define AVP_MAX_TX_BURST 64
111908072e9SAllain Legacy #define AVP_MAX_MAC_ADDRS 1
112908072e9SAllain Legacy #define AVP_MIN_RX_BUFSIZE ETHER_MIN_LEN
113908072e9SAllain Legacy 
114908072e9SAllain Legacy 
115908072e9SAllain Legacy /*
116908072e9SAllain Legacy  * Defines the number of microseconds to wait before checking the response
117908072e9SAllain Legacy  * queue for completion.
118908072e9SAllain Legacy  */
119908072e9SAllain Legacy #define AVP_REQUEST_DELAY_USECS (5000)
120908072e9SAllain Legacy 
121908072e9SAllain Legacy /*
122908072e9SAllain Legacy  * Defines the number times to check the response queue for completion before
123908072e9SAllain Legacy  * declaring a timeout.
124908072e9SAllain Legacy  */
125908072e9SAllain Legacy #define AVP_MAX_REQUEST_RETRY (100)
126908072e9SAllain Legacy 
127908072e9SAllain Legacy /* Defines the current PCI driver version number */
128908072e9SAllain Legacy #define AVP_DPDK_DRIVER_VERSION RTE_AVP_CURRENT_GUEST_VERSION
129908072e9SAllain Legacy 
130908072e9SAllain Legacy /*
131908072e9SAllain Legacy  * The set of PCI devices this driver supports
132908072e9SAllain Legacy  */
133908072e9SAllain Legacy static const struct rte_pci_id pci_id_avp_map[] = {
134908072e9SAllain Legacy 	{ .vendor_id = RTE_AVP_PCI_VENDOR_ID,
135908072e9SAllain Legacy 	  .device_id = RTE_AVP_PCI_DEVICE_ID,
136908072e9SAllain Legacy 	  .subsystem_vendor_id = RTE_AVP_PCI_SUB_VENDOR_ID,
137908072e9SAllain Legacy 	  .subsystem_device_id = RTE_AVP_PCI_SUB_DEVICE_ID,
138908072e9SAllain Legacy 	  .class_id = RTE_CLASS_ANY_ID,
139908072e9SAllain Legacy 	},
140908072e9SAllain Legacy 
141908072e9SAllain Legacy 	{ .vendor_id = 0, /* sentinel */
142908072e9SAllain Legacy 	},
143908072e9SAllain Legacy };
144908072e9SAllain Legacy 
1451a859223SAllain Legacy /*
1461a859223SAllain Legacy  * dev_ops for avp, bare necessities for basic operation
1471a859223SAllain Legacy  */
1481a859223SAllain Legacy static const struct eth_dev_ops avp_eth_dev_ops = {
1491a859223SAllain Legacy 	.dev_configure       = avp_dev_configure,
1501a859223SAllain Legacy 	.dev_infos_get       = avp_dev_info_get,
1511a859223SAllain Legacy 	.vlan_offload_set    = avp_vlan_offload_set,
152*5a5abe2dSAllain Legacy 	.stats_get           = avp_dev_stats_get,
153*5a5abe2dSAllain Legacy 	.stats_reset         = avp_dev_stats_reset,
1541a859223SAllain Legacy 	.link_update         = avp_dev_link_update,
155cce4367fSAllain Legacy 	.rx_queue_setup      = avp_dev_rx_queue_setup,
156cce4367fSAllain Legacy 	.rx_queue_release    = avp_dev_rx_queue_release,
157cce4367fSAllain Legacy 	.tx_queue_setup      = avp_dev_tx_queue_setup,
158cce4367fSAllain Legacy 	.tx_queue_release    = avp_dev_tx_queue_release,
1591a859223SAllain Legacy };
160908072e9SAllain Legacy 
161c0ad5842SAllain Legacy /**@{ AVP device flags */
162c0ad5842SAllain Legacy #define AVP_F_PROMISC (1 << 1)
163c0ad5842SAllain Legacy #define AVP_F_CONFIGURED (1 << 2)
164c0ad5842SAllain Legacy #define AVP_F_LINKUP (1 << 3)
165c0ad5842SAllain Legacy /**@} */
166c0ad5842SAllain Legacy 
167c0ad5842SAllain Legacy /* Ethernet device validation marker */
168c0ad5842SAllain Legacy #define AVP_ETHDEV_MAGIC 0x92972862
169c0ad5842SAllain Legacy 
170908072e9SAllain Legacy /*
171908072e9SAllain Legacy  * Defines the AVP device attributes which are attached to an RTE ethernet
172908072e9SAllain Legacy  * device
173908072e9SAllain Legacy  */
174908072e9SAllain Legacy struct avp_dev {
175908072e9SAllain Legacy 	uint32_t magic; /**< Memory validation marker */
176908072e9SAllain Legacy 	uint64_t device_id; /**< Unique system identifier */
177908072e9SAllain Legacy 	struct ether_addr ethaddr; /**< Host specified MAC address */
178908072e9SAllain Legacy 	struct rte_eth_dev_data *dev_data;
179908072e9SAllain Legacy 	/**< Back pointer to ethernet device data */
180908072e9SAllain Legacy 	volatile uint32_t flags; /**< Device operational flags */
181908072e9SAllain Legacy 	uint8_t port_id; /**< Ethernet port identifier */
182908072e9SAllain Legacy 	struct rte_mempool *pool; /**< pkt mbuf mempool */
183908072e9SAllain Legacy 	unsigned int guest_mbuf_size; /**< local pool mbuf size */
184908072e9SAllain Legacy 	unsigned int host_mbuf_size; /**< host mbuf size */
185908072e9SAllain Legacy 	unsigned int max_rx_pkt_len; /**< maximum receive unit */
186908072e9SAllain Legacy 	uint32_t host_features; /**< Supported feature bitmap */
187908072e9SAllain Legacy 	uint32_t features; /**< Enabled feature bitmap */
188908072e9SAllain Legacy 	unsigned int num_tx_queues; /**< Negotiated number of transmit queues */
189908072e9SAllain Legacy 	unsigned int max_tx_queues; /**< Maximum number of transmit queues */
190908072e9SAllain Legacy 	unsigned int num_rx_queues; /**< Negotiated number of receive queues */
191908072e9SAllain Legacy 	unsigned int max_rx_queues; /**< Maximum number of receive queues */
192908072e9SAllain Legacy 
193908072e9SAllain Legacy 	struct rte_avp_fifo *tx_q[RTE_AVP_MAX_QUEUES]; /**< TX queue */
194908072e9SAllain Legacy 	struct rte_avp_fifo *rx_q[RTE_AVP_MAX_QUEUES]; /**< RX queue */
195908072e9SAllain Legacy 	struct rte_avp_fifo *alloc_q[RTE_AVP_MAX_QUEUES];
196908072e9SAllain Legacy 	/**< Allocated mbufs queue */
197908072e9SAllain Legacy 	struct rte_avp_fifo *free_q[RTE_AVP_MAX_QUEUES];
198908072e9SAllain Legacy 	/**< To be freed mbufs queue */
199908072e9SAllain Legacy 
200908072e9SAllain Legacy 	/* For request & response */
201908072e9SAllain Legacy 	struct rte_avp_fifo *req_q; /**< Request queue */
202908072e9SAllain Legacy 	struct rte_avp_fifo *resp_q; /**< Response queue */
203908072e9SAllain Legacy 	void *host_sync_addr; /**< (host) Req/Resp Mem address */
204908072e9SAllain Legacy 	void *sync_addr; /**< Req/Resp Mem address */
205908072e9SAllain Legacy 	void *host_mbuf_addr; /**< (host) MBUF pool start address */
206908072e9SAllain Legacy 	void *mbuf_addr; /**< MBUF pool start address */
207908072e9SAllain Legacy } __rte_cache_aligned;
208908072e9SAllain Legacy 
209908072e9SAllain Legacy /* RTE ethernet private data */
210908072e9SAllain Legacy struct avp_adapter {
211908072e9SAllain Legacy 	struct avp_dev avp;
212908072e9SAllain Legacy } __rte_cache_aligned;
213908072e9SAllain Legacy 
214c0ad5842SAllain Legacy 
215c0ad5842SAllain Legacy /* 32-bit MMIO register write */
216c0ad5842SAllain Legacy #define AVP_WRITE32(_value, _addr) rte_write32_relaxed((_value), (_addr))
217c0ad5842SAllain Legacy 
218c0ad5842SAllain Legacy /* 32-bit MMIO register read */
219c0ad5842SAllain Legacy #define AVP_READ32(_addr) rte_read32_relaxed((_addr))
220c0ad5842SAllain Legacy 
221908072e9SAllain Legacy /* Macro to cast the ethernet device private data to a AVP object */
222908072e9SAllain Legacy #define AVP_DEV_PRIVATE_TO_HW(adapter) \
223908072e9SAllain Legacy 	(&((struct avp_adapter *)adapter)->avp)
224908072e9SAllain Legacy 
225908072e9SAllain Legacy /*
226c0ad5842SAllain Legacy  * Defines the structure of a AVP device queue for the purpose of handling the
227c0ad5842SAllain Legacy  * receive and transmit burst callback functions
228c0ad5842SAllain Legacy  */
229c0ad5842SAllain Legacy struct avp_queue {
230c0ad5842SAllain Legacy 	struct rte_eth_dev_data *dev_data;
231c0ad5842SAllain Legacy 	/**< Backpointer to ethernet device data */
232c0ad5842SAllain Legacy 	struct avp_dev *avp; /**< Backpointer to AVP device */
233c0ad5842SAllain Legacy 	uint16_t queue_id;
234c0ad5842SAllain Legacy 	/**< Queue identifier used for indexing current queue */
235c0ad5842SAllain Legacy 	uint16_t queue_base;
236c0ad5842SAllain Legacy 	/**< Base queue identifier for queue servicing */
237c0ad5842SAllain Legacy 	uint16_t queue_limit;
238c0ad5842SAllain Legacy 	/**< Maximum queue identifier for queue servicing */
239c0ad5842SAllain Legacy 
240c0ad5842SAllain Legacy 	uint64_t packets;
241c0ad5842SAllain Legacy 	uint64_t bytes;
242c0ad5842SAllain Legacy 	uint64_t errors;
243c0ad5842SAllain Legacy };
244c0ad5842SAllain Legacy 
2451a859223SAllain Legacy /* send a request and wait for a response
2461a859223SAllain Legacy  *
2471a859223SAllain Legacy  * @warning must be called while holding the avp->lock spinlock.
2481a859223SAllain Legacy  */
2491a859223SAllain Legacy static int
2501a859223SAllain Legacy avp_dev_process_request(struct avp_dev *avp, struct rte_avp_request *request)
2511a859223SAllain Legacy {
2521a859223SAllain Legacy 	unsigned int retry = AVP_MAX_REQUEST_RETRY;
2531a859223SAllain Legacy 	void *resp_addr = NULL;
2541a859223SAllain Legacy 	unsigned int count;
2551a859223SAllain Legacy 	int ret;
2561a859223SAllain Legacy 
2571a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Sending request %u to host\n", request->req_id);
2581a859223SAllain Legacy 
2591a859223SAllain Legacy 	request->result = -ENOTSUP;
2601a859223SAllain Legacy 
2611a859223SAllain Legacy 	/* Discard any stale responses before starting a new request */
2621a859223SAllain Legacy 	while (avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1))
2631a859223SAllain Legacy 		PMD_DRV_LOG(DEBUG, "Discarding stale response\n");
2641a859223SAllain Legacy 
2651a859223SAllain Legacy 	rte_memcpy(avp->sync_addr, request, sizeof(*request));
2661a859223SAllain Legacy 	count = avp_fifo_put(avp->req_q, &avp->host_sync_addr, 1);
2671a859223SAllain Legacy 	if (count < 1) {
2681a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Cannot send request %u to host\n",
2691a859223SAllain Legacy 			    request->req_id);
2701a859223SAllain Legacy 		ret = -EBUSY;
2711a859223SAllain Legacy 		goto done;
2721a859223SAllain Legacy 	}
2731a859223SAllain Legacy 
2741a859223SAllain Legacy 	while (retry--) {
2751a859223SAllain Legacy 		/* wait for a response */
2761a859223SAllain Legacy 		usleep(AVP_REQUEST_DELAY_USECS);
2771a859223SAllain Legacy 
2781a859223SAllain Legacy 		count = avp_fifo_count(avp->resp_q);
2791a859223SAllain Legacy 		if (count >= 1) {
2801a859223SAllain Legacy 			/* response received */
2811a859223SAllain Legacy 			break;
2821a859223SAllain Legacy 		}
2831a859223SAllain Legacy 
2841a859223SAllain Legacy 		if ((count < 1) && (retry == 0)) {
2851a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "Timeout while waiting for a response for %u\n",
2861a859223SAllain Legacy 				    request->req_id);
2871a859223SAllain Legacy 			ret = -ETIME;
2881a859223SAllain Legacy 			goto done;
2891a859223SAllain Legacy 		}
2901a859223SAllain Legacy 	}
2911a859223SAllain Legacy 
2921a859223SAllain Legacy 	/* retrieve the response */
2931a859223SAllain Legacy 	count = avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1);
2941a859223SAllain Legacy 	if ((count != 1) || (resp_addr != avp->host_sync_addr)) {
2951a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Invalid response from host, count=%u resp=%p host_sync_addr=%p\n",
2961a859223SAllain Legacy 			    count, resp_addr, avp->host_sync_addr);
2971a859223SAllain Legacy 		ret = -ENODATA;
2981a859223SAllain Legacy 		goto done;
2991a859223SAllain Legacy 	}
3001a859223SAllain Legacy 
3011a859223SAllain Legacy 	/* copy to user buffer */
3021a859223SAllain Legacy 	rte_memcpy(request, avp->sync_addr, sizeof(*request));
3031a859223SAllain Legacy 	ret = 0;
3041a859223SAllain Legacy 
3051a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Result %d received for request %u\n",
3061a859223SAllain Legacy 		    request->result, request->req_id);
3071a859223SAllain Legacy 
3081a859223SAllain Legacy done:
3091a859223SAllain Legacy 	return ret;
3101a859223SAllain Legacy }
3111a859223SAllain Legacy 
3121a859223SAllain Legacy static int
3131a859223SAllain Legacy avp_dev_ctrl_set_config(struct rte_eth_dev *eth_dev,
3141a859223SAllain Legacy 			struct rte_avp_device_config *config)
3151a859223SAllain Legacy {
3161a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
3171a859223SAllain Legacy 	struct rte_avp_request request;
3181a859223SAllain Legacy 	int ret;
3191a859223SAllain Legacy 
3201a859223SAllain Legacy 	/* setup a configure request */
3211a859223SAllain Legacy 	memset(&request, 0, sizeof(request));
3221a859223SAllain Legacy 	request.req_id = RTE_AVP_REQ_CFG_DEVICE;
3231a859223SAllain Legacy 	memcpy(&request.config, config, sizeof(request.config));
3241a859223SAllain Legacy 
3251a859223SAllain Legacy 	ret = avp_dev_process_request(avp, &request);
3261a859223SAllain Legacy 
3271a859223SAllain Legacy 	return ret == 0 ? request.result : ret;
3281a859223SAllain Legacy }
3291a859223SAllain Legacy 
33050db69fdSAllain Legacy /* translate from host mbuf virtual address to guest virtual address */
33150db69fdSAllain Legacy static inline void *
33250db69fdSAllain Legacy avp_dev_translate_buffer(struct avp_dev *avp, void *host_mbuf_address)
33350db69fdSAllain Legacy {
33450db69fdSAllain Legacy 	return RTE_PTR_ADD(RTE_PTR_SUB(host_mbuf_address,
33550db69fdSAllain Legacy 				       (uintptr_t)avp->host_mbuf_addr),
33650db69fdSAllain Legacy 			   (uintptr_t)avp->mbuf_addr);
33750db69fdSAllain Legacy }
33850db69fdSAllain Legacy 
339c0ad5842SAllain Legacy /* translate from host physical address to guest virtual address */
340c0ad5842SAllain Legacy static void *
341c0ad5842SAllain Legacy avp_dev_translate_address(struct rte_eth_dev *eth_dev,
342c0ad5842SAllain Legacy 			  phys_addr_t host_phys_addr)
343c0ad5842SAllain Legacy {
344c0ad5842SAllain Legacy 	struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev);
345c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
346c0ad5842SAllain Legacy 	struct rte_avp_memmap_info *info;
347c0ad5842SAllain Legacy 	struct rte_avp_memmap *map;
348c0ad5842SAllain Legacy 	off_t offset;
349c0ad5842SAllain Legacy 	void *addr;
350c0ad5842SAllain Legacy 	unsigned int i;
351c0ad5842SAllain Legacy 
352c0ad5842SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_MEMORY_BAR].addr;
353c0ad5842SAllain Legacy 	resource = &pci_dev->mem_resource[RTE_AVP_PCI_MEMMAP_BAR];
354c0ad5842SAllain Legacy 	info = (struct rte_avp_memmap_info *)resource->addr;
355c0ad5842SAllain Legacy 
356c0ad5842SAllain Legacy 	offset = 0;
357c0ad5842SAllain Legacy 	for (i = 0; i < info->nb_maps; i++) {
358c0ad5842SAllain Legacy 		/* search all segments looking for a matching address */
359c0ad5842SAllain Legacy 		map = &info->maps[i];
360c0ad5842SAllain Legacy 
361c0ad5842SAllain Legacy 		if ((host_phys_addr >= map->phys_addr) &&
362c0ad5842SAllain Legacy 			(host_phys_addr < (map->phys_addr + map->length))) {
363c0ad5842SAllain Legacy 			/* address is within this segment */
364c0ad5842SAllain Legacy 			offset += (host_phys_addr - map->phys_addr);
365c0ad5842SAllain Legacy 			addr = RTE_PTR_ADD(addr, offset);
366c0ad5842SAllain Legacy 
367c0ad5842SAllain Legacy 			PMD_DRV_LOG(DEBUG, "Translating host physical 0x%" PRIx64 " to guest virtual 0x%p\n",
368c0ad5842SAllain Legacy 				    host_phys_addr, addr);
369c0ad5842SAllain Legacy 
370c0ad5842SAllain Legacy 			return addr;
371c0ad5842SAllain Legacy 		}
372c0ad5842SAllain Legacy 		offset += map->length;
373c0ad5842SAllain Legacy 	}
374c0ad5842SAllain Legacy 
375c0ad5842SAllain Legacy 	return NULL;
376c0ad5842SAllain Legacy }
377c0ad5842SAllain Legacy 
378c0ad5842SAllain Legacy /* verify that the incoming device version is compatible with our version */
379c0ad5842SAllain Legacy static int
380c0ad5842SAllain Legacy avp_dev_version_check(uint32_t version)
381c0ad5842SAllain Legacy {
382c0ad5842SAllain Legacy 	uint32_t driver = RTE_AVP_STRIP_MINOR_VERSION(AVP_DPDK_DRIVER_VERSION);
383c0ad5842SAllain Legacy 	uint32_t device = RTE_AVP_STRIP_MINOR_VERSION(version);
384c0ad5842SAllain Legacy 
385c0ad5842SAllain Legacy 	if (device <= driver) {
386c0ad5842SAllain Legacy 		/* the host driver version is less than or equal to ours */
387c0ad5842SAllain Legacy 		return 0;
388c0ad5842SAllain Legacy 	}
389c0ad5842SAllain Legacy 
390c0ad5842SAllain Legacy 	return 1;
391c0ad5842SAllain Legacy }
392c0ad5842SAllain Legacy 
393c0ad5842SAllain Legacy /* verify that memory regions have expected version and validation markers */
394c0ad5842SAllain Legacy static int
395c0ad5842SAllain Legacy avp_dev_check_regions(struct rte_eth_dev *eth_dev)
396c0ad5842SAllain Legacy {
397c0ad5842SAllain Legacy 	struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev);
398c0ad5842SAllain Legacy 	struct rte_avp_memmap_info *memmap;
399c0ad5842SAllain Legacy 	struct rte_avp_device_info *info;
400c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
401c0ad5842SAllain Legacy 	unsigned int i;
402c0ad5842SAllain Legacy 
403c0ad5842SAllain Legacy 	/* Dump resource info for debug */
404c0ad5842SAllain Legacy 	for (i = 0; i < PCI_MAX_RESOURCE; i++) {
405c0ad5842SAllain Legacy 		resource = &pci_dev->mem_resource[i];
406c0ad5842SAllain Legacy 		if ((resource->phys_addr == 0) || (resource->len == 0))
407c0ad5842SAllain Legacy 			continue;
408c0ad5842SAllain Legacy 
409c0ad5842SAllain Legacy 		PMD_DRV_LOG(DEBUG, "resource[%u]: phys=0x%" PRIx64 " len=%" PRIu64 " addr=%p\n",
410c0ad5842SAllain Legacy 			    i, resource->phys_addr,
411c0ad5842SAllain Legacy 			    resource->len, resource->addr);
412c0ad5842SAllain Legacy 
413c0ad5842SAllain Legacy 		switch (i) {
414c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MEMMAP_BAR:
415c0ad5842SAllain Legacy 			memmap = (struct rte_avp_memmap_info *)resource->addr;
416c0ad5842SAllain Legacy 			if ((memmap->magic != RTE_AVP_MEMMAP_MAGIC) ||
417c0ad5842SAllain Legacy 			    (memmap->version != RTE_AVP_MEMMAP_VERSION)) {
418c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Invalid memmap magic 0x%08x and version %u\n",
419c0ad5842SAllain Legacy 					    memmap->magic, memmap->version);
420c0ad5842SAllain Legacy 				return -EINVAL;
421c0ad5842SAllain Legacy 			}
422c0ad5842SAllain Legacy 			break;
423c0ad5842SAllain Legacy 
424c0ad5842SAllain Legacy 		case RTE_AVP_PCI_DEVICE_BAR:
425c0ad5842SAllain Legacy 			info = (struct rte_avp_device_info *)resource->addr;
426c0ad5842SAllain Legacy 			if ((info->magic != RTE_AVP_DEVICE_MAGIC) ||
427c0ad5842SAllain Legacy 			    avp_dev_version_check(info->version)) {
428c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Invalid device info magic 0x%08x or version 0x%08x > 0x%08x\n",
429c0ad5842SAllain Legacy 					    info->magic, info->version,
430c0ad5842SAllain Legacy 					    AVP_DPDK_DRIVER_VERSION);
431c0ad5842SAllain Legacy 				return -EINVAL;
432c0ad5842SAllain Legacy 			}
433c0ad5842SAllain Legacy 			break;
434c0ad5842SAllain Legacy 
435c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MEMORY_BAR:
436c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MMIO_BAR:
437c0ad5842SAllain Legacy 			if (resource->addr == NULL) {
438c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Missing address space for BAR%u\n",
439c0ad5842SAllain Legacy 					    i);
440c0ad5842SAllain Legacy 				return -EINVAL;
441c0ad5842SAllain Legacy 			}
442c0ad5842SAllain Legacy 			break;
443c0ad5842SAllain Legacy 
444c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MSIX_BAR:
445c0ad5842SAllain Legacy 		default:
446c0ad5842SAllain Legacy 			/* no validation required */
447c0ad5842SAllain Legacy 			break;
448c0ad5842SAllain Legacy 		}
449c0ad5842SAllain Legacy 	}
450c0ad5842SAllain Legacy 
451c0ad5842SAllain Legacy 	return 0;
452c0ad5842SAllain Legacy }
453c0ad5842SAllain Legacy 
4541a859223SAllain Legacy static void
455cce4367fSAllain Legacy _avp_set_rx_queue_mappings(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
456cce4367fSAllain Legacy {
457cce4367fSAllain Legacy 	struct avp_dev *avp =
458cce4367fSAllain Legacy 		AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
459cce4367fSAllain Legacy 	struct avp_queue *rxq;
460cce4367fSAllain Legacy 	uint16_t queue_count;
461cce4367fSAllain Legacy 	uint16_t remainder;
462cce4367fSAllain Legacy 
463cce4367fSAllain Legacy 	rxq = (struct avp_queue *)eth_dev->data->rx_queues[rx_queue_id];
464cce4367fSAllain Legacy 
465cce4367fSAllain Legacy 	/*
466cce4367fSAllain Legacy 	 * Must map all AVP fifos as evenly as possible between the configured
467cce4367fSAllain Legacy 	 * device queues.  Each device queue will service a subset of the AVP
468cce4367fSAllain Legacy 	 * fifos. If there is an odd number of device queues the first set of
469cce4367fSAllain Legacy 	 * device queues will get the extra AVP fifos.
470cce4367fSAllain Legacy 	 */
471cce4367fSAllain Legacy 	queue_count = avp->num_rx_queues / eth_dev->data->nb_rx_queues;
472cce4367fSAllain Legacy 	remainder = avp->num_rx_queues % eth_dev->data->nb_rx_queues;
473cce4367fSAllain Legacy 	if (rx_queue_id < remainder) {
474cce4367fSAllain Legacy 		/* these queues must service one extra FIFO */
475cce4367fSAllain Legacy 		rxq->queue_base = rx_queue_id * (queue_count + 1);
476cce4367fSAllain Legacy 		rxq->queue_limit = rxq->queue_base + (queue_count + 1) - 1;
477cce4367fSAllain Legacy 	} else {
478cce4367fSAllain Legacy 		/* these queues service the regular number of FIFO */
479cce4367fSAllain Legacy 		rxq->queue_base = ((remainder * (queue_count + 1)) +
480cce4367fSAllain Legacy 				   ((rx_queue_id - remainder) * queue_count));
481cce4367fSAllain Legacy 		rxq->queue_limit = rxq->queue_base + queue_count - 1;
482cce4367fSAllain Legacy 	}
483cce4367fSAllain Legacy 
484cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "rxq %u at %p base %u limit %u\n",
485cce4367fSAllain Legacy 		    rx_queue_id, rxq, rxq->queue_base, rxq->queue_limit);
486cce4367fSAllain Legacy 
487cce4367fSAllain Legacy 	rxq->queue_id = rxq->queue_base;
488cce4367fSAllain Legacy }
489cce4367fSAllain Legacy 
490cce4367fSAllain Legacy static void
4911a859223SAllain Legacy _avp_set_queue_counts(struct rte_eth_dev *eth_dev)
4921a859223SAllain Legacy {
4931a859223SAllain Legacy 	struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev);
4941a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
4951a859223SAllain Legacy 	struct rte_avp_device_info *host_info;
4961a859223SAllain Legacy 	void *addr;
4971a859223SAllain Legacy 
4981a859223SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr;
4991a859223SAllain Legacy 	host_info = (struct rte_avp_device_info *)addr;
5001a859223SAllain Legacy 
5011a859223SAllain Legacy 	/*
5021a859223SAllain Legacy 	 * the transmit direction is not negotiated beyond respecting the max
5031a859223SAllain Legacy 	 * number of queues because the host can handle arbitrary guest tx
5041a859223SAllain Legacy 	 * queues (host rx queues).
5051a859223SAllain Legacy 	 */
5061a859223SAllain Legacy 	avp->num_tx_queues = eth_dev->data->nb_tx_queues;
5071a859223SAllain Legacy 
5081a859223SAllain Legacy 	/*
5091a859223SAllain Legacy 	 * the receive direction is more restrictive.  The host requires a
5101a859223SAllain Legacy 	 * minimum number of guest rx queues (host tx queues) therefore
5111a859223SAllain Legacy 	 * negotiate a value that is at least as large as the host minimum
5121a859223SAllain Legacy 	 * requirement.  If the host and guest values are not identical then a
5131a859223SAllain Legacy 	 * mapping will be established in the receive_queue_setup function.
5141a859223SAllain Legacy 	 */
5151a859223SAllain Legacy 	avp->num_rx_queues = RTE_MAX(host_info->min_rx_queues,
5161a859223SAllain Legacy 				     eth_dev->data->nb_rx_queues);
5171a859223SAllain Legacy 
5181a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Requesting %u Tx and %u Rx queues from host\n",
5191a859223SAllain Legacy 		    avp->num_tx_queues, avp->num_rx_queues);
5201a859223SAllain Legacy }
5211a859223SAllain Legacy 
522c0ad5842SAllain Legacy /*
523c0ad5842SAllain Legacy  * create a AVP device using the supplied device info by first translating it
524c0ad5842SAllain Legacy  * to guest address space(s).
525c0ad5842SAllain Legacy  */
526c0ad5842SAllain Legacy static int
527c0ad5842SAllain Legacy avp_dev_create(struct rte_pci_device *pci_dev,
528c0ad5842SAllain Legacy 	       struct rte_eth_dev *eth_dev)
529c0ad5842SAllain Legacy {
530c0ad5842SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
531c0ad5842SAllain Legacy 	struct rte_avp_device_info *host_info;
532c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
533c0ad5842SAllain Legacy 	unsigned int i;
534c0ad5842SAllain Legacy 
535c0ad5842SAllain Legacy 	resource = &pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR];
536c0ad5842SAllain Legacy 	if (resource->addr == NULL) {
537c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "BAR%u is not mapped\n",
538c0ad5842SAllain Legacy 			    RTE_AVP_PCI_DEVICE_BAR);
539c0ad5842SAllain Legacy 		return -EFAULT;
540c0ad5842SAllain Legacy 	}
541c0ad5842SAllain Legacy 	host_info = (struct rte_avp_device_info *)resource->addr;
542c0ad5842SAllain Legacy 
543c0ad5842SAllain Legacy 	if ((host_info->magic != RTE_AVP_DEVICE_MAGIC) ||
544c0ad5842SAllain Legacy 		avp_dev_version_check(host_info->version)) {
545c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Invalid AVP PCI device, magic 0x%08x version 0x%08x > 0x%08x\n",
546c0ad5842SAllain Legacy 			    host_info->magic, host_info->version,
547c0ad5842SAllain Legacy 			    AVP_DPDK_DRIVER_VERSION);
548c0ad5842SAllain Legacy 		return -EINVAL;
549c0ad5842SAllain Legacy 	}
550c0ad5842SAllain Legacy 
551c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host device is v%u.%u.%u\n",
552c0ad5842SAllain Legacy 		    RTE_AVP_GET_RELEASE_VERSION(host_info->version),
553c0ad5842SAllain Legacy 		    RTE_AVP_GET_MAJOR_VERSION(host_info->version),
554c0ad5842SAllain Legacy 		    RTE_AVP_GET_MINOR_VERSION(host_info->version));
555c0ad5842SAllain Legacy 
556c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u TX queue(s)\n",
557c0ad5842SAllain Legacy 		    host_info->min_tx_queues, host_info->max_tx_queues);
558c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u RX queue(s)\n",
559c0ad5842SAllain Legacy 		    host_info->min_rx_queues, host_info->max_rx_queues);
560c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports features 0x%08x\n",
561c0ad5842SAllain Legacy 		    host_info->features);
562c0ad5842SAllain Legacy 
563c0ad5842SAllain Legacy 	if (avp->magic != AVP_ETHDEV_MAGIC) {
564c0ad5842SAllain Legacy 		/*
565c0ad5842SAllain Legacy 		 * First time initialization (i.e., not during a VM
566c0ad5842SAllain Legacy 		 * migration)
567c0ad5842SAllain Legacy 		 */
568c0ad5842SAllain Legacy 		memset(avp, 0, sizeof(*avp));
569c0ad5842SAllain Legacy 		avp->magic = AVP_ETHDEV_MAGIC;
570c0ad5842SAllain Legacy 		avp->dev_data = eth_dev->data;
571c0ad5842SAllain Legacy 		avp->port_id = eth_dev->data->port_id;
572c0ad5842SAllain Legacy 		avp->host_mbuf_size = host_info->mbuf_size;
573c0ad5842SAllain Legacy 		avp->host_features = host_info->features;
574c0ad5842SAllain Legacy 		memcpy(&avp->ethaddr.addr_bytes[0],
575c0ad5842SAllain Legacy 		       host_info->ethaddr, ETHER_ADDR_LEN);
576c0ad5842SAllain Legacy 		/* adjust max values to not exceed our max */
577c0ad5842SAllain Legacy 		avp->max_tx_queues =
578c0ad5842SAllain Legacy 			RTE_MIN(host_info->max_tx_queues, RTE_AVP_MAX_QUEUES);
579c0ad5842SAllain Legacy 		avp->max_rx_queues =
580c0ad5842SAllain Legacy 			RTE_MIN(host_info->max_rx_queues, RTE_AVP_MAX_QUEUES);
581c0ad5842SAllain Legacy 	} else {
582c0ad5842SAllain Legacy 		/* Re-attaching during migration */
583c0ad5842SAllain Legacy 
584c0ad5842SAllain Legacy 		/* TODO... requires validation of host values */
585c0ad5842SAllain Legacy 		if ((host_info->features & avp->features) != avp->features) {
586c0ad5842SAllain Legacy 			PMD_DRV_LOG(ERR, "AVP host features mismatched; 0x%08x, host=0x%08x\n",
587c0ad5842SAllain Legacy 				    avp->features, host_info->features);
588c0ad5842SAllain Legacy 			/* this should not be possible; continue for now */
589c0ad5842SAllain Legacy 		}
590c0ad5842SAllain Legacy 	}
591c0ad5842SAllain Legacy 
592c0ad5842SAllain Legacy 	/* the device id is allowed to change over migrations */
593c0ad5842SAllain Legacy 	avp->device_id = host_info->device_id;
594c0ad5842SAllain Legacy 
595c0ad5842SAllain Legacy 	/* translate incoming host addresses to guest address space */
596c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host tx queue at 0x%" PRIx64 "\n",
597c0ad5842SAllain Legacy 		    host_info->tx_phys);
598c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host alloc queue at 0x%" PRIx64 "\n",
599c0ad5842SAllain Legacy 		    host_info->alloc_phys);
600c0ad5842SAllain Legacy 	for (i = 0; i < avp->max_tx_queues; i++) {
601c0ad5842SAllain Legacy 		avp->tx_q[i] = avp_dev_translate_address(eth_dev,
602c0ad5842SAllain Legacy 			host_info->tx_phys + (i * host_info->tx_size));
603c0ad5842SAllain Legacy 
604c0ad5842SAllain Legacy 		avp->alloc_q[i] = avp_dev_translate_address(eth_dev,
605c0ad5842SAllain Legacy 			host_info->alloc_phys + (i * host_info->alloc_size));
606c0ad5842SAllain Legacy 	}
607c0ad5842SAllain Legacy 
608c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host rx queue at 0x%" PRIx64 "\n",
609c0ad5842SAllain Legacy 		    host_info->rx_phys);
610c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host free queue at 0x%" PRIx64 "\n",
611c0ad5842SAllain Legacy 		    host_info->free_phys);
612c0ad5842SAllain Legacy 	for (i = 0; i < avp->max_rx_queues; i++) {
613c0ad5842SAllain Legacy 		avp->rx_q[i] = avp_dev_translate_address(eth_dev,
614c0ad5842SAllain Legacy 			host_info->rx_phys + (i * host_info->rx_size));
615c0ad5842SAllain Legacy 		avp->free_q[i] = avp_dev_translate_address(eth_dev,
616c0ad5842SAllain Legacy 			host_info->free_phys + (i * host_info->free_size));
617c0ad5842SAllain Legacy 	}
618c0ad5842SAllain Legacy 
619c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host request queue at 0x%" PRIx64 "\n",
620c0ad5842SAllain Legacy 		    host_info->req_phys);
621c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host response queue at 0x%" PRIx64 "\n",
622c0ad5842SAllain Legacy 		    host_info->resp_phys);
623c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host sync address at 0x%" PRIx64 "\n",
624c0ad5842SAllain Legacy 		    host_info->sync_phys);
625c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host mbuf address at 0x%" PRIx64 "\n",
626c0ad5842SAllain Legacy 		    host_info->mbuf_phys);
627c0ad5842SAllain Legacy 	avp->req_q = avp_dev_translate_address(eth_dev, host_info->req_phys);
628c0ad5842SAllain Legacy 	avp->resp_q = avp_dev_translate_address(eth_dev, host_info->resp_phys);
629c0ad5842SAllain Legacy 	avp->sync_addr =
630c0ad5842SAllain Legacy 		avp_dev_translate_address(eth_dev, host_info->sync_phys);
631c0ad5842SAllain Legacy 	avp->mbuf_addr =
632c0ad5842SAllain Legacy 		avp_dev_translate_address(eth_dev, host_info->mbuf_phys);
633c0ad5842SAllain Legacy 
634c0ad5842SAllain Legacy 	/*
635c0ad5842SAllain Legacy 	 * store the host mbuf virtual address so that we can calculate
636c0ad5842SAllain Legacy 	 * relative offsets for each mbuf as they are processed
637c0ad5842SAllain Legacy 	 */
638c0ad5842SAllain Legacy 	avp->host_mbuf_addr = host_info->mbuf_va;
639c0ad5842SAllain Legacy 	avp->host_sync_addr = host_info->sync_va;
640c0ad5842SAllain Legacy 
641c0ad5842SAllain Legacy 	/*
642c0ad5842SAllain Legacy 	 * store the maximum packet length that is supported by the host.
643c0ad5842SAllain Legacy 	 */
644c0ad5842SAllain Legacy 	avp->max_rx_pkt_len = host_info->max_rx_pkt_len;
645c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host max receive packet length is %u\n",
646c0ad5842SAllain Legacy 				host_info->max_rx_pkt_len);
647c0ad5842SAllain Legacy 
648c0ad5842SAllain Legacy 	return 0;
649c0ad5842SAllain Legacy }
650c0ad5842SAllain Legacy 
651c0ad5842SAllain Legacy /*
652908072e9SAllain Legacy  * This function is based on probe() function in avp_pci.c
653908072e9SAllain Legacy  * It returns 0 on success.
654908072e9SAllain Legacy  */
655908072e9SAllain Legacy static int
656908072e9SAllain Legacy eth_avp_dev_init(struct rte_eth_dev *eth_dev)
657908072e9SAllain Legacy {
658c0ad5842SAllain Legacy 	struct avp_dev *avp =
659c0ad5842SAllain Legacy 		AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
660908072e9SAllain Legacy 	struct rte_pci_device *pci_dev;
661c0ad5842SAllain Legacy 	int ret;
662908072e9SAllain Legacy 
663908072e9SAllain Legacy 	pci_dev = AVP_DEV_TO_PCI(eth_dev);
6641a859223SAllain Legacy 	eth_dev->dev_ops = &avp_eth_dev_ops;
66550db69fdSAllain Legacy 	eth_dev->rx_pkt_burst = &avp_recv_pkts;
666295abce2SAllain Legacy 	eth_dev->tx_pkt_burst = &avp_xmit_pkts;
667908072e9SAllain Legacy 
668908072e9SAllain Legacy 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
669908072e9SAllain Legacy 		/*
670908072e9SAllain Legacy 		 * no setup required on secondary processes.  All data is saved
671908072e9SAllain Legacy 		 * in dev_private by the primary process. All resource should
672908072e9SAllain Legacy 		 * be mapped to the same virtual address so all pointers should
673908072e9SAllain Legacy 		 * be valid.
674908072e9SAllain Legacy 		 */
67550db69fdSAllain Legacy 		if (eth_dev->data->scattered_rx) {
67650db69fdSAllain Legacy 			PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n");
67750db69fdSAllain Legacy 			eth_dev->rx_pkt_burst = avp_recv_scattered_pkts;
678295abce2SAllain Legacy 			eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts;
67950db69fdSAllain Legacy 		}
680908072e9SAllain Legacy 		return 0;
681908072e9SAllain Legacy 	}
682908072e9SAllain Legacy 
683908072e9SAllain Legacy 	rte_eth_copy_pci_info(eth_dev, pci_dev);
684908072e9SAllain Legacy 
685908072e9SAllain Legacy 	eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
686908072e9SAllain Legacy 
687c0ad5842SAllain Legacy 	/* Check BAR resources */
688c0ad5842SAllain Legacy 	ret = avp_dev_check_regions(eth_dev);
689c0ad5842SAllain Legacy 	if (ret < 0) {
690c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to validate BAR resources, ret=%d\n",
691c0ad5842SAllain Legacy 			    ret);
692c0ad5842SAllain Legacy 		return ret;
693c0ad5842SAllain Legacy 	}
694c0ad5842SAllain Legacy 
695c0ad5842SAllain Legacy 	/* Handle each subtype */
696c0ad5842SAllain Legacy 	ret = avp_dev_create(pci_dev, eth_dev);
697c0ad5842SAllain Legacy 	if (ret < 0) {
698c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to create device, ret=%d\n", ret);
699c0ad5842SAllain Legacy 		return ret;
700c0ad5842SAllain Legacy 	}
701c0ad5842SAllain Legacy 
702c0ad5842SAllain Legacy 	/* Allocate memory for storing MAC addresses */
703c0ad5842SAllain Legacy 	eth_dev->data->mac_addrs = rte_zmalloc("avp_ethdev", ETHER_ADDR_LEN, 0);
704c0ad5842SAllain Legacy 	if (eth_dev->data->mac_addrs == NULL) {
705c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses\n",
706c0ad5842SAllain Legacy 			    ETHER_ADDR_LEN);
707c0ad5842SAllain Legacy 		return -ENOMEM;
708c0ad5842SAllain Legacy 	}
709c0ad5842SAllain Legacy 
710c0ad5842SAllain Legacy 	/* Get a mac from device config */
711c0ad5842SAllain Legacy 	ether_addr_copy(&avp->ethaddr, &eth_dev->data->mac_addrs[0]);
712c0ad5842SAllain Legacy 
713908072e9SAllain Legacy 	return 0;
714908072e9SAllain Legacy }
715908072e9SAllain Legacy 
716908072e9SAllain Legacy static int
717908072e9SAllain Legacy eth_avp_dev_uninit(struct rte_eth_dev *eth_dev)
718908072e9SAllain Legacy {
719908072e9SAllain Legacy 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
720908072e9SAllain Legacy 		return -EPERM;
721908072e9SAllain Legacy 
722908072e9SAllain Legacy 	if (eth_dev->data == NULL)
723908072e9SAllain Legacy 		return 0;
724908072e9SAllain Legacy 
725c0ad5842SAllain Legacy 	if (eth_dev->data->mac_addrs != NULL) {
726c0ad5842SAllain Legacy 		rte_free(eth_dev->data->mac_addrs);
727c0ad5842SAllain Legacy 		eth_dev->data->mac_addrs = NULL;
728c0ad5842SAllain Legacy 	}
729c0ad5842SAllain Legacy 
730908072e9SAllain Legacy 	return 0;
731908072e9SAllain Legacy }
732908072e9SAllain Legacy 
733908072e9SAllain Legacy 
734908072e9SAllain Legacy static struct eth_driver rte_avp_pmd = {
735908072e9SAllain Legacy 	{
736908072e9SAllain Legacy 		.id_table = pci_id_avp_map,
737908072e9SAllain Legacy 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
738908072e9SAllain Legacy 		.probe = rte_eth_dev_pci_probe,
739908072e9SAllain Legacy 		.remove = rte_eth_dev_pci_remove,
740908072e9SAllain Legacy 	},
741908072e9SAllain Legacy 	.eth_dev_init = eth_avp_dev_init,
742908072e9SAllain Legacy 	.eth_dev_uninit = eth_avp_dev_uninit,
743908072e9SAllain Legacy 	.dev_private_size = sizeof(struct avp_adapter),
744908072e9SAllain Legacy };
745908072e9SAllain Legacy 
7461a859223SAllain Legacy static int
74750db69fdSAllain Legacy avp_dev_enable_scattered(struct rte_eth_dev *eth_dev,
74850db69fdSAllain Legacy 			 struct avp_dev *avp)
74950db69fdSAllain Legacy {
75050db69fdSAllain Legacy 	unsigned int max_rx_pkt_len;
75150db69fdSAllain Legacy 
75250db69fdSAllain Legacy 	max_rx_pkt_len = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len;
75350db69fdSAllain Legacy 
75450db69fdSAllain Legacy 	if ((max_rx_pkt_len > avp->guest_mbuf_size) ||
75550db69fdSAllain Legacy 	    (max_rx_pkt_len > avp->host_mbuf_size)) {
75650db69fdSAllain Legacy 		/*
75750db69fdSAllain Legacy 		 * If the guest MTU is greater than either the host or guest
75850db69fdSAllain Legacy 		 * buffers then chained mbufs have to be enabled in the TX
75950db69fdSAllain Legacy 		 * direction.  It is assumed that the application will not need
76050db69fdSAllain Legacy 		 * to send packets larger than their max_rx_pkt_len (MRU).
76150db69fdSAllain Legacy 		 */
76250db69fdSAllain Legacy 		return 1;
76350db69fdSAllain Legacy 	}
76450db69fdSAllain Legacy 
76550db69fdSAllain Legacy 	if ((avp->max_rx_pkt_len > avp->guest_mbuf_size) ||
76650db69fdSAllain Legacy 	    (avp->max_rx_pkt_len > avp->host_mbuf_size)) {
76750db69fdSAllain Legacy 		/*
76850db69fdSAllain Legacy 		 * If the host MRU is greater than its own mbuf size or the
76950db69fdSAllain Legacy 		 * guest mbuf size then chained mbufs have to be enabled in the
77050db69fdSAllain Legacy 		 * RX direction.
77150db69fdSAllain Legacy 		 */
77250db69fdSAllain Legacy 		return 1;
77350db69fdSAllain Legacy 	}
77450db69fdSAllain Legacy 
77550db69fdSAllain Legacy 	return 0;
77650db69fdSAllain Legacy }
77750db69fdSAllain Legacy 
77850db69fdSAllain Legacy static int
779cce4367fSAllain Legacy avp_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
780cce4367fSAllain Legacy 		       uint16_t rx_queue_id,
781cce4367fSAllain Legacy 		       uint16_t nb_rx_desc,
782cce4367fSAllain Legacy 		       unsigned int socket_id,
783cce4367fSAllain Legacy 		       const struct rte_eth_rxconf *rx_conf,
784cce4367fSAllain Legacy 		       struct rte_mempool *pool)
785cce4367fSAllain Legacy {
786cce4367fSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
787cce4367fSAllain Legacy 	struct rte_pktmbuf_pool_private *mbp_priv;
788cce4367fSAllain Legacy 	struct avp_queue *rxq;
789cce4367fSAllain Legacy 
790cce4367fSAllain Legacy 	if (rx_queue_id >= eth_dev->data->nb_rx_queues) {
791cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "RX queue id is out of range: rx_queue_id=%u, nb_rx_queues=%u\n",
792cce4367fSAllain Legacy 			    rx_queue_id, eth_dev->data->nb_rx_queues);
793cce4367fSAllain Legacy 		return -EINVAL;
794cce4367fSAllain Legacy 	}
795cce4367fSAllain Legacy 
796cce4367fSAllain Legacy 	/* Save mbuf pool pointer */
797cce4367fSAllain Legacy 	avp->pool = pool;
798cce4367fSAllain Legacy 
799cce4367fSAllain Legacy 	/* Save the local mbuf size */
800cce4367fSAllain Legacy 	mbp_priv = rte_mempool_get_priv(pool);
801cce4367fSAllain Legacy 	avp->guest_mbuf_size = (uint16_t)(mbp_priv->mbuf_data_room_size);
802cce4367fSAllain Legacy 	avp->guest_mbuf_size -= RTE_PKTMBUF_HEADROOM;
803cce4367fSAllain Legacy 
80450db69fdSAllain Legacy 	if (avp_dev_enable_scattered(eth_dev, avp)) {
80550db69fdSAllain Legacy 		if (!eth_dev->data->scattered_rx) {
80650db69fdSAllain Legacy 			PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n");
80750db69fdSAllain Legacy 			eth_dev->data->scattered_rx = 1;
80850db69fdSAllain Legacy 			eth_dev->rx_pkt_burst = avp_recv_scattered_pkts;
809295abce2SAllain Legacy 			eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts;
81050db69fdSAllain Legacy 		}
81150db69fdSAllain Legacy 	}
81250db69fdSAllain Legacy 
813cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP max_rx_pkt_len=(%u,%u) mbuf_size=(%u,%u)\n",
814cce4367fSAllain Legacy 		    avp->max_rx_pkt_len,
815cce4367fSAllain Legacy 		    eth_dev->data->dev_conf.rxmode.max_rx_pkt_len,
816cce4367fSAllain Legacy 		    avp->host_mbuf_size,
817cce4367fSAllain Legacy 		    avp->guest_mbuf_size);
818cce4367fSAllain Legacy 
819cce4367fSAllain Legacy 	/* allocate a queue object */
820cce4367fSAllain Legacy 	rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct avp_queue),
821cce4367fSAllain Legacy 				 RTE_CACHE_LINE_SIZE, socket_id);
822cce4367fSAllain Legacy 	if (rxq == NULL) {
823cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate new Rx queue object\n");
824cce4367fSAllain Legacy 		return -ENOMEM;
825cce4367fSAllain Legacy 	}
826cce4367fSAllain Legacy 
827cce4367fSAllain Legacy 	/* save back pointers to AVP and Ethernet devices */
828cce4367fSAllain Legacy 	rxq->avp = avp;
829cce4367fSAllain Legacy 	rxq->dev_data = eth_dev->data;
830cce4367fSAllain Legacy 	eth_dev->data->rx_queues[rx_queue_id] = (void *)rxq;
831cce4367fSAllain Legacy 
832cce4367fSAllain Legacy 	/* setup the queue receive mapping for the current queue. */
833cce4367fSAllain Legacy 	_avp_set_rx_queue_mappings(eth_dev, rx_queue_id);
834cce4367fSAllain Legacy 
835cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "Rx queue %u setup at %p\n", rx_queue_id, rxq);
836cce4367fSAllain Legacy 
837cce4367fSAllain Legacy 	(void)nb_rx_desc;
838cce4367fSAllain Legacy 	(void)rx_conf;
839cce4367fSAllain Legacy 	return 0;
840cce4367fSAllain Legacy }
841cce4367fSAllain Legacy 
842cce4367fSAllain Legacy static int
843cce4367fSAllain Legacy avp_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
844cce4367fSAllain Legacy 		       uint16_t tx_queue_id,
845cce4367fSAllain Legacy 		       uint16_t nb_tx_desc,
846cce4367fSAllain Legacy 		       unsigned int socket_id,
847cce4367fSAllain Legacy 		       const struct rte_eth_txconf *tx_conf)
848cce4367fSAllain Legacy {
849cce4367fSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
850cce4367fSAllain Legacy 	struct avp_queue *txq;
851cce4367fSAllain Legacy 
852cce4367fSAllain Legacy 	if (tx_queue_id >= eth_dev->data->nb_tx_queues) {
853cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "TX queue id is out of range: tx_queue_id=%u, nb_tx_queues=%u\n",
854cce4367fSAllain Legacy 			    tx_queue_id, eth_dev->data->nb_tx_queues);
855cce4367fSAllain Legacy 		return -EINVAL;
856cce4367fSAllain Legacy 	}
857cce4367fSAllain Legacy 
858cce4367fSAllain Legacy 	/* allocate a queue object */
859cce4367fSAllain Legacy 	txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct avp_queue),
860cce4367fSAllain Legacy 				 RTE_CACHE_LINE_SIZE, socket_id);
861cce4367fSAllain Legacy 	if (txq == NULL) {
862cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate new Tx queue object\n");
863cce4367fSAllain Legacy 		return -ENOMEM;
864cce4367fSAllain Legacy 	}
865cce4367fSAllain Legacy 
866cce4367fSAllain Legacy 	/* only the configured set of transmit queues are used */
867cce4367fSAllain Legacy 	txq->queue_id = tx_queue_id;
868cce4367fSAllain Legacy 	txq->queue_base = tx_queue_id;
869cce4367fSAllain Legacy 	txq->queue_limit = tx_queue_id;
870cce4367fSAllain Legacy 
871cce4367fSAllain Legacy 	/* save back pointers to AVP and Ethernet devices */
872cce4367fSAllain Legacy 	txq->avp = avp;
873cce4367fSAllain Legacy 	txq->dev_data = eth_dev->data;
874cce4367fSAllain Legacy 	eth_dev->data->tx_queues[tx_queue_id] = (void *)txq;
875cce4367fSAllain Legacy 
876cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "Tx queue %u setup at %p\n", tx_queue_id, txq);
877cce4367fSAllain Legacy 
878cce4367fSAllain Legacy 	(void)nb_tx_desc;
879cce4367fSAllain Legacy 	(void)tx_conf;
880cce4367fSAllain Legacy 	return 0;
881cce4367fSAllain Legacy }
882cce4367fSAllain Legacy 
88350db69fdSAllain Legacy static inline int
88450db69fdSAllain Legacy _avp_cmp_ether_addr(struct ether_addr *a, struct ether_addr *b)
88550db69fdSAllain Legacy {
88650db69fdSAllain Legacy 	uint16_t *_a = (uint16_t *)&a->addr_bytes[0];
88750db69fdSAllain Legacy 	uint16_t *_b = (uint16_t *)&b->addr_bytes[0];
88850db69fdSAllain Legacy 	return (_a[0] ^ _b[0]) | (_a[1] ^ _b[1]) | (_a[2] ^ _b[2]);
88950db69fdSAllain Legacy }
89050db69fdSAllain Legacy 
89150db69fdSAllain Legacy static inline int
89250db69fdSAllain Legacy _avp_mac_filter(struct avp_dev *avp, struct rte_mbuf *m)
89350db69fdSAllain Legacy {
89450db69fdSAllain Legacy 	struct ether_hdr *eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
89550db69fdSAllain Legacy 
89650db69fdSAllain Legacy 	if (likely(_avp_cmp_ether_addr(&avp->ethaddr, &eth->d_addr) == 0)) {
89750db69fdSAllain Legacy 		/* allow all packets destined to our address */
89850db69fdSAllain Legacy 		return 0;
89950db69fdSAllain Legacy 	}
90050db69fdSAllain Legacy 
90150db69fdSAllain Legacy 	if (likely(is_broadcast_ether_addr(&eth->d_addr))) {
90250db69fdSAllain Legacy 		/* allow all broadcast packets */
90350db69fdSAllain Legacy 		return 0;
90450db69fdSAllain Legacy 	}
90550db69fdSAllain Legacy 
90650db69fdSAllain Legacy 	if (likely(is_multicast_ether_addr(&eth->d_addr))) {
90750db69fdSAllain Legacy 		/* allow all multicast packets */
90850db69fdSAllain Legacy 		return 0;
90950db69fdSAllain Legacy 	}
91050db69fdSAllain Legacy 
91150db69fdSAllain Legacy 	if (avp->flags & AVP_F_PROMISC) {
91250db69fdSAllain Legacy 		/* allow all packets when in promiscuous mode */
91350db69fdSAllain Legacy 		return 0;
91450db69fdSAllain Legacy 	}
91550db69fdSAllain Legacy 
91650db69fdSAllain Legacy 	return -1;
91750db69fdSAllain Legacy }
91850db69fdSAllain Legacy 
91950db69fdSAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS
92050db69fdSAllain Legacy static inline void
92150db69fdSAllain Legacy __avp_dev_buffer_sanity_check(struct avp_dev *avp, struct rte_avp_desc *buf)
92250db69fdSAllain Legacy {
92350db69fdSAllain Legacy 	struct rte_avp_desc *first_buf;
92450db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
92550db69fdSAllain Legacy 	unsigned int pkt_len;
92650db69fdSAllain Legacy 	unsigned int nb_segs;
92750db69fdSAllain Legacy 	void *pkt_data;
92850db69fdSAllain Legacy 	unsigned int i;
92950db69fdSAllain Legacy 
93050db69fdSAllain Legacy 	first_buf = avp_dev_translate_buffer(avp, buf);
93150db69fdSAllain Legacy 
93250db69fdSAllain Legacy 	i = 0;
93350db69fdSAllain Legacy 	pkt_len = 0;
93450db69fdSAllain Legacy 	nb_segs = first_buf->nb_segs;
93550db69fdSAllain Legacy 	do {
93650db69fdSAllain Legacy 		/* Adjust pointers for guest addressing */
93750db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
93850db69fdSAllain Legacy 		if (pkt_buf == NULL)
93950db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has an invalid address %p\n",
94050db69fdSAllain Legacy 				  i, buf);
94150db69fdSAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
94250db69fdSAllain Legacy 		if (pkt_data == NULL)
94350db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has a NULL data pointer\n",
94450db69fdSAllain Legacy 				  i);
94550db69fdSAllain Legacy 		if (pkt_buf->data_len == 0)
94650db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has 0 data length\n",
94750db69fdSAllain Legacy 				  i);
94850db69fdSAllain Legacy 		pkt_len += pkt_buf->data_len;
94950db69fdSAllain Legacy 		nb_segs--;
95050db69fdSAllain Legacy 		i++;
95150db69fdSAllain Legacy 
95250db69fdSAllain Legacy 	} while (nb_segs && (buf = pkt_buf->next) != NULL);
95350db69fdSAllain Legacy 
95450db69fdSAllain Legacy 	if (nb_segs != 0)
95550db69fdSAllain Legacy 		rte_panic("bad buffer: expected %u segments found %u\n",
95650db69fdSAllain Legacy 			  first_buf->nb_segs, (first_buf->nb_segs - nb_segs));
95750db69fdSAllain Legacy 	if (pkt_len != first_buf->pkt_len)
95850db69fdSAllain Legacy 		rte_panic("bad buffer: expected length %u found %u\n",
95950db69fdSAllain Legacy 			  first_buf->pkt_len, pkt_len);
96050db69fdSAllain Legacy }
96150db69fdSAllain Legacy 
96250db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) \
96350db69fdSAllain Legacy 	__avp_dev_buffer_sanity_check((a), (b))
96450db69fdSAllain Legacy 
96550db69fdSAllain Legacy #else /* RTE_LIBRTE_AVP_DEBUG_BUFFERS */
96650db69fdSAllain Legacy 
96750db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) do {} while (0)
96850db69fdSAllain Legacy 
96950db69fdSAllain Legacy #endif
97050db69fdSAllain Legacy 
97150db69fdSAllain Legacy /*
97250db69fdSAllain Legacy  * Copy a host buffer chain to a set of mbufs.	This function assumes that
97350db69fdSAllain Legacy  * there exactly the required number of mbufs to copy all source bytes.
97450db69fdSAllain Legacy  */
97550db69fdSAllain Legacy static inline struct rte_mbuf *
97650db69fdSAllain Legacy avp_dev_copy_from_buffers(struct avp_dev *avp,
97750db69fdSAllain Legacy 			  struct rte_avp_desc *buf,
97850db69fdSAllain Legacy 			  struct rte_mbuf **mbufs,
97950db69fdSAllain Legacy 			  unsigned int count)
98050db69fdSAllain Legacy {
98150db69fdSAllain Legacy 	struct rte_mbuf *m_previous = NULL;
98250db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
98350db69fdSAllain Legacy 	unsigned int total_length = 0;
98450db69fdSAllain Legacy 	unsigned int copy_length;
98550db69fdSAllain Legacy 	unsigned int src_offset;
98650db69fdSAllain Legacy 	struct rte_mbuf *m;
98750db69fdSAllain Legacy 	uint16_t ol_flags;
98850db69fdSAllain Legacy 	uint16_t vlan_tci;
98950db69fdSAllain Legacy 	void *pkt_data;
99050db69fdSAllain Legacy 	unsigned int i;
99150db69fdSAllain Legacy 
99250db69fdSAllain Legacy 	avp_dev_buffer_sanity_check(avp, buf);
99350db69fdSAllain Legacy 
99450db69fdSAllain Legacy 	/* setup the first source buffer */
99550db69fdSAllain Legacy 	pkt_buf = avp_dev_translate_buffer(avp, buf);
99650db69fdSAllain Legacy 	pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
99750db69fdSAllain Legacy 	total_length = pkt_buf->pkt_len;
99850db69fdSAllain Legacy 	src_offset = 0;
99950db69fdSAllain Legacy 
100050db69fdSAllain Legacy 	if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) {
100150db69fdSAllain Legacy 		ol_flags = PKT_RX_VLAN_PKT;
100250db69fdSAllain Legacy 		vlan_tci = pkt_buf->vlan_tci;
100350db69fdSAllain Legacy 	} else {
100450db69fdSAllain Legacy 		ol_flags = 0;
100550db69fdSAllain Legacy 		vlan_tci = 0;
100650db69fdSAllain Legacy 	}
100750db69fdSAllain Legacy 
100850db69fdSAllain Legacy 	for (i = 0; (i < count) && (buf != NULL); i++) {
100950db69fdSAllain Legacy 		/* fill each destination buffer */
101050db69fdSAllain Legacy 		m = mbufs[i];
101150db69fdSAllain Legacy 
101250db69fdSAllain Legacy 		if (m_previous != NULL)
101350db69fdSAllain Legacy 			m_previous->next = m;
101450db69fdSAllain Legacy 
101550db69fdSAllain Legacy 		m_previous = m;
101650db69fdSAllain Legacy 
101750db69fdSAllain Legacy 		do {
101850db69fdSAllain Legacy 			/*
101950db69fdSAllain Legacy 			 * Copy as many source buffers as will fit in the
102050db69fdSAllain Legacy 			 * destination buffer.
102150db69fdSAllain Legacy 			 */
102250db69fdSAllain Legacy 			copy_length = RTE_MIN((avp->guest_mbuf_size -
102350db69fdSAllain Legacy 					       rte_pktmbuf_data_len(m)),
102450db69fdSAllain Legacy 					      (pkt_buf->data_len -
102550db69fdSAllain Legacy 					       src_offset));
102650db69fdSAllain Legacy 			rte_memcpy(RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *),
102750db69fdSAllain Legacy 					       rte_pktmbuf_data_len(m)),
102850db69fdSAllain Legacy 				   RTE_PTR_ADD(pkt_data, src_offset),
102950db69fdSAllain Legacy 				   copy_length);
103050db69fdSAllain Legacy 			rte_pktmbuf_data_len(m) += copy_length;
103150db69fdSAllain Legacy 			src_offset += copy_length;
103250db69fdSAllain Legacy 
103350db69fdSAllain Legacy 			if (likely(src_offset == pkt_buf->data_len)) {
103450db69fdSAllain Legacy 				/* need a new source buffer */
103550db69fdSAllain Legacy 				buf = pkt_buf->next;
103650db69fdSAllain Legacy 				if (buf != NULL) {
103750db69fdSAllain Legacy 					pkt_buf = avp_dev_translate_buffer(
103850db69fdSAllain Legacy 						avp, buf);
103950db69fdSAllain Legacy 					pkt_data = avp_dev_translate_buffer(
104050db69fdSAllain Legacy 						avp, pkt_buf->data);
104150db69fdSAllain Legacy 					src_offset = 0;
104250db69fdSAllain Legacy 				}
104350db69fdSAllain Legacy 			}
104450db69fdSAllain Legacy 
104550db69fdSAllain Legacy 			if (unlikely(rte_pktmbuf_data_len(m) ==
104650db69fdSAllain Legacy 				     avp->guest_mbuf_size)) {
104750db69fdSAllain Legacy 				/* need a new destination mbuf */
104850db69fdSAllain Legacy 				break;
104950db69fdSAllain Legacy 			}
105050db69fdSAllain Legacy 
105150db69fdSAllain Legacy 		} while (buf != NULL);
105250db69fdSAllain Legacy 	}
105350db69fdSAllain Legacy 
105450db69fdSAllain Legacy 	m = mbufs[0];
105550db69fdSAllain Legacy 	m->ol_flags = ol_flags;
105650db69fdSAllain Legacy 	m->nb_segs = count;
105750db69fdSAllain Legacy 	rte_pktmbuf_pkt_len(m) = total_length;
105850db69fdSAllain Legacy 	m->vlan_tci = vlan_tci;
105950db69fdSAllain Legacy 
106050db69fdSAllain Legacy 	__rte_mbuf_sanity_check(m, 1);
106150db69fdSAllain Legacy 
106250db69fdSAllain Legacy 	return m;
106350db69fdSAllain Legacy }
106450db69fdSAllain Legacy 
106550db69fdSAllain Legacy static uint16_t
106650db69fdSAllain Legacy avp_recv_scattered_pkts(void *rx_queue,
106750db69fdSAllain Legacy 			struct rte_mbuf **rx_pkts,
106850db69fdSAllain Legacy 			uint16_t nb_pkts)
106950db69fdSAllain Legacy {
107050db69fdSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
107150db69fdSAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST];
107250db69fdSAllain Legacy 	struct rte_mbuf *mbufs[RTE_AVP_MAX_MBUF_SEGMENTS];
107350db69fdSAllain Legacy 	struct avp_dev *avp = rxq->avp;
107450db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
107550db69fdSAllain Legacy 	struct rte_avp_fifo *free_q;
107650db69fdSAllain Legacy 	struct rte_avp_fifo *rx_q;
107750db69fdSAllain Legacy 	struct rte_avp_desc *buf;
107850db69fdSAllain Legacy 	unsigned int count, avail, n;
107950db69fdSAllain Legacy 	unsigned int guest_mbuf_size;
108050db69fdSAllain Legacy 	struct rte_mbuf *m;
108150db69fdSAllain Legacy 	unsigned int required;
108250db69fdSAllain Legacy 	unsigned int buf_len;
108350db69fdSAllain Legacy 	unsigned int port_id;
108450db69fdSAllain Legacy 	unsigned int i;
108550db69fdSAllain Legacy 
108650db69fdSAllain Legacy 	guest_mbuf_size = avp->guest_mbuf_size;
108750db69fdSAllain Legacy 	port_id = avp->port_id;
108850db69fdSAllain Legacy 	rx_q = avp->rx_q[rxq->queue_id];
108950db69fdSAllain Legacy 	free_q = avp->free_q[rxq->queue_id];
109050db69fdSAllain Legacy 
109150db69fdSAllain Legacy 	/* setup next queue to service */
109250db69fdSAllain Legacy 	rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ?
109350db69fdSAllain Legacy 		(rxq->queue_id + 1) : rxq->queue_base;
109450db69fdSAllain Legacy 
109550db69fdSAllain Legacy 	/* determine how many slots are available in the free queue */
109650db69fdSAllain Legacy 	count = avp_fifo_free_count(free_q);
109750db69fdSAllain Legacy 
109850db69fdSAllain Legacy 	/* determine how many packets are available in the rx queue */
109950db69fdSAllain Legacy 	avail = avp_fifo_count(rx_q);
110050db69fdSAllain Legacy 
110150db69fdSAllain Legacy 	/* determine how many packets can be received */
110250db69fdSAllain Legacy 	count = RTE_MIN(count, avail);
110350db69fdSAllain Legacy 	count = RTE_MIN(count, nb_pkts);
110450db69fdSAllain Legacy 	count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST);
110550db69fdSAllain Legacy 
110650db69fdSAllain Legacy 	if (unlikely(count == 0)) {
110750db69fdSAllain Legacy 		/* no free buffers, or no buffers on the rx queue */
110850db69fdSAllain Legacy 		return 0;
110950db69fdSAllain Legacy 	}
111050db69fdSAllain Legacy 
111150db69fdSAllain Legacy 	/* retrieve pending packets */
111250db69fdSAllain Legacy 	n = avp_fifo_get(rx_q, (void **)&avp_bufs, count);
111350db69fdSAllain Legacy 	PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n",
111450db69fdSAllain Legacy 		   count, rx_q);
111550db69fdSAllain Legacy 
111650db69fdSAllain Legacy 	count = 0;
111750db69fdSAllain Legacy 	for (i = 0; i < n; i++) {
111850db69fdSAllain Legacy 		/* prefetch next entry while processing current one */
111950db69fdSAllain Legacy 		if (i + 1 < n) {
112050db69fdSAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
112150db69fdSAllain Legacy 							   avp_bufs[i + 1]);
112250db69fdSAllain Legacy 			rte_prefetch0(pkt_buf);
112350db69fdSAllain Legacy 		}
112450db69fdSAllain Legacy 		buf = avp_bufs[i];
112550db69fdSAllain Legacy 
112650db69fdSAllain Legacy 		/* Peek into the first buffer to determine the total length */
112750db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
112850db69fdSAllain Legacy 		buf_len = pkt_buf->pkt_len;
112950db69fdSAllain Legacy 
113050db69fdSAllain Legacy 		/* Allocate enough mbufs to receive the entire packet */
113150db69fdSAllain Legacy 		required = (buf_len + guest_mbuf_size - 1) / guest_mbuf_size;
113250db69fdSAllain Legacy 		if (rte_pktmbuf_alloc_bulk(avp->pool, mbufs, required)) {
113350db69fdSAllain Legacy 			rxq->dev_data->rx_mbuf_alloc_failed++;
113450db69fdSAllain Legacy 			continue;
113550db69fdSAllain Legacy 		}
113650db69fdSAllain Legacy 
113750db69fdSAllain Legacy 		/* Copy the data from the buffers to our mbufs */
113850db69fdSAllain Legacy 		m = avp_dev_copy_from_buffers(avp, buf, mbufs, required);
113950db69fdSAllain Legacy 
114050db69fdSAllain Legacy 		/* finalize mbuf */
114150db69fdSAllain Legacy 		m->port = port_id;
114250db69fdSAllain Legacy 
114350db69fdSAllain Legacy 		if (_avp_mac_filter(avp, m) != 0) {
114450db69fdSAllain Legacy 			/* silently discard packets not destined to our MAC */
114550db69fdSAllain Legacy 			rte_pktmbuf_free(m);
114650db69fdSAllain Legacy 			continue;
114750db69fdSAllain Legacy 		}
114850db69fdSAllain Legacy 
114950db69fdSAllain Legacy 		/* return new mbuf to caller */
115050db69fdSAllain Legacy 		rx_pkts[count++] = m;
115150db69fdSAllain Legacy 		rxq->bytes += buf_len;
115250db69fdSAllain Legacy 	}
115350db69fdSAllain Legacy 
115450db69fdSAllain Legacy 	rxq->packets += count;
115550db69fdSAllain Legacy 
115650db69fdSAllain Legacy 	/* return the buffers to the free queue */
115750db69fdSAllain Legacy 	avp_fifo_put(free_q, (void **)&avp_bufs[0], n);
115850db69fdSAllain Legacy 
115950db69fdSAllain Legacy 	return count;
116050db69fdSAllain Legacy }
116150db69fdSAllain Legacy 
116250db69fdSAllain Legacy 
116350db69fdSAllain Legacy static uint16_t
116450db69fdSAllain Legacy avp_recv_pkts(void *rx_queue,
116550db69fdSAllain Legacy 	      struct rte_mbuf **rx_pkts,
116650db69fdSAllain Legacy 	      uint16_t nb_pkts)
116750db69fdSAllain Legacy {
116850db69fdSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
116950db69fdSAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST];
117050db69fdSAllain Legacy 	struct avp_dev *avp = rxq->avp;
117150db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
117250db69fdSAllain Legacy 	struct rte_avp_fifo *free_q;
117350db69fdSAllain Legacy 	struct rte_avp_fifo *rx_q;
117450db69fdSAllain Legacy 	unsigned int count, avail, n;
117550db69fdSAllain Legacy 	unsigned int pkt_len;
117650db69fdSAllain Legacy 	struct rte_mbuf *m;
117750db69fdSAllain Legacy 	char *pkt_data;
117850db69fdSAllain Legacy 	unsigned int i;
117950db69fdSAllain Legacy 
118050db69fdSAllain Legacy 	rx_q = avp->rx_q[rxq->queue_id];
118150db69fdSAllain Legacy 	free_q = avp->free_q[rxq->queue_id];
118250db69fdSAllain Legacy 
118350db69fdSAllain Legacy 	/* setup next queue to service */
118450db69fdSAllain Legacy 	rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ?
118550db69fdSAllain Legacy 		(rxq->queue_id + 1) : rxq->queue_base;
118650db69fdSAllain Legacy 
118750db69fdSAllain Legacy 	/* determine how many slots are available in the free queue */
118850db69fdSAllain Legacy 	count = avp_fifo_free_count(free_q);
118950db69fdSAllain Legacy 
119050db69fdSAllain Legacy 	/* determine how many packets are available in the rx queue */
119150db69fdSAllain Legacy 	avail = avp_fifo_count(rx_q);
119250db69fdSAllain Legacy 
119350db69fdSAllain Legacy 	/* determine how many packets can be received */
119450db69fdSAllain Legacy 	count = RTE_MIN(count, avail);
119550db69fdSAllain Legacy 	count = RTE_MIN(count, nb_pkts);
119650db69fdSAllain Legacy 	count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST);
119750db69fdSAllain Legacy 
119850db69fdSAllain Legacy 	if (unlikely(count == 0)) {
119950db69fdSAllain Legacy 		/* no free buffers, or no buffers on the rx queue */
120050db69fdSAllain Legacy 		return 0;
120150db69fdSAllain Legacy 	}
120250db69fdSAllain Legacy 
120350db69fdSAllain Legacy 	/* retrieve pending packets */
120450db69fdSAllain Legacy 	n = avp_fifo_get(rx_q, (void **)&avp_bufs, count);
120550db69fdSAllain Legacy 	PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n",
120650db69fdSAllain Legacy 		   count, rx_q);
120750db69fdSAllain Legacy 
120850db69fdSAllain Legacy 	count = 0;
120950db69fdSAllain Legacy 	for (i = 0; i < n; i++) {
121050db69fdSAllain Legacy 		/* prefetch next entry while processing current one */
121150db69fdSAllain Legacy 		if (i < n - 1) {
121250db69fdSAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
121350db69fdSAllain Legacy 							   avp_bufs[i + 1]);
121450db69fdSAllain Legacy 			rte_prefetch0(pkt_buf);
121550db69fdSAllain Legacy 		}
121650db69fdSAllain Legacy 
121750db69fdSAllain Legacy 		/* Adjust host pointers for guest addressing */
121850db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]);
121950db69fdSAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
122050db69fdSAllain Legacy 		pkt_len = pkt_buf->pkt_len;
122150db69fdSAllain Legacy 
122250db69fdSAllain Legacy 		if (unlikely((pkt_len > avp->guest_mbuf_size) ||
122350db69fdSAllain Legacy 			     (pkt_buf->nb_segs > 1))) {
122450db69fdSAllain Legacy 			/*
122550db69fdSAllain Legacy 			 * application should be using the scattered receive
122650db69fdSAllain Legacy 			 * function
122750db69fdSAllain Legacy 			 */
122850db69fdSAllain Legacy 			rxq->errors++;
122950db69fdSAllain Legacy 			continue;
123050db69fdSAllain Legacy 		}
123150db69fdSAllain Legacy 
123250db69fdSAllain Legacy 		/* process each packet to be transmitted */
123350db69fdSAllain Legacy 		m = rte_pktmbuf_alloc(avp->pool);
123450db69fdSAllain Legacy 		if (unlikely(m == NULL)) {
123550db69fdSAllain Legacy 			rxq->dev_data->rx_mbuf_alloc_failed++;
123650db69fdSAllain Legacy 			continue;
123750db69fdSAllain Legacy 		}
123850db69fdSAllain Legacy 
123950db69fdSAllain Legacy 		/* copy data out of the host buffer to our buffer */
124050db69fdSAllain Legacy 		m->data_off = RTE_PKTMBUF_HEADROOM;
124150db69fdSAllain Legacy 		rte_memcpy(rte_pktmbuf_mtod(m, void *), pkt_data, pkt_len);
124250db69fdSAllain Legacy 
124350db69fdSAllain Legacy 		/* initialize the local mbuf */
124450db69fdSAllain Legacy 		rte_pktmbuf_data_len(m) = pkt_len;
124550db69fdSAllain Legacy 		rte_pktmbuf_pkt_len(m) = pkt_len;
124650db69fdSAllain Legacy 		m->port = avp->port_id;
124750db69fdSAllain Legacy 
124850db69fdSAllain Legacy 		if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) {
124950db69fdSAllain Legacy 			m->ol_flags = PKT_RX_VLAN_PKT;
125050db69fdSAllain Legacy 			m->vlan_tci = pkt_buf->vlan_tci;
125150db69fdSAllain Legacy 		}
125250db69fdSAllain Legacy 
125350db69fdSAllain Legacy 		if (_avp_mac_filter(avp, m) != 0) {
125450db69fdSAllain Legacy 			/* silently discard packets not destined to our MAC */
125550db69fdSAllain Legacy 			rte_pktmbuf_free(m);
125650db69fdSAllain Legacy 			continue;
125750db69fdSAllain Legacy 		}
125850db69fdSAllain Legacy 
125950db69fdSAllain Legacy 		/* return new mbuf to caller */
126050db69fdSAllain Legacy 		rx_pkts[count++] = m;
126150db69fdSAllain Legacy 		rxq->bytes += pkt_len;
126250db69fdSAllain Legacy 	}
126350db69fdSAllain Legacy 
126450db69fdSAllain Legacy 	rxq->packets += count;
126550db69fdSAllain Legacy 
126650db69fdSAllain Legacy 	/* return the buffers to the free queue */
126750db69fdSAllain Legacy 	avp_fifo_put(free_q, (void **)&avp_bufs[0], n);
126850db69fdSAllain Legacy 
126950db69fdSAllain Legacy 	return count;
127050db69fdSAllain Legacy }
127150db69fdSAllain Legacy 
1272295abce2SAllain Legacy /*
1273295abce2SAllain Legacy  * Copy a chained mbuf to a set of host buffers.  This function assumes that
1274295abce2SAllain Legacy  * there are sufficient destination buffers to contain the entire source
1275295abce2SAllain Legacy  * packet.
1276295abce2SAllain Legacy  */
1277295abce2SAllain Legacy static inline uint16_t
1278295abce2SAllain Legacy avp_dev_copy_to_buffers(struct avp_dev *avp,
1279295abce2SAllain Legacy 			struct rte_mbuf *mbuf,
1280295abce2SAllain Legacy 			struct rte_avp_desc **buffers,
1281295abce2SAllain Legacy 			unsigned int count)
1282295abce2SAllain Legacy {
1283295abce2SAllain Legacy 	struct rte_avp_desc *previous_buf = NULL;
1284295abce2SAllain Legacy 	struct rte_avp_desc *first_buf = NULL;
1285295abce2SAllain Legacy 	struct rte_avp_desc *pkt_buf;
1286295abce2SAllain Legacy 	struct rte_avp_desc *buf;
1287295abce2SAllain Legacy 	size_t total_length;
1288295abce2SAllain Legacy 	struct rte_mbuf *m;
1289295abce2SAllain Legacy 	size_t copy_length;
1290295abce2SAllain Legacy 	size_t src_offset;
1291295abce2SAllain Legacy 	char *pkt_data;
1292295abce2SAllain Legacy 	unsigned int i;
1293295abce2SAllain Legacy 
1294295abce2SAllain Legacy 	__rte_mbuf_sanity_check(mbuf, 1);
1295295abce2SAllain Legacy 
1296295abce2SAllain Legacy 	m = mbuf;
1297295abce2SAllain Legacy 	src_offset = 0;
1298295abce2SAllain Legacy 	total_length = rte_pktmbuf_pkt_len(m);
1299295abce2SAllain Legacy 	for (i = 0; (i < count) && (m != NULL); i++) {
1300295abce2SAllain Legacy 		/* fill each destination buffer */
1301295abce2SAllain Legacy 		buf = buffers[i];
1302295abce2SAllain Legacy 
1303295abce2SAllain Legacy 		if (i < count - 1) {
1304295abce2SAllain Legacy 			/* prefetch next entry while processing this one */
1305295abce2SAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp, buffers[i + 1]);
1306295abce2SAllain Legacy 			rte_prefetch0(pkt_buf);
1307295abce2SAllain Legacy 		}
1308295abce2SAllain Legacy 
1309295abce2SAllain Legacy 		/* Adjust pointers for guest addressing */
1310295abce2SAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
1311295abce2SAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
1312295abce2SAllain Legacy 
1313295abce2SAllain Legacy 		/* setup the buffer chain */
1314295abce2SAllain Legacy 		if (previous_buf != NULL)
1315295abce2SAllain Legacy 			previous_buf->next = buf;
1316295abce2SAllain Legacy 		else
1317295abce2SAllain Legacy 			first_buf = pkt_buf;
1318295abce2SAllain Legacy 
1319295abce2SAllain Legacy 		previous_buf = pkt_buf;
1320295abce2SAllain Legacy 
1321295abce2SAllain Legacy 		do {
1322295abce2SAllain Legacy 			/*
1323295abce2SAllain Legacy 			 * copy as many source mbuf segments as will fit in the
1324295abce2SAllain Legacy 			 * destination buffer.
1325295abce2SAllain Legacy 			 */
1326295abce2SAllain Legacy 			copy_length = RTE_MIN((avp->host_mbuf_size -
1327295abce2SAllain Legacy 					       pkt_buf->data_len),
1328295abce2SAllain Legacy 					      (rte_pktmbuf_data_len(m) -
1329295abce2SAllain Legacy 					       src_offset));
1330295abce2SAllain Legacy 			rte_memcpy(RTE_PTR_ADD(pkt_data, pkt_buf->data_len),
1331295abce2SAllain Legacy 				   RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *),
1332295abce2SAllain Legacy 					       src_offset),
1333295abce2SAllain Legacy 				   copy_length);
1334295abce2SAllain Legacy 			pkt_buf->data_len += copy_length;
1335295abce2SAllain Legacy 			src_offset += copy_length;
1336295abce2SAllain Legacy 
1337295abce2SAllain Legacy 			if (likely(src_offset == rte_pktmbuf_data_len(m))) {
1338295abce2SAllain Legacy 				/* need a new source buffer */
1339295abce2SAllain Legacy 				m = m->next;
1340295abce2SAllain Legacy 				src_offset = 0;
1341295abce2SAllain Legacy 			}
1342295abce2SAllain Legacy 
1343295abce2SAllain Legacy 			if (unlikely(pkt_buf->data_len ==
1344295abce2SAllain Legacy 				     avp->host_mbuf_size)) {
1345295abce2SAllain Legacy 				/* need a new destination buffer */
1346295abce2SAllain Legacy 				break;
1347295abce2SAllain Legacy 			}
1348295abce2SAllain Legacy 
1349295abce2SAllain Legacy 		} while (m != NULL);
1350295abce2SAllain Legacy 	}
1351295abce2SAllain Legacy 
1352295abce2SAllain Legacy 	first_buf->nb_segs = count;
1353295abce2SAllain Legacy 	first_buf->pkt_len = total_length;
1354295abce2SAllain Legacy 
1355295abce2SAllain Legacy 	if (mbuf->ol_flags & PKT_TX_VLAN_PKT) {
1356295abce2SAllain Legacy 		first_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT;
1357295abce2SAllain Legacy 		first_buf->vlan_tci = mbuf->vlan_tci;
1358295abce2SAllain Legacy 	}
1359295abce2SAllain Legacy 
1360295abce2SAllain Legacy 	avp_dev_buffer_sanity_check(avp, buffers[0]);
1361295abce2SAllain Legacy 
1362295abce2SAllain Legacy 	return total_length;
1363295abce2SAllain Legacy }
1364295abce2SAllain Legacy 
1365295abce2SAllain Legacy 
1366295abce2SAllain Legacy static uint16_t
1367295abce2SAllain Legacy avp_xmit_scattered_pkts(void *tx_queue,
1368295abce2SAllain Legacy 			struct rte_mbuf **tx_pkts,
1369295abce2SAllain Legacy 			uint16_t nb_pkts)
1370295abce2SAllain Legacy {
1371295abce2SAllain Legacy 	struct rte_avp_desc *avp_bufs[(AVP_MAX_TX_BURST *
1372295abce2SAllain Legacy 				       RTE_AVP_MAX_MBUF_SEGMENTS)];
1373295abce2SAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1374295abce2SAllain Legacy 	struct rte_avp_desc *tx_bufs[AVP_MAX_TX_BURST];
1375295abce2SAllain Legacy 	struct avp_dev *avp = txq->avp;
1376295abce2SAllain Legacy 	struct rte_avp_fifo *alloc_q;
1377295abce2SAllain Legacy 	struct rte_avp_fifo *tx_q;
1378295abce2SAllain Legacy 	unsigned int count, avail, n;
1379295abce2SAllain Legacy 	unsigned int orig_nb_pkts;
1380295abce2SAllain Legacy 	struct rte_mbuf *m;
1381295abce2SAllain Legacy 	unsigned int required;
1382295abce2SAllain Legacy 	unsigned int segments;
1383295abce2SAllain Legacy 	unsigned int tx_bytes;
1384295abce2SAllain Legacy 	unsigned int i;
1385295abce2SAllain Legacy 
1386295abce2SAllain Legacy 	orig_nb_pkts = nb_pkts;
1387295abce2SAllain Legacy 	tx_q = avp->tx_q[txq->queue_id];
1388295abce2SAllain Legacy 	alloc_q = avp->alloc_q[txq->queue_id];
1389295abce2SAllain Legacy 
1390295abce2SAllain Legacy 	/* limit the number of transmitted packets to the max burst size */
1391295abce2SAllain Legacy 	if (unlikely(nb_pkts > AVP_MAX_TX_BURST))
1392295abce2SAllain Legacy 		nb_pkts = AVP_MAX_TX_BURST;
1393295abce2SAllain Legacy 
1394295abce2SAllain Legacy 	/* determine how many buffers are available to copy into */
1395295abce2SAllain Legacy 	avail = avp_fifo_count(alloc_q);
1396295abce2SAllain Legacy 	if (unlikely(avail > (AVP_MAX_TX_BURST *
1397295abce2SAllain Legacy 			      RTE_AVP_MAX_MBUF_SEGMENTS)))
1398295abce2SAllain Legacy 		avail = AVP_MAX_TX_BURST * RTE_AVP_MAX_MBUF_SEGMENTS;
1399295abce2SAllain Legacy 
1400295abce2SAllain Legacy 	/* determine how many slots are available in the transmit queue */
1401295abce2SAllain Legacy 	count = avp_fifo_free_count(tx_q);
1402295abce2SAllain Legacy 
1403295abce2SAllain Legacy 	/* determine how many packets can be sent */
1404295abce2SAllain Legacy 	nb_pkts = RTE_MIN(count, nb_pkts);
1405295abce2SAllain Legacy 
1406295abce2SAllain Legacy 	/* determine how many packets will fit in the available buffers */
1407295abce2SAllain Legacy 	count = 0;
1408295abce2SAllain Legacy 	segments = 0;
1409295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++) {
1410295abce2SAllain Legacy 		m = tx_pkts[i];
1411295abce2SAllain Legacy 		if (likely(i < (unsigned int)nb_pkts - 1)) {
1412295abce2SAllain Legacy 			/* prefetch next entry while processing this one */
1413295abce2SAllain Legacy 			rte_prefetch0(tx_pkts[i + 1]);
1414295abce2SAllain Legacy 		}
1415295abce2SAllain Legacy 		required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) /
1416295abce2SAllain Legacy 			avp->host_mbuf_size;
1417295abce2SAllain Legacy 
1418295abce2SAllain Legacy 		if (unlikely((required == 0) ||
1419295abce2SAllain Legacy 			     (required > RTE_AVP_MAX_MBUF_SEGMENTS)))
1420295abce2SAllain Legacy 			break;
1421295abce2SAllain Legacy 		else if (unlikely(required + segments > avail))
1422295abce2SAllain Legacy 			break;
1423295abce2SAllain Legacy 		segments += required;
1424295abce2SAllain Legacy 		count++;
1425295abce2SAllain Legacy 	}
1426295abce2SAllain Legacy 	nb_pkts = count;
1427295abce2SAllain Legacy 
1428295abce2SAllain Legacy 	if (unlikely(nb_pkts == 0)) {
1429295abce2SAllain Legacy 		/* no available buffers, or no space on the tx queue */
1430295abce2SAllain Legacy 		txq->errors += orig_nb_pkts;
1431295abce2SAllain Legacy 		return 0;
1432295abce2SAllain Legacy 	}
1433295abce2SAllain Legacy 
1434295abce2SAllain Legacy 	PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n",
1435295abce2SAllain Legacy 		   nb_pkts, tx_q);
1436295abce2SAllain Legacy 
1437295abce2SAllain Legacy 	/* retrieve sufficient send buffers */
1438295abce2SAllain Legacy 	n = avp_fifo_get(alloc_q, (void **)&avp_bufs, segments);
1439295abce2SAllain Legacy 	if (unlikely(n != segments)) {
1440295abce2SAllain Legacy 		PMD_TX_LOG(DEBUG, "Failed to allocate buffers "
1441295abce2SAllain Legacy 			   "n=%u, segments=%u, orig=%u\n",
1442295abce2SAllain Legacy 			   n, segments, orig_nb_pkts);
1443295abce2SAllain Legacy 		txq->errors += orig_nb_pkts;
1444295abce2SAllain Legacy 		return 0;
1445295abce2SAllain Legacy 	}
1446295abce2SAllain Legacy 
1447295abce2SAllain Legacy 	tx_bytes = 0;
1448295abce2SAllain Legacy 	count = 0;
1449295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++) {
1450295abce2SAllain Legacy 		/* process each packet to be transmitted */
1451295abce2SAllain Legacy 		m = tx_pkts[i];
1452295abce2SAllain Legacy 
1453295abce2SAllain Legacy 		/* determine how many buffers are required for this packet */
1454295abce2SAllain Legacy 		required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) /
1455295abce2SAllain Legacy 			avp->host_mbuf_size;
1456295abce2SAllain Legacy 
1457295abce2SAllain Legacy 		tx_bytes += avp_dev_copy_to_buffers(avp, m,
1458295abce2SAllain Legacy 						    &avp_bufs[count], required);
1459295abce2SAllain Legacy 		tx_bufs[i] = avp_bufs[count];
1460295abce2SAllain Legacy 		count += required;
1461295abce2SAllain Legacy 
1462295abce2SAllain Legacy 		/* free the original mbuf */
1463295abce2SAllain Legacy 		rte_pktmbuf_free(m);
1464295abce2SAllain Legacy 	}
1465295abce2SAllain Legacy 
1466295abce2SAllain Legacy 	txq->packets += nb_pkts;
1467295abce2SAllain Legacy 	txq->bytes += tx_bytes;
1468295abce2SAllain Legacy 
1469295abce2SAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS
1470295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++)
1471295abce2SAllain Legacy 		avp_dev_buffer_sanity_check(avp, tx_bufs[i]);
1472295abce2SAllain Legacy #endif
1473295abce2SAllain Legacy 
1474295abce2SAllain Legacy 	/* send the packets */
1475295abce2SAllain Legacy 	n = avp_fifo_put(tx_q, (void **)&tx_bufs[0], nb_pkts);
1476295abce2SAllain Legacy 	if (unlikely(n != orig_nb_pkts))
1477295abce2SAllain Legacy 		txq->errors += (orig_nb_pkts - n);
1478295abce2SAllain Legacy 
1479295abce2SAllain Legacy 	return n;
1480295abce2SAllain Legacy }
1481295abce2SAllain Legacy 
1482295abce2SAllain Legacy 
1483295abce2SAllain Legacy static uint16_t
1484295abce2SAllain Legacy avp_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
1485295abce2SAllain Legacy {
1486295abce2SAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1487295abce2SAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_TX_BURST];
1488295abce2SAllain Legacy 	struct avp_dev *avp = txq->avp;
1489295abce2SAllain Legacy 	struct rte_avp_desc *pkt_buf;
1490295abce2SAllain Legacy 	struct rte_avp_fifo *alloc_q;
1491295abce2SAllain Legacy 	struct rte_avp_fifo *tx_q;
1492295abce2SAllain Legacy 	unsigned int count, avail, n;
1493295abce2SAllain Legacy 	struct rte_mbuf *m;
1494295abce2SAllain Legacy 	unsigned int pkt_len;
1495295abce2SAllain Legacy 	unsigned int tx_bytes;
1496295abce2SAllain Legacy 	char *pkt_data;
1497295abce2SAllain Legacy 	unsigned int i;
1498295abce2SAllain Legacy 
1499295abce2SAllain Legacy 	tx_q = avp->tx_q[txq->queue_id];
1500295abce2SAllain Legacy 	alloc_q = avp->alloc_q[txq->queue_id];
1501295abce2SAllain Legacy 
1502295abce2SAllain Legacy 	/* limit the number of transmitted packets to the max burst size */
1503295abce2SAllain Legacy 	if (unlikely(nb_pkts > AVP_MAX_TX_BURST))
1504295abce2SAllain Legacy 		nb_pkts = AVP_MAX_TX_BURST;
1505295abce2SAllain Legacy 
1506295abce2SAllain Legacy 	/* determine how many buffers are available to copy into */
1507295abce2SAllain Legacy 	avail = avp_fifo_count(alloc_q);
1508295abce2SAllain Legacy 
1509295abce2SAllain Legacy 	/* determine how many slots are available in the transmit queue */
1510295abce2SAllain Legacy 	count = avp_fifo_free_count(tx_q);
1511295abce2SAllain Legacy 
1512295abce2SAllain Legacy 	/* determine how many packets can be sent */
1513295abce2SAllain Legacy 	count = RTE_MIN(count, avail);
1514295abce2SAllain Legacy 	count = RTE_MIN(count, nb_pkts);
1515295abce2SAllain Legacy 
1516295abce2SAllain Legacy 	if (unlikely(count == 0)) {
1517295abce2SAllain Legacy 		/* no available buffers, or no space on the tx queue */
1518295abce2SAllain Legacy 		txq->errors += nb_pkts;
1519295abce2SAllain Legacy 		return 0;
1520295abce2SAllain Legacy 	}
1521295abce2SAllain Legacy 
1522295abce2SAllain Legacy 	PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n",
1523295abce2SAllain Legacy 		   count, tx_q);
1524295abce2SAllain Legacy 
1525295abce2SAllain Legacy 	/* retrieve sufficient send buffers */
1526295abce2SAllain Legacy 	n = avp_fifo_get(alloc_q, (void **)&avp_bufs, count);
1527295abce2SAllain Legacy 	if (unlikely(n != count)) {
1528295abce2SAllain Legacy 		txq->errors++;
1529295abce2SAllain Legacy 		return 0;
1530295abce2SAllain Legacy 	}
1531295abce2SAllain Legacy 
1532295abce2SAllain Legacy 	tx_bytes = 0;
1533295abce2SAllain Legacy 	for (i = 0; i < count; i++) {
1534295abce2SAllain Legacy 		/* prefetch next entry while processing the current one */
1535295abce2SAllain Legacy 		if (i < count - 1) {
1536295abce2SAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
1537295abce2SAllain Legacy 							   avp_bufs[i + 1]);
1538295abce2SAllain Legacy 			rte_prefetch0(pkt_buf);
1539295abce2SAllain Legacy 		}
1540295abce2SAllain Legacy 
1541295abce2SAllain Legacy 		/* process each packet to be transmitted */
1542295abce2SAllain Legacy 		m = tx_pkts[i];
1543295abce2SAllain Legacy 
1544295abce2SAllain Legacy 		/* Adjust pointers for guest addressing */
1545295abce2SAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]);
1546295abce2SAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
1547295abce2SAllain Legacy 		pkt_len = rte_pktmbuf_pkt_len(m);
1548295abce2SAllain Legacy 
1549295abce2SAllain Legacy 		if (unlikely((pkt_len > avp->guest_mbuf_size) ||
1550295abce2SAllain Legacy 					 (pkt_len > avp->host_mbuf_size))) {
1551295abce2SAllain Legacy 			/*
1552295abce2SAllain Legacy 			 * application should be using the scattered transmit
1553295abce2SAllain Legacy 			 * function; send it truncated to avoid the performance
1554295abce2SAllain Legacy 			 * hit of having to manage returning the already
1555295abce2SAllain Legacy 			 * allocated buffer to the free list.  This should not
1556295abce2SAllain Legacy 			 * happen since the application should have set the
1557295abce2SAllain Legacy 			 * max_rx_pkt_len based on its MTU and it should be
1558295abce2SAllain Legacy 			 * policing its own packet sizes.
1559295abce2SAllain Legacy 			 */
1560295abce2SAllain Legacy 			txq->errors++;
1561295abce2SAllain Legacy 			pkt_len = RTE_MIN(avp->guest_mbuf_size,
1562295abce2SAllain Legacy 					  avp->host_mbuf_size);
1563295abce2SAllain Legacy 		}
1564295abce2SAllain Legacy 
1565295abce2SAllain Legacy 		/* copy data out of our mbuf and into the AVP buffer */
1566295abce2SAllain Legacy 		rte_memcpy(pkt_data, rte_pktmbuf_mtod(m, void *), pkt_len);
1567295abce2SAllain Legacy 		pkt_buf->pkt_len = pkt_len;
1568295abce2SAllain Legacy 		pkt_buf->data_len = pkt_len;
1569295abce2SAllain Legacy 		pkt_buf->nb_segs = 1;
1570295abce2SAllain Legacy 		pkt_buf->next = NULL;
1571295abce2SAllain Legacy 
1572295abce2SAllain Legacy 		if (m->ol_flags & PKT_TX_VLAN_PKT) {
1573295abce2SAllain Legacy 			pkt_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT;
1574295abce2SAllain Legacy 			pkt_buf->vlan_tci = m->vlan_tci;
1575295abce2SAllain Legacy 		}
1576295abce2SAllain Legacy 
1577295abce2SAllain Legacy 		tx_bytes += pkt_len;
1578295abce2SAllain Legacy 
1579295abce2SAllain Legacy 		/* free the original mbuf */
1580295abce2SAllain Legacy 		rte_pktmbuf_free(m);
1581295abce2SAllain Legacy 	}
1582295abce2SAllain Legacy 
1583295abce2SAllain Legacy 	txq->packets += count;
1584295abce2SAllain Legacy 	txq->bytes += tx_bytes;
1585295abce2SAllain Legacy 
1586295abce2SAllain Legacy 	/* send the packets */
1587295abce2SAllain Legacy 	n = avp_fifo_put(tx_q, (void **)&avp_bufs[0], count);
1588295abce2SAllain Legacy 
1589295abce2SAllain Legacy 	return n;
1590295abce2SAllain Legacy }
1591295abce2SAllain Legacy 
1592cce4367fSAllain Legacy static void
1593cce4367fSAllain Legacy avp_dev_rx_queue_release(void *rx_queue)
1594cce4367fSAllain Legacy {
1595cce4367fSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
1596cce4367fSAllain Legacy 	struct avp_dev *avp = rxq->avp;
1597cce4367fSAllain Legacy 	struct rte_eth_dev_data *data = avp->dev_data;
1598cce4367fSAllain Legacy 	unsigned int i;
1599cce4367fSAllain Legacy 
1600cce4367fSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
1601cce4367fSAllain Legacy 		if (data->rx_queues[i] == rxq)
1602cce4367fSAllain Legacy 			data->rx_queues[i] = NULL;
1603cce4367fSAllain Legacy 	}
1604cce4367fSAllain Legacy }
1605cce4367fSAllain Legacy 
1606cce4367fSAllain Legacy static void
1607cce4367fSAllain Legacy avp_dev_tx_queue_release(void *tx_queue)
1608cce4367fSAllain Legacy {
1609cce4367fSAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1610cce4367fSAllain Legacy 	struct avp_dev *avp = txq->avp;
1611cce4367fSAllain Legacy 	struct rte_eth_dev_data *data = avp->dev_data;
1612cce4367fSAllain Legacy 	unsigned int i;
1613cce4367fSAllain Legacy 
1614cce4367fSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
1615cce4367fSAllain Legacy 		if (data->tx_queues[i] == txq)
1616cce4367fSAllain Legacy 			data->tx_queues[i] = NULL;
1617cce4367fSAllain Legacy 	}
1618cce4367fSAllain Legacy }
1619cce4367fSAllain Legacy 
1620cce4367fSAllain Legacy static int
16211a859223SAllain Legacy avp_dev_configure(struct rte_eth_dev *eth_dev)
16221a859223SAllain Legacy {
16231a859223SAllain Legacy 	struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev);
16241a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
16251a859223SAllain Legacy 	struct rte_avp_device_info *host_info;
16261a859223SAllain Legacy 	struct rte_avp_device_config config;
16271a859223SAllain Legacy 	int mask = 0;
16281a859223SAllain Legacy 	void *addr;
16291a859223SAllain Legacy 	int ret;
16301a859223SAllain Legacy 
16311a859223SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr;
16321a859223SAllain Legacy 	host_info = (struct rte_avp_device_info *)addr;
16331a859223SAllain Legacy 
16341a859223SAllain Legacy 	/* Setup required number of queues */
16351a859223SAllain Legacy 	_avp_set_queue_counts(eth_dev);
16361a859223SAllain Legacy 
16371a859223SAllain Legacy 	mask = (ETH_VLAN_STRIP_MASK |
16381a859223SAllain Legacy 		ETH_VLAN_FILTER_MASK |
16391a859223SAllain Legacy 		ETH_VLAN_EXTEND_MASK);
16401a859223SAllain Legacy 	avp_vlan_offload_set(eth_dev, mask);
16411a859223SAllain Legacy 
16421a859223SAllain Legacy 	/* update device config */
16431a859223SAllain Legacy 	memset(&config, 0, sizeof(config));
16441a859223SAllain Legacy 	config.device_id = host_info->device_id;
16451a859223SAllain Legacy 	config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK;
16461a859223SAllain Legacy 	config.driver_version = AVP_DPDK_DRIVER_VERSION;
16471a859223SAllain Legacy 	config.features = avp->features;
16481a859223SAllain Legacy 	config.num_tx_queues = avp->num_tx_queues;
16491a859223SAllain Legacy 	config.num_rx_queues = avp->num_rx_queues;
16501a859223SAllain Legacy 
16511a859223SAllain Legacy 	ret = avp_dev_ctrl_set_config(eth_dev, &config);
16521a859223SAllain Legacy 	if (ret < 0) {
16531a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Config request failed by host, ret=%d\n",
16541a859223SAllain Legacy 			    ret);
16551a859223SAllain Legacy 		goto unlock;
16561a859223SAllain Legacy 	}
16571a859223SAllain Legacy 
16581a859223SAllain Legacy 	avp->flags |= AVP_F_CONFIGURED;
16591a859223SAllain Legacy 	ret = 0;
16601a859223SAllain Legacy 
16611a859223SAllain Legacy unlock:
16621a859223SAllain Legacy 	return ret;
16631a859223SAllain Legacy }
16641a859223SAllain Legacy 
16651a859223SAllain Legacy 
16661a859223SAllain Legacy static int
16671a859223SAllain Legacy avp_dev_link_update(struct rte_eth_dev *eth_dev,
16681a859223SAllain Legacy 					__rte_unused int wait_to_complete)
16691a859223SAllain Legacy {
16701a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
16711a859223SAllain Legacy 	struct rte_eth_link *link = &eth_dev->data->dev_link;
16721a859223SAllain Legacy 
16731a859223SAllain Legacy 	link->link_speed = ETH_SPEED_NUM_10G;
16741a859223SAllain Legacy 	link->link_duplex = ETH_LINK_FULL_DUPLEX;
16751a859223SAllain Legacy 	link->link_status = !!(avp->flags & AVP_F_LINKUP);
16761a859223SAllain Legacy 
16771a859223SAllain Legacy 	return -1;
16781a859223SAllain Legacy }
16791a859223SAllain Legacy 
16801a859223SAllain Legacy 
16811a859223SAllain Legacy static void
16821a859223SAllain Legacy avp_dev_info_get(struct rte_eth_dev *eth_dev,
16831a859223SAllain Legacy 		 struct rte_eth_dev_info *dev_info)
16841a859223SAllain Legacy {
16851a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
16861a859223SAllain Legacy 
16871a859223SAllain Legacy 	dev_info->driver_name = "rte_avp_pmd";
16881a859223SAllain Legacy 	dev_info->pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
16891a859223SAllain Legacy 	dev_info->max_rx_queues = avp->max_rx_queues;
16901a859223SAllain Legacy 	dev_info->max_tx_queues = avp->max_tx_queues;
16911a859223SAllain Legacy 	dev_info->min_rx_bufsize = AVP_MIN_RX_BUFSIZE;
16921a859223SAllain Legacy 	dev_info->max_rx_pktlen = avp->max_rx_pkt_len;
16931a859223SAllain Legacy 	dev_info->max_mac_addrs = AVP_MAX_MAC_ADDRS;
16941a859223SAllain Legacy 	if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) {
16951a859223SAllain Legacy 		dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP;
16961a859223SAllain Legacy 		dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT;
16971a859223SAllain Legacy 	}
16981a859223SAllain Legacy }
16991a859223SAllain Legacy 
17001a859223SAllain Legacy static void
17011a859223SAllain Legacy avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
17021a859223SAllain Legacy {
17031a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
17041a859223SAllain Legacy 
17051a859223SAllain Legacy 	if (mask & ETH_VLAN_STRIP_MASK) {
17061a859223SAllain Legacy 		if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) {
17071a859223SAllain Legacy 			if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
17081a859223SAllain Legacy 				avp->features |= RTE_AVP_FEATURE_VLAN_OFFLOAD;
17091a859223SAllain Legacy 			else
17101a859223SAllain Legacy 				avp->features &= ~RTE_AVP_FEATURE_VLAN_OFFLOAD;
17111a859223SAllain Legacy 		} else {
17121a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN strip offload not supported\n");
17131a859223SAllain Legacy 		}
17141a859223SAllain Legacy 	}
17151a859223SAllain Legacy 
17161a859223SAllain Legacy 	if (mask & ETH_VLAN_FILTER_MASK) {
17171a859223SAllain Legacy 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_filter)
17181a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN filter offload not supported\n");
17191a859223SAllain Legacy 	}
17201a859223SAllain Legacy 
17211a859223SAllain Legacy 	if (mask & ETH_VLAN_EXTEND_MASK) {
17221a859223SAllain Legacy 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend)
17231a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
17241a859223SAllain Legacy 	}
17251a859223SAllain Legacy }
17261a859223SAllain Legacy 
1727*5a5abe2dSAllain Legacy static void
1728*5a5abe2dSAllain Legacy avp_dev_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats)
1729*5a5abe2dSAllain Legacy {
1730*5a5abe2dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1731*5a5abe2dSAllain Legacy 	unsigned int i;
1732*5a5abe2dSAllain Legacy 
1733*5a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
1734*5a5abe2dSAllain Legacy 		struct avp_queue *rxq = avp->dev_data->rx_queues[i];
1735*5a5abe2dSAllain Legacy 
1736*5a5abe2dSAllain Legacy 		if (rxq) {
1737*5a5abe2dSAllain Legacy 			stats->ipackets += rxq->packets;
1738*5a5abe2dSAllain Legacy 			stats->ibytes += rxq->bytes;
1739*5a5abe2dSAllain Legacy 			stats->ierrors += rxq->errors;
1740*5a5abe2dSAllain Legacy 
1741*5a5abe2dSAllain Legacy 			stats->q_ipackets[i] += rxq->packets;
1742*5a5abe2dSAllain Legacy 			stats->q_ibytes[i] += rxq->bytes;
1743*5a5abe2dSAllain Legacy 			stats->q_errors[i] += rxq->errors;
1744*5a5abe2dSAllain Legacy 		}
1745*5a5abe2dSAllain Legacy 	}
1746*5a5abe2dSAllain Legacy 
1747*5a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
1748*5a5abe2dSAllain Legacy 		struct avp_queue *txq = avp->dev_data->tx_queues[i];
1749*5a5abe2dSAllain Legacy 
1750*5a5abe2dSAllain Legacy 		if (txq) {
1751*5a5abe2dSAllain Legacy 			stats->opackets += txq->packets;
1752*5a5abe2dSAllain Legacy 			stats->obytes += txq->bytes;
1753*5a5abe2dSAllain Legacy 			stats->oerrors += txq->errors;
1754*5a5abe2dSAllain Legacy 
1755*5a5abe2dSAllain Legacy 			stats->q_opackets[i] += txq->packets;
1756*5a5abe2dSAllain Legacy 			stats->q_obytes[i] += txq->bytes;
1757*5a5abe2dSAllain Legacy 			stats->q_errors[i] += txq->errors;
1758*5a5abe2dSAllain Legacy 		}
1759*5a5abe2dSAllain Legacy 	}
1760*5a5abe2dSAllain Legacy }
1761*5a5abe2dSAllain Legacy 
1762*5a5abe2dSAllain Legacy static void
1763*5a5abe2dSAllain Legacy avp_dev_stats_reset(struct rte_eth_dev *eth_dev)
1764*5a5abe2dSAllain Legacy {
1765*5a5abe2dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1766*5a5abe2dSAllain Legacy 	unsigned int i;
1767*5a5abe2dSAllain Legacy 
1768*5a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
1769*5a5abe2dSAllain Legacy 		struct avp_queue *rxq = avp->dev_data->rx_queues[i];
1770*5a5abe2dSAllain Legacy 
1771*5a5abe2dSAllain Legacy 		if (rxq) {
1772*5a5abe2dSAllain Legacy 			rxq->bytes = 0;
1773*5a5abe2dSAllain Legacy 			rxq->packets = 0;
1774*5a5abe2dSAllain Legacy 			rxq->errors = 0;
1775*5a5abe2dSAllain Legacy 		}
1776*5a5abe2dSAllain Legacy 	}
1777*5a5abe2dSAllain Legacy 
1778*5a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
1779*5a5abe2dSAllain Legacy 		struct avp_queue *txq = avp->dev_data->tx_queues[i];
1780*5a5abe2dSAllain Legacy 
1781*5a5abe2dSAllain Legacy 		if (txq) {
1782*5a5abe2dSAllain Legacy 			txq->bytes = 0;
1783*5a5abe2dSAllain Legacy 			txq->packets = 0;
1784*5a5abe2dSAllain Legacy 			txq->errors = 0;
1785*5a5abe2dSAllain Legacy 		}
1786*5a5abe2dSAllain Legacy 	}
1787*5a5abe2dSAllain Legacy }
1788*5a5abe2dSAllain Legacy 
1789908072e9SAllain Legacy RTE_PMD_REGISTER_PCI(net_avp, rte_avp_pmd.pci_drv);
1790908072e9SAllain Legacy RTE_PMD_REGISTER_PCI_TABLE(net_avp, pci_id_avp_map);
1791