xref: /dpdk/drivers/net/avp/avp_ethdev.c (revision ea37523dbc7b71e861b468dbedb46cbfcf6bd8fb)
1908072e9SAllain Legacy /*
2908072e9SAllain Legacy  *   BSD LICENSE
3908072e9SAllain Legacy  *
4908072e9SAllain Legacy  * Copyright (c) 2013-2017, Wind River Systems, Inc.
5908072e9SAllain Legacy  *
6908072e9SAllain Legacy  * Redistribution and use in source and binary forms, with or without
7908072e9SAllain Legacy  * modification, are permitted provided that the following conditions are met:
8908072e9SAllain Legacy  *
9908072e9SAllain Legacy  * 1) Redistributions of source code must retain the above copyright notice,
10908072e9SAllain Legacy  * this list of conditions and the following disclaimer.
11908072e9SAllain Legacy  *
12908072e9SAllain Legacy  * 2) Redistributions in binary form must reproduce the above copyright notice,
13908072e9SAllain Legacy  * this list of conditions and the following disclaimer in the documentation
14908072e9SAllain Legacy  * and/or other materials provided with the distribution.
15908072e9SAllain Legacy  *
16908072e9SAllain Legacy  * 3) Neither the name of Wind River Systems nor the names of its contributors
17908072e9SAllain Legacy  * may be used to endorse or promote products derived from this software
18908072e9SAllain Legacy  * without specific prior written permission.
19908072e9SAllain Legacy  *
20908072e9SAllain Legacy  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21908072e9SAllain Legacy  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22908072e9SAllain Legacy  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23908072e9SAllain Legacy  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24908072e9SAllain Legacy  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25908072e9SAllain Legacy  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26908072e9SAllain Legacy  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27908072e9SAllain Legacy  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28908072e9SAllain Legacy  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29908072e9SAllain Legacy  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30908072e9SAllain Legacy  * POSSIBILITY OF SUCH DAMAGE.
31908072e9SAllain Legacy  */
32908072e9SAllain Legacy 
33908072e9SAllain Legacy #include <stdint.h>
34908072e9SAllain Legacy #include <string.h>
35908072e9SAllain Legacy #include <stdio.h>
36908072e9SAllain Legacy #include <errno.h>
37908072e9SAllain Legacy #include <unistd.h>
38908072e9SAllain Legacy 
39908072e9SAllain Legacy #include <rte_ethdev.h>
40908072e9SAllain Legacy #include <rte_memcpy.h>
41908072e9SAllain Legacy #include <rte_string_fns.h>
42908072e9SAllain Legacy #include <rte_memzone.h>
43908072e9SAllain Legacy #include <rte_malloc.h>
44908072e9SAllain Legacy #include <rte_atomic.h>
45908072e9SAllain Legacy #include <rte_branch_prediction.h>
46908072e9SAllain Legacy #include <rte_pci.h>
47908072e9SAllain Legacy #include <rte_ether.h>
48908072e9SAllain Legacy #include <rte_common.h>
49908072e9SAllain Legacy #include <rte_cycles.h>
50908072e9SAllain Legacy #include <rte_byteorder.h>
51908072e9SAllain Legacy #include <rte_dev.h>
52908072e9SAllain Legacy #include <rte_memory.h>
53908072e9SAllain Legacy #include <rte_eal.h>
54c0ad5842SAllain Legacy #include <rte_io.h>
55908072e9SAllain Legacy 
56908072e9SAllain Legacy #include "rte_avp_common.h"
57908072e9SAllain Legacy #include "rte_avp_fifo.h"
58908072e9SAllain Legacy 
59908072e9SAllain Legacy #include "avp_logs.h"
60908072e9SAllain Legacy 
61908072e9SAllain Legacy 
62908072e9SAllain Legacy 
631a859223SAllain Legacy static int avp_dev_configure(struct rte_eth_dev *dev);
64*ea37523dSAllain Legacy static int avp_dev_start(struct rte_eth_dev *dev);
65*ea37523dSAllain Legacy static void avp_dev_stop(struct rte_eth_dev *dev);
66*ea37523dSAllain Legacy static void avp_dev_close(struct rte_eth_dev *dev);
671a859223SAllain Legacy static void avp_dev_info_get(struct rte_eth_dev *dev,
681a859223SAllain Legacy 			     struct rte_eth_dev_info *dev_info);
691a859223SAllain Legacy static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
701a859223SAllain Legacy static int avp_dev_link_update(struct rte_eth_dev *dev,
711a859223SAllain Legacy 			       __rte_unused int wait_to_complete);
728129545eSAllain Legacy static void avp_dev_promiscuous_enable(struct rte_eth_dev *dev);
738129545eSAllain Legacy static void avp_dev_promiscuous_disable(struct rte_eth_dev *dev);
748129545eSAllain Legacy 
75cce4367fSAllain Legacy static int avp_dev_rx_queue_setup(struct rte_eth_dev *dev,
76cce4367fSAllain Legacy 				  uint16_t rx_queue_id,
77cce4367fSAllain Legacy 				  uint16_t nb_rx_desc,
78cce4367fSAllain Legacy 				  unsigned int socket_id,
79cce4367fSAllain Legacy 				  const struct rte_eth_rxconf *rx_conf,
80cce4367fSAllain Legacy 				  struct rte_mempool *pool);
811a859223SAllain Legacy 
82cce4367fSAllain Legacy static int avp_dev_tx_queue_setup(struct rte_eth_dev *dev,
83cce4367fSAllain Legacy 				  uint16_t tx_queue_id,
84cce4367fSAllain Legacy 				  uint16_t nb_tx_desc,
85cce4367fSAllain Legacy 				  unsigned int socket_id,
86cce4367fSAllain Legacy 				  const struct rte_eth_txconf *tx_conf);
87cce4367fSAllain Legacy 
8850db69fdSAllain Legacy static uint16_t avp_recv_scattered_pkts(void *rx_queue,
8950db69fdSAllain Legacy 					struct rte_mbuf **rx_pkts,
9050db69fdSAllain Legacy 					uint16_t nb_pkts);
9150db69fdSAllain Legacy 
9250db69fdSAllain Legacy static uint16_t avp_recv_pkts(void *rx_queue,
9350db69fdSAllain Legacy 			      struct rte_mbuf **rx_pkts,
9450db69fdSAllain Legacy 			      uint16_t nb_pkts);
95295abce2SAllain Legacy 
96295abce2SAllain Legacy static uint16_t avp_xmit_scattered_pkts(void *tx_queue,
97295abce2SAllain Legacy 					struct rte_mbuf **tx_pkts,
98295abce2SAllain Legacy 					uint16_t nb_pkts);
99295abce2SAllain Legacy 
100295abce2SAllain Legacy static uint16_t avp_xmit_pkts(void *tx_queue,
101295abce2SAllain Legacy 			      struct rte_mbuf **tx_pkts,
102295abce2SAllain Legacy 			      uint16_t nb_pkts);
103295abce2SAllain Legacy 
104cce4367fSAllain Legacy static void avp_dev_rx_queue_release(void *rxq);
105cce4367fSAllain Legacy static void avp_dev_tx_queue_release(void *txq);
106295abce2SAllain Legacy 
1075a5abe2dSAllain Legacy static void avp_dev_stats_get(struct rte_eth_dev *dev,
1085a5abe2dSAllain Legacy 			      struct rte_eth_stats *stats);
1095a5abe2dSAllain Legacy static void avp_dev_stats_reset(struct rte_eth_dev *dev);
1105a5abe2dSAllain Legacy 
111295abce2SAllain Legacy 
112908072e9SAllain Legacy #define AVP_DEV_TO_PCI(eth_dev) RTE_DEV_TO_PCI((eth_dev)->device)
113908072e9SAllain Legacy 
114908072e9SAllain 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,
156*ea37523dSAllain Legacy 	.dev_start           = avp_dev_start,
157*ea37523dSAllain Legacy 	.dev_stop            = avp_dev_stop,
158*ea37523dSAllain 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)
176c0ad5842SAllain Legacy /**@} */
177c0ad5842SAllain Legacy 
178c0ad5842SAllain Legacy /* Ethernet device validation marker */
179c0ad5842SAllain Legacy #define AVP_ETHDEV_MAGIC 0x92972862
180c0ad5842SAllain Legacy 
181908072e9SAllain Legacy /*
182908072e9SAllain Legacy  * Defines the AVP device attributes which are attached to an RTE ethernet
183908072e9SAllain Legacy  * device
184908072e9SAllain Legacy  */
185908072e9SAllain Legacy struct avp_dev {
186908072e9SAllain Legacy 	uint32_t magic; /**< Memory validation marker */
187908072e9SAllain Legacy 	uint64_t device_id; /**< Unique system identifier */
188908072e9SAllain Legacy 	struct ether_addr ethaddr; /**< Host specified MAC address */
189908072e9SAllain Legacy 	struct rte_eth_dev_data *dev_data;
190908072e9SAllain Legacy 	/**< Back pointer to ethernet device data */
191908072e9SAllain Legacy 	volatile uint32_t flags; /**< Device operational flags */
192908072e9SAllain Legacy 	uint8_t port_id; /**< Ethernet port identifier */
193908072e9SAllain Legacy 	struct rte_mempool *pool; /**< pkt mbuf mempool */
194908072e9SAllain Legacy 	unsigned int guest_mbuf_size; /**< local pool mbuf size */
195908072e9SAllain Legacy 	unsigned int host_mbuf_size; /**< host mbuf size */
196908072e9SAllain Legacy 	unsigned int max_rx_pkt_len; /**< maximum receive unit */
197908072e9SAllain Legacy 	uint32_t host_features; /**< Supported feature bitmap */
198908072e9SAllain Legacy 	uint32_t features; /**< Enabled feature bitmap */
199908072e9SAllain Legacy 	unsigned int num_tx_queues; /**< Negotiated number of transmit queues */
200908072e9SAllain Legacy 	unsigned int max_tx_queues; /**< Maximum number of transmit queues */
201908072e9SAllain Legacy 	unsigned int num_rx_queues; /**< Negotiated number of receive queues */
202908072e9SAllain Legacy 	unsigned int max_rx_queues; /**< Maximum number of receive queues */
203908072e9SAllain Legacy 
204908072e9SAllain Legacy 	struct rte_avp_fifo *tx_q[RTE_AVP_MAX_QUEUES]; /**< TX queue */
205908072e9SAllain Legacy 	struct rte_avp_fifo *rx_q[RTE_AVP_MAX_QUEUES]; /**< RX queue */
206908072e9SAllain Legacy 	struct rte_avp_fifo *alloc_q[RTE_AVP_MAX_QUEUES];
207908072e9SAllain Legacy 	/**< Allocated mbufs queue */
208908072e9SAllain Legacy 	struct rte_avp_fifo *free_q[RTE_AVP_MAX_QUEUES];
209908072e9SAllain Legacy 	/**< To be freed mbufs queue */
210908072e9SAllain Legacy 
211908072e9SAllain Legacy 	/* For request & response */
212908072e9SAllain Legacy 	struct rte_avp_fifo *req_q; /**< Request queue */
213908072e9SAllain Legacy 	struct rte_avp_fifo *resp_q; /**< Response queue */
214908072e9SAllain Legacy 	void *host_sync_addr; /**< (host) Req/Resp Mem address */
215908072e9SAllain Legacy 	void *sync_addr; /**< Req/Resp Mem address */
216908072e9SAllain Legacy 	void *host_mbuf_addr; /**< (host) MBUF pool start address */
217908072e9SAllain Legacy 	void *mbuf_addr; /**< MBUF pool start address */
218908072e9SAllain Legacy } __rte_cache_aligned;
219908072e9SAllain Legacy 
220908072e9SAllain Legacy /* RTE ethernet private data */
221908072e9SAllain Legacy struct avp_adapter {
222908072e9SAllain Legacy 	struct avp_dev avp;
223908072e9SAllain Legacy } __rte_cache_aligned;
224908072e9SAllain Legacy 
225c0ad5842SAllain Legacy 
226c0ad5842SAllain Legacy /* 32-bit MMIO register write */
227c0ad5842SAllain Legacy #define AVP_WRITE32(_value, _addr) rte_write32_relaxed((_value), (_addr))
228c0ad5842SAllain Legacy 
229c0ad5842SAllain Legacy /* 32-bit MMIO register read */
230c0ad5842SAllain Legacy #define AVP_READ32(_addr) rte_read32_relaxed((_addr))
231c0ad5842SAllain Legacy 
232908072e9SAllain Legacy /* Macro to cast the ethernet device private data to a AVP object */
233908072e9SAllain Legacy #define AVP_DEV_PRIVATE_TO_HW(adapter) \
234908072e9SAllain Legacy 	(&((struct avp_adapter *)adapter)->avp)
235908072e9SAllain Legacy 
236908072e9SAllain Legacy /*
237c0ad5842SAllain Legacy  * Defines the structure of a AVP device queue for the purpose of handling the
238c0ad5842SAllain Legacy  * receive and transmit burst callback functions
239c0ad5842SAllain Legacy  */
240c0ad5842SAllain Legacy struct avp_queue {
241c0ad5842SAllain Legacy 	struct rte_eth_dev_data *dev_data;
242c0ad5842SAllain Legacy 	/**< Backpointer to ethernet device data */
243c0ad5842SAllain Legacy 	struct avp_dev *avp; /**< Backpointer to AVP device */
244c0ad5842SAllain Legacy 	uint16_t queue_id;
245c0ad5842SAllain Legacy 	/**< Queue identifier used for indexing current queue */
246c0ad5842SAllain Legacy 	uint16_t queue_base;
247c0ad5842SAllain Legacy 	/**< Base queue identifier for queue servicing */
248c0ad5842SAllain Legacy 	uint16_t queue_limit;
249c0ad5842SAllain Legacy 	/**< Maximum queue identifier for queue servicing */
250c0ad5842SAllain Legacy 
251c0ad5842SAllain Legacy 	uint64_t packets;
252c0ad5842SAllain Legacy 	uint64_t bytes;
253c0ad5842SAllain Legacy 	uint64_t errors;
254c0ad5842SAllain Legacy };
255c0ad5842SAllain Legacy 
2561a859223SAllain Legacy /* send a request and wait for a response
2571a859223SAllain Legacy  *
2581a859223SAllain Legacy  * @warning must be called while holding the avp->lock spinlock.
2591a859223SAllain Legacy  */
2601a859223SAllain Legacy static int
2611a859223SAllain Legacy avp_dev_process_request(struct avp_dev *avp, struct rte_avp_request *request)
2621a859223SAllain Legacy {
2631a859223SAllain Legacy 	unsigned int retry = AVP_MAX_REQUEST_RETRY;
2641a859223SAllain Legacy 	void *resp_addr = NULL;
2651a859223SAllain Legacy 	unsigned int count;
2661a859223SAllain Legacy 	int ret;
2671a859223SAllain Legacy 
2681a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Sending request %u to host\n", request->req_id);
2691a859223SAllain Legacy 
2701a859223SAllain Legacy 	request->result = -ENOTSUP;
2711a859223SAllain Legacy 
2721a859223SAllain Legacy 	/* Discard any stale responses before starting a new request */
2731a859223SAllain Legacy 	while (avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1))
2741a859223SAllain Legacy 		PMD_DRV_LOG(DEBUG, "Discarding stale response\n");
2751a859223SAllain Legacy 
2761a859223SAllain Legacy 	rte_memcpy(avp->sync_addr, request, sizeof(*request));
2771a859223SAllain Legacy 	count = avp_fifo_put(avp->req_q, &avp->host_sync_addr, 1);
2781a859223SAllain Legacy 	if (count < 1) {
2791a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Cannot send request %u to host\n",
2801a859223SAllain Legacy 			    request->req_id);
2811a859223SAllain Legacy 		ret = -EBUSY;
2821a859223SAllain Legacy 		goto done;
2831a859223SAllain Legacy 	}
2841a859223SAllain Legacy 
2851a859223SAllain Legacy 	while (retry--) {
2861a859223SAllain Legacy 		/* wait for a response */
2871a859223SAllain Legacy 		usleep(AVP_REQUEST_DELAY_USECS);
2881a859223SAllain Legacy 
2891a859223SAllain Legacy 		count = avp_fifo_count(avp->resp_q);
2901a859223SAllain Legacy 		if (count >= 1) {
2911a859223SAllain Legacy 			/* response received */
2921a859223SAllain Legacy 			break;
2931a859223SAllain Legacy 		}
2941a859223SAllain Legacy 
2951a859223SAllain Legacy 		if ((count < 1) && (retry == 0)) {
2961a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "Timeout while waiting for a response for %u\n",
2971a859223SAllain Legacy 				    request->req_id);
2981a859223SAllain Legacy 			ret = -ETIME;
2991a859223SAllain Legacy 			goto done;
3001a859223SAllain Legacy 		}
3011a859223SAllain Legacy 	}
3021a859223SAllain Legacy 
3031a859223SAllain Legacy 	/* retrieve the response */
3041a859223SAllain Legacy 	count = avp_fifo_get(avp->resp_q, (void **)&resp_addr, 1);
3051a859223SAllain Legacy 	if ((count != 1) || (resp_addr != avp->host_sync_addr)) {
3061a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Invalid response from host, count=%u resp=%p host_sync_addr=%p\n",
3071a859223SAllain Legacy 			    count, resp_addr, avp->host_sync_addr);
3081a859223SAllain Legacy 		ret = -ENODATA;
3091a859223SAllain Legacy 		goto done;
3101a859223SAllain Legacy 	}
3111a859223SAllain Legacy 
3121a859223SAllain Legacy 	/* copy to user buffer */
3131a859223SAllain Legacy 	rte_memcpy(request, avp->sync_addr, sizeof(*request));
3141a859223SAllain Legacy 	ret = 0;
3151a859223SAllain Legacy 
3161a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Result %d received for request %u\n",
3171a859223SAllain Legacy 		    request->result, request->req_id);
3181a859223SAllain Legacy 
3191a859223SAllain Legacy done:
3201a859223SAllain Legacy 	return ret;
3211a859223SAllain Legacy }
3221a859223SAllain Legacy 
3231a859223SAllain Legacy static int
324*ea37523dSAllain Legacy avp_dev_ctrl_set_link_state(struct rte_eth_dev *eth_dev, unsigned int state)
325*ea37523dSAllain Legacy {
326*ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
327*ea37523dSAllain Legacy 	struct rte_avp_request request;
328*ea37523dSAllain Legacy 	int ret;
329*ea37523dSAllain Legacy 
330*ea37523dSAllain Legacy 	/* setup a link state change request */
331*ea37523dSAllain Legacy 	memset(&request, 0, sizeof(request));
332*ea37523dSAllain Legacy 	request.req_id = RTE_AVP_REQ_CFG_NETWORK_IF;
333*ea37523dSAllain Legacy 	request.if_up = state;
334*ea37523dSAllain Legacy 
335*ea37523dSAllain Legacy 	ret = avp_dev_process_request(avp, &request);
336*ea37523dSAllain Legacy 
337*ea37523dSAllain Legacy 	return ret == 0 ? request.result : ret;
338*ea37523dSAllain Legacy }
339*ea37523dSAllain Legacy 
340*ea37523dSAllain Legacy static int
3411a859223SAllain Legacy avp_dev_ctrl_set_config(struct rte_eth_dev *eth_dev,
3421a859223SAllain Legacy 			struct rte_avp_device_config *config)
3431a859223SAllain Legacy {
3441a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
3451a859223SAllain Legacy 	struct rte_avp_request request;
3461a859223SAllain Legacy 	int ret;
3471a859223SAllain Legacy 
3481a859223SAllain Legacy 	/* setup a configure request */
3491a859223SAllain Legacy 	memset(&request, 0, sizeof(request));
3501a859223SAllain Legacy 	request.req_id = RTE_AVP_REQ_CFG_DEVICE;
3511a859223SAllain Legacy 	memcpy(&request.config, config, sizeof(request.config));
3521a859223SAllain Legacy 
3531a859223SAllain Legacy 	ret = avp_dev_process_request(avp, &request);
3541a859223SAllain Legacy 
3551a859223SAllain Legacy 	return ret == 0 ? request.result : ret;
3561a859223SAllain Legacy }
3571a859223SAllain Legacy 
358*ea37523dSAllain Legacy static int
359*ea37523dSAllain Legacy avp_dev_ctrl_shutdown(struct rte_eth_dev *eth_dev)
360*ea37523dSAllain Legacy {
361*ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
362*ea37523dSAllain Legacy 	struct rte_avp_request request;
363*ea37523dSAllain Legacy 	int ret;
364*ea37523dSAllain Legacy 
365*ea37523dSAllain Legacy 	/* setup a shutdown request */
366*ea37523dSAllain Legacy 	memset(&request, 0, sizeof(request));
367*ea37523dSAllain Legacy 	request.req_id = RTE_AVP_REQ_SHUTDOWN_DEVICE;
368*ea37523dSAllain Legacy 
369*ea37523dSAllain Legacy 	ret = avp_dev_process_request(avp, &request);
370*ea37523dSAllain Legacy 
371*ea37523dSAllain Legacy 	return ret == 0 ? request.result : ret;
372*ea37523dSAllain Legacy }
373*ea37523dSAllain Legacy 
37450db69fdSAllain Legacy /* translate from host mbuf virtual address to guest virtual address */
37550db69fdSAllain Legacy static inline void *
37650db69fdSAllain Legacy avp_dev_translate_buffer(struct avp_dev *avp, void *host_mbuf_address)
37750db69fdSAllain Legacy {
37850db69fdSAllain Legacy 	return RTE_PTR_ADD(RTE_PTR_SUB(host_mbuf_address,
37950db69fdSAllain Legacy 				       (uintptr_t)avp->host_mbuf_addr),
38050db69fdSAllain Legacy 			   (uintptr_t)avp->mbuf_addr);
38150db69fdSAllain Legacy }
38250db69fdSAllain Legacy 
383c0ad5842SAllain Legacy /* translate from host physical address to guest virtual address */
384c0ad5842SAllain Legacy static void *
385c0ad5842SAllain Legacy avp_dev_translate_address(struct rte_eth_dev *eth_dev,
386c0ad5842SAllain Legacy 			  phys_addr_t host_phys_addr)
387c0ad5842SAllain Legacy {
388c0ad5842SAllain Legacy 	struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev);
389c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
390c0ad5842SAllain Legacy 	struct rte_avp_memmap_info *info;
391c0ad5842SAllain Legacy 	struct rte_avp_memmap *map;
392c0ad5842SAllain Legacy 	off_t offset;
393c0ad5842SAllain Legacy 	void *addr;
394c0ad5842SAllain Legacy 	unsigned int i;
395c0ad5842SAllain Legacy 
396c0ad5842SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_MEMORY_BAR].addr;
397c0ad5842SAllain Legacy 	resource = &pci_dev->mem_resource[RTE_AVP_PCI_MEMMAP_BAR];
398c0ad5842SAllain Legacy 	info = (struct rte_avp_memmap_info *)resource->addr;
399c0ad5842SAllain Legacy 
400c0ad5842SAllain Legacy 	offset = 0;
401c0ad5842SAllain Legacy 	for (i = 0; i < info->nb_maps; i++) {
402c0ad5842SAllain Legacy 		/* search all segments looking for a matching address */
403c0ad5842SAllain Legacy 		map = &info->maps[i];
404c0ad5842SAllain Legacy 
405c0ad5842SAllain Legacy 		if ((host_phys_addr >= map->phys_addr) &&
406c0ad5842SAllain Legacy 			(host_phys_addr < (map->phys_addr + map->length))) {
407c0ad5842SAllain Legacy 			/* address is within this segment */
408c0ad5842SAllain Legacy 			offset += (host_phys_addr - map->phys_addr);
409c0ad5842SAllain Legacy 			addr = RTE_PTR_ADD(addr, offset);
410c0ad5842SAllain Legacy 
411c0ad5842SAllain Legacy 			PMD_DRV_LOG(DEBUG, "Translating host physical 0x%" PRIx64 " to guest virtual 0x%p\n",
412c0ad5842SAllain Legacy 				    host_phys_addr, addr);
413c0ad5842SAllain Legacy 
414c0ad5842SAllain Legacy 			return addr;
415c0ad5842SAllain Legacy 		}
416c0ad5842SAllain Legacy 		offset += map->length;
417c0ad5842SAllain Legacy 	}
418c0ad5842SAllain Legacy 
419c0ad5842SAllain Legacy 	return NULL;
420c0ad5842SAllain Legacy }
421c0ad5842SAllain Legacy 
422c0ad5842SAllain Legacy /* verify that the incoming device version is compatible with our version */
423c0ad5842SAllain Legacy static int
424c0ad5842SAllain Legacy avp_dev_version_check(uint32_t version)
425c0ad5842SAllain Legacy {
426c0ad5842SAllain Legacy 	uint32_t driver = RTE_AVP_STRIP_MINOR_VERSION(AVP_DPDK_DRIVER_VERSION);
427c0ad5842SAllain Legacy 	uint32_t device = RTE_AVP_STRIP_MINOR_VERSION(version);
428c0ad5842SAllain Legacy 
429c0ad5842SAllain Legacy 	if (device <= driver) {
430c0ad5842SAllain Legacy 		/* the host driver version is less than or equal to ours */
431c0ad5842SAllain Legacy 		return 0;
432c0ad5842SAllain Legacy 	}
433c0ad5842SAllain Legacy 
434c0ad5842SAllain Legacy 	return 1;
435c0ad5842SAllain Legacy }
436c0ad5842SAllain Legacy 
437c0ad5842SAllain Legacy /* verify that memory regions have expected version and validation markers */
438c0ad5842SAllain Legacy static int
439c0ad5842SAllain Legacy avp_dev_check_regions(struct rte_eth_dev *eth_dev)
440c0ad5842SAllain Legacy {
441c0ad5842SAllain Legacy 	struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev);
442c0ad5842SAllain Legacy 	struct rte_avp_memmap_info *memmap;
443c0ad5842SAllain Legacy 	struct rte_avp_device_info *info;
444c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
445c0ad5842SAllain Legacy 	unsigned int i;
446c0ad5842SAllain Legacy 
447c0ad5842SAllain Legacy 	/* Dump resource info for debug */
448c0ad5842SAllain Legacy 	for (i = 0; i < PCI_MAX_RESOURCE; i++) {
449c0ad5842SAllain Legacy 		resource = &pci_dev->mem_resource[i];
450c0ad5842SAllain Legacy 		if ((resource->phys_addr == 0) || (resource->len == 0))
451c0ad5842SAllain Legacy 			continue;
452c0ad5842SAllain Legacy 
453c0ad5842SAllain Legacy 		PMD_DRV_LOG(DEBUG, "resource[%u]: phys=0x%" PRIx64 " len=%" PRIu64 " addr=%p\n",
454c0ad5842SAllain Legacy 			    i, resource->phys_addr,
455c0ad5842SAllain Legacy 			    resource->len, resource->addr);
456c0ad5842SAllain Legacy 
457c0ad5842SAllain Legacy 		switch (i) {
458c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MEMMAP_BAR:
459c0ad5842SAllain Legacy 			memmap = (struct rte_avp_memmap_info *)resource->addr;
460c0ad5842SAllain Legacy 			if ((memmap->magic != RTE_AVP_MEMMAP_MAGIC) ||
461c0ad5842SAllain Legacy 			    (memmap->version != RTE_AVP_MEMMAP_VERSION)) {
462c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Invalid memmap magic 0x%08x and version %u\n",
463c0ad5842SAllain Legacy 					    memmap->magic, memmap->version);
464c0ad5842SAllain Legacy 				return -EINVAL;
465c0ad5842SAllain Legacy 			}
466c0ad5842SAllain Legacy 			break;
467c0ad5842SAllain Legacy 
468c0ad5842SAllain Legacy 		case RTE_AVP_PCI_DEVICE_BAR:
469c0ad5842SAllain Legacy 			info = (struct rte_avp_device_info *)resource->addr;
470c0ad5842SAllain Legacy 			if ((info->magic != RTE_AVP_DEVICE_MAGIC) ||
471c0ad5842SAllain Legacy 			    avp_dev_version_check(info->version)) {
472c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Invalid device info magic 0x%08x or version 0x%08x > 0x%08x\n",
473c0ad5842SAllain Legacy 					    info->magic, info->version,
474c0ad5842SAllain Legacy 					    AVP_DPDK_DRIVER_VERSION);
475c0ad5842SAllain Legacy 				return -EINVAL;
476c0ad5842SAllain Legacy 			}
477c0ad5842SAllain Legacy 			break;
478c0ad5842SAllain Legacy 
479c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MEMORY_BAR:
480c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MMIO_BAR:
481c0ad5842SAllain Legacy 			if (resource->addr == NULL) {
482c0ad5842SAllain Legacy 				PMD_DRV_LOG(ERR, "Missing address space for BAR%u\n",
483c0ad5842SAllain Legacy 					    i);
484c0ad5842SAllain Legacy 				return -EINVAL;
485c0ad5842SAllain Legacy 			}
486c0ad5842SAllain Legacy 			break;
487c0ad5842SAllain Legacy 
488c0ad5842SAllain Legacy 		case RTE_AVP_PCI_MSIX_BAR:
489c0ad5842SAllain Legacy 		default:
490c0ad5842SAllain Legacy 			/* no validation required */
491c0ad5842SAllain Legacy 			break;
492c0ad5842SAllain Legacy 		}
493c0ad5842SAllain Legacy 	}
494c0ad5842SAllain Legacy 
495c0ad5842SAllain Legacy 	return 0;
496c0ad5842SAllain Legacy }
497c0ad5842SAllain Legacy 
4981a859223SAllain Legacy static void
499cce4367fSAllain Legacy _avp_set_rx_queue_mappings(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
500cce4367fSAllain Legacy {
501cce4367fSAllain Legacy 	struct avp_dev *avp =
502cce4367fSAllain Legacy 		AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
503cce4367fSAllain Legacy 	struct avp_queue *rxq;
504cce4367fSAllain Legacy 	uint16_t queue_count;
505cce4367fSAllain Legacy 	uint16_t remainder;
506cce4367fSAllain Legacy 
507cce4367fSAllain Legacy 	rxq = (struct avp_queue *)eth_dev->data->rx_queues[rx_queue_id];
508cce4367fSAllain Legacy 
509cce4367fSAllain Legacy 	/*
510cce4367fSAllain Legacy 	 * Must map all AVP fifos as evenly as possible between the configured
511cce4367fSAllain Legacy 	 * device queues.  Each device queue will service a subset of the AVP
512cce4367fSAllain Legacy 	 * fifos. If there is an odd number of device queues the first set of
513cce4367fSAllain Legacy 	 * device queues will get the extra AVP fifos.
514cce4367fSAllain Legacy 	 */
515cce4367fSAllain Legacy 	queue_count = avp->num_rx_queues / eth_dev->data->nb_rx_queues;
516cce4367fSAllain Legacy 	remainder = avp->num_rx_queues % eth_dev->data->nb_rx_queues;
517cce4367fSAllain Legacy 	if (rx_queue_id < remainder) {
518cce4367fSAllain Legacy 		/* these queues must service one extra FIFO */
519cce4367fSAllain Legacy 		rxq->queue_base = rx_queue_id * (queue_count + 1);
520cce4367fSAllain Legacy 		rxq->queue_limit = rxq->queue_base + (queue_count + 1) - 1;
521cce4367fSAllain Legacy 	} else {
522cce4367fSAllain Legacy 		/* these queues service the regular number of FIFO */
523cce4367fSAllain Legacy 		rxq->queue_base = ((remainder * (queue_count + 1)) +
524cce4367fSAllain Legacy 				   ((rx_queue_id - remainder) * queue_count));
525cce4367fSAllain Legacy 		rxq->queue_limit = rxq->queue_base + queue_count - 1;
526cce4367fSAllain Legacy 	}
527cce4367fSAllain Legacy 
528cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "rxq %u at %p base %u limit %u\n",
529cce4367fSAllain Legacy 		    rx_queue_id, rxq, rxq->queue_base, rxq->queue_limit);
530cce4367fSAllain Legacy 
531cce4367fSAllain Legacy 	rxq->queue_id = rxq->queue_base;
532cce4367fSAllain Legacy }
533cce4367fSAllain Legacy 
534cce4367fSAllain Legacy static void
5351a859223SAllain Legacy _avp_set_queue_counts(struct rte_eth_dev *eth_dev)
5361a859223SAllain Legacy {
5371a859223SAllain Legacy 	struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev);
5381a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
5391a859223SAllain Legacy 	struct rte_avp_device_info *host_info;
5401a859223SAllain Legacy 	void *addr;
5411a859223SAllain Legacy 
5421a859223SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr;
5431a859223SAllain Legacy 	host_info = (struct rte_avp_device_info *)addr;
5441a859223SAllain Legacy 
5451a859223SAllain Legacy 	/*
5461a859223SAllain Legacy 	 * the transmit direction is not negotiated beyond respecting the max
5471a859223SAllain Legacy 	 * number of queues because the host can handle arbitrary guest tx
5481a859223SAllain Legacy 	 * queues (host rx queues).
5491a859223SAllain Legacy 	 */
5501a859223SAllain Legacy 	avp->num_tx_queues = eth_dev->data->nb_tx_queues;
5511a859223SAllain Legacy 
5521a859223SAllain Legacy 	/*
5531a859223SAllain Legacy 	 * the receive direction is more restrictive.  The host requires a
5541a859223SAllain Legacy 	 * minimum number of guest rx queues (host tx queues) therefore
5551a859223SAllain Legacy 	 * negotiate a value that is at least as large as the host minimum
5561a859223SAllain Legacy 	 * requirement.  If the host and guest values are not identical then a
5571a859223SAllain Legacy 	 * mapping will be established in the receive_queue_setup function.
5581a859223SAllain Legacy 	 */
5591a859223SAllain Legacy 	avp->num_rx_queues = RTE_MAX(host_info->min_rx_queues,
5601a859223SAllain Legacy 				     eth_dev->data->nb_rx_queues);
5611a859223SAllain Legacy 
5621a859223SAllain Legacy 	PMD_DRV_LOG(DEBUG, "Requesting %u Tx and %u Rx queues from host\n",
5631a859223SAllain Legacy 		    avp->num_tx_queues, avp->num_rx_queues);
5641a859223SAllain Legacy }
5651a859223SAllain Legacy 
566c0ad5842SAllain Legacy /*
567c0ad5842SAllain Legacy  * create a AVP device using the supplied device info by first translating it
568c0ad5842SAllain Legacy  * to guest address space(s).
569c0ad5842SAllain Legacy  */
570c0ad5842SAllain Legacy static int
571c0ad5842SAllain Legacy avp_dev_create(struct rte_pci_device *pci_dev,
572c0ad5842SAllain Legacy 	       struct rte_eth_dev *eth_dev)
573c0ad5842SAllain Legacy {
574c0ad5842SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
575c0ad5842SAllain Legacy 	struct rte_avp_device_info *host_info;
576c0ad5842SAllain Legacy 	struct rte_mem_resource *resource;
577c0ad5842SAllain Legacy 	unsigned int i;
578c0ad5842SAllain Legacy 
579c0ad5842SAllain Legacy 	resource = &pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR];
580c0ad5842SAllain Legacy 	if (resource->addr == NULL) {
581c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "BAR%u is not mapped\n",
582c0ad5842SAllain Legacy 			    RTE_AVP_PCI_DEVICE_BAR);
583c0ad5842SAllain Legacy 		return -EFAULT;
584c0ad5842SAllain Legacy 	}
585c0ad5842SAllain Legacy 	host_info = (struct rte_avp_device_info *)resource->addr;
586c0ad5842SAllain Legacy 
587c0ad5842SAllain Legacy 	if ((host_info->magic != RTE_AVP_DEVICE_MAGIC) ||
588c0ad5842SAllain Legacy 		avp_dev_version_check(host_info->version)) {
589c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Invalid AVP PCI device, magic 0x%08x version 0x%08x > 0x%08x\n",
590c0ad5842SAllain Legacy 			    host_info->magic, host_info->version,
591c0ad5842SAllain Legacy 			    AVP_DPDK_DRIVER_VERSION);
592c0ad5842SAllain Legacy 		return -EINVAL;
593c0ad5842SAllain Legacy 	}
594c0ad5842SAllain Legacy 
595c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host device is v%u.%u.%u\n",
596c0ad5842SAllain Legacy 		    RTE_AVP_GET_RELEASE_VERSION(host_info->version),
597c0ad5842SAllain Legacy 		    RTE_AVP_GET_MAJOR_VERSION(host_info->version),
598c0ad5842SAllain Legacy 		    RTE_AVP_GET_MINOR_VERSION(host_info->version));
599c0ad5842SAllain Legacy 
600c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u TX queue(s)\n",
601c0ad5842SAllain Legacy 		    host_info->min_tx_queues, host_info->max_tx_queues);
602c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports %u to %u RX queue(s)\n",
603c0ad5842SAllain Legacy 		    host_info->min_rx_queues, host_info->max_rx_queues);
604c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host supports features 0x%08x\n",
605c0ad5842SAllain Legacy 		    host_info->features);
606c0ad5842SAllain Legacy 
607c0ad5842SAllain Legacy 	if (avp->magic != AVP_ETHDEV_MAGIC) {
608c0ad5842SAllain Legacy 		/*
609c0ad5842SAllain Legacy 		 * First time initialization (i.e., not during a VM
610c0ad5842SAllain Legacy 		 * migration)
611c0ad5842SAllain Legacy 		 */
612c0ad5842SAllain Legacy 		memset(avp, 0, sizeof(*avp));
613c0ad5842SAllain Legacy 		avp->magic = AVP_ETHDEV_MAGIC;
614c0ad5842SAllain Legacy 		avp->dev_data = eth_dev->data;
615c0ad5842SAllain Legacy 		avp->port_id = eth_dev->data->port_id;
616c0ad5842SAllain Legacy 		avp->host_mbuf_size = host_info->mbuf_size;
617c0ad5842SAllain Legacy 		avp->host_features = host_info->features;
618c0ad5842SAllain Legacy 		memcpy(&avp->ethaddr.addr_bytes[0],
619c0ad5842SAllain Legacy 		       host_info->ethaddr, ETHER_ADDR_LEN);
620c0ad5842SAllain Legacy 		/* adjust max values to not exceed our max */
621c0ad5842SAllain Legacy 		avp->max_tx_queues =
622c0ad5842SAllain Legacy 			RTE_MIN(host_info->max_tx_queues, RTE_AVP_MAX_QUEUES);
623c0ad5842SAllain Legacy 		avp->max_rx_queues =
624c0ad5842SAllain Legacy 			RTE_MIN(host_info->max_rx_queues, RTE_AVP_MAX_QUEUES);
625c0ad5842SAllain Legacy 	} else {
626c0ad5842SAllain Legacy 		/* Re-attaching during migration */
627c0ad5842SAllain Legacy 
628c0ad5842SAllain Legacy 		/* TODO... requires validation of host values */
629c0ad5842SAllain Legacy 		if ((host_info->features & avp->features) != avp->features) {
630c0ad5842SAllain Legacy 			PMD_DRV_LOG(ERR, "AVP host features mismatched; 0x%08x, host=0x%08x\n",
631c0ad5842SAllain Legacy 				    avp->features, host_info->features);
632c0ad5842SAllain Legacy 			/* this should not be possible; continue for now */
633c0ad5842SAllain Legacy 		}
634c0ad5842SAllain Legacy 	}
635c0ad5842SAllain Legacy 
636c0ad5842SAllain Legacy 	/* the device id is allowed to change over migrations */
637c0ad5842SAllain Legacy 	avp->device_id = host_info->device_id;
638c0ad5842SAllain Legacy 
639c0ad5842SAllain Legacy 	/* translate incoming host addresses to guest address space */
640c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host tx queue at 0x%" PRIx64 "\n",
641c0ad5842SAllain Legacy 		    host_info->tx_phys);
642c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host alloc queue at 0x%" PRIx64 "\n",
643c0ad5842SAllain Legacy 		    host_info->alloc_phys);
644c0ad5842SAllain Legacy 	for (i = 0; i < avp->max_tx_queues; i++) {
645c0ad5842SAllain Legacy 		avp->tx_q[i] = avp_dev_translate_address(eth_dev,
646c0ad5842SAllain Legacy 			host_info->tx_phys + (i * host_info->tx_size));
647c0ad5842SAllain Legacy 
648c0ad5842SAllain Legacy 		avp->alloc_q[i] = avp_dev_translate_address(eth_dev,
649c0ad5842SAllain Legacy 			host_info->alloc_phys + (i * host_info->alloc_size));
650c0ad5842SAllain Legacy 	}
651c0ad5842SAllain Legacy 
652c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host rx queue at 0x%" PRIx64 "\n",
653c0ad5842SAllain Legacy 		    host_info->rx_phys);
654c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP first host free queue at 0x%" PRIx64 "\n",
655c0ad5842SAllain Legacy 		    host_info->free_phys);
656c0ad5842SAllain Legacy 	for (i = 0; i < avp->max_rx_queues; i++) {
657c0ad5842SAllain Legacy 		avp->rx_q[i] = avp_dev_translate_address(eth_dev,
658c0ad5842SAllain Legacy 			host_info->rx_phys + (i * host_info->rx_size));
659c0ad5842SAllain Legacy 		avp->free_q[i] = avp_dev_translate_address(eth_dev,
660c0ad5842SAllain Legacy 			host_info->free_phys + (i * host_info->free_size));
661c0ad5842SAllain Legacy 	}
662c0ad5842SAllain Legacy 
663c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host request queue at 0x%" PRIx64 "\n",
664c0ad5842SAllain Legacy 		    host_info->req_phys);
665c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host response queue at 0x%" PRIx64 "\n",
666c0ad5842SAllain Legacy 		    host_info->resp_phys);
667c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host sync address at 0x%" PRIx64 "\n",
668c0ad5842SAllain Legacy 		    host_info->sync_phys);
669c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host mbuf address at 0x%" PRIx64 "\n",
670c0ad5842SAllain Legacy 		    host_info->mbuf_phys);
671c0ad5842SAllain Legacy 	avp->req_q = avp_dev_translate_address(eth_dev, host_info->req_phys);
672c0ad5842SAllain Legacy 	avp->resp_q = avp_dev_translate_address(eth_dev, host_info->resp_phys);
673c0ad5842SAllain Legacy 	avp->sync_addr =
674c0ad5842SAllain Legacy 		avp_dev_translate_address(eth_dev, host_info->sync_phys);
675c0ad5842SAllain Legacy 	avp->mbuf_addr =
676c0ad5842SAllain Legacy 		avp_dev_translate_address(eth_dev, host_info->mbuf_phys);
677c0ad5842SAllain Legacy 
678c0ad5842SAllain Legacy 	/*
679c0ad5842SAllain Legacy 	 * store the host mbuf virtual address so that we can calculate
680c0ad5842SAllain Legacy 	 * relative offsets for each mbuf as they are processed
681c0ad5842SAllain Legacy 	 */
682c0ad5842SAllain Legacy 	avp->host_mbuf_addr = host_info->mbuf_va;
683c0ad5842SAllain Legacy 	avp->host_sync_addr = host_info->sync_va;
684c0ad5842SAllain Legacy 
685c0ad5842SAllain Legacy 	/*
686c0ad5842SAllain Legacy 	 * store the maximum packet length that is supported by the host.
687c0ad5842SAllain Legacy 	 */
688c0ad5842SAllain Legacy 	avp->max_rx_pkt_len = host_info->max_rx_pkt_len;
689c0ad5842SAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP host max receive packet length is %u\n",
690c0ad5842SAllain Legacy 				host_info->max_rx_pkt_len);
691c0ad5842SAllain Legacy 
692c0ad5842SAllain Legacy 	return 0;
693c0ad5842SAllain Legacy }
694c0ad5842SAllain Legacy 
695c0ad5842SAllain Legacy /*
696908072e9SAllain Legacy  * This function is based on probe() function in avp_pci.c
697908072e9SAllain Legacy  * It returns 0 on success.
698908072e9SAllain Legacy  */
699908072e9SAllain Legacy static int
700908072e9SAllain Legacy eth_avp_dev_init(struct rte_eth_dev *eth_dev)
701908072e9SAllain Legacy {
702c0ad5842SAllain Legacy 	struct avp_dev *avp =
703c0ad5842SAllain Legacy 		AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
704908072e9SAllain Legacy 	struct rte_pci_device *pci_dev;
705c0ad5842SAllain Legacy 	int ret;
706908072e9SAllain Legacy 
707908072e9SAllain Legacy 	pci_dev = AVP_DEV_TO_PCI(eth_dev);
7081a859223SAllain Legacy 	eth_dev->dev_ops = &avp_eth_dev_ops;
70950db69fdSAllain Legacy 	eth_dev->rx_pkt_burst = &avp_recv_pkts;
710295abce2SAllain Legacy 	eth_dev->tx_pkt_burst = &avp_xmit_pkts;
711908072e9SAllain Legacy 
712908072e9SAllain Legacy 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
713908072e9SAllain Legacy 		/*
714908072e9SAllain Legacy 		 * no setup required on secondary processes.  All data is saved
715908072e9SAllain Legacy 		 * in dev_private by the primary process. All resource should
716908072e9SAllain Legacy 		 * be mapped to the same virtual address so all pointers should
717908072e9SAllain Legacy 		 * be valid.
718908072e9SAllain Legacy 		 */
71950db69fdSAllain Legacy 		if (eth_dev->data->scattered_rx) {
72050db69fdSAllain Legacy 			PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n");
72150db69fdSAllain Legacy 			eth_dev->rx_pkt_burst = avp_recv_scattered_pkts;
722295abce2SAllain Legacy 			eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts;
72350db69fdSAllain Legacy 		}
724908072e9SAllain Legacy 		return 0;
725908072e9SAllain Legacy 	}
726908072e9SAllain Legacy 
727908072e9SAllain Legacy 	rte_eth_copy_pci_info(eth_dev, pci_dev);
728908072e9SAllain Legacy 
729908072e9SAllain Legacy 	eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
730908072e9SAllain Legacy 
731c0ad5842SAllain Legacy 	/* Check BAR resources */
732c0ad5842SAllain Legacy 	ret = avp_dev_check_regions(eth_dev);
733c0ad5842SAllain Legacy 	if (ret < 0) {
734c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to validate BAR resources, ret=%d\n",
735c0ad5842SAllain Legacy 			    ret);
736c0ad5842SAllain Legacy 		return ret;
737c0ad5842SAllain Legacy 	}
738c0ad5842SAllain Legacy 
739c0ad5842SAllain Legacy 	/* Handle each subtype */
740c0ad5842SAllain Legacy 	ret = avp_dev_create(pci_dev, eth_dev);
741c0ad5842SAllain Legacy 	if (ret < 0) {
742c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to create device, ret=%d\n", ret);
743c0ad5842SAllain Legacy 		return ret;
744c0ad5842SAllain Legacy 	}
745c0ad5842SAllain Legacy 
746c0ad5842SAllain Legacy 	/* Allocate memory for storing MAC addresses */
747c0ad5842SAllain Legacy 	eth_dev->data->mac_addrs = rte_zmalloc("avp_ethdev", ETHER_ADDR_LEN, 0);
748c0ad5842SAllain Legacy 	if (eth_dev->data->mac_addrs == NULL) {
749c0ad5842SAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses\n",
750c0ad5842SAllain Legacy 			    ETHER_ADDR_LEN);
751c0ad5842SAllain Legacy 		return -ENOMEM;
752c0ad5842SAllain Legacy 	}
753c0ad5842SAllain Legacy 
754c0ad5842SAllain Legacy 	/* Get a mac from device config */
755c0ad5842SAllain Legacy 	ether_addr_copy(&avp->ethaddr, &eth_dev->data->mac_addrs[0]);
756c0ad5842SAllain Legacy 
757908072e9SAllain Legacy 	return 0;
758908072e9SAllain Legacy }
759908072e9SAllain Legacy 
760908072e9SAllain Legacy static int
761908072e9SAllain Legacy eth_avp_dev_uninit(struct rte_eth_dev *eth_dev)
762908072e9SAllain Legacy {
763908072e9SAllain Legacy 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
764908072e9SAllain Legacy 		return -EPERM;
765908072e9SAllain Legacy 
766908072e9SAllain Legacy 	if (eth_dev->data == NULL)
767908072e9SAllain Legacy 		return 0;
768908072e9SAllain Legacy 
769c0ad5842SAllain Legacy 	if (eth_dev->data->mac_addrs != NULL) {
770c0ad5842SAllain Legacy 		rte_free(eth_dev->data->mac_addrs);
771c0ad5842SAllain Legacy 		eth_dev->data->mac_addrs = NULL;
772c0ad5842SAllain Legacy 	}
773c0ad5842SAllain Legacy 
774908072e9SAllain Legacy 	return 0;
775908072e9SAllain Legacy }
776908072e9SAllain Legacy 
777908072e9SAllain Legacy 
778908072e9SAllain Legacy static struct eth_driver rte_avp_pmd = {
779908072e9SAllain Legacy 	{
780908072e9SAllain Legacy 		.id_table = pci_id_avp_map,
781908072e9SAllain Legacy 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
782908072e9SAllain Legacy 		.probe = rte_eth_dev_pci_probe,
783908072e9SAllain Legacy 		.remove = rte_eth_dev_pci_remove,
784908072e9SAllain Legacy 	},
785908072e9SAllain Legacy 	.eth_dev_init = eth_avp_dev_init,
786908072e9SAllain Legacy 	.eth_dev_uninit = eth_avp_dev_uninit,
787908072e9SAllain Legacy 	.dev_private_size = sizeof(struct avp_adapter),
788908072e9SAllain Legacy };
789908072e9SAllain Legacy 
7901a859223SAllain Legacy static int
79150db69fdSAllain Legacy avp_dev_enable_scattered(struct rte_eth_dev *eth_dev,
79250db69fdSAllain Legacy 			 struct avp_dev *avp)
79350db69fdSAllain Legacy {
79450db69fdSAllain Legacy 	unsigned int max_rx_pkt_len;
79550db69fdSAllain Legacy 
79650db69fdSAllain Legacy 	max_rx_pkt_len = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len;
79750db69fdSAllain Legacy 
79850db69fdSAllain Legacy 	if ((max_rx_pkt_len > avp->guest_mbuf_size) ||
79950db69fdSAllain Legacy 	    (max_rx_pkt_len > avp->host_mbuf_size)) {
80050db69fdSAllain Legacy 		/*
80150db69fdSAllain Legacy 		 * If the guest MTU is greater than either the host or guest
80250db69fdSAllain Legacy 		 * buffers then chained mbufs have to be enabled in the TX
80350db69fdSAllain Legacy 		 * direction.  It is assumed that the application will not need
80450db69fdSAllain Legacy 		 * to send packets larger than their max_rx_pkt_len (MRU).
80550db69fdSAllain Legacy 		 */
80650db69fdSAllain Legacy 		return 1;
80750db69fdSAllain Legacy 	}
80850db69fdSAllain Legacy 
80950db69fdSAllain Legacy 	if ((avp->max_rx_pkt_len > avp->guest_mbuf_size) ||
81050db69fdSAllain Legacy 	    (avp->max_rx_pkt_len > avp->host_mbuf_size)) {
81150db69fdSAllain Legacy 		/*
81250db69fdSAllain Legacy 		 * If the host MRU is greater than its own mbuf size or the
81350db69fdSAllain Legacy 		 * guest mbuf size then chained mbufs have to be enabled in the
81450db69fdSAllain Legacy 		 * RX direction.
81550db69fdSAllain Legacy 		 */
81650db69fdSAllain Legacy 		return 1;
81750db69fdSAllain Legacy 	}
81850db69fdSAllain Legacy 
81950db69fdSAllain Legacy 	return 0;
82050db69fdSAllain Legacy }
82150db69fdSAllain Legacy 
82250db69fdSAllain Legacy static int
823cce4367fSAllain Legacy avp_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
824cce4367fSAllain Legacy 		       uint16_t rx_queue_id,
825cce4367fSAllain Legacy 		       uint16_t nb_rx_desc,
826cce4367fSAllain Legacy 		       unsigned int socket_id,
827cce4367fSAllain Legacy 		       const struct rte_eth_rxconf *rx_conf,
828cce4367fSAllain Legacy 		       struct rte_mempool *pool)
829cce4367fSAllain Legacy {
830cce4367fSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
831cce4367fSAllain Legacy 	struct rte_pktmbuf_pool_private *mbp_priv;
832cce4367fSAllain Legacy 	struct avp_queue *rxq;
833cce4367fSAllain Legacy 
834cce4367fSAllain Legacy 	if (rx_queue_id >= eth_dev->data->nb_rx_queues) {
835cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "RX queue id is out of range: rx_queue_id=%u, nb_rx_queues=%u\n",
836cce4367fSAllain Legacy 			    rx_queue_id, eth_dev->data->nb_rx_queues);
837cce4367fSAllain Legacy 		return -EINVAL;
838cce4367fSAllain Legacy 	}
839cce4367fSAllain Legacy 
840cce4367fSAllain Legacy 	/* Save mbuf pool pointer */
841cce4367fSAllain Legacy 	avp->pool = pool;
842cce4367fSAllain Legacy 
843cce4367fSAllain Legacy 	/* Save the local mbuf size */
844cce4367fSAllain Legacy 	mbp_priv = rte_mempool_get_priv(pool);
845cce4367fSAllain Legacy 	avp->guest_mbuf_size = (uint16_t)(mbp_priv->mbuf_data_room_size);
846cce4367fSAllain Legacy 	avp->guest_mbuf_size -= RTE_PKTMBUF_HEADROOM;
847cce4367fSAllain Legacy 
84850db69fdSAllain Legacy 	if (avp_dev_enable_scattered(eth_dev, avp)) {
84950db69fdSAllain Legacy 		if (!eth_dev->data->scattered_rx) {
85050db69fdSAllain Legacy 			PMD_DRV_LOG(NOTICE, "AVP device configured for chained mbufs\n");
85150db69fdSAllain Legacy 			eth_dev->data->scattered_rx = 1;
85250db69fdSAllain Legacy 			eth_dev->rx_pkt_burst = avp_recv_scattered_pkts;
853295abce2SAllain Legacy 			eth_dev->tx_pkt_burst = avp_xmit_scattered_pkts;
85450db69fdSAllain Legacy 		}
85550db69fdSAllain Legacy 	}
85650db69fdSAllain Legacy 
857cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "AVP max_rx_pkt_len=(%u,%u) mbuf_size=(%u,%u)\n",
858cce4367fSAllain Legacy 		    avp->max_rx_pkt_len,
859cce4367fSAllain Legacy 		    eth_dev->data->dev_conf.rxmode.max_rx_pkt_len,
860cce4367fSAllain Legacy 		    avp->host_mbuf_size,
861cce4367fSAllain Legacy 		    avp->guest_mbuf_size);
862cce4367fSAllain Legacy 
863cce4367fSAllain Legacy 	/* allocate a queue object */
864cce4367fSAllain Legacy 	rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct avp_queue),
865cce4367fSAllain Legacy 				 RTE_CACHE_LINE_SIZE, socket_id);
866cce4367fSAllain Legacy 	if (rxq == NULL) {
867cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate new Rx queue object\n");
868cce4367fSAllain Legacy 		return -ENOMEM;
869cce4367fSAllain Legacy 	}
870cce4367fSAllain Legacy 
871cce4367fSAllain Legacy 	/* save back pointers to AVP and Ethernet devices */
872cce4367fSAllain Legacy 	rxq->avp = avp;
873cce4367fSAllain Legacy 	rxq->dev_data = eth_dev->data;
874cce4367fSAllain Legacy 	eth_dev->data->rx_queues[rx_queue_id] = (void *)rxq;
875cce4367fSAllain Legacy 
876cce4367fSAllain Legacy 	/* setup the queue receive mapping for the current queue. */
877cce4367fSAllain Legacy 	_avp_set_rx_queue_mappings(eth_dev, rx_queue_id);
878cce4367fSAllain Legacy 
879cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "Rx queue %u setup at %p\n", rx_queue_id, rxq);
880cce4367fSAllain Legacy 
881cce4367fSAllain Legacy 	(void)nb_rx_desc;
882cce4367fSAllain Legacy 	(void)rx_conf;
883cce4367fSAllain Legacy 	return 0;
884cce4367fSAllain Legacy }
885cce4367fSAllain Legacy 
886cce4367fSAllain Legacy static int
887cce4367fSAllain Legacy avp_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
888cce4367fSAllain Legacy 		       uint16_t tx_queue_id,
889cce4367fSAllain Legacy 		       uint16_t nb_tx_desc,
890cce4367fSAllain Legacy 		       unsigned int socket_id,
891cce4367fSAllain Legacy 		       const struct rte_eth_txconf *tx_conf)
892cce4367fSAllain Legacy {
893cce4367fSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
894cce4367fSAllain Legacy 	struct avp_queue *txq;
895cce4367fSAllain Legacy 
896cce4367fSAllain Legacy 	if (tx_queue_id >= eth_dev->data->nb_tx_queues) {
897cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "TX queue id is out of range: tx_queue_id=%u, nb_tx_queues=%u\n",
898cce4367fSAllain Legacy 			    tx_queue_id, eth_dev->data->nb_tx_queues);
899cce4367fSAllain Legacy 		return -EINVAL;
900cce4367fSAllain Legacy 	}
901cce4367fSAllain Legacy 
902cce4367fSAllain Legacy 	/* allocate a queue object */
903cce4367fSAllain Legacy 	txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct avp_queue),
904cce4367fSAllain Legacy 				 RTE_CACHE_LINE_SIZE, socket_id);
905cce4367fSAllain Legacy 	if (txq == NULL) {
906cce4367fSAllain Legacy 		PMD_DRV_LOG(ERR, "Failed to allocate new Tx queue object\n");
907cce4367fSAllain Legacy 		return -ENOMEM;
908cce4367fSAllain Legacy 	}
909cce4367fSAllain Legacy 
910cce4367fSAllain Legacy 	/* only the configured set of transmit queues are used */
911cce4367fSAllain Legacy 	txq->queue_id = tx_queue_id;
912cce4367fSAllain Legacy 	txq->queue_base = tx_queue_id;
913cce4367fSAllain Legacy 	txq->queue_limit = tx_queue_id;
914cce4367fSAllain Legacy 
915cce4367fSAllain Legacy 	/* save back pointers to AVP and Ethernet devices */
916cce4367fSAllain Legacy 	txq->avp = avp;
917cce4367fSAllain Legacy 	txq->dev_data = eth_dev->data;
918cce4367fSAllain Legacy 	eth_dev->data->tx_queues[tx_queue_id] = (void *)txq;
919cce4367fSAllain Legacy 
920cce4367fSAllain Legacy 	PMD_DRV_LOG(DEBUG, "Tx queue %u setup at %p\n", tx_queue_id, txq);
921cce4367fSAllain Legacy 
922cce4367fSAllain Legacy 	(void)nb_tx_desc;
923cce4367fSAllain Legacy 	(void)tx_conf;
924cce4367fSAllain Legacy 	return 0;
925cce4367fSAllain Legacy }
926cce4367fSAllain Legacy 
92750db69fdSAllain Legacy static inline int
92850db69fdSAllain Legacy _avp_cmp_ether_addr(struct ether_addr *a, struct ether_addr *b)
92950db69fdSAllain Legacy {
93050db69fdSAllain Legacy 	uint16_t *_a = (uint16_t *)&a->addr_bytes[0];
93150db69fdSAllain Legacy 	uint16_t *_b = (uint16_t *)&b->addr_bytes[0];
93250db69fdSAllain Legacy 	return (_a[0] ^ _b[0]) | (_a[1] ^ _b[1]) | (_a[2] ^ _b[2]);
93350db69fdSAllain Legacy }
93450db69fdSAllain Legacy 
93550db69fdSAllain Legacy static inline int
93650db69fdSAllain Legacy _avp_mac_filter(struct avp_dev *avp, struct rte_mbuf *m)
93750db69fdSAllain Legacy {
93850db69fdSAllain Legacy 	struct ether_hdr *eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
93950db69fdSAllain Legacy 
94050db69fdSAllain Legacy 	if (likely(_avp_cmp_ether_addr(&avp->ethaddr, &eth->d_addr) == 0)) {
94150db69fdSAllain Legacy 		/* allow all packets destined to our address */
94250db69fdSAllain Legacy 		return 0;
94350db69fdSAllain Legacy 	}
94450db69fdSAllain Legacy 
94550db69fdSAllain Legacy 	if (likely(is_broadcast_ether_addr(&eth->d_addr))) {
94650db69fdSAllain Legacy 		/* allow all broadcast packets */
94750db69fdSAllain Legacy 		return 0;
94850db69fdSAllain Legacy 	}
94950db69fdSAllain Legacy 
95050db69fdSAllain Legacy 	if (likely(is_multicast_ether_addr(&eth->d_addr))) {
95150db69fdSAllain Legacy 		/* allow all multicast packets */
95250db69fdSAllain Legacy 		return 0;
95350db69fdSAllain Legacy 	}
95450db69fdSAllain Legacy 
95550db69fdSAllain Legacy 	if (avp->flags & AVP_F_PROMISC) {
95650db69fdSAllain Legacy 		/* allow all packets when in promiscuous mode */
95750db69fdSAllain Legacy 		return 0;
95850db69fdSAllain Legacy 	}
95950db69fdSAllain Legacy 
96050db69fdSAllain Legacy 	return -1;
96150db69fdSAllain Legacy }
96250db69fdSAllain Legacy 
96350db69fdSAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS
96450db69fdSAllain Legacy static inline void
96550db69fdSAllain Legacy __avp_dev_buffer_sanity_check(struct avp_dev *avp, struct rte_avp_desc *buf)
96650db69fdSAllain Legacy {
96750db69fdSAllain Legacy 	struct rte_avp_desc *first_buf;
96850db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
96950db69fdSAllain Legacy 	unsigned int pkt_len;
97050db69fdSAllain Legacy 	unsigned int nb_segs;
97150db69fdSAllain Legacy 	void *pkt_data;
97250db69fdSAllain Legacy 	unsigned int i;
97350db69fdSAllain Legacy 
97450db69fdSAllain Legacy 	first_buf = avp_dev_translate_buffer(avp, buf);
97550db69fdSAllain Legacy 
97650db69fdSAllain Legacy 	i = 0;
97750db69fdSAllain Legacy 	pkt_len = 0;
97850db69fdSAllain Legacy 	nb_segs = first_buf->nb_segs;
97950db69fdSAllain Legacy 	do {
98050db69fdSAllain Legacy 		/* Adjust pointers for guest addressing */
98150db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
98250db69fdSAllain Legacy 		if (pkt_buf == NULL)
98350db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has an invalid address %p\n",
98450db69fdSAllain Legacy 				  i, buf);
98550db69fdSAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
98650db69fdSAllain Legacy 		if (pkt_data == NULL)
98750db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has a NULL data pointer\n",
98850db69fdSAllain Legacy 				  i);
98950db69fdSAllain Legacy 		if (pkt_buf->data_len == 0)
99050db69fdSAllain Legacy 			rte_panic("bad buffer: segment %u has 0 data length\n",
99150db69fdSAllain Legacy 				  i);
99250db69fdSAllain Legacy 		pkt_len += pkt_buf->data_len;
99350db69fdSAllain Legacy 		nb_segs--;
99450db69fdSAllain Legacy 		i++;
99550db69fdSAllain Legacy 
99650db69fdSAllain Legacy 	} while (nb_segs && (buf = pkt_buf->next) != NULL);
99750db69fdSAllain Legacy 
99850db69fdSAllain Legacy 	if (nb_segs != 0)
99950db69fdSAllain Legacy 		rte_panic("bad buffer: expected %u segments found %u\n",
100050db69fdSAllain Legacy 			  first_buf->nb_segs, (first_buf->nb_segs - nb_segs));
100150db69fdSAllain Legacy 	if (pkt_len != first_buf->pkt_len)
100250db69fdSAllain Legacy 		rte_panic("bad buffer: expected length %u found %u\n",
100350db69fdSAllain Legacy 			  first_buf->pkt_len, pkt_len);
100450db69fdSAllain Legacy }
100550db69fdSAllain Legacy 
100650db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) \
100750db69fdSAllain Legacy 	__avp_dev_buffer_sanity_check((a), (b))
100850db69fdSAllain Legacy 
100950db69fdSAllain Legacy #else /* RTE_LIBRTE_AVP_DEBUG_BUFFERS */
101050db69fdSAllain Legacy 
101150db69fdSAllain Legacy #define avp_dev_buffer_sanity_check(a, b) do {} while (0)
101250db69fdSAllain Legacy 
101350db69fdSAllain Legacy #endif
101450db69fdSAllain Legacy 
101550db69fdSAllain Legacy /*
101650db69fdSAllain Legacy  * Copy a host buffer chain to a set of mbufs.	This function assumes that
101750db69fdSAllain Legacy  * there exactly the required number of mbufs to copy all source bytes.
101850db69fdSAllain Legacy  */
101950db69fdSAllain Legacy static inline struct rte_mbuf *
102050db69fdSAllain Legacy avp_dev_copy_from_buffers(struct avp_dev *avp,
102150db69fdSAllain Legacy 			  struct rte_avp_desc *buf,
102250db69fdSAllain Legacy 			  struct rte_mbuf **mbufs,
102350db69fdSAllain Legacy 			  unsigned int count)
102450db69fdSAllain Legacy {
102550db69fdSAllain Legacy 	struct rte_mbuf *m_previous = NULL;
102650db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
102750db69fdSAllain Legacy 	unsigned int total_length = 0;
102850db69fdSAllain Legacy 	unsigned int copy_length;
102950db69fdSAllain Legacy 	unsigned int src_offset;
103050db69fdSAllain Legacy 	struct rte_mbuf *m;
103150db69fdSAllain Legacy 	uint16_t ol_flags;
103250db69fdSAllain Legacy 	uint16_t vlan_tci;
103350db69fdSAllain Legacy 	void *pkt_data;
103450db69fdSAllain Legacy 	unsigned int i;
103550db69fdSAllain Legacy 
103650db69fdSAllain Legacy 	avp_dev_buffer_sanity_check(avp, buf);
103750db69fdSAllain Legacy 
103850db69fdSAllain Legacy 	/* setup the first source buffer */
103950db69fdSAllain Legacy 	pkt_buf = avp_dev_translate_buffer(avp, buf);
104050db69fdSAllain Legacy 	pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
104150db69fdSAllain Legacy 	total_length = pkt_buf->pkt_len;
104250db69fdSAllain Legacy 	src_offset = 0;
104350db69fdSAllain Legacy 
104450db69fdSAllain Legacy 	if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) {
104550db69fdSAllain Legacy 		ol_flags = PKT_RX_VLAN_PKT;
104650db69fdSAllain Legacy 		vlan_tci = pkt_buf->vlan_tci;
104750db69fdSAllain Legacy 	} else {
104850db69fdSAllain Legacy 		ol_flags = 0;
104950db69fdSAllain Legacy 		vlan_tci = 0;
105050db69fdSAllain Legacy 	}
105150db69fdSAllain Legacy 
105250db69fdSAllain Legacy 	for (i = 0; (i < count) && (buf != NULL); i++) {
105350db69fdSAllain Legacy 		/* fill each destination buffer */
105450db69fdSAllain Legacy 		m = mbufs[i];
105550db69fdSAllain Legacy 
105650db69fdSAllain Legacy 		if (m_previous != NULL)
105750db69fdSAllain Legacy 			m_previous->next = m;
105850db69fdSAllain Legacy 
105950db69fdSAllain Legacy 		m_previous = m;
106050db69fdSAllain Legacy 
106150db69fdSAllain Legacy 		do {
106250db69fdSAllain Legacy 			/*
106350db69fdSAllain Legacy 			 * Copy as many source buffers as will fit in the
106450db69fdSAllain Legacy 			 * destination buffer.
106550db69fdSAllain Legacy 			 */
106650db69fdSAllain Legacy 			copy_length = RTE_MIN((avp->guest_mbuf_size -
106750db69fdSAllain Legacy 					       rte_pktmbuf_data_len(m)),
106850db69fdSAllain Legacy 					      (pkt_buf->data_len -
106950db69fdSAllain Legacy 					       src_offset));
107050db69fdSAllain Legacy 			rte_memcpy(RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *),
107150db69fdSAllain Legacy 					       rte_pktmbuf_data_len(m)),
107250db69fdSAllain Legacy 				   RTE_PTR_ADD(pkt_data, src_offset),
107350db69fdSAllain Legacy 				   copy_length);
107450db69fdSAllain Legacy 			rte_pktmbuf_data_len(m) += copy_length;
107550db69fdSAllain Legacy 			src_offset += copy_length;
107650db69fdSAllain Legacy 
107750db69fdSAllain Legacy 			if (likely(src_offset == pkt_buf->data_len)) {
107850db69fdSAllain Legacy 				/* need a new source buffer */
107950db69fdSAllain Legacy 				buf = pkt_buf->next;
108050db69fdSAllain Legacy 				if (buf != NULL) {
108150db69fdSAllain Legacy 					pkt_buf = avp_dev_translate_buffer(
108250db69fdSAllain Legacy 						avp, buf);
108350db69fdSAllain Legacy 					pkt_data = avp_dev_translate_buffer(
108450db69fdSAllain Legacy 						avp, pkt_buf->data);
108550db69fdSAllain Legacy 					src_offset = 0;
108650db69fdSAllain Legacy 				}
108750db69fdSAllain Legacy 			}
108850db69fdSAllain Legacy 
108950db69fdSAllain Legacy 			if (unlikely(rte_pktmbuf_data_len(m) ==
109050db69fdSAllain Legacy 				     avp->guest_mbuf_size)) {
109150db69fdSAllain Legacy 				/* need a new destination mbuf */
109250db69fdSAllain Legacy 				break;
109350db69fdSAllain Legacy 			}
109450db69fdSAllain Legacy 
109550db69fdSAllain Legacy 		} while (buf != NULL);
109650db69fdSAllain Legacy 	}
109750db69fdSAllain Legacy 
109850db69fdSAllain Legacy 	m = mbufs[0];
109950db69fdSAllain Legacy 	m->ol_flags = ol_flags;
110050db69fdSAllain Legacy 	m->nb_segs = count;
110150db69fdSAllain Legacy 	rte_pktmbuf_pkt_len(m) = total_length;
110250db69fdSAllain Legacy 	m->vlan_tci = vlan_tci;
110350db69fdSAllain Legacy 
110450db69fdSAllain Legacy 	__rte_mbuf_sanity_check(m, 1);
110550db69fdSAllain Legacy 
110650db69fdSAllain Legacy 	return m;
110750db69fdSAllain Legacy }
110850db69fdSAllain Legacy 
110950db69fdSAllain Legacy static uint16_t
111050db69fdSAllain Legacy avp_recv_scattered_pkts(void *rx_queue,
111150db69fdSAllain Legacy 			struct rte_mbuf **rx_pkts,
111250db69fdSAllain Legacy 			uint16_t nb_pkts)
111350db69fdSAllain Legacy {
111450db69fdSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
111550db69fdSAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST];
111650db69fdSAllain Legacy 	struct rte_mbuf *mbufs[RTE_AVP_MAX_MBUF_SEGMENTS];
111750db69fdSAllain Legacy 	struct avp_dev *avp = rxq->avp;
111850db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
111950db69fdSAllain Legacy 	struct rte_avp_fifo *free_q;
112050db69fdSAllain Legacy 	struct rte_avp_fifo *rx_q;
112150db69fdSAllain Legacy 	struct rte_avp_desc *buf;
112250db69fdSAllain Legacy 	unsigned int count, avail, n;
112350db69fdSAllain Legacy 	unsigned int guest_mbuf_size;
112450db69fdSAllain Legacy 	struct rte_mbuf *m;
112550db69fdSAllain Legacy 	unsigned int required;
112650db69fdSAllain Legacy 	unsigned int buf_len;
112750db69fdSAllain Legacy 	unsigned int port_id;
112850db69fdSAllain Legacy 	unsigned int i;
112950db69fdSAllain Legacy 
113050db69fdSAllain Legacy 	guest_mbuf_size = avp->guest_mbuf_size;
113150db69fdSAllain Legacy 	port_id = avp->port_id;
113250db69fdSAllain Legacy 	rx_q = avp->rx_q[rxq->queue_id];
113350db69fdSAllain Legacy 	free_q = avp->free_q[rxq->queue_id];
113450db69fdSAllain Legacy 
113550db69fdSAllain Legacy 	/* setup next queue to service */
113650db69fdSAllain Legacy 	rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ?
113750db69fdSAllain Legacy 		(rxq->queue_id + 1) : rxq->queue_base;
113850db69fdSAllain Legacy 
113950db69fdSAllain Legacy 	/* determine how many slots are available in the free queue */
114050db69fdSAllain Legacy 	count = avp_fifo_free_count(free_q);
114150db69fdSAllain Legacy 
114250db69fdSAllain Legacy 	/* determine how many packets are available in the rx queue */
114350db69fdSAllain Legacy 	avail = avp_fifo_count(rx_q);
114450db69fdSAllain Legacy 
114550db69fdSAllain Legacy 	/* determine how many packets can be received */
114650db69fdSAllain Legacy 	count = RTE_MIN(count, avail);
114750db69fdSAllain Legacy 	count = RTE_MIN(count, nb_pkts);
114850db69fdSAllain Legacy 	count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST);
114950db69fdSAllain Legacy 
115050db69fdSAllain Legacy 	if (unlikely(count == 0)) {
115150db69fdSAllain Legacy 		/* no free buffers, or no buffers on the rx queue */
115250db69fdSAllain Legacy 		return 0;
115350db69fdSAllain Legacy 	}
115450db69fdSAllain Legacy 
115550db69fdSAllain Legacy 	/* retrieve pending packets */
115650db69fdSAllain Legacy 	n = avp_fifo_get(rx_q, (void **)&avp_bufs, count);
115750db69fdSAllain Legacy 	PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n",
115850db69fdSAllain Legacy 		   count, rx_q);
115950db69fdSAllain Legacy 
116050db69fdSAllain Legacy 	count = 0;
116150db69fdSAllain Legacy 	for (i = 0; i < n; i++) {
116250db69fdSAllain Legacy 		/* prefetch next entry while processing current one */
116350db69fdSAllain Legacy 		if (i + 1 < n) {
116450db69fdSAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
116550db69fdSAllain Legacy 							   avp_bufs[i + 1]);
116650db69fdSAllain Legacy 			rte_prefetch0(pkt_buf);
116750db69fdSAllain Legacy 		}
116850db69fdSAllain Legacy 		buf = avp_bufs[i];
116950db69fdSAllain Legacy 
117050db69fdSAllain Legacy 		/* Peek into the first buffer to determine the total length */
117150db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
117250db69fdSAllain Legacy 		buf_len = pkt_buf->pkt_len;
117350db69fdSAllain Legacy 
117450db69fdSAllain Legacy 		/* Allocate enough mbufs to receive the entire packet */
117550db69fdSAllain Legacy 		required = (buf_len + guest_mbuf_size - 1) / guest_mbuf_size;
117650db69fdSAllain Legacy 		if (rte_pktmbuf_alloc_bulk(avp->pool, mbufs, required)) {
117750db69fdSAllain Legacy 			rxq->dev_data->rx_mbuf_alloc_failed++;
117850db69fdSAllain Legacy 			continue;
117950db69fdSAllain Legacy 		}
118050db69fdSAllain Legacy 
118150db69fdSAllain Legacy 		/* Copy the data from the buffers to our mbufs */
118250db69fdSAllain Legacy 		m = avp_dev_copy_from_buffers(avp, buf, mbufs, required);
118350db69fdSAllain Legacy 
118450db69fdSAllain Legacy 		/* finalize mbuf */
118550db69fdSAllain Legacy 		m->port = port_id;
118650db69fdSAllain Legacy 
118750db69fdSAllain Legacy 		if (_avp_mac_filter(avp, m) != 0) {
118850db69fdSAllain Legacy 			/* silently discard packets not destined to our MAC */
118950db69fdSAllain Legacy 			rte_pktmbuf_free(m);
119050db69fdSAllain Legacy 			continue;
119150db69fdSAllain Legacy 		}
119250db69fdSAllain Legacy 
119350db69fdSAllain Legacy 		/* return new mbuf to caller */
119450db69fdSAllain Legacy 		rx_pkts[count++] = m;
119550db69fdSAllain Legacy 		rxq->bytes += buf_len;
119650db69fdSAllain Legacy 	}
119750db69fdSAllain Legacy 
119850db69fdSAllain Legacy 	rxq->packets += count;
119950db69fdSAllain Legacy 
120050db69fdSAllain Legacy 	/* return the buffers to the free queue */
120150db69fdSAllain Legacy 	avp_fifo_put(free_q, (void **)&avp_bufs[0], n);
120250db69fdSAllain Legacy 
120350db69fdSAllain Legacy 	return count;
120450db69fdSAllain Legacy }
120550db69fdSAllain Legacy 
120650db69fdSAllain Legacy 
120750db69fdSAllain Legacy static uint16_t
120850db69fdSAllain Legacy avp_recv_pkts(void *rx_queue,
120950db69fdSAllain Legacy 	      struct rte_mbuf **rx_pkts,
121050db69fdSAllain Legacy 	      uint16_t nb_pkts)
121150db69fdSAllain Legacy {
121250db69fdSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
121350db69fdSAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_RX_BURST];
121450db69fdSAllain Legacy 	struct avp_dev *avp = rxq->avp;
121550db69fdSAllain Legacy 	struct rte_avp_desc *pkt_buf;
121650db69fdSAllain Legacy 	struct rte_avp_fifo *free_q;
121750db69fdSAllain Legacy 	struct rte_avp_fifo *rx_q;
121850db69fdSAllain Legacy 	unsigned int count, avail, n;
121950db69fdSAllain Legacy 	unsigned int pkt_len;
122050db69fdSAllain Legacy 	struct rte_mbuf *m;
122150db69fdSAllain Legacy 	char *pkt_data;
122250db69fdSAllain Legacy 	unsigned int i;
122350db69fdSAllain Legacy 
122450db69fdSAllain Legacy 	rx_q = avp->rx_q[rxq->queue_id];
122550db69fdSAllain Legacy 	free_q = avp->free_q[rxq->queue_id];
122650db69fdSAllain Legacy 
122750db69fdSAllain Legacy 	/* setup next queue to service */
122850db69fdSAllain Legacy 	rxq->queue_id = (rxq->queue_id < rxq->queue_limit) ?
122950db69fdSAllain Legacy 		(rxq->queue_id + 1) : rxq->queue_base;
123050db69fdSAllain Legacy 
123150db69fdSAllain Legacy 	/* determine how many slots are available in the free queue */
123250db69fdSAllain Legacy 	count = avp_fifo_free_count(free_q);
123350db69fdSAllain Legacy 
123450db69fdSAllain Legacy 	/* determine how many packets are available in the rx queue */
123550db69fdSAllain Legacy 	avail = avp_fifo_count(rx_q);
123650db69fdSAllain Legacy 
123750db69fdSAllain Legacy 	/* determine how many packets can be received */
123850db69fdSAllain Legacy 	count = RTE_MIN(count, avail);
123950db69fdSAllain Legacy 	count = RTE_MIN(count, nb_pkts);
124050db69fdSAllain Legacy 	count = RTE_MIN(count, (unsigned int)AVP_MAX_RX_BURST);
124150db69fdSAllain Legacy 
124250db69fdSAllain Legacy 	if (unlikely(count == 0)) {
124350db69fdSAllain Legacy 		/* no free buffers, or no buffers on the rx queue */
124450db69fdSAllain Legacy 		return 0;
124550db69fdSAllain Legacy 	}
124650db69fdSAllain Legacy 
124750db69fdSAllain Legacy 	/* retrieve pending packets */
124850db69fdSAllain Legacy 	n = avp_fifo_get(rx_q, (void **)&avp_bufs, count);
124950db69fdSAllain Legacy 	PMD_RX_LOG(DEBUG, "Receiving %u packets from Rx queue at %p\n",
125050db69fdSAllain Legacy 		   count, rx_q);
125150db69fdSAllain Legacy 
125250db69fdSAllain Legacy 	count = 0;
125350db69fdSAllain Legacy 	for (i = 0; i < n; i++) {
125450db69fdSAllain Legacy 		/* prefetch next entry while processing current one */
125550db69fdSAllain Legacy 		if (i < n - 1) {
125650db69fdSAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
125750db69fdSAllain Legacy 							   avp_bufs[i + 1]);
125850db69fdSAllain Legacy 			rte_prefetch0(pkt_buf);
125950db69fdSAllain Legacy 		}
126050db69fdSAllain Legacy 
126150db69fdSAllain Legacy 		/* Adjust host pointers for guest addressing */
126250db69fdSAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]);
126350db69fdSAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
126450db69fdSAllain Legacy 		pkt_len = pkt_buf->pkt_len;
126550db69fdSAllain Legacy 
126650db69fdSAllain Legacy 		if (unlikely((pkt_len > avp->guest_mbuf_size) ||
126750db69fdSAllain Legacy 			     (pkt_buf->nb_segs > 1))) {
126850db69fdSAllain Legacy 			/*
126950db69fdSAllain Legacy 			 * application should be using the scattered receive
127050db69fdSAllain Legacy 			 * function
127150db69fdSAllain Legacy 			 */
127250db69fdSAllain Legacy 			rxq->errors++;
127350db69fdSAllain Legacy 			continue;
127450db69fdSAllain Legacy 		}
127550db69fdSAllain Legacy 
127650db69fdSAllain Legacy 		/* process each packet to be transmitted */
127750db69fdSAllain Legacy 		m = rte_pktmbuf_alloc(avp->pool);
127850db69fdSAllain Legacy 		if (unlikely(m == NULL)) {
127950db69fdSAllain Legacy 			rxq->dev_data->rx_mbuf_alloc_failed++;
128050db69fdSAllain Legacy 			continue;
128150db69fdSAllain Legacy 		}
128250db69fdSAllain Legacy 
128350db69fdSAllain Legacy 		/* copy data out of the host buffer to our buffer */
128450db69fdSAllain Legacy 		m->data_off = RTE_PKTMBUF_HEADROOM;
128550db69fdSAllain Legacy 		rte_memcpy(rte_pktmbuf_mtod(m, void *), pkt_data, pkt_len);
128650db69fdSAllain Legacy 
128750db69fdSAllain Legacy 		/* initialize the local mbuf */
128850db69fdSAllain Legacy 		rte_pktmbuf_data_len(m) = pkt_len;
128950db69fdSAllain Legacy 		rte_pktmbuf_pkt_len(m) = pkt_len;
129050db69fdSAllain Legacy 		m->port = avp->port_id;
129150db69fdSAllain Legacy 
129250db69fdSAllain Legacy 		if (pkt_buf->ol_flags & RTE_AVP_RX_VLAN_PKT) {
129350db69fdSAllain Legacy 			m->ol_flags = PKT_RX_VLAN_PKT;
129450db69fdSAllain Legacy 			m->vlan_tci = pkt_buf->vlan_tci;
129550db69fdSAllain Legacy 		}
129650db69fdSAllain Legacy 
129750db69fdSAllain Legacy 		if (_avp_mac_filter(avp, m) != 0) {
129850db69fdSAllain Legacy 			/* silently discard packets not destined to our MAC */
129950db69fdSAllain Legacy 			rte_pktmbuf_free(m);
130050db69fdSAllain Legacy 			continue;
130150db69fdSAllain Legacy 		}
130250db69fdSAllain Legacy 
130350db69fdSAllain Legacy 		/* return new mbuf to caller */
130450db69fdSAllain Legacy 		rx_pkts[count++] = m;
130550db69fdSAllain Legacy 		rxq->bytes += pkt_len;
130650db69fdSAllain Legacy 	}
130750db69fdSAllain Legacy 
130850db69fdSAllain Legacy 	rxq->packets += count;
130950db69fdSAllain Legacy 
131050db69fdSAllain Legacy 	/* return the buffers to the free queue */
131150db69fdSAllain Legacy 	avp_fifo_put(free_q, (void **)&avp_bufs[0], n);
131250db69fdSAllain Legacy 
131350db69fdSAllain Legacy 	return count;
131450db69fdSAllain Legacy }
131550db69fdSAllain Legacy 
1316295abce2SAllain Legacy /*
1317295abce2SAllain Legacy  * Copy a chained mbuf to a set of host buffers.  This function assumes that
1318295abce2SAllain Legacy  * there are sufficient destination buffers to contain the entire source
1319295abce2SAllain Legacy  * packet.
1320295abce2SAllain Legacy  */
1321295abce2SAllain Legacy static inline uint16_t
1322295abce2SAllain Legacy avp_dev_copy_to_buffers(struct avp_dev *avp,
1323295abce2SAllain Legacy 			struct rte_mbuf *mbuf,
1324295abce2SAllain Legacy 			struct rte_avp_desc **buffers,
1325295abce2SAllain Legacy 			unsigned int count)
1326295abce2SAllain Legacy {
1327295abce2SAllain Legacy 	struct rte_avp_desc *previous_buf = NULL;
1328295abce2SAllain Legacy 	struct rte_avp_desc *first_buf = NULL;
1329295abce2SAllain Legacy 	struct rte_avp_desc *pkt_buf;
1330295abce2SAllain Legacy 	struct rte_avp_desc *buf;
1331295abce2SAllain Legacy 	size_t total_length;
1332295abce2SAllain Legacy 	struct rte_mbuf *m;
1333295abce2SAllain Legacy 	size_t copy_length;
1334295abce2SAllain Legacy 	size_t src_offset;
1335295abce2SAllain Legacy 	char *pkt_data;
1336295abce2SAllain Legacy 	unsigned int i;
1337295abce2SAllain Legacy 
1338295abce2SAllain Legacy 	__rte_mbuf_sanity_check(mbuf, 1);
1339295abce2SAllain Legacy 
1340295abce2SAllain Legacy 	m = mbuf;
1341295abce2SAllain Legacy 	src_offset = 0;
1342295abce2SAllain Legacy 	total_length = rte_pktmbuf_pkt_len(m);
1343295abce2SAllain Legacy 	for (i = 0; (i < count) && (m != NULL); i++) {
1344295abce2SAllain Legacy 		/* fill each destination buffer */
1345295abce2SAllain Legacy 		buf = buffers[i];
1346295abce2SAllain Legacy 
1347295abce2SAllain Legacy 		if (i < count - 1) {
1348295abce2SAllain Legacy 			/* prefetch next entry while processing this one */
1349295abce2SAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp, buffers[i + 1]);
1350295abce2SAllain Legacy 			rte_prefetch0(pkt_buf);
1351295abce2SAllain Legacy 		}
1352295abce2SAllain Legacy 
1353295abce2SAllain Legacy 		/* Adjust pointers for guest addressing */
1354295abce2SAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, buf);
1355295abce2SAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
1356295abce2SAllain Legacy 
1357295abce2SAllain Legacy 		/* setup the buffer chain */
1358295abce2SAllain Legacy 		if (previous_buf != NULL)
1359295abce2SAllain Legacy 			previous_buf->next = buf;
1360295abce2SAllain Legacy 		else
1361295abce2SAllain Legacy 			first_buf = pkt_buf;
1362295abce2SAllain Legacy 
1363295abce2SAllain Legacy 		previous_buf = pkt_buf;
1364295abce2SAllain Legacy 
1365295abce2SAllain Legacy 		do {
1366295abce2SAllain Legacy 			/*
1367295abce2SAllain Legacy 			 * copy as many source mbuf segments as will fit in the
1368295abce2SAllain Legacy 			 * destination buffer.
1369295abce2SAllain Legacy 			 */
1370295abce2SAllain Legacy 			copy_length = RTE_MIN((avp->host_mbuf_size -
1371295abce2SAllain Legacy 					       pkt_buf->data_len),
1372295abce2SAllain Legacy 					      (rte_pktmbuf_data_len(m) -
1373295abce2SAllain Legacy 					       src_offset));
1374295abce2SAllain Legacy 			rte_memcpy(RTE_PTR_ADD(pkt_data, pkt_buf->data_len),
1375295abce2SAllain Legacy 				   RTE_PTR_ADD(rte_pktmbuf_mtod(m, void *),
1376295abce2SAllain Legacy 					       src_offset),
1377295abce2SAllain Legacy 				   copy_length);
1378295abce2SAllain Legacy 			pkt_buf->data_len += copy_length;
1379295abce2SAllain Legacy 			src_offset += copy_length;
1380295abce2SAllain Legacy 
1381295abce2SAllain Legacy 			if (likely(src_offset == rte_pktmbuf_data_len(m))) {
1382295abce2SAllain Legacy 				/* need a new source buffer */
1383295abce2SAllain Legacy 				m = m->next;
1384295abce2SAllain Legacy 				src_offset = 0;
1385295abce2SAllain Legacy 			}
1386295abce2SAllain Legacy 
1387295abce2SAllain Legacy 			if (unlikely(pkt_buf->data_len ==
1388295abce2SAllain Legacy 				     avp->host_mbuf_size)) {
1389295abce2SAllain Legacy 				/* need a new destination buffer */
1390295abce2SAllain Legacy 				break;
1391295abce2SAllain Legacy 			}
1392295abce2SAllain Legacy 
1393295abce2SAllain Legacy 		} while (m != NULL);
1394295abce2SAllain Legacy 	}
1395295abce2SAllain Legacy 
1396295abce2SAllain Legacy 	first_buf->nb_segs = count;
1397295abce2SAllain Legacy 	first_buf->pkt_len = total_length;
1398295abce2SAllain Legacy 
1399295abce2SAllain Legacy 	if (mbuf->ol_flags & PKT_TX_VLAN_PKT) {
1400295abce2SAllain Legacy 		first_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT;
1401295abce2SAllain Legacy 		first_buf->vlan_tci = mbuf->vlan_tci;
1402295abce2SAllain Legacy 	}
1403295abce2SAllain Legacy 
1404295abce2SAllain Legacy 	avp_dev_buffer_sanity_check(avp, buffers[0]);
1405295abce2SAllain Legacy 
1406295abce2SAllain Legacy 	return total_length;
1407295abce2SAllain Legacy }
1408295abce2SAllain Legacy 
1409295abce2SAllain Legacy 
1410295abce2SAllain Legacy static uint16_t
1411295abce2SAllain Legacy avp_xmit_scattered_pkts(void *tx_queue,
1412295abce2SAllain Legacy 			struct rte_mbuf **tx_pkts,
1413295abce2SAllain Legacy 			uint16_t nb_pkts)
1414295abce2SAllain Legacy {
1415295abce2SAllain Legacy 	struct rte_avp_desc *avp_bufs[(AVP_MAX_TX_BURST *
1416295abce2SAllain Legacy 				       RTE_AVP_MAX_MBUF_SEGMENTS)];
1417295abce2SAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1418295abce2SAllain Legacy 	struct rte_avp_desc *tx_bufs[AVP_MAX_TX_BURST];
1419295abce2SAllain Legacy 	struct avp_dev *avp = txq->avp;
1420295abce2SAllain Legacy 	struct rte_avp_fifo *alloc_q;
1421295abce2SAllain Legacy 	struct rte_avp_fifo *tx_q;
1422295abce2SAllain Legacy 	unsigned int count, avail, n;
1423295abce2SAllain Legacy 	unsigned int orig_nb_pkts;
1424295abce2SAllain Legacy 	struct rte_mbuf *m;
1425295abce2SAllain Legacy 	unsigned int required;
1426295abce2SAllain Legacy 	unsigned int segments;
1427295abce2SAllain Legacy 	unsigned int tx_bytes;
1428295abce2SAllain Legacy 	unsigned int i;
1429295abce2SAllain Legacy 
1430295abce2SAllain Legacy 	orig_nb_pkts = nb_pkts;
1431295abce2SAllain Legacy 	tx_q = avp->tx_q[txq->queue_id];
1432295abce2SAllain Legacy 	alloc_q = avp->alloc_q[txq->queue_id];
1433295abce2SAllain Legacy 
1434295abce2SAllain Legacy 	/* limit the number of transmitted packets to the max burst size */
1435295abce2SAllain Legacy 	if (unlikely(nb_pkts > AVP_MAX_TX_BURST))
1436295abce2SAllain Legacy 		nb_pkts = AVP_MAX_TX_BURST;
1437295abce2SAllain Legacy 
1438295abce2SAllain Legacy 	/* determine how many buffers are available to copy into */
1439295abce2SAllain Legacy 	avail = avp_fifo_count(alloc_q);
1440295abce2SAllain Legacy 	if (unlikely(avail > (AVP_MAX_TX_BURST *
1441295abce2SAllain Legacy 			      RTE_AVP_MAX_MBUF_SEGMENTS)))
1442295abce2SAllain Legacy 		avail = AVP_MAX_TX_BURST * RTE_AVP_MAX_MBUF_SEGMENTS;
1443295abce2SAllain Legacy 
1444295abce2SAllain Legacy 	/* determine how many slots are available in the transmit queue */
1445295abce2SAllain Legacy 	count = avp_fifo_free_count(tx_q);
1446295abce2SAllain Legacy 
1447295abce2SAllain Legacy 	/* determine how many packets can be sent */
1448295abce2SAllain Legacy 	nb_pkts = RTE_MIN(count, nb_pkts);
1449295abce2SAllain Legacy 
1450295abce2SAllain Legacy 	/* determine how many packets will fit in the available buffers */
1451295abce2SAllain Legacy 	count = 0;
1452295abce2SAllain Legacy 	segments = 0;
1453295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++) {
1454295abce2SAllain Legacy 		m = tx_pkts[i];
1455295abce2SAllain Legacy 		if (likely(i < (unsigned int)nb_pkts - 1)) {
1456295abce2SAllain Legacy 			/* prefetch next entry while processing this one */
1457295abce2SAllain Legacy 			rte_prefetch0(tx_pkts[i + 1]);
1458295abce2SAllain Legacy 		}
1459295abce2SAllain Legacy 		required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) /
1460295abce2SAllain Legacy 			avp->host_mbuf_size;
1461295abce2SAllain Legacy 
1462295abce2SAllain Legacy 		if (unlikely((required == 0) ||
1463295abce2SAllain Legacy 			     (required > RTE_AVP_MAX_MBUF_SEGMENTS)))
1464295abce2SAllain Legacy 			break;
1465295abce2SAllain Legacy 		else if (unlikely(required + segments > avail))
1466295abce2SAllain Legacy 			break;
1467295abce2SAllain Legacy 		segments += required;
1468295abce2SAllain Legacy 		count++;
1469295abce2SAllain Legacy 	}
1470295abce2SAllain Legacy 	nb_pkts = count;
1471295abce2SAllain Legacy 
1472295abce2SAllain Legacy 	if (unlikely(nb_pkts == 0)) {
1473295abce2SAllain Legacy 		/* no available buffers, or no space on the tx queue */
1474295abce2SAllain Legacy 		txq->errors += orig_nb_pkts;
1475295abce2SAllain Legacy 		return 0;
1476295abce2SAllain Legacy 	}
1477295abce2SAllain Legacy 
1478295abce2SAllain Legacy 	PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n",
1479295abce2SAllain Legacy 		   nb_pkts, tx_q);
1480295abce2SAllain Legacy 
1481295abce2SAllain Legacy 	/* retrieve sufficient send buffers */
1482295abce2SAllain Legacy 	n = avp_fifo_get(alloc_q, (void **)&avp_bufs, segments);
1483295abce2SAllain Legacy 	if (unlikely(n != segments)) {
1484295abce2SAllain Legacy 		PMD_TX_LOG(DEBUG, "Failed to allocate buffers "
1485295abce2SAllain Legacy 			   "n=%u, segments=%u, orig=%u\n",
1486295abce2SAllain Legacy 			   n, segments, orig_nb_pkts);
1487295abce2SAllain Legacy 		txq->errors += orig_nb_pkts;
1488295abce2SAllain Legacy 		return 0;
1489295abce2SAllain Legacy 	}
1490295abce2SAllain Legacy 
1491295abce2SAllain Legacy 	tx_bytes = 0;
1492295abce2SAllain Legacy 	count = 0;
1493295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++) {
1494295abce2SAllain Legacy 		/* process each packet to be transmitted */
1495295abce2SAllain Legacy 		m = tx_pkts[i];
1496295abce2SAllain Legacy 
1497295abce2SAllain Legacy 		/* determine how many buffers are required for this packet */
1498295abce2SAllain Legacy 		required = (rte_pktmbuf_pkt_len(m) + avp->host_mbuf_size - 1) /
1499295abce2SAllain Legacy 			avp->host_mbuf_size;
1500295abce2SAllain Legacy 
1501295abce2SAllain Legacy 		tx_bytes += avp_dev_copy_to_buffers(avp, m,
1502295abce2SAllain Legacy 						    &avp_bufs[count], required);
1503295abce2SAllain Legacy 		tx_bufs[i] = avp_bufs[count];
1504295abce2SAllain Legacy 		count += required;
1505295abce2SAllain Legacy 
1506295abce2SAllain Legacy 		/* free the original mbuf */
1507295abce2SAllain Legacy 		rte_pktmbuf_free(m);
1508295abce2SAllain Legacy 	}
1509295abce2SAllain Legacy 
1510295abce2SAllain Legacy 	txq->packets += nb_pkts;
1511295abce2SAllain Legacy 	txq->bytes += tx_bytes;
1512295abce2SAllain Legacy 
1513295abce2SAllain Legacy #ifdef RTE_LIBRTE_AVP_DEBUG_BUFFERS
1514295abce2SAllain Legacy 	for (i = 0; i < nb_pkts; i++)
1515295abce2SAllain Legacy 		avp_dev_buffer_sanity_check(avp, tx_bufs[i]);
1516295abce2SAllain Legacy #endif
1517295abce2SAllain Legacy 
1518295abce2SAllain Legacy 	/* send the packets */
1519295abce2SAllain Legacy 	n = avp_fifo_put(tx_q, (void **)&tx_bufs[0], nb_pkts);
1520295abce2SAllain Legacy 	if (unlikely(n != orig_nb_pkts))
1521295abce2SAllain Legacy 		txq->errors += (orig_nb_pkts - n);
1522295abce2SAllain Legacy 
1523295abce2SAllain Legacy 	return n;
1524295abce2SAllain Legacy }
1525295abce2SAllain Legacy 
1526295abce2SAllain Legacy 
1527295abce2SAllain Legacy static uint16_t
1528295abce2SAllain Legacy avp_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
1529295abce2SAllain Legacy {
1530295abce2SAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1531295abce2SAllain Legacy 	struct rte_avp_desc *avp_bufs[AVP_MAX_TX_BURST];
1532295abce2SAllain Legacy 	struct avp_dev *avp = txq->avp;
1533295abce2SAllain Legacy 	struct rte_avp_desc *pkt_buf;
1534295abce2SAllain Legacy 	struct rte_avp_fifo *alloc_q;
1535295abce2SAllain Legacy 	struct rte_avp_fifo *tx_q;
1536295abce2SAllain Legacy 	unsigned int count, avail, n;
1537295abce2SAllain Legacy 	struct rte_mbuf *m;
1538295abce2SAllain Legacy 	unsigned int pkt_len;
1539295abce2SAllain Legacy 	unsigned int tx_bytes;
1540295abce2SAllain Legacy 	char *pkt_data;
1541295abce2SAllain Legacy 	unsigned int i;
1542295abce2SAllain Legacy 
1543295abce2SAllain Legacy 	tx_q = avp->tx_q[txq->queue_id];
1544295abce2SAllain Legacy 	alloc_q = avp->alloc_q[txq->queue_id];
1545295abce2SAllain Legacy 
1546295abce2SAllain Legacy 	/* limit the number of transmitted packets to the max burst size */
1547295abce2SAllain Legacy 	if (unlikely(nb_pkts > AVP_MAX_TX_BURST))
1548295abce2SAllain Legacy 		nb_pkts = AVP_MAX_TX_BURST;
1549295abce2SAllain Legacy 
1550295abce2SAllain Legacy 	/* determine how many buffers are available to copy into */
1551295abce2SAllain Legacy 	avail = avp_fifo_count(alloc_q);
1552295abce2SAllain Legacy 
1553295abce2SAllain Legacy 	/* determine how many slots are available in the transmit queue */
1554295abce2SAllain Legacy 	count = avp_fifo_free_count(tx_q);
1555295abce2SAllain Legacy 
1556295abce2SAllain Legacy 	/* determine how many packets can be sent */
1557295abce2SAllain Legacy 	count = RTE_MIN(count, avail);
1558295abce2SAllain Legacy 	count = RTE_MIN(count, nb_pkts);
1559295abce2SAllain Legacy 
1560295abce2SAllain Legacy 	if (unlikely(count == 0)) {
1561295abce2SAllain Legacy 		/* no available buffers, or no space on the tx queue */
1562295abce2SAllain Legacy 		txq->errors += nb_pkts;
1563295abce2SAllain Legacy 		return 0;
1564295abce2SAllain Legacy 	}
1565295abce2SAllain Legacy 
1566295abce2SAllain Legacy 	PMD_TX_LOG(DEBUG, "Sending %u packets on Tx queue at %p\n",
1567295abce2SAllain Legacy 		   count, tx_q);
1568295abce2SAllain Legacy 
1569295abce2SAllain Legacy 	/* retrieve sufficient send buffers */
1570295abce2SAllain Legacy 	n = avp_fifo_get(alloc_q, (void **)&avp_bufs, count);
1571295abce2SAllain Legacy 	if (unlikely(n != count)) {
1572295abce2SAllain Legacy 		txq->errors++;
1573295abce2SAllain Legacy 		return 0;
1574295abce2SAllain Legacy 	}
1575295abce2SAllain Legacy 
1576295abce2SAllain Legacy 	tx_bytes = 0;
1577295abce2SAllain Legacy 	for (i = 0; i < count; i++) {
1578295abce2SAllain Legacy 		/* prefetch next entry while processing the current one */
1579295abce2SAllain Legacy 		if (i < count - 1) {
1580295abce2SAllain Legacy 			pkt_buf = avp_dev_translate_buffer(avp,
1581295abce2SAllain Legacy 							   avp_bufs[i + 1]);
1582295abce2SAllain Legacy 			rte_prefetch0(pkt_buf);
1583295abce2SAllain Legacy 		}
1584295abce2SAllain Legacy 
1585295abce2SAllain Legacy 		/* process each packet to be transmitted */
1586295abce2SAllain Legacy 		m = tx_pkts[i];
1587295abce2SAllain Legacy 
1588295abce2SAllain Legacy 		/* Adjust pointers for guest addressing */
1589295abce2SAllain Legacy 		pkt_buf = avp_dev_translate_buffer(avp, avp_bufs[i]);
1590295abce2SAllain Legacy 		pkt_data = avp_dev_translate_buffer(avp, pkt_buf->data);
1591295abce2SAllain Legacy 		pkt_len = rte_pktmbuf_pkt_len(m);
1592295abce2SAllain Legacy 
1593295abce2SAllain Legacy 		if (unlikely((pkt_len > avp->guest_mbuf_size) ||
1594295abce2SAllain Legacy 					 (pkt_len > avp->host_mbuf_size))) {
1595295abce2SAllain Legacy 			/*
1596295abce2SAllain Legacy 			 * application should be using the scattered transmit
1597295abce2SAllain Legacy 			 * function; send it truncated to avoid the performance
1598295abce2SAllain Legacy 			 * hit of having to manage returning the already
1599295abce2SAllain Legacy 			 * allocated buffer to the free list.  This should not
1600295abce2SAllain Legacy 			 * happen since the application should have set the
1601295abce2SAllain Legacy 			 * max_rx_pkt_len based on its MTU and it should be
1602295abce2SAllain Legacy 			 * policing its own packet sizes.
1603295abce2SAllain Legacy 			 */
1604295abce2SAllain Legacy 			txq->errors++;
1605295abce2SAllain Legacy 			pkt_len = RTE_MIN(avp->guest_mbuf_size,
1606295abce2SAllain Legacy 					  avp->host_mbuf_size);
1607295abce2SAllain Legacy 		}
1608295abce2SAllain Legacy 
1609295abce2SAllain Legacy 		/* copy data out of our mbuf and into the AVP buffer */
1610295abce2SAllain Legacy 		rte_memcpy(pkt_data, rte_pktmbuf_mtod(m, void *), pkt_len);
1611295abce2SAllain Legacy 		pkt_buf->pkt_len = pkt_len;
1612295abce2SAllain Legacy 		pkt_buf->data_len = pkt_len;
1613295abce2SAllain Legacy 		pkt_buf->nb_segs = 1;
1614295abce2SAllain Legacy 		pkt_buf->next = NULL;
1615295abce2SAllain Legacy 
1616295abce2SAllain Legacy 		if (m->ol_flags & PKT_TX_VLAN_PKT) {
1617295abce2SAllain Legacy 			pkt_buf->ol_flags |= RTE_AVP_TX_VLAN_PKT;
1618295abce2SAllain Legacy 			pkt_buf->vlan_tci = m->vlan_tci;
1619295abce2SAllain Legacy 		}
1620295abce2SAllain Legacy 
1621295abce2SAllain Legacy 		tx_bytes += pkt_len;
1622295abce2SAllain Legacy 
1623295abce2SAllain Legacy 		/* free the original mbuf */
1624295abce2SAllain Legacy 		rte_pktmbuf_free(m);
1625295abce2SAllain Legacy 	}
1626295abce2SAllain Legacy 
1627295abce2SAllain Legacy 	txq->packets += count;
1628295abce2SAllain Legacy 	txq->bytes += tx_bytes;
1629295abce2SAllain Legacy 
1630295abce2SAllain Legacy 	/* send the packets */
1631295abce2SAllain Legacy 	n = avp_fifo_put(tx_q, (void **)&avp_bufs[0], count);
1632295abce2SAllain Legacy 
1633295abce2SAllain Legacy 	return n;
1634295abce2SAllain Legacy }
1635295abce2SAllain Legacy 
1636cce4367fSAllain Legacy static void
1637cce4367fSAllain Legacy avp_dev_rx_queue_release(void *rx_queue)
1638cce4367fSAllain Legacy {
1639cce4367fSAllain Legacy 	struct avp_queue *rxq = (struct avp_queue *)rx_queue;
1640cce4367fSAllain Legacy 	struct avp_dev *avp = rxq->avp;
1641cce4367fSAllain Legacy 	struct rte_eth_dev_data *data = avp->dev_data;
1642cce4367fSAllain Legacy 	unsigned int i;
1643cce4367fSAllain Legacy 
1644cce4367fSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
1645cce4367fSAllain Legacy 		if (data->rx_queues[i] == rxq)
1646cce4367fSAllain Legacy 			data->rx_queues[i] = NULL;
1647cce4367fSAllain Legacy 	}
1648cce4367fSAllain Legacy }
1649cce4367fSAllain Legacy 
1650cce4367fSAllain Legacy static void
1651cce4367fSAllain Legacy avp_dev_tx_queue_release(void *tx_queue)
1652cce4367fSAllain Legacy {
1653cce4367fSAllain Legacy 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
1654cce4367fSAllain Legacy 	struct avp_dev *avp = txq->avp;
1655cce4367fSAllain Legacy 	struct rte_eth_dev_data *data = avp->dev_data;
1656cce4367fSAllain Legacy 	unsigned int i;
1657cce4367fSAllain Legacy 
1658cce4367fSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
1659cce4367fSAllain Legacy 		if (data->tx_queues[i] == txq)
1660cce4367fSAllain Legacy 			data->tx_queues[i] = NULL;
1661cce4367fSAllain Legacy 	}
1662cce4367fSAllain Legacy }
1663cce4367fSAllain Legacy 
1664cce4367fSAllain Legacy static int
16651a859223SAllain Legacy avp_dev_configure(struct rte_eth_dev *eth_dev)
16661a859223SAllain Legacy {
16671a859223SAllain Legacy 	struct rte_pci_device *pci_dev = AVP_DEV_TO_PCI(eth_dev);
16681a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
16691a859223SAllain Legacy 	struct rte_avp_device_info *host_info;
16701a859223SAllain Legacy 	struct rte_avp_device_config config;
16711a859223SAllain Legacy 	int mask = 0;
16721a859223SAllain Legacy 	void *addr;
16731a859223SAllain Legacy 	int ret;
16741a859223SAllain Legacy 
16751a859223SAllain Legacy 	addr = pci_dev->mem_resource[RTE_AVP_PCI_DEVICE_BAR].addr;
16761a859223SAllain Legacy 	host_info = (struct rte_avp_device_info *)addr;
16771a859223SAllain Legacy 
16781a859223SAllain Legacy 	/* Setup required number of queues */
16791a859223SAllain Legacy 	_avp_set_queue_counts(eth_dev);
16801a859223SAllain Legacy 
16811a859223SAllain Legacy 	mask = (ETH_VLAN_STRIP_MASK |
16821a859223SAllain Legacy 		ETH_VLAN_FILTER_MASK |
16831a859223SAllain Legacy 		ETH_VLAN_EXTEND_MASK);
16841a859223SAllain Legacy 	avp_vlan_offload_set(eth_dev, mask);
16851a859223SAllain Legacy 
16861a859223SAllain Legacy 	/* update device config */
16871a859223SAllain Legacy 	memset(&config, 0, sizeof(config));
16881a859223SAllain Legacy 	config.device_id = host_info->device_id;
16891a859223SAllain Legacy 	config.driver_type = RTE_AVP_DRIVER_TYPE_DPDK;
16901a859223SAllain Legacy 	config.driver_version = AVP_DPDK_DRIVER_VERSION;
16911a859223SAllain Legacy 	config.features = avp->features;
16921a859223SAllain Legacy 	config.num_tx_queues = avp->num_tx_queues;
16931a859223SAllain Legacy 	config.num_rx_queues = avp->num_rx_queues;
16941a859223SAllain Legacy 
16951a859223SAllain Legacy 	ret = avp_dev_ctrl_set_config(eth_dev, &config);
16961a859223SAllain Legacy 	if (ret < 0) {
16971a859223SAllain Legacy 		PMD_DRV_LOG(ERR, "Config request failed by host, ret=%d\n",
16981a859223SAllain Legacy 			    ret);
16991a859223SAllain Legacy 		goto unlock;
17001a859223SAllain Legacy 	}
17011a859223SAllain Legacy 
17021a859223SAllain Legacy 	avp->flags |= AVP_F_CONFIGURED;
17031a859223SAllain Legacy 	ret = 0;
17041a859223SAllain Legacy 
17051a859223SAllain Legacy unlock:
17061a859223SAllain Legacy 	return ret;
17071a859223SAllain Legacy }
17081a859223SAllain Legacy 
1709*ea37523dSAllain Legacy static int
1710*ea37523dSAllain Legacy avp_dev_start(struct rte_eth_dev *eth_dev)
1711*ea37523dSAllain Legacy {
1712*ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1713*ea37523dSAllain Legacy 	int ret;
1714*ea37523dSAllain Legacy 
1715*ea37523dSAllain Legacy 	/* disable features that we do not support */
1716*ea37523dSAllain Legacy 	eth_dev->data->dev_conf.rxmode.hw_ip_checksum = 0;
1717*ea37523dSAllain Legacy 	eth_dev->data->dev_conf.rxmode.hw_vlan_filter = 0;
1718*ea37523dSAllain Legacy 	eth_dev->data->dev_conf.rxmode.hw_vlan_extend = 0;
1719*ea37523dSAllain Legacy 	eth_dev->data->dev_conf.rxmode.hw_strip_crc = 0;
1720*ea37523dSAllain Legacy 
1721*ea37523dSAllain Legacy 	/* update link state */
1722*ea37523dSAllain Legacy 	ret = avp_dev_ctrl_set_link_state(eth_dev, 1);
1723*ea37523dSAllain Legacy 	if (ret < 0) {
1724*ea37523dSAllain Legacy 		PMD_DRV_LOG(ERR, "Link state change failed by host, ret=%d\n",
1725*ea37523dSAllain Legacy 			    ret);
1726*ea37523dSAllain Legacy 		goto unlock;
1727*ea37523dSAllain Legacy 	}
1728*ea37523dSAllain Legacy 
1729*ea37523dSAllain Legacy 	/* remember current link state */
1730*ea37523dSAllain Legacy 	avp->flags |= AVP_F_LINKUP;
1731*ea37523dSAllain Legacy 
1732*ea37523dSAllain Legacy 	ret = 0;
1733*ea37523dSAllain Legacy 
1734*ea37523dSAllain Legacy unlock:
1735*ea37523dSAllain Legacy 	return ret;
1736*ea37523dSAllain Legacy }
1737*ea37523dSAllain Legacy 
1738*ea37523dSAllain Legacy static void
1739*ea37523dSAllain Legacy avp_dev_stop(struct rte_eth_dev *eth_dev)
1740*ea37523dSAllain Legacy {
1741*ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1742*ea37523dSAllain Legacy 	int ret;
1743*ea37523dSAllain Legacy 
1744*ea37523dSAllain Legacy 	avp->flags &= ~AVP_F_LINKUP;
1745*ea37523dSAllain Legacy 
1746*ea37523dSAllain Legacy 	/* update link state */
1747*ea37523dSAllain Legacy 	ret = avp_dev_ctrl_set_link_state(eth_dev, 0);
1748*ea37523dSAllain Legacy 	if (ret < 0) {
1749*ea37523dSAllain Legacy 		PMD_DRV_LOG(ERR, "Link state change failed by host, ret=%d\n",
1750*ea37523dSAllain Legacy 			    ret);
1751*ea37523dSAllain Legacy 	}
1752*ea37523dSAllain Legacy }
1753*ea37523dSAllain Legacy 
1754*ea37523dSAllain Legacy static void
1755*ea37523dSAllain Legacy avp_dev_close(struct rte_eth_dev *eth_dev)
1756*ea37523dSAllain Legacy {
1757*ea37523dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1758*ea37523dSAllain Legacy 	int ret;
1759*ea37523dSAllain Legacy 
1760*ea37523dSAllain Legacy 	/* remember current link state */
1761*ea37523dSAllain Legacy 	avp->flags &= ~AVP_F_LINKUP;
1762*ea37523dSAllain Legacy 	avp->flags &= ~AVP_F_CONFIGURED;
1763*ea37523dSAllain Legacy 
1764*ea37523dSAllain Legacy 	/* update device state */
1765*ea37523dSAllain Legacy 	ret = avp_dev_ctrl_shutdown(eth_dev);
1766*ea37523dSAllain Legacy 	if (ret < 0) {
1767*ea37523dSAllain Legacy 		PMD_DRV_LOG(ERR, "Device shutdown failed by host, ret=%d\n",
1768*ea37523dSAllain Legacy 			    ret);
1769*ea37523dSAllain Legacy 		/* continue */
1770*ea37523dSAllain Legacy 	}
1771*ea37523dSAllain Legacy }
17721a859223SAllain Legacy 
17731a859223SAllain Legacy static int
17741a859223SAllain Legacy avp_dev_link_update(struct rte_eth_dev *eth_dev,
17751a859223SAllain Legacy 					__rte_unused int wait_to_complete)
17761a859223SAllain Legacy {
17771a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
17781a859223SAllain Legacy 	struct rte_eth_link *link = &eth_dev->data->dev_link;
17791a859223SAllain Legacy 
17801a859223SAllain Legacy 	link->link_speed = ETH_SPEED_NUM_10G;
17811a859223SAllain Legacy 	link->link_duplex = ETH_LINK_FULL_DUPLEX;
17821a859223SAllain Legacy 	link->link_status = !!(avp->flags & AVP_F_LINKUP);
17831a859223SAllain Legacy 
17841a859223SAllain Legacy 	return -1;
17851a859223SAllain Legacy }
17861a859223SAllain Legacy 
17878129545eSAllain Legacy static void
17888129545eSAllain Legacy avp_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
17898129545eSAllain Legacy {
17908129545eSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
17918129545eSAllain Legacy 
17928129545eSAllain Legacy 	if ((avp->flags & AVP_F_PROMISC) == 0) {
17938129545eSAllain Legacy 		avp->flags |= AVP_F_PROMISC;
17948129545eSAllain Legacy 		PMD_DRV_LOG(DEBUG, "Promiscuous mode enabled on %u\n",
17958129545eSAllain Legacy 			    eth_dev->data->port_id);
17968129545eSAllain Legacy 	}
17978129545eSAllain Legacy }
17988129545eSAllain Legacy 
17998129545eSAllain Legacy static void
18008129545eSAllain Legacy avp_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
18018129545eSAllain Legacy {
18028129545eSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
18038129545eSAllain Legacy 
18048129545eSAllain Legacy 	if ((avp->flags & AVP_F_PROMISC) != 0) {
18058129545eSAllain Legacy 		avp->flags &= ~AVP_F_PROMISC;
18068129545eSAllain Legacy 		PMD_DRV_LOG(DEBUG, "Promiscuous mode disabled on %u\n",
18078129545eSAllain Legacy 			    eth_dev->data->port_id);
18088129545eSAllain Legacy 	}
18098129545eSAllain Legacy }
18101a859223SAllain Legacy 
18111a859223SAllain Legacy static void
18121a859223SAllain Legacy avp_dev_info_get(struct rte_eth_dev *eth_dev,
18131a859223SAllain Legacy 		 struct rte_eth_dev_info *dev_info)
18141a859223SAllain Legacy {
18151a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
18161a859223SAllain Legacy 
18171a859223SAllain Legacy 	dev_info->driver_name = "rte_avp_pmd";
18181a859223SAllain Legacy 	dev_info->pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
18191a859223SAllain Legacy 	dev_info->max_rx_queues = avp->max_rx_queues;
18201a859223SAllain Legacy 	dev_info->max_tx_queues = avp->max_tx_queues;
18211a859223SAllain Legacy 	dev_info->min_rx_bufsize = AVP_MIN_RX_BUFSIZE;
18221a859223SAllain Legacy 	dev_info->max_rx_pktlen = avp->max_rx_pkt_len;
18231a859223SAllain Legacy 	dev_info->max_mac_addrs = AVP_MAX_MAC_ADDRS;
18241a859223SAllain Legacy 	if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) {
18251a859223SAllain Legacy 		dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP;
18261a859223SAllain Legacy 		dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT;
18271a859223SAllain Legacy 	}
18281a859223SAllain Legacy }
18291a859223SAllain Legacy 
18301a859223SAllain Legacy static void
18311a859223SAllain Legacy avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
18321a859223SAllain Legacy {
18331a859223SAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
18341a859223SAllain Legacy 
18351a859223SAllain Legacy 	if (mask & ETH_VLAN_STRIP_MASK) {
18361a859223SAllain Legacy 		if (avp->host_features & RTE_AVP_FEATURE_VLAN_OFFLOAD) {
18371a859223SAllain Legacy 			if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
18381a859223SAllain Legacy 				avp->features |= RTE_AVP_FEATURE_VLAN_OFFLOAD;
18391a859223SAllain Legacy 			else
18401a859223SAllain Legacy 				avp->features &= ~RTE_AVP_FEATURE_VLAN_OFFLOAD;
18411a859223SAllain Legacy 		} else {
18421a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN strip offload not supported\n");
18431a859223SAllain Legacy 		}
18441a859223SAllain Legacy 	}
18451a859223SAllain Legacy 
18461a859223SAllain Legacy 	if (mask & ETH_VLAN_FILTER_MASK) {
18471a859223SAllain Legacy 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_filter)
18481a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN filter offload not supported\n");
18491a859223SAllain Legacy 	}
18501a859223SAllain Legacy 
18511a859223SAllain Legacy 	if (mask & ETH_VLAN_EXTEND_MASK) {
18521a859223SAllain Legacy 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend)
18531a859223SAllain Legacy 			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
18541a859223SAllain Legacy 	}
18551a859223SAllain Legacy }
18561a859223SAllain Legacy 
18575a5abe2dSAllain Legacy static void
18585a5abe2dSAllain Legacy avp_dev_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats)
18595a5abe2dSAllain Legacy {
18605a5abe2dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
18615a5abe2dSAllain Legacy 	unsigned int i;
18625a5abe2dSAllain Legacy 
18635a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
18645a5abe2dSAllain Legacy 		struct avp_queue *rxq = avp->dev_data->rx_queues[i];
18655a5abe2dSAllain Legacy 
18665a5abe2dSAllain Legacy 		if (rxq) {
18675a5abe2dSAllain Legacy 			stats->ipackets += rxq->packets;
18685a5abe2dSAllain Legacy 			stats->ibytes += rxq->bytes;
18695a5abe2dSAllain Legacy 			stats->ierrors += rxq->errors;
18705a5abe2dSAllain Legacy 
18715a5abe2dSAllain Legacy 			stats->q_ipackets[i] += rxq->packets;
18725a5abe2dSAllain Legacy 			stats->q_ibytes[i] += rxq->bytes;
18735a5abe2dSAllain Legacy 			stats->q_errors[i] += rxq->errors;
18745a5abe2dSAllain Legacy 		}
18755a5abe2dSAllain Legacy 	}
18765a5abe2dSAllain Legacy 
18775a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
18785a5abe2dSAllain Legacy 		struct avp_queue *txq = avp->dev_data->tx_queues[i];
18795a5abe2dSAllain Legacy 
18805a5abe2dSAllain Legacy 		if (txq) {
18815a5abe2dSAllain Legacy 			stats->opackets += txq->packets;
18825a5abe2dSAllain Legacy 			stats->obytes += txq->bytes;
18835a5abe2dSAllain Legacy 			stats->oerrors += txq->errors;
18845a5abe2dSAllain Legacy 
18855a5abe2dSAllain Legacy 			stats->q_opackets[i] += txq->packets;
18865a5abe2dSAllain Legacy 			stats->q_obytes[i] += txq->bytes;
18875a5abe2dSAllain Legacy 			stats->q_errors[i] += txq->errors;
18885a5abe2dSAllain Legacy 		}
18895a5abe2dSAllain Legacy 	}
18905a5abe2dSAllain Legacy }
18915a5abe2dSAllain Legacy 
18925a5abe2dSAllain Legacy static void
18935a5abe2dSAllain Legacy avp_dev_stats_reset(struct rte_eth_dev *eth_dev)
18945a5abe2dSAllain Legacy {
18955a5abe2dSAllain Legacy 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
18965a5abe2dSAllain Legacy 	unsigned int i;
18975a5abe2dSAllain Legacy 
18985a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_rx_queues; i++) {
18995a5abe2dSAllain Legacy 		struct avp_queue *rxq = avp->dev_data->rx_queues[i];
19005a5abe2dSAllain Legacy 
19015a5abe2dSAllain Legacy 		if (rxq) {
19025a5abe2dSAllain Legacy 			rxq->bytes = 0;
19035a5abe2dSAllain Legacy 			rxq->packets = 0;
19045a5abe2dSAllain Legacy 			rxq->errors = 0;
19055a5abe2dSAllain Legacy 		}
19065a5abe2dSAllain Legacy 	}
19075a5abe2dSAllain Legacy 
19085a5abe2dSAllain Legacy 	for (i = 0; i < avp->num_tx_queues; i++) {
19095a5abe2dSAllain Legacy 		struct avp_queue *txq = avp->dev_data->tx_queues[i];
19105a5abe2dSAllain Legacy 
19115a5abe2dSAllain Legacy 		if (txq) {
19125a5abe2dSAllain Legacy 			txq->bytes = 0;
19135a5abe2dSAllain Legacy 			txq->packets = 0;
19145a5abe2dSAllain Legacy 			txq->errors = 0;
19155a5abe2dSAllain Legacy 		}
19165a5abe2dSAllain Legacy 	}
19175a5abe2dSAllain Legacy }
19185a5abe2dSAllain Legacy 
1919908072e9SAllain Legacy RTE_PMD_REGISTER_PCI(net_avp, rte_avp_pmd.pci_drv);
1920908072e9SAllain Legacy RTE_PMD_REGISTER_PCI_TABLE(net_avp, pci_id_avp_map);
1921