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