xref: /dpdk/drivers/net/avp/avp_ethdev.c (revision ec87d3b2c2451ce0fa71f53f64987c68a0b3423c)
150da8b0dSAllain Legacy /* SPDX-License-Identifier: BSD-3-Clause
250da8b0dSAllain Legacy  * Copyright(c) 2013-2017 Wind River Systems, Inc.
3908072e9SAllain Legacy  */
4908072e9SAllain Legacy 
5908072e9SAllain Legacy #include <stdint.h>
6908072e9SAllain Legacy #include <string.h>
7908072e9SAllain Legacy #include <stdio.h>
8908072e9SAllain Legacy #include <errno.h>
9908072e9SAllain Legacy #include <unistd.h>
10908072e9SAllain Legacy 
11ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h>
12fdf91e0fSJan Blunck #include <rte_ethdev_pci.h>
13908072e9SAllain Legacy #include <rte_memcpy.h>
14908072e9SAllain Legacy #include <rte_string_fns.h>
15908072e9SAllain Legacy #include <rte_malloc.h>
16908072e9SAllain Legacy #include <rte_atomic.h>
17908072e9SAllain Legacy #include <rte_branch_prediction.h>
18908072e9SAllain Legacy #include <rte_pci.h>
19c752998bSGaetan Rivet #include <rte_bus_pci.h>
20908072e9SAllain Legacy #include <rte_ether.h>
21908072e9SAllain Legacy #include <rte_common.h>
22908072e9SAllain Legacy #include <rte_cycles.h>
2382e140b8SAllain Legacy #include <rte_spinlock.h>
24908072e9SAllain Legacy #include <rte_byteorder.h>
25908072e9SAllain Legacy #include <rte_dev.h>
26908072e9SAllain Legacy #include <rte_memory.h>
27908072e9SAllain Legacy #include <rte_eal.h>
28c0ad5842SAllain Legacy #include <rte_io.h>
29908072e9SAllain Legacy 
30908072e9SAllain Legacy #include "rte_avp_common.h"
31908072e9SAllain Legacy #include "rte_avp_fifo.h"
32908072e9SAllain Legacy 
33908072e9SAllain Legacy #include "avp_logs.h"
34908072e9SAllain Legacy 
35e6b790c0SStephen Hemminger int avp_logtype_driver;
36908072e9SAllain Legacy 
3782e140b8SAllain Legacy static int avp_dev_create(struct rte_pci_device *pci_dev,
3882e140b8SAllain Legacy 			  struct rte_eth_dev *eth_dev);
39908072e9SAllain Legacy 
401a859223SAllain Legacy static int avp_dev_configure(struct rte_eth_dev *dev);
41ea37523dSAllain Legacy static int avp_dev_start(struct rte_eth_dev *dev);
42ea37523dSAllain Legacy static void avp_dev_stop(struct rte_eth_dev *dev);
43ea37523dSAllain Legacy static void avp_dev_close(struct rte_eth_dev *dev);
44bdad90d1SIvan Ilchenko static int avp_dev_info_get(struct rte_eth_dev *dev,
451a859223SAllain Legacy 			    struct rte_eth_dev_info *dev_info);
46289ba0c0SDavid Harton static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
47dd2c630aSFerruh Yigit static int avp_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
489039c812SAndrew Rybchenko static int avp_dev_promiscuous_enable(struct rte_eth_dev *dev);
499039c812SAndrew Rybchenko static int avp_dev_promiscuous_disable(struct rte_eth_dev *dev);
508129545eSAllain Legacy 
51cce4367fSAllain Legacy static int avp_dev_rx_queue_setup(struct rte_eth_dev *dev,
52cce4367fSAllain Legacy 				  uint16_t rx_queue_id,
53cce4367fSAllain Legacy 				  uint16_t nb_rx_desc,
54cce4367fSAllain Legacy 				  unsigned int socket_id,
55cce4367fSAllain Legacy 				  const struct rte_eth_rxconf *rx_conf,
56cce4367fSAllain Legacy 				  struct rte_mempool *pool);
571a859223SAllain Legacy 
58cce4367fSAllain Legacy static int avp_dev_tx_queue_setup(struct rte_eth_dev *dev,
59cce4367fSAllain Legacy 				  uint16_t tx_queue_id,
60cce4367fSAllain Legacy 				  uint16_t nb_tx_desc,
61cce4367fSAllain Legacy 				  unsigned int socket_id,
62cce4367fSAllain Legacy 				  const struct rte_eth_txconf *tx_conf);
63cce4367fSAllain Legacy 
6450db69fdSAllain Legacy static uint16_t avp_recv_scattered_pkts(void *rx_queue,
6550db69fdSAllain Legacy 					struct rte_mbuf **rx_pkts,
6650db69fdSAllain Legacy 					uint16_t nb_pkts);
6750db69fdSAllain Legacy 
6850db69fdSAllain Legacy static uint16_t avp_recv_pkts(void *rx_queue,
6950db69fdSAllain Legacy 			      struct rte_mbuf **rx_pkts,
7050db69fdSAllain Legacy 			      uint16_t nb_pkts);
71295abce2SAllain Legacy 
72295abce2SAllain Legacy static uint16_t avp_xmit_scattered_pkts(void *tx_queue,
73295abce2SAllain Legacy 					struct rte_mbuf **tx_pkts,
74295abce2SAllain Legacy 					uint16_t nb_pkts);
75295abce2SAllain Legacy 
76295abce2SAllain Legacy static uint16_t avp_xmit_pkts(void *tx_queue,
77295abce2SAllain Legacy 			      struct rte_mbuf **tx_pkts,
78295abce2SAllain Legacy 			      uint16_t nb_pkts);
79295abce2SAllain Legacy 
80cce4367fSAllain Legacy static void avp_dev_rx_queue_release(void *rxq);
81cce4367fSAllain Legacy static void avp_dev_tx_queue_release(void *txq);
82295abce2SAllain Legacy 
83d5b0924bSMatan Azrad static int avp_dev_stats_get(struct rte_eth_dev *dev,
845a5abe2dSAllain Legacy 			      struct rte_eth_stats *stats);
859970a9adSIgor Romanov static int avp_dev_stats_reset(struct rte_eth_dev *dev);
865a5abe2dSAllain Legacy 
87295abce2SAllain Legacy 
8850db69fdSAllain Legacy #define AVP_MAX_RX_BURST 64
89295abce2SAllain Legacy #define AVP_MAX_TX_BURST 64
90908072e9SAllain Legacy #define AVP_MAX_MAC_ADDRS 1
9135b2d13fSOlivier Matz #define AVP_MIN_RX_BUFSIZE RTE_ETHER_MIN_LEN
92908072e9SAllain Legacy 
93908072e9SAllain Legacy 
94908072e9SAllain Legacy /*
95908072e9SAllain Legacy  * Defines the number of microseconds to wait before checking the response
96908072e9SAllain Legacy  * queue for completion.
97908072e9SAllain Legacy  */
98908072e9SAllain Legacy #define AVP_REQUEST_DELAY_USECS (5000)
99908072e9SAllain Legacy 
100908072e9SAllain Legacy /*
101908072e9SAllain Legacy  * Defines the number times to check the response queue for completion before
102908072e9SAllain Legacy  * declaring a timeout.
103908072e9SAllain Legacy  */
104908072e9SAllain Legacy #define AVP_MAX_REQUEST_RETRY (100)
105908072e9SAllain Legacy 
106908072e9SAllain Legacy /* Defines the current PCI driver version number */
107908072e9SAllain Legacy #define AVP_DPDK_DRIVER_VERSION RTE_AVP_CURRENT_GUEST_VERSION
108908072e9SAllain Legacy 
109908072e9SAllain Legacy /*
110908072e9SAllain Legacy  * The set of PCI devices this driver supports
111908072e9SAllain Legacy  */
112908072e9SAllain Legacy static const struct rte_pci_id pci_id_avp_map[] = {
113908072e9SAllain Legacy 	{ .vendor_id = RTE_AVP_PCI_VENDOR_ID,
114908072e9SAllain Legacy 	  .device_id = RTE_AVP_PCI_DEVICE_ID,
115908072e9SAllain Legacy 	  .subsystem_vendor_id = RTE_AVP_PCI_SUB_VENDOR_ID,
116908072e9SAllain Legacy 	  .subsystem_device_id = RTE_AVP_PCI_SUB_DEVICE_ID,
117908072e9SAllain Legacy 	  .class_id = RTE_CLASS_ANY_ID,
118908072e9SAllain Legacy 	},
119908072e9SAllain Legacy 
120908072e9SAllain Legacy 	{ .vendor_id = 0, /* sentinel */
121908072e9SAllain Legacy 	},
122908072e9SAllain Legacy };
123908072e9SAllain Legacy 
1241a859223SAllain Legacy /*
1251a859223SAllain Legacy  * dev_ops for avp, bare necessities for basic operation
1261a859223SAllain Legacy  */
1271a859223SAllain Legacy static const struct eth_dev_ops avp_eth_dev_ops = {
1281a859223SAllain Legacy 	.dev_configure       = avp_dev_configure,
129ea37523dSAllain Legacy 	.dev_start           = avp_dev_start,
130ea37523dSAllain Legacy 	.dev_stop            = avp_dev_stop,
131ea37523dSAllain Legacy 	.dev_close           = avp_dev_close,
1321a859223SAllain Legacy 	.dev_infos_get       = avp_dev_info_get,
1331a859223SAllain Legacy 	.vlan_offload_set    = avp_vlan_offload_set,
1345a5abe2dSAllain Legacy 	.stats_get           = avp_dev_stats_get,
1355a5abe2dSAllain Legacy 	.stats_reset         = avp_dev_stats_reset,
1361a859223SAllain Legacy 	.link_update         = avp_dev_link_update,
1378129545eSAllain Legacy 	.promiscuous_enable  = avp_dev_promiscuous_enable,
1388129545eSAllain Legacy 	.promiscuous_disable = avp_dev_promiscuous_disable,
139cce4367fSAllain Legacy 	.rx_queue_setup      = avp_dev_rx_queue_setup,
140cce4367fSAllain Legacy 	.rx_queue_release    = avp_dev_rx_queue_release,
141cce4367fSAllain Legacy 	.tx_queue_setup      = avp_dev_tx_queue_setup,
142cce4367fSAllain Legacy 	.tx_queue_release    = avp_dev_tx_queue_release,
1431a859223SAllain Legacy };
144908072e9SAllain Legacy 
145c0ad5842SAllain Legacy /**@{ AVP device flags */
146c0ad5842SAllain Legacy #define AVP_F_PROMISC (1 << 1)
147c0ad5842SAllain Legacy #define AVP_F_CONFIGURED (1 << 2)
148c0ad5842SAllain Legacy #define AVP_F_LINKUP (1 << 3)
14982e140b8SAllain Legacy #define AVP_F_DETACHED (1 << 4)
150c0ad5842SAllain Legacy /**@} */
151c0ad5842SAllain Legacy 
152c0ad5842SAllain Legacy /* Ethernet device validation marker */
153c0ad5842SAllain Legacy #define AVP_ETHDEV_MAGIC 0x92972862
154c0ad5842SAllain Legacy 
155908072e9SAllain Legacy /*
156908072e9SAllain Legacy  * Defines the AVP device attributes which are attached to an RTE ethernet
157908072e9SAllain Legacy  * device
158908072e9SAllain Legacy  */
159908072e9SAllain Legacy struct avp_dev {
160908072e9SAllain Legacy 	uint32_t magic; /**< Memory validation marker */
161908072e9SAllain Legacy 	uint64_t device_id; /**< Unique system identifier */
1626d13ea8eSOlivier Matz 	struct rte_ether_addr ethaddr; /**< Host specified MAC address */
163908072e9SAllain Legacy 	struct rte_eth_dev_data *dev_data;
164908072e9SAllain Legacy 	/**< Back pointer to ethernet device data */
165908072e9SAllain Legacy 	volatile uint32_t flags; /**< Device operational flags */
166f8244c63SZhiyong Yang 	uint16_t port_id; /**< Ethernet port identifier */
167908072e9SAllain Legacy 	struct rte_mempool *pool; /**< pkt mbuf mempool */
168908072e9SAllain Legacy 	unsigned int guest_mbuf_size; /**< local pool mbuf size */
169908072e9SAllain Legacy 	unsigned int host_mbuf_size; /**< host mbuf size */
170908072e9SAllain Legacy 	unsigned int max_rx_pkt_len; /**< maximum receive unit */
171908072e9SAllain Legacy 	uint32_t host_features; /**< Supported feature bitmap */
172908072e9SAllain Legacy 	uint32_t features; /**< Enabled feature bitmap */
173908072e9SAllain Legacy 	unsigned int num_tx_queues; /**< Negotiated number of transmit queues */
174908072e9SAllain Legacy 	unsigned int max_tx_queues; /**< Maximum number of transmit queues */
175908072e9SAllain Legacy 	unsigned int num_rx_queues; /**< Negotiated number of receive queues */
176908072e9SAllain Legacy 	unsigned int max_rx_queues; /**< Maximum number of receive queues */
177908072e9SAllain Legacy 
178908072e9SAllain Legacy 	struct rte_avp_fifo *tx_q[RTE_AVP_MAX_QUEUES]; /**< TX queue */
179908072e9SAllain Legacy 	struct rte_avp_fifo *rx_q[RTE_AVP_MAX_QUEUES]; /**< RX queue */
180908072e9SAllain Legacy 	struct rte_avp_fifo *alloc_q[RTE_AVP_MAX_QUEUES];
181908072e9SAllain Legacy 	/**< Allocated mbufs queue */
182908072e9SAllain Legacy 	struct rte_avp_fifo *free_q[RTE_AVP_MAX_QUEUES];
183908072e9SAllain Legacy 	/**< To be freed mbufs queue */
184908072e9SAllain Legacy 
18582e140b8SAllain Legacy 	/* mutual exclusion over the 'flag' and 'resp_q/req_q' fields */
18682e140b8SAllain Legacy 	rte_spinlock_t lock;
18782e140b8SAllain Legacy 
188908072e9SAllain Legacy 	/* For request & response */
189908072e9SAllain Legacy 	struct rte_avp_fifo *req_q; /**< Request queue */
190908072e9SAllain Legacy 	struct rte_avp_fifo *resp_q; /**< Response queue */
191908072e9SAllain Legacy 	void *host_sync_addr; /**< (host) Req/Resp Mem address */
192908072e9SAllain Legacy 	void *sync_addr; /**< Req/Resp Mem address */
193908072e9SAllain Legacy 	void *host_mbuf_addr; /**< (host) MBUF pool start address */
194908072e9SAllain Legacy 	void *mbuf_addr; /**< MBUF pool start address */
195908072e9SAllain Legacy } __rte_cache_aligned;
196908072e9SAllain Legacy 
197908072e9SAllain Legacy /* RTE ethernet private data */
198908072e9SAllain Legacy struct avp_adapter {
199908072e9SAllain Legacy 	struct avp_dev avp;
200908072e9SAllain Legacy } __rte_cache_aligned;
201908072e9SAllain Legacy 
202c0ad5842SAllain Legacy 
203c0ad5842SAllain Legacy /* 32-bit MMIO register write */
204c0ad5842SAllain Legacy #define AVP_WRITE32(_value, _addr) rte_write32_relaxed((_value), (_addr))
205c0ad5842SAllain Legacy 
206c0ad5842SAllain Legacy /* 32-bit MMIO register read */
207c0ad5842SAllain Legacy #define AVP_READ32(_addr) rte_read32_relaxed((_addr))
208c0ad5842SAllain Legacy 
209908072e9SAllain Legacy /* Macro to cast the ethernet device private data to a AVP object */
210908072e9SAllain Legacy #define AVP_DEV_PRIVATE_TO_HW(adapter) \
211908072e9SAllain Legacy 	(&((struct avp_adapter *)adapter)->avp)
212908072e9SAllain Legacy 
213908072e9SAllain Legacy /*
214c0ad5842SAllain Legacy  * Defines the structure of a AVP device queue for the purpose of handling the
215c0ad5842SAllain Legacy  * receive and transmit burst callback functions
216c0ad5842SAllain Legacy  */
217c0ad5842SAllain Legacy struct avp_queue {
218c0ad5842SAllain Legacy 	struct rte_eth_dev_data *dev_data;
219c0ad5842SAllain Legacy 	/**< Backpointer to ethernet device data */
220c0ad5842SAllain Legacy 	struct avp_dev *avp; /**< Backpointer to AVP device */
221c0ad5842SAllain Legacy 	uint16_t queue_id;
222c0ad5842SAllain Legacy 	/**< Queue identifier used for indexing current queue */
223c0ad5842SAllain Legacy 	uint16_t queue_base;
224c0ad5842SAllain Legacy 	/**< Base queue identifier for queue servicing */
225c0ad5842SAllain Legacy 	uint16_t queue_limit;
226c0ad5842SAllain Legacy 	/**< Maximum queue identifier for queue servicing */
227c0ad5842SAllain Legacy 
228c0ad5842SAllain Legacy 	uint64_t packets;
229c0ad5842SAllain Legacy 	uint64_t bytes;
230c0ad5842SAllain Legacy 	uint64_t errors;
231c0ad5842SAllain Legacy };
232c0ad5842SAllain Legacy 
2331a859223SAllain Legacy /* send a request and wait for a response
2341a859223SAllain Legacy  *
2351a859223SAllain Legacy  * @warning must be called while holding the avp->lock spinlock.
2361a859223SAllain Legacy  */
2371a859223SAllain Legacy static int
2381a859223SAllain Legacy avp_dev_process_request(struct avp_dev *avp, struct rte_avp_request *request)
2391a859223SAllain Legacy {
2401a859223SAllain Legacy 	unsigned int retry = AVP_MAX_REQUEST_RETRY;
2411a859223SAllain Legacy 	void *resp_addr = NULL;
2421a859223SAllain Legacy 	unsigned int count;
2431a859223SAllain Legacy 	int ret;
2441a859223SAllain Legacy 
2451a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Sending request %u to host\n", request->req_id);
2461a859223SAllain Legacy 
2471a859223SAllain Legacy 	request->result = -ENOTSUP;
2481a859223SAllain Legacy 
2491a859223SAllain Legacy 	/* Discard any stale responses before starting a new request */
2501a859223SAllain Legacy 	while (avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1))
2511a859223SAllain Legacy 		PMD_DRV_LOG(DEBUG, "Discarding stale response\n");
2521a859223SAllain Legacy 
2531a859223SAllain Legacy 	rte_memcpy(avp->sync_addr, request, sizeof(*request));
2541a859223SAllain Legacy 	count = avp_fifo_put(avp->req_q, &avp->host_sync_addr, 1);
2551a859223SAllain Legacy 	if (count < 1) {
2561a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Cannot send request %u to host\n",
2571a859223SAllain Legacy 			    request->req_id);
2581a859223SAllain Legacy 		ret = -EBUSY;
2591a859223SAllain Legacy 		goto done;
2601a859223SAllain Legacy 	}
2611a859223SAllain Legacy 
2621a859223SAllain Legacy 	while (retry--) {
2631a859223SAllain Legacy 		/* wait for a response */
2641a859223SAllain Legacy 		usleep(AVP_REQUEST_DELAY_USECS);
2651a859223SAllain Legacy 
2661a859223SAllain Legacy 		count = avp_fifo_count(avp->resp_q);
2671a859223SAllain Legacy 		if (count >= 1) {
2681a859223SAllain Legacy 			/* response received */
2691a859223SAllain Legacy 			break;
2701a859223SAllain Legacy 		}
2711a859223SAllain Legacy 
2721a859223SAllain Legacy 		if ((count < 1) && (retry == 0)) {
2731a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "Timeout while waiting for a response for %u\n",
2741a859223SAllain Legacy 				    request->req_id);
2751a859223SAllain Legacy 			ret = -ETIME;
2761a859223SAllain Legacy 			goto done;
2771a859223SAllain Legacy 		}
2781a859223SAllain Legacy 	}
2791a859223SAllain Legacy 
2801a859223SAllain Legacy 	/* retrieve the response */
2811a859223SAllain Legacy 	count = avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1);
2821a859223SAllain Legacy 	if ((count != 1) || (resp_addr != avp->host_sync_addr)) {
2831a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Invalid response from host, count=%u resp=%p host_sync_addr=%p\n",
2841a859223SAllain Legacy 			    count, resp_addr, avp->host_sync_addr);
2851a859223SAllain Legacy 		ret = -ENODATA;
2861a859223SAllain Legacy 		goto done;
2871a859223SAllain Legacy 	}
2881a859223SAllain Legacy 
2891a859223SAllain Legacy 	/* copy to user buffer */
2901a859223SAllain Legacy 	rte_memcpy(request, avp->sync_addr, sizeof(*request));
2911a859223SAllain Legacy 	ret = 0;
2921a859223SAllain Legacy 
2931a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Result %d received for request %u\n",
2941a859223SAllain Legacy 		    request->result, request->req_id);
2951a859223SAllain Legacy 
2961a859223SAllain Legacy done:
2971a859223SAllain Legacy 	return ret;
2981a859223SAllain Legacy }
2991a859223SAllain Legacy 
3001a859223SAllain Legacy static int
301ea37523dSAllain Legacy avp_dev_ctrl_set_link_state(struct rte_eth_dev *eth_dev, unsigned int state)
302ea37523dSAllain Legacy {
303ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
304ea37523dSAllain Legacy 	struct rte_avp_request request;
305ea37523dSAllain Legacy 	int ret;
306ea37523dSAllain Legacy 
307ea37523dSAllain Legacy 	/* setup a link state change request */
308ea37523dSAllain Legacy 	memset(&request, 0, sizeof(request));
309ea37523dSAllain Legacy 	request.req_id = RTE_AVP_REQ_CFG_NETWORK_IF;
310ea37523dSAllain Legacy 	request.if_up = state;
311ea37523dSAllain Legacy 
312ea37523dSAllain Legacy 	ret = avp_dev_process_request(avp, &request);
313ea37523dSAllain Legacy 
314ea37523dSAllain Legacy 	return ret == 0 ? request.result : ret;
315ea37523dSAllain Legacy }
316ea37523dSAllain Legacy 
317ea37523dSAllain Legacy static int
3181a859223SAllain Legacy avp_dev_ctrl_set_config(struct rte_eth_dev *eth_dev,
3191a859223SAllain Legacy 			struct rte_avp_device_config *config)
3201a859223SAllain Legacy {
3211a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
3221a859223SAllain Legacy 	struct rte_avp_request request;
3231a859223SAllain Legacy 	int ret;
3241a859223SAllain Legacy 
3251a859223SAllain Legacy 	/* setup a configure request */
3261a859223SAllain Legacy 	memset(&request, 0, sizeof(request));
3271a859223SAllain Legacy 	request.req_id = RTE_AVP_REQ_CFG_DEVICE;
3281a859223SAllain Legacy 	memcpy(&request.config, config, sizeof(request.config));
3291a859223SAllain Legacy 
3301a859223SAllain Legacy 	ret = avp_dev_process_request(avp, &request);
3311a859223SAllain Legacy 
3321a859223SAllain Legacy 	return ret == 0 ? request.result : ret;
3331a859223SAllain Legacy }
3341a859223SAllain Legacy 
335ea37523dSAllain Legacy static int
336ea37523dSAllain Legacy avp_dev_ctrl_shutdown(struct rte_eth_dev *eth_dev)
337ea37523dSAllain Legacy {
338ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
339ea37523dSAllain Legacy 	struct rte_avp_request request;
340ea37523dSAllain Legacy 	int ret;
341ea37523dSAllain Legacy 
342ea37523dSAllain Legacy 	/* setup a shutdown request */
343ea37523dSAllain Legacy 	memset(&request, 0, sizeof(request));
344ea37523dSAllain Legacy 	request.req_id = RTE_AVP_REQ_SHUTDOWN_DEVICE;
345ea37523dSAllain Legacy 
346ea37523dSAllain Legacy 	ret = avp_dev_process_request(avp, &request);
347ea37523dSAllain Legacy 
348ea37523dSAllain Legacy 	return ret == 0 ? request.result : ret;
349ea37523dSAllain Legacy }
350ea37523dSAllain Legacy 
35150db69fdSAllain Legacy /* translate from host mbuf virtual address to guest virtual address */
35250db69fdSAllain Legacy static inline void *
35350db69fdSAllain Legacy avp_dev_translate_buffer(struct avp_dev *avp, void *host_mbuf_address)
35450db69fdSAllain Legacy {
35550db69fdSAllain Legacy 	return RTE_PTR_ADD(RTE_PTR_SUB(host_mbuf_address,
35650db69fdSAllain Legacy 				       (uintptr_t)avp->host_mbuf_addr),
35750db69fdSAllain Legacy 			   (uintptr_t)avp->mbuf_addr);
35850db69fdSAllain Legacy }
35950db69fdSAllain Legacy 
360c0ad5842SAllain Legacy /* translate from host physical address to guest virtual address */
361c0ad5842SAllain Legacy static void *
362c0ad5842SAllain Legacy avp_dev_translate_address(struct rte_eth_dev *eth_dev,
363df6e0a06SSantosh Shukla 			  rte_iova_t host_phys_addr)
364c0ad5842SAllain Legacy {
365c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
366c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
367c0ad5842SAllain Legacy 	struct rte_avp_memmap_info *info;
368c0ad5842SAllain Legacy 	struct rte_avp_memmap *map;
369c0ad5842SAllain Legacy 	off_t offset;
370c0ad5842SAllain Legacy 	void *addr;
371c0ad5842SAllain Legacy 	unsigned int i;
372c0ad5842SAllain Legacy 
373c0ad5842SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_MEMORY_BAR].addr;
374c0ad5842SAllain Legacy 	resource = &pci_dev->mem_resource[RTE_AVP_PCI_MEMMAP_BAR];
375c0ad5842SAllain Legacy 	info = (struct rte_avp_memmap_info *)resource->addr;
376c0ad5842SAllain Legacy 
377c0ad5842SAllain Legacy 	offset = 0;
378c0ad5842SAllain Legacy 	for (i = 0; i < info->nb_maps; i++) {
379c0ad5842SAllain Legacy 		/* search all segments looking for a matching address */
380c0ad5842SAllain Legacy 		map = &info->maps[i];
381c0ad5842SAllain Legacy 
382c0ad5842SAllain Legacy 		if ((host_phys_addr >= map->phys_addr) &&
383c0ad5842SAllain Legacy 			(host_phys_addr < (map->phys_addr + map->length))) {
384c0ad5842SAllain Legacy 			/* address is within this segment */
385c0ad5842SAllain Legacy 			offset += (host_phys_addr - map->phys_addr);
3868a70b112SBruce Richardson 			addr = RTE_PTR_ADD(addr, (uintptr_t)offset);
387c0ad5842SAllain Legacy 
388c0ad5842SAllain Legacy 			PMD_DRV_LOG(DEBUG, "Translating host physical 0x%" PRIx64 " to guest virtual 0x%p\n",
389c0ad5842SAllain Legacy 				    host_phys_addr, addr);
390c0ad5842SAllain Legacy 
391c0ad5842SAllain Legacy 			return addr;
392c0ad5842SAllain Legacy 		}
393c0ad5842SAllain Legacy 		offset += map->length;
394c0ad5842SAllain Legacy 	}
395c0ad5842SAllain Legacy 
396c0ad5842SAllain Legacy 	return NULL;
397c0ad5842SAllain Legacy }
398c0ad5842SAllain Legacy 
399c0ad5842SAllain Legacy /* verify that the incoming device version is compatible with our version */
400c0ad5842SAllain Legacy static int
401c0ad5842SAllain Legacy avp_dev_version_check(uint32_t version)
402c0ad5842SAllain Legacy {
403c0ad5842SAllain Legacy 	uint32_t driver = RTE_AVP_STRIP_MINOR_VERSION(AVP_DPDK_DRIVER_VERSION);
404c0ad5842SAllain Legacy 	uint32_t device = RTE_AVP_STRIP_MINOR_VERSION(version);
405c0ad5842SAllain Legacy 
406c0ad5842SAllain Legacy 	if (device <= driver) {
407c0ad5842SAllain Legacy 		/* the host driver version is less than or equal to ours */
408c0ad5842SAllain Legacy 		return 0;
409c0ad5842SAllain Legacy 	}
410c0ad5842SAllain Legacy 
411c0ad5842SAllain Legacy 	return 1;
412c0ad5842SAllain Legacy }
413c0ad5842SAllain Legacy 
414c0ad5842SAllain Legacy /* verify that memory regions have expected version and validation markers */
415c0ad5842SAllain Legacy static int
416c0ad5842SAllain Legacy avp_dev_check_regions(struct rte_eth_dev *eth_dev)
417c0ad5842SAllain Legacy {
418c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
419c0ad5842SAllain Legacy 	struct rte_avp_memmap_info *memmap;
420c0ad5842SAllain Legacy 	struct rte_avp_device_info *info;
421c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
422c0ad5842SAllain Legacy 	unsigned int i;
423c0ad5842SAllain Legacy 
424c0ad5842SAllain Legacy 	/* Dump resource info for debug */
425c0ad5842SAllain Legacy 	for (i = 0; i < PCI_MAX_RESOURCE; i++) {
426c0ad5842SAllain Legacy 		resource = &pci_dev->mem_resource[i];
427c0ad5842SAllain Legacy 		if ((resource->phys_addr == 0) || (resource->len == 0))
428c0ad5842SAllain Legacy 			continue;
429c0ad5842SAllain Legacy 
430c0ad5842SAllain Legacy 		PMD_DRV_LOG(DEBUG, "resource[%u]: phys=0x%" PRIx64 " len=%" PRIu64 " addr=%p\n",
431c0ad5842SAllain Legacy 			    i, resource->phys_addr,
432c0ad5842SAllain Legacy 			    resource->len, resource->addr);
433c0ad5842SAllain Legacy 
434c0ad5842SAllain Legacy 		switch (i) {
435c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MEMMAP_BAR:
436c0ad5842SAllain Legacy 			memmap = (struct rte_avp_memmap_info *)resource->addr;
437c0ad5842SAllain Legacy 			if ((memmap->magic != RTE_AVP_MEMMAP_MAGIC) ||
438c0ad5842SAllain Legacy 			    (memmap->version != RTE_AVP_MEMMAP_VERSION)) {
439c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Invalid memmap magic 0x%08x and version %u\n",
440c0ad5842SAllain Legacy 					    memmap->magic, memmap->version);
441c0ad5842SAllain Legacy 				return -EINVAL;
442c0ad5842SAllain Legacy 			}
443c0ad5842SAllain Legacy 			break;
444c0ad5842SAllain Legacy 
445c0ad5842SAllain Legacy 		case RTE_AVP_PCI_DEVICE_BAR:
446c0ad5842SAllain Legacy 			info = (struct rte_avp_device_info *)resource->addr;
447c0ad5842SAllain Legacy 			if ((info->magic != RTE_AVP_DEVICE_MAGIC) ||
448c0ad5842SAllain Legacy 			    avp_dev_version_check(info->version)) {
449c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Invalid device info magic 0x%08x or version 0x%08x > 0x%08x\n",
450c0ad5842SAllain Legacy 					    info->magic, info->version,
451c0ad5842SAllain Legacy 					    AVP_DPDK_DRIVER_VERSION);
452c0ad5842SAllain Legacy 				return -EINVAL;
453c0ad5842SAllain Legacy 			}
454c0ad5842SAllain Legacy 			break;
455c0ad5842SAllain Legacy 
456c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MEMORY_BAR:
457c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MMIO_BAR:
458c0ad5842SAllain Legacy 			if (resource->addr == NULL) {
459c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Missing address space for BAR%u\n",
460c0ad5842SAllain Legacy 					    i);
461c0ad5842SAllain Legacy 				return -EINVAL;
462c0ad5842SAllain Legacy 			}
463c0ad5842SAllain Legacy 			break;
464c0ad5842SAllain Legacy 
465c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MSIX_BAR:
466c0ad5842SAllain Legacy 		default:
467c0ad5842SAllain Legacy 			/* no validation required */
468c0ad5842SAllain Legacy 			break;
469c0ad5842SAllain Legacy 		}
470c0ad5842SAllain Legacy 	}
471c0ad5842SAllain Legacy 
472c0ad5842SAllain Legacy 	return 0;
473c0ad5842SAllain Legacy }
474c0ad5842SAllain Legacy 
47582e140b8SAllain Legacy static int
47682e140b8SAllain Legacy avp_dev_detach(struct rte_eth_dev *eth_dev)
47782e140b8SAllain Legacy {
47882e140b8SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
47982e140b8SAllain Legacy 	int ret;
48082e140b8SAllain Legacy 
48182e140b8SAllain Legacy 	PMD_DRV_LOG(NOTICE, "Detaching port %u from AVP device 0x%" PRIx64 "\n",
48282e140b8SAllain Legacy 		    eth_dev->data->port_id, avp->device_id);
48382e140b8SAllain Legacy 
48482e140b8SAllain Legacy 	rte_spinlock_lock(&avp->lock);
48582e140b8SAllain Legacy 
48682e140b8SAllain Legacy 	if (avp->flags & AVP_F_DETACHED) {
48782e140b8SAllain Legacy 		PMD_DRV_LOG(NOTICE, "port %u already detached\n",
48882e140b8SAllain Legacy 			    eth_dev->data->port_id);
48982e140b8SAllain Legacy 		ret = 0;
49082e140b8SAllain Legacy 		goto unlock;
49182e140b8SAllain Legacy 	}
49282e140b8SAllain Legacy 
49382e140b8SAllain Legacy 	/* shutdown the device first so the host stops sending us packets. */
49482e140b8SAllain Legacy 	ret = avp_dev_ctrl_shutdown(eth_dev);
49582e140b8SAllain Legacy 	if (ret < 0) {
49682e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to send/recv shutdown to host, ret=%d\n",
49782e140b8SAllain Legacy 			    ret);
49882e140b8SAllain Legacy 		avp->flags &= ~AVP_F_DETACHED;
49982e140b8SAllain Legacy 		goto unlock;
50082e140b8SAllain Legacy 	}
50182e140b8SAllain Legacy 
50282e140b8SAllain Legacy 	avp->flags |= AVP_F_DETACHED;
50382e140b8SAllain Legacy 	rte_wmb();
50482e140b8SAllain Legacy 
50582e140b8SAllain Legacy 	/* wait for queues to acknowledge the presence of the detach flag */
50682e140b8SAllain Legacy 	rte_delay_ms(1);
50782e140b8SAllain Legacy 
50882e140b8SAllain Legacy 	ret = 0;
50982e140b8SAllain Legacy 
51082e140b8SAllain Legacy unlock:
51182e140b8SAllain Legacy 	rte_spinlock_unlock(&avp->lock);
51282e140b8SAllain Legacy 	return ret;
51382e140b8SAllain Legacy }
51482e140b8SAllain Legacy 
5151a859223SAllain Legacy static void
516cce4367fSAllain Legacy _avp_set_rx_queue_mappings(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
517cce4367fSAllain Legacy {
518cce4367fSAllain Legacy 	struct avp_dev *avp =
519cce4367fSAllain Legacy 		AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
520cce4367fSAllain Legacy 	struct avp_queue *rxq;
521cce4367fSAllain Legacy 	uint16_t queue_count;
522cce4367fSAllain Legacy 	uint16_t remainder;
523cce4367fSAllain Legacy 
524cce4367fSAllain Legacy 	rxq = (struct avp_queue *)eth_dev->data->rx_queues[rx_queue_id];
525cce4367fSAllain Legacy 
526cce4367fSAllain Legacy 	/*
527cce4367fSAllain Legacy 	 * Must map all AVP fifos as evenly as possible between the configured
528cce4367fSAllain Legacy 	 * device queues.  Each device queue will service a subset of the AVP
529cce4367fSAllain Legacy 	 * fifos. If there is an odd number of device queues the first set of
530cce4367fSAllain Legacy 	 * device queues will get the extra AVP fifos.
531cce4367fSAllain Legacy 	 */
532cce4367fSAllain Legacy 	queue_count = avp->num_rx_queues / eth_dev->data->nb_rx_queues;
533cce4367fSAllain Legacy 	remainder = avp->num_rx_queues % eth_dev->data->nb_rx_queues;
534cce4367fSAllain Legacy 	if (rx_queue_id < remainder) {
535cce4367fSAllain Legacy 		/* these queues must service one extra FIFO */
536cce4367fSAllain Legacy 		rxq->queue_base = rx_queue_id * (queue_count + 1);
537cce4367fSAllain Legacy 		rxq->queue_limit = rxq->queue_base + (queue_count + 1) - 1;
538cce4367fSAllain Legacy 	} else {
539cce4367fSAllain Legacy 		/* these queues service the regular number of FIFO */
540cce4367fSAllain Legacy 		rxq->queue_base = ((remainder * (queue_count + 1)) +
541cce4367fSAllain Legacy 				   ((rx_queue_id - remainder) * queue_count));
542cce4367fSAllain Legacy 		rxq->queue_limit = rxq->queue_base + queue_count - 1;
543cce4367fSAllain Legacy 	}
544cce4367fSAllain Legacy 
545cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "rxq %u at %p base %u limit %u\n",
546cce4367fSAllain Legacy 		    rx_queue_id, rxq, rxq->queue_base, rxq->queue_limit);
547cce4367fSAllain Legacy 
548cce4367fSAllain Legacy 	rxq->queue_id = rxq->queue_base;
549cce4367fSAllain Legacy }
550cce4367fSAllain Legacy 
551cce4367fSAllain Legacy static void
5521a859223SAllain Legacy _avp_set_queue_counts(struct rte_eth_dev *eth_dev)
5531a859223SAllain Legacy {
554c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
5551a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
5561a859223SAllain Legacy 	struct rte_avp_device_info *host_info;
5571a859223SAllain Legacy 	void *addr;
5581a859223SAllain Legacy 
5591a859223SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr;
5601a859223SAllain Legacy 	host_info = (struct rte_avp_device_info *)addr;
5611a859223SAllain Legacy 
5621a859223SAllain Legacy 	/*
5631a859223SAllain Legacy 	 * the transmit direction is not negotiated beyond respecting the max
5641a859223SAllain Legacy 	 * number of queues because the host can handle arbitrary guest tx
5651a859223SAllain Legacy 	 * queues (host rx queues).
5661a859223SAllain Legacy 	 */
5671a859223SAllain Legacy 	avp->num_tx_queues = eth_dev->data->nb_tx_queues;
5681a859223SAllain Legacy 
5691a859223SAllain Legacy 	/*
5701a859223SAllain Legacy 	 * the receive direction is more restrictive.  The host requires a
5711a859223SAllain Legacy 	 * minimum number of guest rx queues (host tx queues) therefore
5721a859223SAllain Legacy 	 * negotiate a value that is at least as large as the host minimum
5731a859223SAllain Legacy 	 * requirement.  If the host and guest values are not identical then a
5741a859223SAllain Legacy 	 * mapping will be established in the receive_queue_setup function.
5751a859223SAllain Legacy 	 */
5761a859223SAllain Legacy 	avp->num_rx_queues = RTE_MAX(host_info->min_rx_queues,
5771a859223SAllain Legacy 				     eth_dev->data->nb_rx_queues);
5781a859223SAllain Legacy 
5791a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Requesting %u Tx and %u Rx queues from host\n",
5801a859223SAllain Legacy 		    avp->num_tx_queues, avp->num_rx_queues);
5811a859223SAllain Legacy }
5821a859223SAllain Legacy 
58382e140b8SAllain Legacy static int
58482e140b8SAllain Legacy avp_dev_attach(struct rte_eth_dev *eth_dev)
58582e140b8SAllain Legacy {
58682e140b8SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
58782e140b8SAllain Legacy 	struct rte_avp_device_config config;
58882e140b8SAllain Legacy 	unsigned int i;
58982e140b8SAllain Legacy 	int ret;
59082e140b8SAllain Legacy 
59182e140b8SAllain Legacy 	PMD_DRV_LOG(NOTICE, "Attaching port %u to AVP device 0x%" PRIx64 "\n",
59282e140b8SAllain Legacy 		    eth_dev->data->port_id, avp->device_id);
59382e140b8SAllain Legacy 
59482e140b8SAllain Legacy 	rte_spinlock_lock(&avp->lock);
59582e140b8SAllain Legacy 
59682e140b8SAllain Legacy 	if (!(avp->flags & AVP_F_DETACHED)) {
59782e140b8SAllain Legacy 		PMD_DRV_LOG(NOTICE, "port %u already attached\n",
59882e140b8SAllain Legacy 			    eth_dev->data->port_id);
59982e140b8SAllain Legacy 		ret = 0;
60082e140b8SAllain Legacy 		goto unlock;
60182e140b8SAllain Legacy 	}
60282e140b8SAllain Legacy 
60382e140b8SAllain Legacy 	/*
60482e140b8SAllain Legacy 	 * make sure that the detached flag is set prior to reconfiguring the
60582e140b8SAllain Legacy 	 * queues.
60682e140b8SAllain Legacy 	 */
60782e140b8SAllain Legacy 	avp->flags |= AVP_F_DETACHED;
60882e140b8SAllain Legacy 	rte_wmb();
60982e140b8SAllain Legacy 
61082e140b8SAllain Legacy 	/*
61182e140b8SAllain Legacy 	 * re-run the device create utility which will parse the new host info
61282e140b8SAllain Legacy 	 * and setup the AVP device queue pointers.
61382e140b8SAllain Legacy 	 */
614c0802544SFerruh Yigit 	ret = avp_dev_create(RTE_ETH_DEV_TO_PCI(eth_dev), eth_dev);
61582e140b8SAllain Legacy 	if (ret < 0) {
61682e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to re-create AVP device, ret=%d\n",
61782e140b8SAllain Legacy 			    ret);
61882e140b8SAllain Legacy 		goto unlock;
61982e140b8SAllain Legacy 	}
62082e140b8SAllain Legacy 
62182e140b8SAllain Legacy 	if (avp->flags & AVP_F_CONFIGURED) {
62282e140b8SAllain Legacy 		/*
62382e140b8SAllain Legacy 		 * Update the receive queue mapping to handle cases where the
62482e140b8SAllain Legacy 		 * source and destination hosts have different queue
62582e140b8SAllain Legacy 		 * requirements.  As long as the DETACHED flag is asserted the
62682e140b8SAllain Legacy 		 * queue table should not be referenced so it should be safe to
62782e140b8SAllain Legacy 		 * update it.
62882e140b8SAllain Legacy 		 */
62982e140b8SAllain Legacy 		_avp_set_queue_counts(eth_dev);
63082e140b8SAllain Legacy 		for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
63182e140b8SAllain Legacy 			_avp_set_rx_queue_mappings(eth_dev, i);
63282e140b8SAllain Legacy 
63382e140b8SAllain Legacy 		/*
63482e140b8SAllain Legacy 		 * Update the host with our config details so that it knows the
63582e140b8SAllain Legacy 		 * device is active.
63682e140b8SAllain Legacy 		 */
63782e140b8SAllain Legacy 		memset(&config, 0, sizeof(config));
63882e140b8SAllain Legacy 		config.device_id = avp->device_id;
63982e140b8SAllain Legacy 		config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK;
64082e140b8SAllain Legacy 		config.driver_version = AVP_DPDK_DRIVER_VERSION;
64182e140b8SAllain Legacy 		config.features = avp->features;
64282e140b8SAllain Legacy 		config.num_tx_queues = avp->num_tx_queues;
64382e140b8SAllain Legacy 		config.num_rx_queues = avp->num_rx_queues;
64482e140b8SAllain Legacy 		config.if_up = !!(avp->flags & AVP_F_LINKUP);
64582e140b8SAllain Legacy 
64682e140b8SAllain Legacy 		ret = avp_dev_ctrl_set_config(eth_dev, &config);
64782e140b8SAllain Legacy 		if (ret < 0) {
64882e140b8SAllain Legacy 			PMD_DRV_LOG(ERR, "Config request failed by host, ret=%d\n",
64982e140b8SAllain Legacy 				    ret);
65082e140b8SAllain Legacy 			goto unlock;
65182e140b8SAllain Legacy 		}
65282e140b8SAllain Legacy 	}
65382e140b8SAllain Legacy 
65482e140b8SAllain Legacy 	rte_wmb();
65582e140b8SAllain Legacy 	avp->flags &= ~AVP_F_DETACHED;
65682e140b8SAllain Legacy 
65782e140b8SAllain Legacy 	ret = 0;
65882e140b8SAllain Legacy 
65982e140b8SAllain Legacy unlock:
66082e140b8SAllain Legacy 	rte_spinlock_unlock(&avp->lock);
66182e140b8SAllain Legacy 	return ret;
66282e140b8SAllain Legacy }
66382e140b8SAllain Legacy 
66482e140b8SAllain Legacy static void
665c23a1a30SQi Zhang avp_dev_interrupt_handler(void *data)
66682e140b8SAllain Legacy {
66782e140b8SAllain Legacy 	struct rte_eth_dev *eth_dev = data;
668c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
66982e140b8SAllain Legacy 	void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr;
67082e140b8SAllain Legacy 	uint32_t status, value;
67182e140b8SAllain Legacy 	int ret;
67282e140b8SAllain Legacy 
67382e140b8SAllain Legacy 	if (registers == NULL)
67482e140b8SAllain Legacy 		rte_panic("no mapped MMIO register space\n");
67582e140b8SAllain Legacy 
67682e140b8SAllain Legacy 	/* read the interrupt status register
67782e140b8SAllain Legacy 	 * note: this register clears on read so all raised interrupts must be
67882e140b8SAllain Legacy 	 *    handled or remembered for later processing
67982e140b8SAllain Legacy 	 */
68082e140b8SAllain Legacy 	status = AVP_READ32(
68182e140b8SAllain Legacy 		RTE_PTR_ADD(registers,
68282e140b8SAllain Legacy 			    RTE_AVP_INTERRUPT_STATUS_OFFSET));
68382e140b8SAllain Legacy 
684f353fbc5SFerruh Yigit 	if (status & RTE_AVP_MIGRATION_INTERRUPT_MASK) {
68582e140b8SAllain Legacy 		/* handle interrupt based on current status */
68682e140b8SAllain Legacy 		value = AVP_READ32(
68782e140b8SAllain Legacy 			RTE_PTR_ADD(registers,
68882e140b8SAllain Legacy 				    RTE_AVP_MIGRATION_STATUS_OFFSET));
68982e140b8SAllain Legacy 		switch (value) {
69082e140b8SAllain Legacy 		case RTE_AVP_MIGRATION_DETACHED:
69182e140b8SAllain Legacy 			ret = avp_dev_detach(eth_dev);
69282e140b8SAllain Legacy 			break;
69382e140b8SAllain Legacy 		case RTE_AVP_MIGRATION_ATTACHED:
69482e140b8SAllain Legacy 			ret = avp_dev_attach(eth_dev);
69582e140b8SAllain Legacy 			break;
69682e140b8SAllain Legacy 		default:
69782e140b8SAllain Legacy 			PMD_DRV_LOG(ERR, "unexpected migration status, status=%u\n",
69882e140b8SAllain Legacy 				    value);
69982e140b8SAllain Legacy 			ret = -EINVAL;
70082e140b8SAllain Legacy 		}
70182e140b8SAllain Legacy 
70282e140b8SAllain Legacy 		/* acknowledge the request by writing out our current status */
70382e140b8SAllain Legacy 		value = (ret == 0 ? value : RTE_AVP_MIGRATION_ERROR);
70482e140b8SAllain Legacy 		AVP_WRITE32(value,
70582e140b8SAllain Legacy 			    RTE_PTR_ADD(registers,
70682e140b8SAllain Legacy 					RTE_AVP_MIGRATION_ACK_OFFSET));
70782e140b8SAllain Legacy 
70882e140b8SAllain Legacy 		PMD_DRV_LOG(NOTICE, "AVP migration interrupt handled\n");
70982e140b8SAllain Legacy 	}
71082e140b8SAllain Legacy 
71182e140b8SAllain Legacy 	if (status & ~RTE_AVP_MIGRATION_INTERRUPT_MASK)
71282e140b8SAllain Legacy 		PMD_DRV_LOG(WARNING, "AVP unexpected interrupt, status=0x%08x\n",
71382e140b8SAllain Legacy 			    status);
71482e140b8SAllain Legacy 
71582e140b8SAllain Legacy 	/* re-enable UIO interrupt handling */
7166bee9d5fSNithin Dabilpuram 	ret = rte_intr_ack(&pci_dev->intr_handle);
71782e140b8SAllain Legacy 	if (ret < 0) {
71882e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to re-enable UIO interrupts, ret=%d\n",
71982e140b8SAllain Legacy 			    ret);
72082e140b8SAllain Legacy 		/* continue */
72182e140b8SAllain Legacy 	}
72282e140b8SAllain Legacy }
72382e140b8SAllain Legacy 
72482e140b8SAllain Legacy static int
72582e140b8SAllain Legacy avp_dev_enable_interrupts(struct rte_eth_dev *eth_dev)
72682e140b8SAllain Legacy {
727c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
72882e140b8SAllain Legacy 	void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr;
72982e140b8SAllain Legacy 	int ret;
73082e140b8SAllain Legacy 
73182e140b8SAllain Legacy 	if (registers == NULL)
73282e140b8SAllain Legacy 		return -EINVAL;
73382e140b8SAllain Legacy 
73482e140b8SAllain Legacy 	/* enable UIO interrupt handling */
73582e140b8SAllain Legacy 	ret = rte_intr_enable(&pci_dev->intr_handle);
73682e140b8SAllain Legacy 	if (ret < 0) {
73782e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to enable UIO interrupts, ret=%d\n",
73882e140b8SAllain Legacy 			    ret);
73982e140b8SAllain Legacy 		return ret;
74082e140b8SAllain Legacy 	}
74182e140b8SAllain Legacy 
74282e140b8SAllain Legacy 	/* inform the device that all interrupts are enabled */
74382e140b8SAllain Legacy 	AVP_WRITE32(RTE_AVP_APP_INTERRUPTS_MASK,
74482e140b8SAllain Legacy 		    RTE_PTR_ADD(registers, RTE_AVP_INTERRUPT_MASK_OFFSET));
74582e140b8SAllain Legacy 
74682e140b8SAllain Legacy 	return 0;
74782e140b8SAllain Legacy }
74882e140b8SAllain Legacy 
74982e140b8SAllain Legacy static int
75082e140b8SAllain Legacy avp_dev_disable_interrupts(struct rte_eth_dev *eth_dev)
75182e140b8SAllain Legacy {
752c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
75382e140b8SAllain Legacy 	void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr;
75482e140b8SAllain Legacy 	int ret;
75582e140b8SAllain Legacy 
75682e140b8SAllain Legacy 	if (registers == NULL)
75782e140b8SAllain Legacy 		return 0;
75882e140b8SAllain Legacy 
75982e140b8SAllain Legacy 	/* inform the device that all interrupts are disabled */
76082e140b8SAllain Legacy 	AVP_WRITE32(RTE_AVP_NO_INTERRUPTS_MASK,
76182e140b8SAllain Legacy 		    RTE_PTR_ADD(registers, RTE_AVP_INTERRUPT_MASK_OFFSET));
76282e140b8SAllain Legacy 
76382e140b8SAllain Legacy 	/* enable UIO interrupt handling */
76482e140b8SAllain Legacy 	ret = rte_intr_disable(&pci_dev->intr_handle);
76582e140b8SAllain Legacy 	if (ret < 0) {
76682e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to disable UIO interrupts, ret=%d\n",
76782e140b8SAllain Legacy 			    ret);
76882e140b8SAllain Legacy 		return ret;
76982e140b8SAllain Legacy 	}
77082e140b8SAllain Legacy 
77182e140b8SAllain Legacy 	return 0;
77282e140b8SAllain Legacy }
77382e140b8SAllain Legacy 
77482e140b8SAllain Legacy static int
77582e140b8SAllain Legacy avp_dev_setup_interrupts(struct rte_eth_dev *eth_dev)
77682e140b8SAllain Legacy {
777c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
77882e140b8SAllain Legacy 	int ret;
77982e140b8SAllain Legacy 
78082e140b8SAllain Legacy 	/* register a callback handler with UIO for interrupt notifications */
78182e140b8SAllain Legacy 	ret = rte_intr_callback_register(&pci_dev->intr_handle,
78282e140b8SAllain Legacy 					 avp_dev_interrupt_handler,
78382e140b8SAllain Legacy 					 (void *)eth_dev);
78482e140b8SAllain Legacy 	if (ret < 0) {
78582e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to register UIO interrupt callback, ret=%d\n",
78682e140b8SAllain Legacy 			    ret);
78782e140b8SAllain Legacy 		return ret;
78882e140b8SAllain Legacy 	}
78982e140b8SAllain Legacy 
79082e140b8SAllain Legacy 	/* enable interrupt processing */
79182e140b8SAllain Legacy 	return avp_dev_enable_interrupts(eth_dev);
79282e140b8SAllain Legacy }
79382e140b8SAllain Legacy 
79482e140b8SAllain Legacy static int
79582e140b8SAllain Legacy avp_dev_migration_pending(struct rte_eth_dev *eth_dev)
79682e140b8SAllain Legacy {
797c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
79882e140b8SAllain Legacy 	void *registers = pci_dev->mem_resource[RTE_AVP_PCI_MMIO_BAR].addr;
79982e140b8SAllain Legacy 	uint32_t value;
80082e140b8SAllain Legacy 
80182e140b8SAllain Legacy 	if (registers == NULL)
80282e140b8SAllain Legacy 		return 0;
80382e140b8SAllain Legacy 
80482e140b8SAllain Legacy 	value = AVP_READ32(RTE_PTR_ADD(registers,
80582e140b8SAllain Legacy 				       RTE_AVP_MIGRATION_STATUS_OFFSET));
80682e140b8SAllain Legacy 	if (value == RTE_AVP_MIGRATION_DETACHED) {
80782e140b8SAllain Legacy 		/* migration is in progress; ack it if we have not already */
80882e140b8SAllain Legacy 		AVP_WRITE32(value,
80982e140b8SAllain Legacy 			    RTE_PTR_ADD(registers,
81082e140b8SAllain Legacy 					RTE_AVP_MIGRATION_ACK_OFFSET));
81182e140b8SAllain Legacy 		return 1;
81282e140b8SAllain Legacy 	}
81382e140b8SAllain Legacy 	return 0;
81482e140b8SAllain Legacy }
81582e140b8SAllain Legacy 
816c0ad5842SAllain Legacy /*
817c0ad5842SAllain Legacy  * create a AVP device using the supplied device info by first translating it
818c0ad5842SAllain Legacy  * to guest address space(s).
819c0ad5842SAllain Legacy  */
820c0ad5842SAllain Legacy static int
821c0ad5842SAllain Legacy avp_dev_create(struct rte_pci_device *pci_dev,
822c0ad5842SAllain Legacy 	       struct rte_eth_dev *eth_dev)
823c0ad5842SAllain Legacy {
824c0ad5842SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
825c0ad5842SAllain Legacy 	struct rte_avp_device_info *host_info;
826c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
827c0ad5842SAllain Legacy 	unsigned int i;
828c0ad5842SAllain Legacy 
829c0ad5842SAllain Legacy 	resource = &pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR];
830c0ad5842SAllain Legacy 	if (resource->addr == NULL) {
831c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "BAR%u is not mapped\n",
832c0ad5842SAllain Legacy 			    RTE_AVP_PCI_DEVICE_BAR);
833c0ad5842SAllain Legacy 		return -EFAULT;
834c0ad5842SAllain Legacy 	}
835c0ad5842SAllain Legacy 	host_info = (struct rte_avp_device_info *)resource->addr;
836c0ad5842SAllain Legacy 
837c0ad5842SAllain Legacy 	if ((host_info->magic != RTE_AVP_DEVICE_MAGIC) ||
838c0ad5842SAllain Legacy 		avp_dev_version_check(host_info->version)) {
839c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Invalid AVP PCI device, magic 0x%08x version 0x%08x > 0x%08x\n",
840c0ad5842SAllain Legacy 			    host_info->magic, host_info->version,
841c0ad5842SAllain Legacy 			    AVP_DPDK_DRIVER_VERSION);
842c0ad5842SAllain Legacy 		return -EINVAL;
843c0ad5842SAllain Legacy 	}
844c0ad5842SAllain Legacy 
845c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host device is v%u.%u.%u\n",
846c0ad5842SAllain Legacy 		    RTE_AVP_GET_RELEASE_VERSION(host_info->version),
847c0ad5842SAllain Legacy 		    RTE_AVP_GET_MAJOR_VERSION(host_info->version),
848c0ad5842SAllain Legacy 		    RTE_AVP_GET_MINOR_VERSION(host_info->version));
849c0ad5842SAllain Legacy 
850c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u TX queue(s)\n",
851c0ad5842SAllain Legacy 		    host_info->min_tx_queues, host_info->max_tx_queues);
852c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u RX queue(s)\n",
853c0ad5842SAllain Legacy 		    host_info->min_rx_queues, host_info->max_rx_queues);
854c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports features 0x%08x\n",
855c0ad5842SAllain Legacy 		    host_info->features);
856c0ad5842SAllain Legacy 
857c0ad5842SAllain Legacy 	if (avp->magic != AVP_ETHDEV_MAGIC) {
858c0ad5842SAllain Legacy 		/*
859c0ad5842SAllain Legacy 		 * First time initialization (i.e., not during a VM
860c0ad5842SAllain Legacy 		 * migration)
861c0ad5842SAllain Legacy 		 */
862c0ad5842SAllain Legacy 		memset(avp, 0, sizeof(*avp));
863c0ad5842SAllain Legacy 		avp->magic = AVP_ETHDEV_MAGIC;
864c0ad5842SAllain Legacy 		avp->dev_data = eth_dev->data;
865c0ad5842SAllain Legacy 		avp->port_id = eth_dev->data->port_id;
866c0ad5842SAllain Legacy 		avp->host_mbuf_size = host_info->mbuf_size;
867c0ad5842SAllain Legacy 		avp->host_features = host_info->features;
86882e140b8SAllain Legacy 		rte_spinlock_init(&avp->lock);
869c0ad5842SAllain Legacy 		memcpy(&avp->ethaddr.addr_bytes[0],
87035b2d13fSOlivier Matz 		       host_info->ethaddr, RTE_ETHER_ADDR_LEN);
871c0ad5842SAllain Legacy 		/* adjust max values to not exceed our max */
872c0ad5842SAllain Legacy 		avp->max_tx_queues =
873c0ad5842SAllain Legacy 			RTE_MIN(host_info->max_tx_queues, RTE_AVP_MAX_QUEUES);
874c0ad5842SAllain Legacy 		avp->max_rx_queues =
875c0ad5842SAllain Legacy 			RTE_MIN(host_info->max_rx_queues, RTE_AVP_MAX_QUEUES);
876c0ad5842SAllain Legacy 	} else {
877c0ad5842SAllain Legacy 		/* Re-attaching during migration */
878c0ad5842SAllain Legacy 
879c0ad5842SAllain Legacy 		/* TODO... requires validation of host values */
880c0ad5842SAllain Legacy 		if ((host_info->features & avp->features) != avp->features) {
881c0ad5842SAllain Legacy 			PMD_DRV_LOG(ERR, "AVP host features mismatched; 0x%08x, host=0x%08x\n",
882c0ad5842SAllain Legacy 				    avp->features, host_info->features);
883c0ad5842SAllain Legacy 			/* this should not be possible; continue for now */
884c0ad5842SAllain Legacy 		}
885c0ad5842SAllain Legacy 	}
886c0ad5842SAllain Legacy 
887c0ad5842SAllain Legacy 	/* the device id is allowed to change over migrations */
888c0ad5842SAllain Legacy 	avp->device_id = host_info->device_id;
889c0ad5842SAllain Legacy 
890c0ad5842SAllain Legacy 	/* translate incoming host addresses to guest address space */
891c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host tx queue at 0x%" PRIx64 "\n",
892c0ad5842SAllain Legacy 		    host_info->tx_phys);
893c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host alloc queue at 0x%" PRIx64 "\n",
894c0ad5842SAllain Legacy 		    host_info->alloc_phys);
895c0ad5842SAllain Legacy 	for (i = 0; i < avp->max_tx_queues; i++) {
896c0ad5842SAllain Legacy 		avp->tx_q[i] = avp_dev_translate_address(eth_dev,
897c0ad5842SAllain Legacy 			host_info->tx_phys + (i * host_info->tx_size));
898c0ad5842SAllain Legacy 
899c0ad5842SAllain Legacy 		avp->alloc_q[i] = avp_dev_translate_address(eth_dev,
900c0ad5842SAllain Legacy 			host_info->alloc_phys + (i * host_info->alloc_size));
901c0ad5842SAllain Legacy 	}
902c0ad5842SAllain Legacy 
903c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host rx queue at 0x%" PRIx64 "\n",
904c0ad5842SAllain Legacy 		    host_info->rx_phys);
905c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host free queue at 0x%" PRIx64 "\n",
906c0ad5842SAllain Legacy 		    host_info->free_phys);
907c0ad5842SAllain Legacy 	for (i = 0; i < avp->max_rx_queues; i++) {
908c0ad5842SAllain Legacy 		avp->rx_q[i] = avp_dev_translate_address(eth_dev,
909c0ad5842SAllain Legacy 			host_info->rx_phys + (i * host_info->rx_size));
910c0ad5842SAllain Legacy 		avp->free_q[i] = avp_dev_translate_address(eth_dev,
911c0ad5842SAllain Legacy 			host_info->free_phys + (i * host_info->free_size));
912c0ad5842SAllain Legacy 	}
913c0ad5842SAllain Legacy 
914c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host request queue at 0x%" PRIx64 "\n",
915c0ad5842SAllain Legacy 		    host_info->req_phys);
916c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host response queue at 0x%" PRIx64 "\n",
917c0ad5842SAllain Legacy 		    host_info->resp_phys);
918c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host sync address at 0x%" PRIx64 "\n",
919c0ad5842SAllain Legacy 		    host_info->sync_phys);
920c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host mbuf address at 0x%" PRIx64 "\n",
921c0ad5842SAllain Legacy 		    host_info->mbuf_phys);
922c0ad5842SAllain Legacy 	avp->req_q = avp_dev_translate_address(eth_dev, host_info->req_phys);
923c0ad5842SAllain Legacy 	avp->resp_q = avp_dev_translate_address(eth_dev, host_info->resp_phys);
924c0ad5842SAllain Legacy 	avp->sync_addr =
925c0ad5842SAllain Legacy 		avp_dev_translate_address(eth_dev, host_info->sync_phys);
926c0ad5842SAllain Legacy 	avp->mbuf_addr =
927c0ad5842SAllain Legacy 		avp_dev_translate_address(eth_dev, host_info->mbuf_phys);
928c0ad5842SAllain Legacy 
929c0ad5842SAllain Legacy 	/*
930c0ad5842SAllain Legacy 	 * store the host mbuf virtual address so that we can calculate
931c0ad5842SAllain Legacy 	 * relative offsets for each mbuf as they are processed
932c0ad5842SAllain Legacy 	 */
933c0ad5842SAllain Legacy 	avp->host_mbuf_addr = host_info->mbuf_va;
934c0ad5842SAllain Legacy 	avp->host_sync_addr = host_info->sync_va;
935c0ad5842SAllain Legacy 
936c0ad5842SAllain Legacy 	/*
937c0ad5842SAllain Legacy 	 * store the maximum packet length that is supported by the host.
938c0ad5842SAllain Legacy 	 */
939c0ad5842SAllain Legacy 	avp->max_rx_pkt_len = host_info->max_rx_pkt_len;
940c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host max receive packet length is %u\n",
941c0ad5842SAllain Legacy 				host_info->max_rx_pkt_len);
942c0ad5842SAllain Legacy 
943c0ad5842SAllain Legacy 	return 0;
944c0ad5842SAllain Legacy }
945c0ad5842SAllain Legacy 
946c0ad5842SAllain Legacy /*
947908072e9SAllain Legacy  * This function is based on probe() function in avp_pci.c
948908072e9SAllain Legacy  * It returns 0 on success.
949908072e9SAllain Legacy  */
950908072e9SAllain Legacy static int
951908072e9SAllain Legacy eth_avp_dev_init(struct rte_eth_dev *eth_dev)
952908072e9SAllain Legacy {
953c0ad5842SAllain Legacy 	struct avp_dev *avp =
954c0ad5842SAllain Legacy 		AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
955908072e9SAllain Legacy 	struct rte_pci_device *pci_dev;
956c0ad5842SAllain Legacy 	int ret;
957908072e9SAllain Legacy 
958c0802544SFerruh Yigit 	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
9591a859223SAllain Legacy 	eth_dev->dev_ops = &avp_eth_dev_ops;
96050db69fdSAllain Legacy 	eth_dev->rx_pkt_burst = &avp_recv_pkts;
961295abce2SAllain Legacy 	eth_dev->tx_pkt_burst = &avp_xmit_pkts;
96215fb42d5SAllain Legacy 	/* Let rte_eth_dev_close() release the port resources */
96315fb42d5SAllain Legacy 	eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE;
964908072e9SAllain Legacy 
965908072e9SAllain Legacy 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
966908072e9SAllain Legacy 		/*
967908072e9SAllain Legacy 		 * no setup required on secondary processes.  All data is saved
968908072e9SAllain Legacy 		 * in dev_private by the primary process. All resource should
969908072e9SAllain Legacy 		 * be mapped to the same virtual address so all pointers should
970908072e9SAllain Legacy 		 * be valid.
971908072e9SAllain Legacy 		 */
97250db69fdSAllain Legacy 		if (eth_dev->data->scattered_rx) {
97350db69fdSAllain Legacy 			PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n");
97450db69fdSAllain Legacy 			eth_dev->rx_pkt_burst = avp_recv_scattered_pkts;
975295abce2SAllain Legacy 			eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts;
97650db69fdSAllain Legacy 		}
977908072e9SAllain Legacy 		return 0;
978908072e9SAllain Legacy 	}
979908072e9SAllain Legacy 
980908072e9SAllain Legacy 	rte_eth_copy_pci_info(eth_dev, pci_dev);
981908072e9SAllain Legacy 
98282e140b8SAllain Legacy 	/* Check current migration status */
98382e140b8SAllain Legacy 	if (avp_dev_migration_pending(eth_dev)) {
98482e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "VM live migration operation in progress\n");
98582e140b8SAllain Legacy 		return -EBUSY;
98682e140b8SAllain Legacy 	}
98782e140b8SAllain Legacy 
988c0ad5842SAllain Legacy 	/* Check BAR resources */
989c0ad5842SAllain Legacy 	ret = avp_dev_check_regions(eth_dev);
990c0ad5842SAllain Legacy 	if (ret < 0) {
991c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to validate BAR resources, ret=%d\n",
992c0ad5842SAllain Legacy 			    ret);
993c0ad5842SAllain Legacy 		return ret;
994c0ad5842SAllain Legacy 	}
995c0ad5842SAllain Legacy 
99682e140b8SAllain Legacy 	/* Enable interrupts */
99782e140b8SAllain Legacy 	ret = avp_dev_setup_interrupts(eth_dev);
99882e140b8SAllain Legacy 	if (ret < 0) {
99982e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to enable interrupts, ret=%d\n", ret);
100082e140b8SAllain Legacy 		return ret;
100182e140b8SAllain Legacy 	}
100282e140b8SAllain Legacy 
1003c0ad5842SAllain Legacy 	/* Handle each subtype */
1004c0ad5842SAllain Legacy 	ret = avp_dev_create(pci_dev, eth_dev);
1005c0ad5842SAllain Legacy 	if (ret < 0) {
1006c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to create device, ret=%d\n", ret);
1007c0ad5842SAllain Legacy 		return ret;
1008c0ad5842SAllain Legacy 	}
1009c0ad5842SAllain Legacy 
1010c0ad5842SAllain Legacy 	/* Allocate memory for storing MAC addresses */
101135b2d13fSOlivier Matz 	eth_dev->data->mac_addrs = rte_zmalloc("avp_ethdev",
101235b2d13fSOlivier Matz 					RTE_ETHER_ADDR_LEN, 0);
1013c0ad5842SAllain Legacy 	if (eth_dev->data->mac_addrs == NULL) {
1014c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses\n",
101535b2d13fSOlivier Matz 			    RTE_ETHER_ADDR_LEN);
1016c0ad5842SAllain Legacy 		return -ENOMEM;
1017c0ad5842SAllain Legacy 	}
1018c0ad5842SAllain Legacy 
1019c0ad5842SAllain Legacy 	/* Get a mac from device config */
1020538da7a1SOlivier Matz 	rte_ether_addr_copy(&avp->ethaddr, &eth_dev->data->mac_addrs[0]);
1021c0ad5842SAllain Legacy 
1022908072e9SAllain Legacy 	return 0;
1023908072e9SAllain Legacy }
1024908072e9SAllain Legacy 
1025908072e9SAllain Legacy static int
1026908072e9SAllain Legacy eth_avp_dev_uninit(struct rte_eth_dev *eth_dev)
1027908072e9SAllain Legacy {
1028908072e9SAllain Legacy 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
1029908072e9SAllain Legacy 		return -EPERM;
1030908072e9SAllain Legacy 
1031908072e9SAllain Legacy 	if (eth_dev->data == NULL)
1032908072e9SAllain Legacy 		return 0;
1033908072e9SAllain Legacy 
103415fb42d5SAllain Legacy 	avp_dev_close(eth_dev);
103582e140b8SAllain Legacy 
1036908072e9SAllain Legacy 	return 0;
1037908072e9SAllain Legacy }
1038908072e9SAllain Legacy 
1039fdf91e0fSJan Blunck static int
1040fdf91e0fSJan Blunck eth_avp_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
1041fdf91e0fSJan Blunck 		  struct rte_pci_device *pci_dev)
1042908072e9SAllain Legacy {
104301a98fddSThomas Monjalon 	return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct avp_adapter),
104401a98fddSThomas Monjalon 			eth_avp_dev_init);
1045fdf91e0fSJan Blunck }
1046fdf91e0fSJan Blunck 
1047fdf91e0fSJan Blunck static int
1048fdf91e0fSJan Blunck eth_avp_pci_remove(struct rte_pci_device *pci_dev)
1049fdf91e0fSJan Blunck {
1050fdf91e0fSJan Blunck 	return rte_eth_dev_pci_generic_remove(pci_dev,
1051fdf91e0fSJan Blunck 					      eth_avp_dev_uninit);
1052fdf91e0fSJan Blunck }
1053fdf91e0fSJan Blunck 
1054fdf91e0fSJan Blunck static struct rte_pci_driver rte_avp_pmd = {
1055908072e9SAllain Legacy 	.id_table = pci_id_avp_map,
1056908072e9SAllain Legacy 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
1057fdf91e0fSJan Blunck 	.probe = eth_avp_pci_probe,
1058fdf91e0fSJan Blunck 	.remove = eth_avp_pci_remove,
1059908072e9SAllain Legacy };
1060908072e9SAllain Legacy 
10611a859223SAllain Legacy static int
106250db69fdSAllain Legacy avp_dev_enable_scattered(struct rte_eth_dev *eth_dev,
106350db69fdSAllain Legacy 			 struct avp_dev *avp)
106450db69fdSAllain Legacy {
106550db69fdSAllain Legacy 	unsigned int max_rx_pkt_len;
106650db69fdSAllain Legacy 
106750db69fdSAllain Legacy 	max_rx_pkt_len = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len;
106850db69fdSAllain Legacy 
106950db69fdSAllain Legacy 	if ((max_rx_pkt_len > avp->guest_mbuf_size) ||
107050db69fdSAllain Legacy 	    (max_rx_pkt_len > avp->host_mbuf_size)) {
107150db69fdSAllain Legacy 		/*
107250db69fdSAllain Legacy 		 * If the guest MTU is greater than either the host or guest
107350db69fdSAllain Legacy 		 * buffers then chained mbufs have to be enabled in the TX
107450db69fdSAllain Legacy 		 * direction.  It is assumed that the application will not need
107550db69fdSAllain Legacy 		 * to send packets larger than their max_rx_pkt_len (MRU).
107650db69fdSAllain Legacy 		 */
107750db69fdSAllain Legacy 		return 1;
107850db69fdSAllain Legacy 	}
107950db69fdSAllain Legacy 
108050db69fdSAllain Legacy 	if ((avp->max_rx_pkt_len > avp->guest_mbuf_size) ||
108150db69fdSAllain Legacy 	    (avp->max_rx_pkt_len > avp->host_mbuf_size)) {
108250db69fdSAllain Legacy 		/*
108350db69fdSAllain Legacy 		 * If the host MRU is greater than its own mbuf size or the
108450db69fdSAllain Legacy 		 * guest mbuf size then chained mbufs have to be enabled in the
108550db69fdSAllain Legacy 		 * RX direction.
108650db69fdSAllain Legacy 		 */
108750db69fdSAllain Legacy 		return 1;
108850db69fdSAllain Legacy 	}
108950db69fdSAllain Legacy 
109050db69fdSAllain Legacy 	return 0;
109150db69fdSAllain Legacy }
109250db69fdSAllain Legacy 
109350db69fdSAllain Legacy static int
1094cce4367fSAllain Legacy avp_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
1095cce4367fSAllain Legacy 		       uint16_t rx_queue_id,
1096cce4367fSAllain Legacy 		       uint16_t nb_rx_desc,
1097cce4367fSAllain Legacy 		       unsigned int socket_id,
1098cce4367fSAllain Legacy 		       const struct rte_eth_rxconf *rx_conf,
1099cce4367fSAllain Legacy 		       struct rte_mempool *pool)
1100cce4367fSAllain Legacy {
1101cce4367fSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1102cce4367fSAllain Legacy 	struct rte_pktmbuf_pool_private *mbp_priv;
1103cce4367fSAllain Legacy 	struct avp_queue *rxq;
1104cce4367fSAllain Legacy 
1105cce4367fSAllain Legacy 	if (rx_queue_id >= eth_dev->data->nb_rx_queues) {
1106cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "RX queue id is out of range: rx_queue_id=%u, nb_rx_queues=%u\n",
1107cce4367fSAllain Legacy 			    rx_queue_id, eth_dev->data->nb_rx_queues);
1108cce4367fSAllain Legacy 		return -EINVAL;
1109cce4367fSAllain Legacy 	}
1110cce4367fSAllain Legacy 
1111cce4367fSAllain Legacy 	/* Save mbuf pool pointer */
1112cce4367fSAllain Legacy 	avp->pool = pool;
1113cce4367fSAllain Legacy 
1114cce4367fSAllain Legacy 	/* Save the local mbuf size */
1115cce4367fSAllain Legacy 	mbp_priv = rte_mempool_get_priv(pool);
1116cce4367fSAllain Legacy 	avp->guest_mbuf_size = (uint16_t)(mbp_priv->mbuf_data_room_size);
1117cce4367fSAllain Legacy 	avp->guest_mbuf_size -= RTE_PKTMBUF_HEADROOM;
1118cce4367fSAllain Legacy 
111950db69fdSAllain Legacy 	if (avp_dev_enable_scattered(eth_dev, avp)) {
112050db69fdSAllain Legacy 		if (!eth_dev->data->scattered_rx) {
112150db69fdSAllain Legacy 			PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n");
112250db69fdSAllain Legacy 			eth_dev->data->scattered_rx = 1;
112350db69fdSAllain Legacy 			eth_dev->rx_pkt_burst = avp_recv_scattered_pkts;
1124295abce2SAllain Legacy 			eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts;
112550db69fdSAllain Legacy 		}
112650db69fdSAllain Legacy 	}
112750db69fdSAllain Legacy 
1128cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP max_rx_pkt_len=(%u,%u) mbuf_size=(%u,%u)\n",
1129cce4367fSAllain Legacy 		    avp->max_rx_pkt_len,
1130cce4367fSAllain Legacy 		    eth_dev->data->dev_conf.rxmode.max_rx_pkt_len,
1131cce4367fSAllain Legacy 		    avp->host_mbuf_size,
1132cce4367fSAllain Legacy 		    avp->guest_mbuf_size);
1133cce4367fSAllain Legacy 
1134cce4367fSAllain Legacy 	/* allocate a queue object */
1135cce4367fSAllain Legacy 	rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct avp_queue),
1136cce4367fSAllain Legacy 				 RTE_CACHE_LINE_SIZE, socket_id);
1137cce4367fSAllain Legacy 	if (rxq == NULL) {
1138cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate new Rx queue object\n");
1139cce4367fSAllain Legacy 		return -ENOMEM;
1140cce4367fSAllain Legacy 	}
1141cce4367fSAllain Legacy 
1142cce4367fSAllain Legacy 	/* save back pointers to AVP and Ethernet devices */
1143cce4367fSAllain Legacy 	rxq->avp = avp;
1144cce4367fSAllain Legacy 	rxq->dev_data = eth_dev->data;
1145cce4367fSAllain Legacy 	eth_dev->data->rx_queues[rx_queue_id] = (void *)rxq;
1146cce4367fSAllain Legacy 
1147cce4367fSAllain Legacy 	/* setup the queue receive mapping for the current queue. */
1148cce4367fSAllain Legacy 	_avp_set_rx_queue_mappings(eth_dev, rx_queue_id);
1149cce4367fSAllain Legacy 
1150cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "Rx queue %u setup at %p\n", rx_queue_id, rxq);
1151cce4367fSAllain Legacy 
1152cce4367fSAllain Legacy 	(void)nb_rx_desc;
1153cce4367fSAllain Legacy 	(void)rx_conf;
1154cce4367fSAllain Legacy 	return 0;
1155cce4367fSAllain Legacy }
1156cce4367fSAllain Legacy 
1157cce4367fSAllain Legacy static int
1158cce4367fSAllain Legacy avp_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
1159cce4367fSAllain Legacy 		       uint16_t tx_queue_id,
1160cce4367fSAllain Legacy 		       uint16_t nb_tx_desc,
1161cce4367fSAllain Legacy 		       unsigned int socket_id,
1162cce4367fSAllain Legacy 		       const struct rte_eth_txconf *tx_conf)
1163cce4367fSAllain Legacy {
1164cce4367fSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1165cce4367fSAllain Legacy 	struct avp_queue *txq;
1166cce4367fSAllain Legacy 
1167cce4367fSAllain Legacy 	if (tx_queue_id >= eth_dev->data->nb_tx_queues) {
1168cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "TX queue id is out of range: tx_queue_id=%u, nb_tx_queues=%u\n",
1169cce4367fSAllain Legacy 			    tx_queue_id, eth_dev->data->nb_tx_queues);
1170cce4367fSAllain Legacy 		return -EINVAL;
1171cce4367fSAllain Legacy 	}
1172cce4367fSAllain Legacy 
1173cce4367fSAllain Legacy 	/* allocate a queue object */
1174cce4367fSAllain Legacy 	txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct avp_queue),
1175cce4367fSAllain Legacy 				 RTE_CACHE_LINE_SIZE, socket_id);
1176cce4367fSAllain Legacy 	if (txq == NULL) {
1177cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate new Tx queue object\n");
1178cce4367fSAllain Legacy 		return -ENOMEM;
1179cce4367fSAllain Legacy 	}
1180cce4367fSAllain Legacy 
1181cce4367fSAllain Legacy 	/* only the configured set of transmit queues are used */
1182cce4367fSAllain Legacy 	txq->queue_id = tx_queue_id;
1183cce4367fSAllain Legacy 	txq->queue_base = tx_queue_id;
1184cce4367fSAllain Legacy 	txq->queue_limit = tx_queue_id;
1185cce4367fSAllain Legacy 
1186cce4367fSAllain Legacy 	/* save back pointers to AVP and Ethernet devices */
1187cce4367fSAllain Legacy 	txq->avp = avp;
1188cce4367fSAllain Legacy 	txq->dev_data = eth_dev->data;
1189cce4367fSAllain Legacy 	eth_dev->data->tx_queues[tx_queue_id] = (void *)txq;
1190cce4367fSAllain Legacy 
1191cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "Tx queue %u setup at %p\n", tx_queue_id, txq);
1192cce4367fSAllain Legacy 
1193cce4367fSAllain Legacy 	(void)nb_tx_desc;
1194cce4367fSAllain Legacy 	(void)tx_conf;
1195cce4367fSAllain Legacy 	return 0;
1196cce4367fSAllain Legacy }
1197cce4367fSAllain Legacy 
119850db69fdSAllain Legacy static inline int
11996d13ea8eSOlivier Matz _avp_cmp_ether_addr(struct rte_ether_addr *a, struct rte_ether_addr *b)
120050db69fdSAllain Legacy {
120150db69fdSAllain Legacy 	uint16_t *_a = (uint16_t *)&a->addr_bytes[0];
120250db69fdSAllain Legacy 	uint16_t *_b = (uint16_t *)&b->addr_bytes[0];
120350db69fdSAllain Legacy 	return (_a[0] ^ _b[0]) | (_a[1] ^ _b[1]) | (_a[2] ^ _b[2]);
120450db69fdSAllain Legacy }
120550db69fdSAllain Legacy 
120650db69fdSAllain Legacy static inline int
120750db69fdSAllain Legacy _avp_mac_filter(struct avp_dev *avp, struct rte_mbuf *m)
120850db69fdSAllain Legacy {
12096d13ea8eSOlivier Matz 	struct rte_ether_hdr *eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
121050db69fdSAllain Legacy 
121150db69fdSAllain Legacy 	if (likely(_avp_cmp_ether_addr(&avp->ethaddr, &eth->d_addr) == 0)) {
121250db69fdSAllain Legacy 		/* allow all packets destined to our address */
121350db69fdSAllain Legacy 		return 0;
121450db69fdSAllain Legacy 	}
121550db69fdSAllain Legacy 
1216538da7a1SOlivier Matz 	if (likely(rte_is_broadcast_ether_addr(&eth->d_addr))) {
121750db69fdSAllain Legacy 		/* allow all broadcast packets */
121850db69fdSAllain Legacy 		return 0;
121950db69fdSAllain Legacy 	}
122050db69fdSAllain Legacy 
1221538da7a1SOlivier Matz 	if (likely(rte_is_multicast_ether_addr(&eth->d_addr))) {
122250db69fdSAllain Legacy 		/* allow all multicast packets */
122350db69fdSAllain Legacy 		return 0;
122450db69fdSAllain Legacy 	}
122550db69fdSAllain Legacy 
122650db69fdSAllain Legacy 	if (avp->flags & AVP_F_PROMISC) {
122750db69fdSAllain Legacy 		/* allow all packets when in promiscuous mode */
122850db69fdSAllain Legacy 		return 0;
122950db69fdSAllain Legacy 	}
123050db69fdSAllain Legacy 
123150db69fdSAllain Legacy 	return -1;
123250db69fdSAllain Legacy }
123350db69fdSAllain Legacy 
123450db69fdSAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS
123550db69fdSAllain Legacy static inline void
123650db69fdSAllain Legacy __avp_dev_buffer_sanity_check(struct avp_dev *avp, struct rte_avp_desc *buf)
123750db69fdSAllain Legacy {
123850db69fdSAllain Legacy 	struct rte_avp_desc *first_buf;
123950db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
124050db69fdSAllain Legacy 	unsigned int pkt_len;
124150db69fdSAllain Legacy 	unsigned int nb_segs;
124250db69fdSAllain Legacy 	void *pkt_data;
124350db69fdSAllain Legacy 	unsigned int i;
124450db69fdSAllain Legacy 
124550db69fdSAllain Legacy 	first_buf = avp_dev_translate_buffer(avp, buf);
124650db69fdSAllain Legacy 
124750db69fdSAllain Legacy 	i = 0;
124850db69fdSAllain Legacy 	pkt_len = 0;
124950db69fdSAllain Legacy 	nb_segs = first_buf->nb_segs;
125050db69fdSAllain Legacy 	do {
125150db69fdSAllain Legacy 		/* Adjust pointers for guest addressing */
125250db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
125350db69fdSAllain Legacy 		if (pkt_buf == NULL)
125450db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has an invalid address %p\n",
125550db69fdSAllain Legacy 				  i, buf);
125650db69fdSAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
125750db69fdSAllain Legacy 		if (pkt_data == NULL)
125850db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has a NULL data pointer\n",
125950db69fdSAllain Legacy 				  i);
126050db69fdSAllain Legacy 		if (pkt_buf->data_len == 0)
126150db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has 0 data length\n",
126250db69fdSAllain Legacy 				  i);
126350db69fdSAllain Legacy 		pkt_len += pkt_buf->data_len;
126450db69fdSAllain Legacy 		nb_segs--;
126550db69fdSAllain Legacy 		i++;
126650db69fdSAllain Legacy 
126750db69fdSAllain Legacy 	} while (nb_segs && (buf = pkt_buf->next) != NULL);
126850db69fdSAllain Legacy 
126950db69fdSAllain Legacy 	if (nb_segs != 0)
127050db69fdSAllain Legacy 		rte_panic("bad buffer: expected %u segments found %u\n",
127150db69fdSAllain Legacy 			  first_buf->nb_segs, (first_buf->nb_segs - nb_segs));
127250db69fdSAllain Legacy 	if (pkt_len != first_buf->pkt_len)
127350db69fdSAllain Legacy 		rte_panic("bad buffer: expected length %u found %u\n",
127450db69fdSAllain Legacy 			  first_buf->pkt_len, pkt_len);
127550db69fdSAllain Legacy }
127650db69fdSAllain Legacy 
127750db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) \
127850db69fdSAllain Legacy 	__avp_dev_buffer_sanity_check((a), (b))
127950db69fdSAllain Legacy 
128050db69fdSAllain Legacy #else /* RTE_LIBRTE_AVP_DEBUG_BUFFERS */
128150db69fdSAllain Legacy 
128250db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) do {} while (0)
128350db69fdSAllain Legacy 
128450db69fdSAllain Legacy #endif
128550db69fdSAllain Legacy 
128650db69fdSAllain Legacy /*
128750db69fdSAllain Legacy  * Copy a host buffer chain to a set of mbufs.	This function assumes that
128850db69fdSAllain Legacy  * there exactly the required number of mbufs to copy all source bytes.
128950db69fdSAllain Legacy  */
129050db69fdSAllain Legacy static inline struct rte_mbuf *
129150db69fdSAllain Legacy avp_dev_copy_from_buffers(struct avp_dev *avp,
129250db69fdSAllain Legacy 			  struct rte_avp_desc *buf,
129350db69fdSAllain Legacy 			  struct rte_mbuf **mbufs,
129450db69fdSAllain Legacy 			  unsigned int count)
129550db69fdSAllain Legacy {
129650db69fdSAllain Legacy 	struct rte_mbuf *m_previous = NULL;
129750db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
129850db69fdSAllain Legacy 	unsigned int total_length = 0;
129950db69fdSAllain Legacy 	unsigned int copy_length;
130050db69fdSAllain Legacy 	unsigned int src_offset;
130150db69fdSAllain Legacy 	struct rte_mbuf *m;
130250db69fdSAllain Legacy 	uint16_t ol_flags;
130350db69fdSAllain Legacy 	uint16_t vlan_tci;
130450db69fdSAllain Legacy 	void *pkt_data;
130550db69fdSAllain Legacy 	unsigned int i;
130650db69fdSAllain Legacy 
130750db69fdSAllain Legacy 	avp_dev_buffer_sanity_check(avp, buf);
130850db69fdSAllain Legacy 
130950db69fdSAllain Legacy 	/* setup the first source buffer */
131050db69fdSAllain Legacy 	pkt_buf = avp_dev_translate_buffer(avp, buf);
131150db69fdSAllain Legacy 	pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
131250db69fdSAllain Legacy 	total_length = pkt_buf->pkt_len;
131350db69fdSAllain Legacy 	src_offset = 0;
131450db69fdSAllain Legacy 
131550db69fdSAllain Legacy 	if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) {
1316380a7aabSOlivier Matz 		ol_flags = PKT_RX_VLAN;
131750db69fdSAllain Legacy 		vlan_tci = pkt_buf->vlan_tci;
131850db69fdSAllain Legacy 	} else {
131950db69fdSAllain Legacy 		ol_flags = 0;
132050db69fdSAllain Legacy 		vlan_tci = 0;
132150db69fdSAllain Legacy 	}
132250db69fdSAllain Legacy 
132350db69fdSAllain Legacy 	for (i = 0; (i < count) && (buf != NULL); i++) {
132450db69fdSAllain Legacy 		/* fill each destination buffer */
132550db69fdSAllain Legacy 		m = mbufs[i];
132650db69fdSAllain Legacy 
132750db69fdSAllain Legacy 		if (m_previous != NULL)
132850db69fdSAllain Legacy 			m_previous->next = m;
132950db69fdSAllain Legacy 
133050db69fdSAllain Legacy 		m_previous = m;
133150db69fdSAllain Legacy 
133250db69fdSAllain Legacy 		do {
133350db69fdSAllain Legacy 			/*
133450db69fdSAllain Legacy 			 * Copy as many source buffers as will fit in the
133550db69fdSAllain Legacy 			 * destination buffer.
133650db69fdSAllain Legacy 			 */
133750db69fdSAllain Legacy 			copy_length = RTE_MIN((avp->guest_mbuf_size -
133850db69fdSAllain Legacy 					       rte_pktmbuf_data_len(m)),
133950db69fdSAllain Legacy 					      (pkt_buf->data_len -
134050db69fdSAllain Legacy 					       src_offset));
134150db69fdSAllain Legacy 			rte_memcpy(RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *),
134250db69fdSAllain Legacy 					       rte_pktmbuf_data_len(m)),
134350db69fdSAllain Legacy 				   RTE_PTR_ADD(pkt_data, src_offset),
134450db69fdSAllain Legacy 				   copy_length);
134550db69fdSAllain Legacy 			rte_pktmbuf_data_len(m) += copy_length;
134650db69fdSAllain Legacy 			src_offset += copy_length;
134750db69fdSAllain Legacy 
134850db69fdSAllain Legacy 			if (likely(src_offset == pkt_buf->data_len)) {
134950db69fdSAllain Legacy 				/* need a new source buffer */
135050db69fdSAllain Legacy 				buf = pkt_buf->next;
135150db69fdSAllain Legacy 				if (buf != NULL) {
135250db69fdSAllain Legacy 					pkt_buf = avp_dev_translate_buffer(
135350db69fdSAllain Legacy 						avp, buf);
135450db69fdSAllain Legacy 					pkt_data = avp_dev_translate_buffer(
135550db69fdSAllain Legacy 						avp, pkt_buf->data);
135650db69fdSAllain Legacy 					src_offset = 0;
135750db69fdSAllain Legacy 				}
135850db69fdSAllain Legacy 			}
135950db69fdSAllain Legacy 
136050db69fdSAllain Legacy 			if (unlikely(rte_pktmbuf_data_len(m) ==
136150db69fdSAllain Legacy 				     avp->guest_mbuf_size)) {
136250db69fdSAllain Legacy 				/* need a new destination mbuf */
136350db69fdSAllain Legacy 				break;
136450db69fdSAllain Legacy 			}
136550db69fdSAllain Legacy 
136650db69fdSAllain Legacy 		} while (buf != NULL);
136750db69fdSAllain Legacy 	}
136850db69fdSAllain Legacy 
136950db69fdSAllain Legacy 	m = mbufs[0];
137050db69fdSAllain Legacy 	m->ol_flags = ol_flags;
137150db69fdSAllain Legacy 	m->nb_segs = count;
137250db69fdSAllain Legacy 	rte_pktmbuf_pkt_len(m) = total_length;
137350db69fdSAllain Legacy 	m->vlan_tci = vlan_tci;
137450db69fdSAllain Legacy 
137550db69fdSAllain Legacy 	__rte_mbuf_sanity_check(m, 1);
137650db69fdSAllain Legacy 
137750db69fdSAllain Legacy 	return m;
137850db69fdSAllain Legacy }
137950db69fdSAllain Legacy 
138050db69fdSAllain Legacy static uint16_t
138150db69fdSAllain Legacy avp_recv_scattered_pkts(void *rx_queue,
138250db69fdSAllain Legacy 			struct rte_mbuf **rx_pkts,
138350db69fdSAllain Legacy 			uint16_t nb_pkts)
138450db69fdSAllain Legacy {
138550db69fdSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
138650db69fdSAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST];
138750db69fdSAllain Legacy 	struct rte_mbuf *mbufs[RTE_AVP_MAX_MBUF_SEGMENTS];
138850db69fdSAllain Legacy 	struct avp_dev *avp = rxq->avp;
138950db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
139050db69fdSAllain Legacy 	struct rte_avp_fifo *free_q;
139150db69fdSAllain Legacy 	struct rte_avp_fifo *rx_q;
139250db69fdSAllain Legacy 	struct rte_avp_desc *buf;
139350db69fdSAllain Legacy 	unsigned int count, avail, n;
139450db69fdSAllain Legacy 	unsigned int guest_mbuf_size;
139550db69fdSAllain Legacy 	struct rte_mbuf *m;
139650db69fdSAllain Legacy 	unsigned int required;
139750db69fdSAllain Legacy 	unsigned int buf_len;
139850db69fdSAllain Legacy 	unsigned int port_id;
139950db69fdSAllain Legacy 	unsigned int i;
140050db69fdSAllain Legacy 
140182e140b8SAllain Legacy 	if (unlikely(avp->flags & AVP_F_DETACHED)) {
140282e140b8SAllain Legacy 		/* VM live migration in progress */
140382e140b8SAllain Legacy 		return 0;
140482e140b8SAllain Legacy 	}
140582e140b8SAllain Legacy 
140650db69fdSAllain Legacy 	guest_mbuf_size = avp->guest_mbuf_size;
140750db69fdSAllain Legacy 	port_id = avp->port_id;
140850db69fdSAllain Legacy 	rx_q = avp->rx_q[rxq->queue_id];
140950db69fdSAllain Legacy 	free_q = avp->free_q[rxq->queue_id];
141050db69fdSAllain Legacy 
141150db69fdSAllain Legacy 	/* setup next queue to service */
141250db69fdSAllain Legacy 	rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ?
141350db69fdSAllain Legacy 		(rxq->queue_id + 1) : rxq->queue_base;
141450db69fdSAllain Legacy 
141550db69fdSAllain Legacy 	/* determine how many slots are available in the free queue */
141650db69fdSAllain Legacy 	count = avp_fifo_free_count(free_q);
141750db69fdSAllain Legacy 
141850db69fdSAllain Legacy 	/* determine how many packets are available in the rx queue */
141950db69fdSAllain Legacy 	avail = avp_fifo_count(rx_q);
142050db69fdSAllain Legacy 
142150db69fdSAllain Legacy 	/* determine how many packets can be received */
142250db69fdSAllain Legacy 	count = RTE_MIN(count, avail);
142350db69fdSAllain Legacy 	count = RTE_MIN(count, nb_pkts);
142450db69fdSAllain Legacy 	count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST);
142550db69fdSAllain Legacy 
142650db69fdSAllain Legacy 	if (unlikely(count == 0)) {
142750db69fdSAllain Legacy 		/* no free buffers, or no buffers on the rx queue */
142850db69fdSAllain Legacy 		return 0;
142950db69fdSAllain Legacy 	}
143050db69fdSAllain Legacy 
143150db69fdSAllain Legacy 	/* retrieve pending packets */
143250db69fdSAllain Legacy 	n = avp_fifo_get(rx_q, (void **)&avp_bufs, count);
143350db69fdSAllain Legacy 	PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n",
143450db69fdSAllain Legacy 		   count, rx_q);
143550db69fdSAllain Legacy 
143650db69fdSAllain Legacy 	count = 0;
143750db69fdSAllain Legacy 	for (i = 0; i < n; i++) {
143850db69fdSAllain Legacy 		/* prefetch next entry while processing current one */
143950db69fdSAllain Legacy 		if (i + 1 < n) {
144050db69fdSAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
144150db69fdSAllain Legacy 							   avp_bufs[i + 1]);
144250db69fdSAllain Legacy 			rte_prefetch0(pkt_buf);
144350db69fdSAllain Legacy 		}
144450db69fdSAllain Legacy 		buf = avp_bufs[i];
144550db69fdSAllain Legacy 
144650db69fdSAllain Legacy 		/* Peek into the first buffer to determine the total length */
144750db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
144850db69fdSAllain Legacy 		buf_len = pkt_buf->pkt_len;
144950db69fdSAllain Legacy 
145050db69fdSAllain Legacy 		/* Allocate enough mbufs to receive the entire packet */
145150db69fdSAllain Legacy 		required = (buf_len + guest_mbuf_size - 1) / guest_mbuf_size;
145250db69fdSAllain Legacy 		if (rte_pktmbuf_alloc_bulk(avp->pool, mbufs, required)) {
145350db69fdSAllain Legacy 			rxq->dev_data->rx_mbuf_alloc_failed++;
145450db69fdSAllain Legacy 			continue;
145550db69fdSAllain Legacy 		}
145650db69fdSAllain Legacy 
145750db69fdSAllain Legacy 		/* Copy the data from the buffers to our mbufs */
145850db69fdSAllain Legacy 		m = avp_dev_copy_from_buffers(avp, buf, mbufs, required);
145950db69fdSAllain Legacy 
146050db69fdSAllain Legacy 		/* finalize mbuf */
146150db69fdSAllain Legacy 		m->port = port_id;
146250db69fdSAllain Legacy 
146350db69fdSAllain Legacy 		if (_avp_mac_filter(avp, m) != 0) {
146450db69fdSAllain Legacy 			/* silently discard packets not destined to our MAC */
146550db69fdSAllain Legacy 			rte_pktmbuf_free(m);
146650db69fdSAllain Legacy 			continue;
146750db69fdSAllain Legacy 		}
146850db69fdSAllain Legacy 
146950db69fdSAllain Legacy 		/* return new mbuf to caller */
147050db69fdSAllain Legacy 		rx_pkts[count++] = m;
147150db69fdSAllain Legacy 		rxq->bytes += buf_len;
147250db69fdSAllain Legacy 	}
147350db69fdSAllain Legacy 
147450db69fdSAllain Legacy 	rxq->packets += count;
147550db69fdSAllain Legacy 
147650db69fdSAllain Legacy 	/* return the buffers to the free queue */
147750db69fdSAllain Legacy 	avp_fifo_put(free_q, (void **)&avp_bufs[0], n);
147850db69fdSAllain Legacy 
147950db69fdSAllain Legacy 	return count;
148050db69fdSAllain Legacy }
148150db69fdSAllain Legacy 
148250db69fdSAllain Legacy 
148350db69fdSAllain Legacy static uint16_t
148450db69fdSAllain Legacy avp_recv_pkts(void *rx_queue,
148550db69fdSAllain Legacy 	      struct rte_mbuf **rx_pkts,
148650db69fdSAllain Legacy 	      uint16_t nb_pkts)
148750db69fdSAllain Legacy {
148850db69fdSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
148950db69fdSAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST];
149050db69fdSAllain Legacy 	struct avp_dev *avp = rxq->avp;
149150db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
149250db69fdSAllain Legacy 	struct rte_avp_fifo *free_q;
149350db69fdSAllain Legacy 	struct rte_avp_fifo *rx_q;
149450db69fdSAllain Legacy 	unsigned int count, avail, n;
149550db69fdSAllain Legacy 	unsigned int pkt_len;
149650db69fdSAllain Legacy 	struct rte_mbuf *m;
149750db69fdSAllain Legacy 	char *pkt_data;
149850db69fdSAllain Legacy 	unsigned int i;
149950db69fdSAllain Legacy 
150082e140b8SAllain Legacy 	if (unlikely(avp->flags & AVP_F_DETACHED)) {
150182e140b8SAllain Legacy 		/* VM live migration in progress */
150282e140b8SAllain Legacy 		return 0;
150382e140b8SAllain Legacy 	}
150482e140b8SAllain Legacy 
150550db69fdSAllain Legacy 	rx_q = avp->rx_q[rxq->queue_id];
150650db69fdSAllain Legacy 	free_q = avp->free_q[rxq->queue_id];
150750db69fdSAllain Legacy 
150850db69fdSAllain Legacy 	/* setup next queue to service */
150950db69fdSAllain Legacy 	rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ?
151050db69fdSAllain Legacy 		(rxq->queue_id + 1) : rxq->queue_base;
151150db69fdSAllain Legacy 
151250db69fdSAllain Legacy 	/* determine how many slots are available in the free queue */
151350db69fdSAllain Legacy 	count = avp_fifo_free_count(free_q);
151450db69fdSAllain Legacy 
151550db69fdSAllain Legacy 	/* determine how many packets are available in the rx queue */
151650db69fdSAllain Legacy 	avail = avp_fifo_count(rx_q);
151750db69fdSAllain Legacy 
151850db69fdSAllain Legacy 	/* determine how many packets can be received */
151950db69fdSAllain Legacy 	count = RTE_MIN(count, avail);
152050db69fdSAllain Legacy 	count = RTE_MIN(count, nb_pkts);
152150db69fdSAllain Legacy 	count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST);
152250db69fdSAllain Legacy 
152350db69fdSAllain Legacy 	if (unlikely(count == 0)) {
152450db69fdSAllain Legacy 		/* no free buffers, or no buffers on the rx queue */
152550db69fdSAllain Legacy 		return 0;
152650db69fdSAllain Legacy 	}
152750db69fdSAllain Legacy 
152850db69fdSAllain Legacy 	/* retrieve pending packets */
152950db69fdSAllain Legacy 	n = avp_fifo_get(rx_q, (void **)&avp_bufs, count);
153050db69fdSAllain Legacy 	PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n",
153150db69fdSAllain Legacy 		   count, rx_q);
153250db69fdSAllain Legacy 
153350db69fdSAllain Legacy 	count = 0;
153450db69fdSAllain Legacy 	for (i = 0; i < n; i++) {
153550db69fdSAllain Legacy 		/* prefetch next entry while processing current one */
153650db69fdSAllain Legacy 		if (i < n - 1) {
153750db69fdSAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
153850db69fdSAllain Legacy 							   avp_bufs[i + 1]);
153950db69fdSAllain Legacy 			rte_prefetch0(pkt_buf);
154050db69fdSAllain Legacy 		}
154150db69fdSAllain Legacy 
154250db69fdSAllain Legacy 		/* Adjust host pointers for guest addressing */
154350db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]);
154450db69fdSAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
154550db69fdSAllain Legacy 		pkt_len = pkt_buf->pkt_len;
154650db69fdSAllain Legacy 
154750db69fdSAllain Legacy 		if (unlikely((pkt_len > avp->guest_mbuf_size) ||
154850db69fdSAllain Legacy 			     (pkt_buf->nb_segs > 1))) {
154950db69fdSAllain Legacy 			/*
155050db69fdSAllain Legacy 			 * application should be using the scattered receive
155150db69fdSAllain Legacy 			 * function
155250db69fdSAllain Legacy 			 */
155350db69fdSAllain Legacy 			rxq->errors++;
155450db69fdSAllain Legacy 			continue;
155550db69fdSAllain Legacy 		}
155650db69fdSAllain Legacy 
155750db69fdSAllain Legacy 		/* process each packet to be transmitted */
155850db69fdSAllain Legacy 		m = rte_pktmbuf_alloc(avp->pool);
155950db69fdSAllain Legacy 		if (unlikely(m == NULL)) {
156050db69fdSAllain Legacy 			rxq->dev_data->rx_mbuf_alloc_failed++;
156150db69fdSAllain Legacy 			continue;
156250db69fdSAllain Legacy 		}
156350db69fdSAllain Legacy 
156450db69fdSAllain Legacy 		/* copy data out of the host buffer to our buffer */
156550db69fdSAllain Legacy 		m->data_off = RTE_PKTMBUF_HEADROOM;
156650db69fdSAllain Legacy 		rte_memcpy(rte_pktmbuf_mtod(m, void *), pkt_data, pkt_len);
156750db69fdSAllain Legacy 
156850db69fdSAllain Legacy 		/* initialize the local mbuf */
156950db69fdSAllain Legacy 		rte_pktmbuf_data_len(m) = pkt_len;
157050db69fdSAllain Legacy 		rte_pktmbuf_pkt_len(m) = pkt_len;
157150db69fdSAllain Legacy 		m->port = avp->port_id;
157250db69fdSAllain Legacy 
157350db69fdSAllain Legacy 		if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) {
1574380a7aabSOlivier Matz 			m->ol_flags = PKT_RX_VLAN;
157550db69fdSAllain Legacy 			m->vlan_tci = pkt_buf->vlan_tci;
157650db69fdSAllain Legacy 		}
157750db69fdSAllain Legacy 
157850db69fdSAllain Legacy 		if (_avp_mac_filter(avp, m) != 0) {
157950db69fdSAllain Legacy 			/* silently discard packets not destined to our MAC */
158050db69fdSAllain Legacy 			rte_pktmbuf_free(m);
158150db69fdSAllain Legacy 			continue;
158250db69fdSAllain Legacy 		}
158350db69fdSAllain Legacy 
158450db69fdSAllain Legacy 		/* return new mbuf to caller */
158550db69fdSAllain Legacy 		rx_pkts[count++] = m;
158650db69fdSAllain Legacy 		rxq->bytes += pkt_len;
158750db69fdSAllain Legacy 	}
158850db69fdSAllain Legacy 
158950db69fdSAllain Legacy 	rxq->packets += count;
159050db69fdSAllain Legacy 
159150db69fdSAllain Legacy 	/* return the buffers to the free queue */
159250db69fdSAllain Legacy 	avp_fifo_put(free_q, (void **)&avp_bufs[0], n);
159350db69fdSAllain Legacy 
159450db69fdSAllain Legacy 	return count;
159550db69fdSAllain Legacy }
159650db69fdSAllain Legacy 
1597295abce2SAllain Legacy /*
1598295abce2SAllain Legacy  * Copy a chained mbuf to a set of host buffers.  This function assumes that
1599295abce2SAllain Legacy  * there are sufficient destination buffers to contain the entire source
1600295abce2SAllain Legacy  * packet.
1601295abce2SAllain Legacy  */
1602295abce2SAllain Legacy static inline uint16_t
1603295abce2SAllain Legacy avp_dev_copy_to_buffers(struct avp_dev *avp,
1604295abce2SAllain Legacy 			struct rte_mbuf *mbuf,
1605295abce2SAllain Legacy 			struct rte_avp_desc **buffers,
1606295abce2SAllain Legacy 			unsigned int count)
1607295abce2SAllain Legacy {
1608295abce2SAllain Legacy 	struct rte_avp_desc *previous_buf = NULL;
1609295abce2SAllain Legacy 	struct rte_avp_desc *first_buf = NULL;
1610295abce2SAllain Legacy 	struct rte_avp_desc *pkt_buf;
1611295abce2SAllain Legacy 	struct rte_avp_desc *buf;
1612295abce2SAllain Legacy 	size_t total_length;
1613295abce2SAllain Legacy 	struct rte_mbuf *m;
1614295abce2SAllain Legacy 	size_t copy_length;
1615295abce2SAllain Legacy 	size_t src_offset;
1616295abce2SAllain Legacy 	char *pkt_data;
1617295abce2SAllain Legacy 	unsigned int i;
1618295abce2SAllain Legacy 
1619295abce2SAllain Legacy 	__rte_mbuf_sanity_check(mbuf, 1);
1620295abce2SAllain Legacy 
1621295abce2SAllain Legacy 	m = mbuf;
1622295abce2SAllain Legacy 	src_offset = 0;
1623295abce2SAllain Legacy 	total_length = rte_pktmbuf_pkt_len(m);
1624295abce2SAllain Legacy 	for (i = 0; (i < count) && (m != NULL); i++) {
1625295abce2SAllain Legacy 		/* fill each destination buffer */
1626295abce2SAllain Legacy 		buf = buffers[i];
1627295abce2SAllain Legacy 
1628295abce2SAllain Legacy 		if (i < count - 1) {
1629295abce2SAllain Legacy 			/* prefetch next entry while processing this one */
1630295abce2SAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp, buffers[i + 1]);
1631295abce2SAllain Legacy 			rte_prefetch0(pkt_buf);
1632295abce2SAllain Legacy 		}
1633295abce2SAllain Legacy 
1634295abce2SAllain Legacy 		/* Adjust pointers for guest addressing */
1635295abce2SAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
1636295abce2SAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
1637295abce2SAllain Legacy 
1638295abce2SAllain Legacy 		/* setup the buffer chain */
1639295abce2SAllain Legacy 		if (previous_buf != NULL)
1640295abce2SAllain Legacy 			previous_buf->next = buf;
1641295abce2SAllain Legacy 		else
1642295abce2SAllain Legacy 			first_buf = pkt_buf;
1643295abce2SAllain Legacy 
1644295abce2SAllain Legacy 		previous_buf = pkt_buf;
1645295abce2SAllain Legacy 
1646295abce2SAllain Legacy 		do {
1647295abce2SAllain Legacy 			/*
1648295abce2SAllain Legacy 			 * copy as many source mbuf segments as will fit in the
1649295abce2SAllain Legacy 			 * destination buffer.
1650295abce2SAllain Legacy 			 */
1651295abce2SAllain Legacy 			copy_length = RTE_MIN((avp->host_mbuf_size -
1652295abce2SAllain Legacy 					       pkt_buf->data_len),
1653295abce2SAllain Legacy 					      (rte_pktmbuf_data_len(m) -
1654295abce2SAllain Legacy 					       src_offset));
1655295abce2SAllain Legacy 			rte_memcpy(RTE_PTR_ADD(pkt_data, pkt_buf->data_len),
1656295abce2SAllain Legacy 				   RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *),
1657295abce2SAllain Legacy 					       src_offset),
1658295abce2SAllain Legacy 				   copy_length);
1659295abce2SAllain Legacy 			pkt_buf->data_len += copy_length;
1660295abce2SAllain Legacy 			src_offset += copy_length;
1661295abce2SAllain Legacy 
1662295abce2SAllain Legacy 			if (likely(src_offset == rte_pktmbuf_data_len(m))) {
1663295abce2SAllain Legacy 				/* need a new source buffer */
1664295abce2SAllain Legacy 				m = m->next;
1665295abce2SAllain Legacy 				src_offset = 0;
1666295abce2SAllain Legacy 			}
1667295abce2SAllain Legacy 
1668295abce2SAllain Legacy 			if (unlikely(pkt_buf->data_len ==
1669295abce2SAllain Legacy 				     avp->host_mbuf_size)) {
1670295abce2SAllain Legacy 				/* need a new destination buffer */
1671295abce2SAllain Legacy 				break;
1672295abce2SAllain Legacy 			}
1673295abce2SAllain Legacy 
1674295abce2SAllain Legacy 		} while (m != NULL);
1675295abce2SAllain Legacy 	}
1676295abce2SAllain Legacy 
1677295abce2SAllain Legacy 	first_buf->nb_segs = count;
1678295abce2SAllain Legacy 	first_buf->pkt_len = total_length;
1679295abce2SAllain Legacy 
1680295abce2SAllain Legacy 	if (mbuf->ol_flags & PKT_TX_VLAN_PKT) {
1681295abce2SAllain Legacy 		first_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT;
1682295abce2SAllain Legacy 		first_buf->vlan_tci = mbuf->vlan_tci;
1683295abce2SAllain Legacy 	}
1684295abce2SAllain Legacy 
1685295abce2SAllain Legacy 	avp_dev_buffer_sanity_check(avp, buffers[0]);
1686295abce2SAllain Legacy 
1687295abce2SAllain Legacy 	return total_length;
1688295abce2SAllain Legacy }
1689295abce2SAllain Legacy 
1690295abce2SAllain Legacy 
1691295abce2SAllain Legacy static uint16_t
1692295abce2SAllain Legacy avp_xmit_scattered_pkts(void *tx_queue,
1693295abce2SAllain Legacy 			struct rte_mbuf **tx_pkts,
1694295abce2SAllain Legacy 			uint16_t nb_pkts)
1695295abce2SAllain Legacy {
1696295abce2SAllain Legacy 	struct rte_avp_desc *avp_bufs[(AVP_MAX_TX_BURST *
1697*ec87d3b2SKevin Traynor 				       RTE_AVP_MAX_MBUF_SEGMENTS)] = {};
1698295abce2SAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1699295abce2SAllain Legacy 	struct rte_avp_desc *tx_bufs[AVP_MAX_TX_BURST];
1700295abce2SAllain Legacy 	struct avp_dev *avp = txq->avp;
1701295abce2SAllain Legacy 	struct rte_avp_fifo *alloc_q;
1702295abce2SAllain Legacy 	struct rte_avp_fifo *tx_q;
1703295abce2SAllain Legacy 	unsigned int count, avail, n;
1704295abce2SAllain Legacy 	unsigned int orig_nb_pkts;
1705295abce2SAllain Legacy 	struct rte_mbuf *m;
1706295abce2SAllain Legacy 	unsigned int required;
1707295abce2SAllain Legacy 	unsigned int segments;
1708295abce2SAllain Legacy 	unsigned int tx_bytes;
1709295abce2SAllain Legacy 	unsigned int i;
1710295abce2SAllain Legacy 
1711295abce2SAllain Legacy 	orig_nb_pkts = nb_pkts;
171282e140b8SAllain Legacy 	if (unlikely(avp->flags & AVP_F_DETACHED)) {
171382e140b8SAllain Legacy 		/* VM live migration in progress */
171482e140b8SAllain Legacy 		/* TODO ... buffer for X packets then drop? */
171582e140b8SAllain Legacy 		txq->errors += nb_pkts;
171682e140b8SAllain Legacy 		return 0;
171782e140b8SAllain Legacy 	}
171882e140b8SAllain Legacy 
1719295abce2SAllain Legacy 	tx_q = avp->tx_q[txq->queue_id];
1720295abce2SAllain Legacy 	alloc_q = avp->alloc_q[txq->queue_id];
1721295abce2SAllain Legacy 
1722295abce2SAllain Legacy 	/* limit the number of transmitted packets to the max burst size */
1723295abce2SAllain Legacy 	if (unlikely(nb_pkts > AVP_MAX_TX_BURST))
1724295abce2SAllain Legacy 		nb_pkts = AVP_MAX_TX_BURST;
1725295abce2SAllain Legacy 
1726295abce2SAllain Legacy 	/* determine how many buffers are available to copy into */
1727295abce2SAllain Legacy 	avail = avp_fifo_count(alloc_q);
1728295abce2SAllain Legacy 	if (unlikely(avail > (AVP_MAX_TX_BURST *
1729295abce2SAllain Legacy 			      RTE_AVP_MAX_MBUF_SEGMENTS)))
1730295abce2SAllain Legacy 		avail = AVP_MAX_TX_BURST * RTE_AVP_MAX_MBUF_SEGMENTS;
1731295abce2SAllain Legacy 
1732295abce2SAllain Legacy 	/* determine how many slots are available in the transmit queue */
1733295abce2SAllain Legacy 	count = avp_fifo_free_count(tx_q);
1734295abce2SAllain Legacy 
1735295abce2SAllain Legacy 	/* determine how many packets can be sent */
1736295abce2SAllain Legacy 	nb_pkts = RTE_MIN(count, nb_pkts);
1737295abce2SAllain Legacy 
1738295abce2SAllain Legacy 	/* determine how many packets will fit in the available buffers */
1739295abce2SAllain Legacy 	count = 0;
1740295abce2SAllain Legacy 	segments = 0;
1741295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++) {
1742295abce2SAllain Legacy 		m = tx_pkts[i];
1743295abce2SAllain Legacy 		if (likely(i < (unsigned int)nb_pkts - 1)) {
1744295abce2SAllain Legacy 			/* prefetch next entry while processing this one */
1745295abce2SAllain Legacy 			rte_prefetch0(tx_pkts[i + 1]);
1746295abce2SAllain Legacy 		}
1747295abce2SAllain Legacy 		required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) /
1748295abce2SAllain Legacy 			avp->host_mbuf_size;
1749295abce2SAllain Legacy 
1750295abce2SAllain Legacy 		if (unlikely((required == 0) ||
1751295abce2SAllain Legacy 			     (required > RTE_AVP_MAX_MBUF_SEGMENTS)))
1752295abce2SAllain Legacy 			break;
1753295abce2SAllain Legacy 		else if (unlikely(required + segments > avail))
1754295abce2SAllain Legacy 			break;
1755295abce2SAllain Legacy 		segments += required;
1756295abce2SAllain Legacy 		count++;
1757295abce2SAllain Legacy 	}
1758295abce2SAllain Legacy 	nb_pkts = count;
1759295abce2SAllain Legacy 
1760295abce2SAllain Legacy 	if (unlikely(nb_pkts == 0)) {
1761295abce2SAllain Legacy 		/* no available buffers, or no space on the tx queue */
1762295abce2SAllain Legacy 		txq->errors += orig_nb_pkts;
1763295abce2SAllain Legacy 		return 0;
1764295abce2SAllain Legacy 	}
1765295abce2SAllain Legacy 
1766295abce2SAllain Legacy 	PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n",
1767295abce2SAllain Legacy 		   nb_pkts, tx_q);
1768295abce2SAllain Legacy 
1769295abce2SAllain Legacy 	/* retrieve sufficient send buffers */
1770295abce2SAllain Legacy 	n = avp_fifo_get(alloc_q, (void **)&avp_bufs, segments);
1771295abce2SAllain Legacy 	if (unlikely(n != segments)) {
1772295abce2SAllain Legacy 		PMD_TX_LOG(DEBUG, "Failed to allocate buffers "
1773295abce2SAllain Legacy 			   "n=%u, segments=%u, orig=%u\n",
1774295abce2SAllain Legacy 			   n, segments, orig_nb_pkts);
1775295abce2SAllain Legacy 		txq->errors += orig_nb_pkts;
1776295abce2SAllain Legacy 		return 0;
1777295abce2SAllain Legacy 	}
1778295abce2SAllain Legacy 
1779295abce2SAllain Legacy 	tx_bytes = 0;
1780295abce2SAllain Legacy 	count = 0;
1781295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++) {
1782295abce2SAllain Legacy 		/* process each packet to be transmitted */
1783295abce2SAllain Legacy 		m = tx_pkts[i];
1784295abce2SAllain Legacy 
1785295abce2SAllain Legacy 		/* determine how many buffers are required for this packet */
1786295abce2SAllain Legacy 		required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) /
1787295abce2SAllain Legacy 			avp->host_mbuf_size;
1788295abce2SAllain Legacy 
1789295abce2SAllain Legacy 		tx_bytes += avp_dev_copy_to_buffers(avp, m,
1790295abce2SAllain Legacy 						    &avp_bufs[count], required);
1791295abce2SAllain Legacy 		tx_bufs[i] = avp_bufs[count];
1792295abce2SAllain Legacy 		count += required;
1793295abce2SAllain Legacy 
1794295abce2SAllain Legacy 		/* free the original mbuf */
1795295abce2SAllain Legacy 		rte_pktmbuf_free(m);
1796295abce2SAllain Legacy 	}
1797295abce2SAllain Legacy 
1798295abce2SAllain Legacy 	txq->packets += nb_pkts;
1799295abce2SAllain Legacy 	txq->bytes += tx_bytes;
1800295abce2SAllain Legacy 
1801295abce2SAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS
1802295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++)
1803295abce2SAllain Legacy 		avp_dev_buffer_sanity_check(avp, tx_bufs[i]);
1804295abce2SAllain Legacy #endif
1805295abce2SAllain Legacy 
1806295abce2SAllain Legacy 	/* send the packets */
1807295abce2SAllain Legacy 	n = avp_fifo_put(tx_q, (void **)&tx_bufs[0], nb_pkts);
1808295abce2SAllain Legacy 	if (unlikely(n != orig_nb_pkts))
1809295abce2SAllain Legacy 		txq->errors += (orig_nb_pkts - n);
1810295abce2SAllain Legacy 
1811295abce2SAllain Legacy 	return n;
1812295abce2SAllain Legacy }
1813295abce2SAllain Legacy 
1814295abce2SAllain Legacy 
1815295abce2SAllain Legacy static uint16_t
1816295abce2SAllain Legacy avp_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
1817295abce2SAllain Legacy {
1818295abce2SAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1819295abce2SAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_TX_BURST];
1820295abce2SAllain Legacy 	struct avp_dev *avp = txq->avp;
1821295abce2SAllain Legacy 	struct rte_avp_desc *pkt_buf;
1822295abce2SAllain Legacy 	struct rte_avp_fifo *alloc_q;
1823295abce2SAllain Legacy 	struct rte_avp_fifo *tx_q;
1824295abce2SAllain Legacy 	unsigned int count, avail, n;
1825295abce2SAllain Legacy 	struct rte_mbuf *m;
1826295abce2SAllain Legacy 	unsigned int pkt_len;
1827295abce2SAllain Legacy 	unsigned int tx_bytes;
1828295abce2SAllain Legacy 	char *pkt_data;
1829295abce2SAllain Legacy 	unsigned int i;
1830295abce2SAllain Legacy 
183182e140b8SAllain Legacy 	if (unlikely(avp->flags & AVP_F_DETACHED)) {
183282e140b8SAllain Legacy 		/* VM live migration in progress */
183382e140b8SAllain Legacy 		/* TODO ... buffer for X packets then drop?! */
183482e140b8SAllain Legacy 		txq->errors++;
183582e140b8SAllain Legacy 		return 0;
183682e140b8SAllain Legacy 	}
183782e140b8SAllain Legacy 
1838295abce2SAllain Legacy 	tx_q = avp->tx_q[txq->queue_id];
1839295abce2SAllain Legacy 	alloc_q = avp->alloc_q[txq->queue_id];
1840295abce2SAllain Legacy 
1841295abce2SAllain Legacy 	/* limit the number of transmitted packets to the max burst size */
1842295abce2SAllain Legacy 	if (unlikely(nb_pkts > AVP_MAX_TX_BURST))
1843295abce2SAllain Legacy 		nb_pkts = AVP_MAX_TX_BURST;
1844295abce2SAllain Legacy 
1845295abce2SAllain Legacy 	/* determine how many buffers are available to copy into */
1846295abce2SAllain Legacy 	avail = avp_fifo_count(alloc_q);
1847295abce2SAllain Legacy 
1848295abce2SAllain Legacy 	/* determine how many slots are available in the transmit queue */
1849295abce2SAllain Legacy 	count = avp_fifo_free_count(tx_q);
1850295abce2SAllain Legacy 
1851295abce2SAllain Legacy 	/* determine how many packets can be sent */
1852295abce2SAllain Legacy 	count = RTE_MIN(count, avail);
1853295abce2SAllain Legacy 	count = RTE_MIN(count, nb_pkts);
1854295abce2SAllain Legacy 
1855295abce2SAllain Legacy 	if (unlikely(count == 0)) {
1856295abce2SAllain Legacy 		/* no available buffers, or no space on the tx queue */
1857295abce2SAllain Legacy 		txq->errors += nb_pkts;
1858295abce2SAllain Legacy 		return 0;
1859295abce2SAllain Legacy 	}
1860295abce2SAllain Legacy 
1861295abce2SAllain Legacy 	PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n",
1862295abce2SAllain Legacy 		   count, tx_q);
1863295abce2SAllain Legacy 
1864295abce2SAllain Legacy 	/* retrieve sufficient send buffers */
1865295abce2SAllain Legacy 	n = avp_fifo_get(alloc_q, (void **)&avp_bufs, count);
1866295abce2SAllain Legacy 	if (unlikely(n != count)) {
1867295abce2SAllain Legacy 		txq->errors++;
1868295abce2SAllain Legacy 		return 0;
1869295abce2SAllain Legacy 	}
1870295abce2SAllain Legacy 
1871295abce2SAllain Legacy 	tx_bytes = 0;
1872295abce2SAllain Legacy 	for (i = 0; i < count; i++) {
1873295abce2SAllain Legacy 		/* prefetch next entry while processing the current one */
1874295abce2SAllain Legacy 		if (i < count - 1) {
1875295abce2SAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
1876295abce2SAllain Legacy 							   avp_bufs[i + 1]);
1877295abce2SAllain Legacy 			rte_prefetch0(pkt_buf);
1878295abce2SAllain Legacy 		}
1879295abce2SAllain Legacy 
1880295abce2SAllain Legacy 		/* process each packet to be transmitted */
1881295abce2SAllain Legacy 		m = tx_pkts[i];
1882295abce2SAllain Legacy 
1883295abce2SAllain Legacy 		/* Adjust pointers for guest addressing */
1884295abce2SAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]);
1885295abce2SAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
1886295abce2SAllain Legacy 		pkt_len = rte_pktmbuf_pkt_len(m);
1887295abce2SAllain Legacy 
1888295abce2SAllain Legacy 		if (unlikely((pkt_len > avp->guest_mbuf_size) ||
1889295abce2SAllain Legacy 					 (pkt_len > avp->host_mbuf_size))) {
1890295abce2SAllain Legacy 			/*
1891295abce2SAllain Legacy 			 * application should be using the scattered transmit
1892295abce2SAllain Legacy 			 * function; send it truncated to avoid the performance
1893295abce2SAllain Legacy 			 * hit of having to manage returning the already
1894295abce2SAllain Legacy 			 * allocated buffer to the free list.  This should not
1895295abce2SAllain Legacy 			 * happen since the application should have set the
1896295abce2SAllain Legacy 			 * max_rx_pkt_len based on its MTU and it should be
1897295abce2SAllain Legacy 			 * policing its own packet sizes.
1898295abce2SAllain Legacy 			 */
1899295abce2SAllain Legacy 			txq->errors++;
1900295abce2SAllain Legacy 			pkt_len = RTE_MIN(avp->guest_mbuf_size,
1901295abce2SAllain Legacy 					  avp->host_mbuf_size);
1902295abce2SAllain Legacy 		}
1903295abce2SAllain Legacy 
1904295abce2SAllain Legacy 		/* copy data out of our mbuf and into the AVP buffer */
1905295abce2SAllain Legacy 		rte_memcpy(pkt_data, rte_pktmbuf_mtod(m, void *), pkt_len);
1906295abce2SAllain Legacy 		pkt_buf->pkt_len = pkt_len;
1907295abce2SAllain Legacy 		pkt_buf->data_len = pkt_len;
1908295abce2SAllain Legacy 		pkt_buf->nb_segs = 1;
1909295abce2SAllain Legacy 		pkt_buf->next = NULL;
1910295abce2SAllain Legacy 
1911295abce2SAllain Legacy 		if (m->ol_flags & PKT_TX_VLAN_PKT) {
1912295abce2SAllain Legacy 			pkt_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT;
1913295abce2SAllain Legacy 			pkt_buf->vlan_tci = m->vlan_tci;
1914295abce2SAllain Legacy 		}
1915295abce2SAllain Legacy 
1916295abce2SAllain Legacy 		tx_bytes += pkt_len;
1917295abce2SAllain Legacy 
1918295abce2SAllain Legacy 		/* free the original mbuf */
1919295abce2SAllain Legacy 		rte_pktmbuf_free(m);
1920295abce2SAllain Legacy 	}
1921295abce2SAllain Legacy 
1922295abce2SAllain Legacy 	txq->packets += count;
1923295abce2SAllain Legacy 	txq->bytes += tx_bytes;
1924295abce2SAllain Legacy 
1925295abce2SAllain Legacy 	/* send the packets */
1926295abce2SAllain Legacy 	n = avp_fifo_put(tx_q, (void **)&avp_bufs[0], count);
1927295abce2SAllain Legacy 
1928295abce2SAllain Legacy 	return n;
1929295abce2SAllain Legacy }
1930295abce2SAllain Legacy 
1931cce4367fSAllain Legacy static void
1932cce4367fSAllain Legacy avp_dev_rx_queue_release(void *rx_queue)
1933cce4367fSAllain Legacy {
1934cce4367fSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
1935cce4367fSAllain Legacy 	struct avp_dev *avp = rxq->avp;
1936cce4367fSAllain Legacy 	struct rte_eth_dev_data *data = avp->dev_data;
1937cce4367fSAllain Legacy 	unsigned int i;
1938cce4367fSAllain Legacy 
1939cce4367fSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
194015fb42d5SAllain Legacy 		if (data->rx_queues[i] == rxq) {
194115fb42d5SAllain Legacy 			rte_free(data->rx_queues[i]);
1942cce4367fSAllain Legacy 			data->rx_queues[i] = NULL;
1943cce4367fSAllain Legacy 		}
1944cce4367fSAllain Legacy 	}
194515fb42d5SAllain Legacy }
194615fb42d5SAllain Legacy 
194715fb42d5SAllain Legacy static void
194815fb42d5SAllain Legacy avp_dev_rx_queue_release_all(struct rte_eth_dev *eth_dev)
194915fb42d5SAllain Legacy {
195015fb42d5SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
195115fb42d5SAllain Legacy 	struct rte_eth_dev_data *data = avp->dev_data;
195215fb42d5SAllain Legacy 	unsigned int i;
195315fb42d5SAllain Legacy 
195415fb42d5SAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
195515fb42d5SAllain Legacy 		if (data->rx_queues[i]) {
195615fb42d5SAllain Legacy 			rte_free(data->rx_queues[i]);
195715fb42d5SAllain Legacy 			data->rx_queues[i] = NULL;
195815fb42d5SAllain Legacy 		}
195915fb42d5SAllain Legacy 	}
196015fb42d5SAllain Legacy }
1961cce4367fSAllain Legacy 
1962cce4367fSAllain Legacy static void
1963cce4367fSAllain Legacy avp_dev_tx_queue_release(void *tx_queue)
1964cce4367fSAllain Legacy {
1965cce4367fSAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1966cce4367fSAllain Legacy 	struct avp_dev *avp = txq->avp;
1967cce4367fSAllain Legacy 	struct rte_eth_dev_data *data = avp->dev_data;
1968cce4367fSAllain Legacy 	unsigned int i;
1969cce4367fSAllain Legacy 
1970cce4367fSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
197115fb42d5SAllain Legacy 		if (data->tx_queues[i] == txq) {
197215fb42d5SAllain Legacy 			rte_free(data->tx_queues[i]);
1973cce4367fSAllain Legacy 			data->tx_queues[i] = NULL;
1974cce4367fSAllain Legacy 		}
1975cce4367fSAllain Legacy 	}
197615fb42d5SAllain Legacy }
197715fb42d5SAllain Legacy 
197815fb42d5SAllain Legacy static void
197915fb42d5SAllain Legacy avp_dev_tx_queue_release_all(struct rte_eth_dev *eth_dev)
198015fb42d5SAllain Legacy {
198115fb42d5SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
198215fb42d5SAllain Legacy 	struct rte_eth_dev_data *data = avp->dev_data;
198315fb42d5SAllain Legacy 	unsigned int i;
198415fb42d5SAllain Legacy 
198515fb42d5SAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
198615fb42d5SAllain Legacy 		if (data->tx_queues[i]) {
198715fb42d5SAllain Legacy 			rte_free(data->tx_queues[i]);
198815fb42d5SAllain Legacy 			data->tx_queues[i] = NULL;
198915fb42d5SAllain Legacy 		}
199015fb42d5SAllain Legacy 	}
199115fb42d5SAllain Legacy }
1992cce4367fSAllain Legacy 
1993cce4367fSAllain Legacy static int
19941a859223SAllain Legacy avp_dev_configure(struct rte_eth_dev *eth_dev)
19951a859223SAllain Legacy {
1996c0802544SFerruh Yigit 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
19971a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
19981a859223SAllain Legacy 	struct rte_avp_device_info *host_info;
19991a859223SAllain Legacy 	struct rte_avp_device_config config;
20001a859223SAllain Legacy 	int mask = 0;
20011a859223SAllain Legacy 	void *addr;
20021a859223SAllain Legacy 	int ret;
20031a859223SAllain Legacy 
200482e140b8SAllain Legacy 	rte_spinlock_lock(&avp->lock);
200582e140b8SAllain Legacy 	if (avp->flags & AVP_F_DETACHED) {
200682e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Operation not supported during VM live migration\n");
200782e140b8SAllain Legacy 		ret = -ENOTSUP;
200882e140b8SAllain Legacy 		goto unlock;
200982e140b8SAllain Legacy 	}
201082e140b8SAllain Legacy 
20111a859223SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr;
20121a859223SAllain Legacy 	host_info = (struct rte_avp_device_info *)addr;
20131a859223SAllain Legacy 
20141a859223SAllain Legacy 	/* Setup required number of queues */
20151a859223SAllain Legacy 	_avp_set_queue_counts(eth_dev);
20161a859223SAllain Legacy 
20171a859223SAllain Legacy 	mask = (ETH_VLAN_STRIP_MASK |
20181a859223SAllain Legacy 		ETH_VLAN_FILTER_MASK |
20191a859223SAllain Legacy 		ETH_VLAN_EXTEND_MASK);
2020289ba0c0SDavid Harton 	ret = avp_vlan_offload_set(eth_dev, mask);
2021289ba0c0SDavid Harton 	if (ret < 0) {
2022289ba0c0SDavid Harton 		PMD_DRV_LOG(ERR, "VLAN offload set failed by host, ret=%d\n",
2023289ba0c0SDavid Harton 			    ret);
2024289ba0c0SDavid Harton 		goto unlock;
2025289ba0c0SDavid Harton 	}
20261a859223SAllain Legacy 
20271a859223SAllain Legacy 	/* update device config */
20281a859223SAllain Legacy 	memset(&config, 0, sizeof(config));
20291a859223SAllain Legacy 	config.device_id = host_info->device_id;
20301a859223SAllain Legacy 	config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK;
20311a859223SAllain Legacy 	config.driver_version = AVP_DPDK_DRIVER_VERSION;
20321a859223SAllain Legacy 	config.features = avp->features;
20331a859223SAllain Legacy 	config.num_tx_queues = avp->num_tx_queues;
20341a859223SAllain Legacy 	config.num_rx_queues = avp->num_rx_queues;
20351a859223SAllain Legacy 
20361a859223SAllain Legacy 	ret = avp_dev_ctrl_set_config(eth_dev, &config);
20371a859223SAllain Legacy 	if (ret < 0) {
20381a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Config request failed by host, ret=%d\n",
20391a859223SAllain Legacy 			    ret);
20401a859223SAllain Legacy 		goto unlock;
20411a859223SAllain Legacy 	}
20421a859223SAllain Legacy 
20431a859223SAllain Legacy 	avp->flags |= AVP_F_CONFIGURED;
20441a859223SAllain Legacy 	ret = 0;
20451a859223SAllain Legacy 
20461a859223SAllain Legacy unlock:
204782e140b8SAllain Legacy 	rte_spinlock_unlock(&avp->lock);
20481a859223SAllain Legacy 	return ret;
20491a859223SAllain Legacy }
20501a859223SAllain Legacy 
2051ea37523dSAllain Legacy static int
2052ea37523dSAllain Legacy avp_dev_start(struct rte_eth_dev *eth_dev)
2053ea37523dSAllain Legacy {
2054ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
2055ea37523dSAllain Legacy 	int ret;
2056ea37523dSAllain Legacy 
205782e140b8SAllain Legacy 	rte_spinlock_lock(&avp->lock);
205882e140b8SAllain Legacy 	if (avp->flags & AVP_F_DETACHED) {
205982e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Operation not supported during VM live migration\n");
206082e140b8SAllain Legacy 		ret = -ENOTSUP;
206182e140b8SAllain Legacy 		goto unlock;
206282e140b8SAllain Legacy 	}
206382e140b8SAllain Legacy 
2064ea37523dSAllain Legacy 	/* update link state */
2065ea37523dSAllain Legacy 	ret = avp_dev_ctrl_set_link_state(eth_dev, 1);
2066ea37523dSAllain Legacy 	if (ret < 0) {
2067ea37523dSAllain Legacy 		PMD_DRV_LOG(ERR, "Link state change failed by host, ret=%d\n",
2068ea37523dSAllain Legacy 			    ret);
2069ea37523dSAllain Legacy 		goto unlock;
2070ea37523dSAllain Legacy 	}
2071ea37523dSAllain Legacy 
2072ea37523dSAllain Legacy 	/* remember current link state */
2073ea37523dSAllain Legacy 	avp->flags |= AVP_F_LINKUP;
2074ea37523dSAllain Legacy 
2075ea37523dSAllain Legacy 	ret = 0;
2076ea37523dSAllain Legacy 
2077ea37523dSAllain Legacy unlock:
207882e140b8SAllain Legacy 	rte_spinlock_unlock(&avp->lock);
2079ea37523dSAllain Legacy 	return ret;
2080ea37523dSAllain Legacy }
2081ea37523dSAllain Legacy 
2082ea37523dSAllain Legacy static void
2083ea37523dSAllain Legacy avp_dev_stop(struct rte_eth_dev *eth_dev)
2084ea37523dSAllain Legacy {
2085ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
2086ea37523dSAllain Legacy 	int ret;
2087ea37523dSAllain Legacy 
208882e140b8SAllain Legacy 	rte_spinlock_lock(&avp->lock);
208982e140b8SAllain Legacy 	if (avp->flags & AVP_F_DETACHED) {
209082e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Operation not supported during VM live migration\n");
209182e140b8SAllain Legacy 		goto unlock;
209282e140b8SAllain Legacy 	}
209382e140b8SAllain Legacy 
209482e140b8SAllain Legacy 	/* remember current link state */
2095ea37523dSAllain Legacy 	avp->flags &= ~AVP_F_LINKUP;
2096ea37523dSAllain Legacy 
2097ea37523dSAllain Legacy 	/* update link state */
2098ea37523dSAllain Legacy 	ret = avp_dev_ctrl_set_link_state(eth_dev, 0);
2099ea37523dSAllain Legacy 	if (ret < 0) {
2100ea37523dSAllain Legacy 		PMD_DRV_LOG(ERR, "Link state change failed by host, ret=%d\n",
2101ea37523dSAllain Legacy 			    ret);
2102ea37523dSAllain Legacy 	}
210382e140b8SAllain Legacy 
210482e140b8SAllain Legacy unlock:
210582e140b8SAllain Legacy 	rte_spinlock_unlock(&avp->lock);
2106ea37523dSAllain Legacy }
2107ea37523dSAllain Legacy 
2108ea37523dSAllain Legacy static void
2109ea37523dSAllain Legacy avp_dev_close(struct rte_eth_dev *eth_dev)
2110ea37523dSAllain Legacy {
2111ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
2112ea37523dSAllain Legacy 	int ret;
2113ea37523dSAllain Legacy 
211482e140b8SAllain Legacy 	rte_spinlock_lock(&avp->lock);
211582e140b8SAllain Legacy 	if (avp->flags & AVP_F_DETACHED) {
211682e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Operation not supported during VM live migration\n");
211782e140b8SAllain Legacy 		goto unlock;
211882e140b8SAllain Legacy 	}
211982e140b8SAllain Legacy 
2120ea37523dSAllain Legacy 	/* remember current link state */
2121ea37523dSAllain Legacy 	avp->flags &= ~AVP_F_LINKUP;
2122ea37523dSAllain Legacy 	avp->flags &= ~AVP_F_CONFIGURED;
2123ea37523dSAllain Legacy 
212482e140b8SAllain Legacy 	ret = avp_dev_disable_interrupts(eth_dev);
212582e140b8SAllain Legacy 	if (ret < 0) {
212682e140b8SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to disable interrupts\n");
212782e140b8SAllain Legacy 		/* continue */
212882e140b8SAllain Legacy 	}
212982e140b8SAllain Legacy 
2130ea37523dSAllain Legacy 	/* update device state */
2131ea37523dSAllain Legacy 	ret = avp_dev_ctrl_shutdown(eth_dev);
2132ea37523dSAllain Legacy 	if (ret < 0) {
2133ea37523dSAllain Legacy 		PMD_DRV_LOG(ERR, "Device shutdown failed by host, ret=%d\n",
2134ea37523dSAllain Legacy 			    ret);
2135ea37523dSAllain Legacy 		/* continue */
2136ea37523dSAllain Legacy 	}
213782e140b8SAllain Legacy 
213815fb42d5SAllain Legacy 	/* release dynamic storage for rx/tx queues */
213915fb42d5SAllain Legacy 	avp_dev_rx_queue_release_all(eth_dev);
214015fb42d5SAllain Legacy 	avp_dev_tx_queue_release_all(eth_dev);
214115fb42d5SAllain Legacy 
214282e140b8SAllain Legacy unlock:
214382e140b8SAllain Legacy 	rte_spinlock_unlock(&avp->lock);
2144ea37523dSAllain Legacy }
21451a859223SAllain Legacy 
21461a859223SAllain Legacy static int
21471a859223SAllain Legacy avp_dev_link_update(struct rte_eth_dev *eth_dev,
21481a859223SAllain Legacy 					__rte_unused int wait_to_complete)
21491a859223SAllain Legacy {
21501a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
21511a859223SAllain Legacy 	struct rte_eth_link *link = &eth_dev->data->dev_link;
21521a859223SAllain Legacy 
21531a859223SAllain Legacy 	link->link_speed = ETH_SPEED_NUM_10G;
21541a859223SAllain Legacy 	link->link_duplex = ETH_LINK_FULL_DUPLEX;
21551a859223SAllain Legacy 	link->link_status = !!(avp->flags & AVP_F_LINKUP);
21561a859223SAllain Legacy 
21571a859223SAllain Legacy 	return -1;
21581a859223SAllain Legacy }
21591a859223SAllain Legacy 
21609039c812SAndrew Rybchenko static int
21618129545eSAllain Legacy avp_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
21628129545eSAllain Legacy {
21638129545eSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
21648129545eSAllain Legacy 
216582e140b8SAllain Legacy 	rte_spinlock_lock(&avp->lock);
21668129545eSAllain Legacy 	if ((avp->flags & AVP_F_PROMISC) == 0) {
21678129545eSAllain Legacy 		avp->flags |= AVP_F_PROMISC;
21688129545eSAllain Legacy 		PMD_DRV_LOG(DEBUG, "Promiscuous mode enabled on %u\n",
21698129545eSAllain Legacy 			    eth_dev->data->port_id);
21708129545eSAllain Legacy 	}
217182e140b8SAllain Legacy 	rte_spinlock_unlock(&avp->lock);
21729039c812SAndrew Rybchenko 
21739039c812SAndrew Rybchenko 	return 0;
21748129545eSAllain Legacy }
21758129545eSAllain Legacy 
21769039c812SAndrew Rybchenko static int
21778129545eSAllain Legacy avp_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
21788129545eSAllain Legacy {
21798129545eSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
21808129545eSAllain Legacy 
218182e140b8SAllain Legacy 	rte_spinlock_lock(&avp->lock);
21828129545eSAllain Legacy 	if ((avp->flags & AVP_F_PROMISC) != 0) {
21838129545eSAllain Legacy 		avp->flags &= ~AVP_F_PROMISC;
21848129545eSAllain Legacy 		PMD_DRV_LOG(DEBUG, "Promiscuous mode disabled on %u\n",
21858129545eSAllain Legacy 			    eth_dev->data->port_id);
21868129545eSAllain Legacy 	}
218782e140b8SAllain Legacy 	rte_spinlock_unlock(&avp->lock);
21889039c812SAndrew Rybchenko 
21899039c812SAndrew Rybchenko 	return 0;
21908129545eSAllain Legacy }
21911a859223SAllain Legacy 
2192bdad90d1SIvan Ilchenko static int
21931a859223SAllain Legacy avp_dev_info_get(struct rte_eth_dev *eth_dev,
21941a859223SAllain Legacy 		 struct rte_eth_dev_info *dev_info)
21951a859223SAllain Legacy {
21961a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
21971a859223SAllain Legacy 
21981a859223SAllain Legacy 	dev_info->max_rx_queues = avp->max_rx_queues;
21991a859223SAllain Legacy 	dev_info->max_tx_queues = avp->max_tx_queues;
22001a859223SAllain Legacy 	dev_info->min_rx_bufsize = AVP_MIN_RX_BUFSIZE;
22011a859223SAllain Legacy 	dev_info->max_rx_pktlen = avp->max_rx_pkt_len;
22021a859223SAllain Legacy 	dev_info->max_mac_addrs = AVP_MAX_MAC_ADDRS;
22031a859223SAllain Legacy 	if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) {
22041a859223SAllain Legacy 		dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP;
22051a859223SAllain Legacy 		dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT;
22061a859223SAllain Legacy 	}
2207bdad90d1SIvan Ilchenko 
2208bdad90d1SIvan Ilchenko 	return 0;
22091a859223SAllain Legacy }
22101a859223SAllain Legacy 
2211289ba0c0SDavid Harton static int
22121a859223SAllain Legacy avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
22131a859223SAllain Legacy {
22141a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
2215462b66d8SAllain Legacy 	struct rte_eth_conf *dev_conf = &eth_dev->data->dev_conf;
2216462b66d8SAllain Legacy 	uint64_t offloads = dev_conf->rxmode.offloads;
22171a859223SAllain Legacy 
22181a859223SAllain Legacy 	if (mask & ETH_VLAN_STRIP_MASK) {
22191a859223SAllain Legacy 		if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) {
2220462b66d8SAllain Legacy 			if (offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
22211a859223SAllain Legacy 				avp->features |= RTE_AVP_FEATURE_VLAN_OFFLOAD;
22221a859223SAllain Legacy 			else
22231a859223SAllain Legacy 				avp->features &= ~RTE_AVP_FEATURE_VLAN_OFFLOAD;
22241a859223SAllain Legacy 		} else {
22251a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN strip offload not supported\n");
22261a859223SAllain Legacy 		}
22271a859223SAllain Legacy 	}
22281a859223SAllain Legacy 
22291a859223SAllain Legacy 	if (mask & ETH_VLAN_FILTER_MASK) {
2230462b66d8SAllain Legacy 		if (offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
22311a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN filter offload not supported\n");
22321a859223SAllain Legacy 	}
22331a859223SAllain Legacy 
22341a859223SAllain Legacy 	if (mask & ETH_VLAN_EXTEND_MASK) {
2235462b66d8SAllain Legacy 		if (offloads & DEV_RX_OFFLOAD_VLAN_EXTEND)
22361a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
22371a859223SAllain Legacy 	}
2238289ba0c0SDavid Harton 
2239289ba0c0SDavid Harton 	return 0;
22401a859223SAllain Legacy }
22411a859223SAllain Legacy 
2242d5b0924bSMatan Azrad static int
22435a5abe2dSAllain Legacy avp_dev_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats)
22445a5abe2dSAllain Legacy {
22455a5abe2dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
22465a5abe2dSAllain Legacy 	unsigned int i;
22475a5abe2dSAllain Legacy 
22485a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
22495a5abe2dSAllain Legacy 		struct avp_queue *rxq = avp->dev_data->rx_queues[i];
22505a5abe2dSAllain Legacy 
22515a5abe2dSAllain Legacy 		if (rxq) {
22525a5abe2dSAllain Legacy 			stats->ipackets += rxq->packets;
22535a5abe2dSAllain Legacy 			stats->ibytes += rxq->bytes;
22545a5abe2dSAllain Legacy 			stats->ierrors += rxq->errors;
22555a5abe2dSAllain Legacy 
22565a5abe2dSAllain Legacy 			stats->q_ipackets[i] += rxq->packets;
22575a5abe2dSAllain Legacy 			stats->q_ibytes[i] += rxq->bytes;
22585a5abe2dSAllain Legacy 			stats->q_errors[i] += rxq->errors;
22595a5abe2dSAllain Legacy 		}
22605a5abe2dSAllain Legacy 	}
22615a5abe2dSAllain Legacy 
22625a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
22635a5abe2dSAllain Legacy 		struct avp_queue *txq = avp->dev_data->tx_queues[i];
22645a5abe2dSAllain Legacy 
22655a5abe2dSAllain Legacy 		if (txq) {
22665a5abe2dSAllain Legacy 			stats->opackets += txq->packets;
22675a5abe2dSAllain Legacy 			stats->obytes += txq->bytes;
22685a5abe2dSAllain Legacy 			stats->oerrors += txq->errors;
22695a5abe2dSAllain Legacy 
22705a5abe2dSAllain Legacy 			stats->q_opackets[i] += txq->packets;
22715a5abe2dSAllain Legacy 			stats->q_obytes[i] += txq->bytes;
22725a5abe2dSAllain Legacy 		}
22735a5abe2dSAllain Legacy 	}
2274d5b0924bSMatan Azrad 
2275d5b0924bSMatan Azrad 	return 0;
22765a5abe2dSAllain Legacy }
22775a5abe2dSAllain Legacy 
22789970a9adSIgor Romanov static int
22795a5abe2dSAllain Legacy avp_dev_stats_reset(struct rte_eth_dev *eth_dev)
22805a5abe2dSAllain Legacy {
22815a5abe2dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
22825a5abe2dSAllain Legacy 	unsigned int i;
22835a5abe2dSAllain Legacy 
22845a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
22855a5abe2dSAllain Legacy 		struct avp_queue *rxq = avp->dev_data->rx_queues[i];
22865a5abe2dSAllain Legacy 
22875a5abe2dSAllain Legacy 		if (rxq) {
22885a5abe2dSAllain Legacy 			rxq->bytes = 0;
22895a5abe2dSAllain Legacy 			rxq->packets = 0;
22905a5abe2dSAllain Legacy 			rxq->errors = 0;
22915a5abe2dSAllain Legacy 		}
22925a5abe2dSAllain Legacy 	}
22935a5abe2dSAllain Legacy 
22945a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
22955a5abe2dSAllain Legacy 		struct avp_queue *txq = avp->dev_data->tx_queues[i];
22965a5abe2dSAllain Legacy 
22975a5abe2dSAllain Legacy 		if (txq) {
22985a5abe2dSAllain Legacy 			txq->bytes = 0;
22995a5abe2dSAllain Legacy 			txq->packets = 0;
23005a5abe2dSAllain Legacy 			txq->errors = 0;
23015a5abe2dSAllain Legacy 		}
23025a5abe2dSAllain Legacy 	}
23039970a9adSIgor Romanov 
23049970a9adSIgor Romanov 	return 0;
23055a5abe2dSAllain Legacy }
23065a5abe2dSAllain Legacy 
2307fdf91e0fSJan Blunck RTE_PMD_REGISTER_PCI(net_avp, rte_avp_pmd);
2308908072e9SAllain Legacy RTE_PMD_REGISTER_PCI_TABLE(net_avp, pci_id_avp_map);
2309e6b790c0SStephen Hemminger 
2310f8e99896SThomas Monjalon RTE_INIT(avp_init_log)
2311e6b790c0SStephen Hemminger {
2312bd34cd80SHarry van Haaren 	avp_logtype_driver = rte_log_register("pmd.net.avp.driver");
2313e6b790c0SStephen Hemminger 	if (avp_logtype_driver >= 0)
2314e6b790c0SStephen Hemminger 		rte_log_set_level(avp_logtype_driver, RTE_LOG_NOTICE);
2315e6b790c0SStephen Hemminger }
2316