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