blob: 2aa4840dbc70630fe99fcb47989cae34f729304e [file] [log] [blame]
Todd Foggoaa292c8c2016-04-06 09:57:01 -04001From 057358356e7d05f07ab2df37c12b1cce37a3cca9 Mon Sep 17 00:00:00 2001
2From: John Daley <johndale@cisco.com>
3Date: Fri, 4 Mar 2016 13:09:00 -0800
4Subject: [PATCH 11/22] enic: improve Rx performance
John Loa6a8bfd2016-03-08 22:15:20 -05005
John Lo23650e62016-03-29 16:14:35 -04006 This is a wholesale replacement of the Enic PMD receive path in order
7 to improve performance and code clarity. The changes are:
8 - Simplify and reduce code path length of receive function.
9 - Put most of the fast-path receive functions in one file.
10 - Reduce the number of posted_index updates (pay attention to
11 rx_free_thresh)
12 - Remove the unneeded container structure around the RQ mbuf ring
13 - Prefetch next Mbuf and descriptors while processing the current one
14 - Use a lookup table for converting CQ flags to mbuf flags.
Todd Foggoaa292c8c2016-04-06 09:57:01 -040015
John Lo23650e62016-03-29 16:14:35 -040016 Signed-off-by: John Daley <johndale@cisco.com>
Todd Foggoaa292c8c2016-04-06 09:57:01 -040017---
18 drivers/net/enic/Makefile | 1 +
19 drivers/net/enic/base/vnic_rq.c | 99 ++---------
20 drivers/net/enic/base/vnic_rq.h | 147 +---------------
21 drivers/net/enic/enic.h | 16 +-
22 drivers/net/enic/enic_ethdev.c | 27 ++-
23 drivers/net/enic/enic_main.c | 321 ++++++++++------------------------
24 drivers/net/enic/enic_res.h | 16 +-
25 drivers/net/enic/enic_rx.c | 370 ++++++++++++++++++++++++++++++++++++++++
26 8 files changed, 511 insertions(+), 486 deletions(-)
27 create mode 100644 drivers/net/enic/enic_rx.c
John Loa6a8bfd2016-03-08 22:15:20 -050028
29diff --git a/drivers/net/enic/Makefile b/drivers/net/enic/Makefile
30index f0ee093..f316274 100644
31--- a/drivers/net/enic/Makefile
32+++ b/drivers/net/enic/Makefile
33@@ -53,6 +53,7 @@ VPATH += $(SRCDIR)/src
34 #
35 SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_ethdev.c
36 SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_main.c
37+SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_rx.c
38 SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_clsf.c
39 SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_res.c
40 SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_cq.c
41diff --git a/drivers/net/enic/base/vnic_rq.c b/drivers/net/enic/base/vnic_rq.c
42index 1441604..cb62c5e 100644
43--- a/drivers/net/enic/base/vnic_rq.c
44+++ b/drivers/net/enic/base/vnic_rq.c
45@@ -35,77 +35,21 @@
46 #include "vnic_dev.h"
47 #include "vnic_rq.h"
48
49-static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
50-{
51- struct vnic_rq_buf *buf;
52- unsigned int i, j, count = rq->ring.desc_count;
53- unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count);
54-
55- for (i = 0; i < blks; i++) {
56- rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC);
57- if (!rq->bufs[i])
58- return -ENOMEM;
59- }
60-
61- for (i = 0; i < blks; i++) {
62- buf = rq->bufs[i];
63- for (j = 0; j < VNIC_RQ_BUF_BLK_ENTRIES(count); j++) {
64- buf->index = i * VNIC_RQ_BUF_BLK_ENTRIES(count) + j;
65- buf->desc = (u8 *)rq->ring.descs +
66- rq->ring.desc_size * buf->index;
67- if (buf->index + 1 == count) {
68- buf->next = rq->bufs[0];
69- break;
70- } else if (j + 1 == VNIC_RQ_BUF_BLK_ENTRIES(count)) {
71- buf->next = rq->bufs[i + 1];
72- } else {
73- buf->next = buf + 1;
74- buf++;
75- }
76- }
77- }
78-
79- rq->to_use = rq->to_clean = rq->bufs[0];
80-
81- return 0;
82-}
83-
84-int vnic_rq_mem_size(struct vnic_rq *rq, unsigned int desc_count,
85- unsigned int desc_size)
86-{
87- int mem_size = 0;
88-
89- mem_size += vnic_dev_desc_ring_size(&rq->ring, desc_count, desc_size);
90-
91- mem_size += VNIC_RQ_BUF_BLKS_NEEDED(rq->ring.desc_count) *
92- VNIC_RQ_BUF_BLK_SZ(rq->ring.desc_count);
93-
94- return mem_size;
95-}
96-
97 void vnic_rq_free(struct vnic_rq *rq)
98 {
99 struct vnic_dev *vdev;
100- unsigned int i;
101
102 vdev = rq->vdev;
103
104 vnic_dev_free_desc_ring(vdev, &rq->ring);
105
106- for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) {
107- if (rq->bufs[i]) {
108- kfree(rq->bufs[i]);
109- rq->bufs[i] = NULL;
110- }
111- }
112-
113 rq->ctrl = NULL;
114 }
115
116 int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
117 unsigned int desc_count, unsigned int desc_size)
118 {
119- int err;
120+ int rc;
121 char res_name[NAME_MAX];
122 static int instance;
123
124@@ -121,18 +65,9 @@ int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
125 vnic_rq_disable(rq);
126
127 snprintf(res_name, sizeof(res_name), "%d-rq-%d", instance++, index);
128- err = vnic_dev_alloc_desc_ring(vdev, &rq->ring, desc_count, desc_size,
129+ rc = vnic_dev_alloc_desc_ring(vdev, &rq->ring, desc_count, desc_size,
130 rq->socket_id, res_name);
131- if (err)
132- return err;
133-
134- err = vnic_rq_alloc_bufs(rq);
135- if (err) {
136- vnic_rq_free(rq);
137- return err;
138- }
139-
140- return 0;
141+ return rc;
142 }
143
144 void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
145@@ -154,9 +89,6 @@ void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
146 iowrite32(fetch_index, &rq->ctrl->fetch_index);
147 iowrite32(posted_index, &rq->ctrl->posted_index);
148
149- rq->to_use = rq->to_clean =
150- &rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES(count)]
151- [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES(count)];
152 }
153
154 void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
155@@ -176,6 +108,8 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
156 fetch_index, fetch_index,
157 error_interrupt_enable,
158 error_interrupt_offset);
159+ rq->rxst_idx = 0;
160+ rq->tot_pkts = 0;
161 }
162
163 void vnic_rq_error_out(struct vnic_rq *rq, unsigned int error)
164@@ -212,21 +146,20 @@ int vnic_rq_disable(struct vnic_rq *rq)
165 }
166
167 void vnic_rq_clean(struct vnic_rq *rq,
168- void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf))
169+ void (*buf_clean)(struct rte_mbuf **buf))
170 {
171- struct vnic_rq_buf *buf;
172- u32 fetch_index;
173+ struct rte_mbuf **buf;
174+ u32 fetch_index, i;
175 unsigned int count = rq->ring.desc_count;
176
177- buf = rq->to_clean;
178-
179- while (vnic_rq_desc_used(rq) > 0) {
180+ buf = &rq->mbuf_ring[0];
181
182- (*buf_clean)(rq, buf);
183-
184- buf = rq->to_clean = buf->next;
185- rq->ring.desc_avail++;
186+ for (i = 0; i < count; i++) {
187+ (*buf_clean)(buf);
188+ buf++;
189 }
190+ rq->ring.desc_avail = count - 1;
191+ rq->rx_nb_hold = 0;
192
193 /* Use current fetch_index as the ring starting point */
194 fetch_index = ioread32(&rq->ctrl->fetch_index);
195@@ -235,9 +168,7 @@ void vnic_rq_clean(struct vnic_rq *rq,
196 /* Hardware surprise removal: reset fetch_index */
197 fetch_index = 0;
198 }
199- rq->to_use = rq->to_clean =
200- &rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES(count)]
201- [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES(count)];
202+
203 iowrite32(fetch_index, &rq->ctrl->posted_index);
204
205 vnic_dev_clear_desc_ring(&rq->ring);
206diff --git a/drivers/net/enic/base/vnic_rq.h b/drivers/net/enic/base/vnic_rq.h
207index 0f5c3c1..e083ccc 100644
208--- a/drivers/net/enic/base/vnic_rq.h
209+++ b/drivers/net/enic/base/vnic_rq.h
210@@ -66,42 +66,22 @@ struct vnic_rq_ctrl {
211 u32 pad10;
212 };
213
214-/* Break the vnic_rq_buf allocations into blocks of 32/64 entries */
215-#define VNIC_RQ_BUF_MIN_BLK_ENTRIES 32
216-#define VNIC_RQ_BUF_DFLT_BLK_ENTRIES 64
217-#define VNIC_RQ_BUF_BLK_ENTRIES(entries) \
218- ((unsigned int)((entries < VNIC_RQ_BUF_DFLT_BLK_ENTRIES) ? \
219- VNIC_RQ_BUF_MIN_BLK_ENTRIES : VNIC_RQ_BUF_DFLT_BLK_ENTRIES))
220-#define VNIC_RQ_BUF_BLK_SZ(entries) \
221- (VNIC_RQ_BUF_BLK_ENTRIES(entries) * sizeof(struct vnic_rq_buf))
222-#define VNIC_RQ_BUF_BLKS_NEEDED(entries) \
223- DIV_ROUND_UP(entries, VNIC_RQ_BUF_BLK_ENTRIES(entries))
224-#define VNIC_RQ_BUF_BLKS_MAX VNIC_RQ_BUF_BLKS_NEEDED(4096)
225-
226-struct vnic_rq_buf {
227- struct vnic_rq_buf *next;
228- dma_addr_t dma_addr;
229- void *os_buf;
230- unsigned int os_buf_index;
231- unsigned int len;
232- unsigned int index;
233- void *desc;
234- uint64_t wr_id;
235-};
236-
237 struct vnic_rq {
238 unsigned int index;
239+ unsigned int posted_index;
240 struct vnic_dev *vdev;
241- struct vnic_rq_ctrl __iomem *ctrl; /* memory-mapped */
242+ struct vnic_rq_ctrl __iomem *ctrl; /* memory-mapped */
243 struct vnic_dev_ring ring;
244- struct vnic_rq_buf *bufs[VNIC_RQ_BUF_BLKS_MAX];
245- struct vnic_rq_buf *to_use;
246- struct vnic_rq_buf *to_clean;
247+ struct rte_mbuf **mbuf_ring; /* array of allocated mbufs */
248+ unsigned int mbuf_next_idx; /* next mb to consume */
249 void *os_buf_head;
250 unsigned int pkts_outstanding;
251-
252+ uint16_t rx_nb_hold;
253+ uint16_t rx_free_thresh;
254 unsigned int socket_id;
255 struct rte_mempool *mp;
256+ uint16_t rxst_idx;
257+ uint32_t tot_pkts;
258 };
259
260 static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq)
261@@ -116,119 +96,13 @@ static inline unsigned int vnic_rq_desc_used(struct vnic_rq *rq)
262 return rq->ring.desc_count - rq->ring.desc_avail - 1;
263 }
264
265-static inline void *vnic_rq_next_desc(struct vnic_rq *rq)
266-{
267- return rq->to_use->desc;
268-}
269-
270-static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)
271-{
272- return rq->to_use->index;
273-}
274-
275-static inline void vnic_rq_post(struct vnic_rq *rq,
276- void *os_buf, unsigned int os_buf_index,
277- dma_addr_t dma_addr, unsigned int len,
278- uint64_t wrid)
279-{
280- struct vnic_rq_buf *buf = rq->to_use;
281-
282- buf->os_buf = os_buf;
283- buf->os_buf_index = os_buf_index;
284- buf->dma_addr = dma_addr;
285- buf->len = len;
286- buf->wr_id = wrid;
287-
288- buf = buf->next;
289- rq->to_use = buf;
290- rq->ring.desc_avail--;
291-
292- /* Move the posted_index every nth descriptor
293- */
294-
295-#ifndef VNIC_RQ_RETURN_RATE
296-#define VNIC_RQ_RETURN_RATE 0xf /* keep 2^n - 1 */
297-#endif
298-
299- if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) {
300- /* Adding write memory barrier prevents compiler and/or CPU
301- * reordering, thus avoiding descriptor posting before
302- * descriptor is initialized. Otherwise, hardware can read
303- * stale descriptor fields.
304- */
305- wmb();
306- iowrite32(buf->index, &rq->ctrl->posted_index);
307- }
308-}
309-
310-static inline void vnic_rq_post_commit(struct vnic_rq *rq,
311- void *os_buf, unsigned int os_buf_index,
312- dma_addr_t dma_addr, unsigned int len)
313-{
314- struct vnic_rq_buf *buf = rq->to_use;
315-
316- buf->os_buf = os_buf;
317- buf->os_buf_index = os_buf_index;
318- buf->dma_addr = dma_addr;
319- buf->len = len;
320-
321- buf = buf->next;
322- rq->to_use = buf;
323- rq->ring.desc_avail--;
324-
325- /* Move the posted_index every descriptor
326- */
327-
328- /* Adding write memory barrier prevents compiler and/or CPU
329- * reordering, thus avoiding descriptor posting before
330- * descriptor is initialized. Otherwise, hardware can read
331- * stale descriptor fields.
332- */
333- wmb();
334- iowrite32(buf->index, &rq->ctrl->posted_index);
335-}
336
337-static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
338-{
339- rq->ring.desc_avail += count;
340-}
341
342 enum desc_return_options {
343 VNIC_RQ_RETURN_DESC,
344 VNIC_RQ_DEFER_RETURN_DESC,
345 };
346
347-static inline int vnic_rq_service(struct vnic_rq *rq,
348- struct cq_desc *cq_desc, u16 completed_index,
349- int desc_return, int (*buf_service)(struct vnic_rq *rq,
350- struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
351- int skipped, void *opaque), void *opaque)
352-{
353- struct vnic_rq_buf *buf;
354- int skipped;
355- int eop = 0;
356-
357- buf = rq->to_clean;
358- while (1) {
359-
360- skipped = (buf->index != completed_index);
361-
362- if ((*buf_service)(rq, cq_desc, buf, skipped, opaque))
363- eop++;
364-
365- if (desc_return == VNIC_RQ_RETURN_DESC)
366- rq->ring.desc_avail++;
367-
368- rq->to_clean = buf->next;
369-
370- if (!skipped)
371- break;
372-
373- buf = rq->to_clean;
374- }
375- return eop;
376-}
377-
378 static inline int vnic_rq_fill(struct vnic_rq *rq,
379 int (*buf_fill)(struct vnic_rq *rq))
380 {
381@@ -274,8 +148,5 @@ unsigned int vnic_rq_error_status(struct vnic_rq *rq);
382 void vnic_rq_enable(struct vnic_rq *rq);
383 int vnic_rq_disable(struct vnic_rq *rq);
384 void vnic_rq_clean(struct vnic_rq *rq,
385- void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf));
386-int vnic_rq_mem_size(struct vnic_rq *rq, unsigned int desc_count,
387- unsigned int desc_size);
388-
389+ void (*buf_clean)(struct rte_mbuf **buf));
390 #endif /* _VNIC_RQ_H_ */
391diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
392index 9e78305..8c914f5 100644
393--- a/drivers/net/enic/enic.h
394+++ b/drivers/net/enic/enic.h
395@@ -45,6 +45,7 @@
396 #include "vnic_nic.h"
397 #include "vnic_rss.h"
398 #include "enic_res.h"
399+#include "cq_enet_desc.h"
400
401 #define DRV_NAME "enic_pmd"
402 #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Poll-mode Driver"
403@@ -154,6 +155,16 @@ static inline struct enic *pmd_priv(struct rte_eth_dev *eth_dev)
404 return (struct enic *)eth_dev->data->dev_private;
405 }
406
407+#define RTE_LIBRTE_ENIC_ASSERT_ENABLE
408+#ifdef RTE_LIBRTE_ENIC_ASSERT_ENABLE
409+#define ASSERT(x) do { \
410+ if (!(x)) \
411+ rte_panic("ENIC: x"); \
412+} while (0)
413+#else
414+#define ASSERT(x)
415+#endif
416+
417 extern void enic_fdir_stats_get(struct enic *enic,
418 struct rte_eth_fdir_stats *stats);
419 extern int enic_fdir_add_fltr(struct enic *enic,
420@@ -193,9 +204,10 @@ extern void enic_send_pkt(struct enic *enic, struct vnic_wq *wq,
421 uint16_t ol_flags, uint16_t vlan_tag);
422
423 extern void enic_post_wq_index(struct vnic_wq *wq);
424-extern int enic_poll(struct vnic_rq *rq, struct rte_mbuf **rx_pkts,
425- unsigned int budget, unsigned int *work_done);
426 extern int enic_probe(struct enic *enic);
427 extern int enic_clsf_init(struct enic *enic);
428 extern void enic_clsf_destroy(struct enic *enic);
429+uint16_t enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
430+ uint16_t nb_pkts);
431+
432 #endif /* _ENIC_H_ */
433diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
434index 2a88043..6f2ada5 100644
435--- a/drivers/net/enic/enic_ethdev.c
436+++ b/drivers/net/enic/enic_ethdev.c
437@@ -255,7 +255,7 @@ static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
438 uint16_t queue_idx,
439 uint16_t nb_desc,
440 unsigned int socket_id,
441- __rte_unused const struct rte_eth_rxconf *rx_conf,
442+ const struct rte_eth_rxconf *rx_conf,
443 struct rte_mempool *mp)
444 {
445 int ret;
446@@ -270,6 +270,10 @@ static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
447 return ret;
448 }
449
450+ enic->rq[queue_idx].rx_free_thresh = rx_conf->rx_free_thresh;
451+ dev_debug(enic, "Set queue_id:%u free thresh:%u\n", queue_idx,
452+ enic->rq[queue_idx].rx_free_thresh);
453+
454 return enicpmd_dev_setup_intr(enic);
455 }
456
457@@ -429,6 +433,9 @@ static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev,
458 DEV_TX_OFFLOAD_IPV4_CKSUM |
459 DEV_TX_OFFLOAD_UDP_CKSUM |
460 DEV_TX_OFFLOAD_TCP_CKSUM;
461+ device_info->default_rxconf = (struct rte_eth_rxconf) {
462+ .rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH
463+ };
464 }
465
466 static void enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
467@@ -538,18 +545,6 @@ static uint16_t enicpmd_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
468 return index;
469 }
470
471-static uint16_t enicpmd_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
472- uint16_t nb_pkts)
473-{
474- struct vnic_rq *rq = (struct vnic_rq *)rx_queue;
475- unsigned int work_done;
476-
477- if (enic_poll(rq, rx_pkts, (unsigned int)nb_pkts, &work_done))
478- dev_err(enic, "error in enicpmd poll\n");
479-
480- return work_done;
481-}
482-
483 static const struct eth_dev_ops enicpmd_eth_dev_ops = {
484 .dev_configure = enicpmd_dev_configure,
485 .dev_start = enicpmd_dev_start,
486@@ -606,7 +601,7 @@ static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
487 enic->port_id = eth_dev->data->port_id;
488 enic->rte_dev = eth_dev;
489 eth_dev->dev_ops = &enicpmd_eth_dev_ops;
490- eth_dev->rx_pkt_burst = &enicpmd_recv_pkts;
491+ eth_dev->rx_pkt_burst = &enic_recv_pkts;
492 eth_dev->tx_pkt_burst = &enicpmd_xmit_pkts;
493
494 pdev = eth_dev->pci_dev;
495@@ -635,8 +630,8 @@ static struct eth_driver rte_enic_pmd = {
496 * Register as the [Poll Mode] Driver of Cisco ENIC device.
497 */
498 static int
499-rte_enic_pmd_init(const char *name __rte_unused,
500- const char *params __rte_unused)
501+rte_enic_pmd_init(__rte_unused const char *name,
502+ __rte_unused const char *params)
503 {
504 ENICPMD_FUNC_TRACE();
505
506diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
John Lo23650e62016-03-29 16:14:35 -0400507index f818c32..9fff020 100644
John Loa6a8bfd2016-03-08 22:15:20 -0500508--- a/drivers/net/enic/enic_main.c
509+++ b/drivers/net/enic/enic_main.c
510@@ -60,6 +60,17 @@
511 #include "vnic_nic.h"
512 #include "enic_vnic_wq.h"
513
514+static inline struct rte_mbuf *
515+rte_rxmbuf_alloc(struct rte_mempool *mp)
516+{
517+ struct rte_mbuf *m;
518+
519+ m = __rte_mbuf_raw_alloc(mp);
520+ __rte_mbuf_sanity_check_raw(m, 0);
521+ return m;
522+}
523+
524+
525 static inline int enic_is_sriov_vf(struct enic *enic)
526 {
527 return enic->pdev->id.device_id == PCI_DEVICE_ID_CISCO_VIC_ENET_VF;
528@@ -80,16 +91,25 @@ static int is_eth_addr_valid(uint8_t *addr)
529 return !is_mcast_addr(addr) && !is_zero_addr(addr);
530 }
531
532-static inline struct rte_mbuf *
533-enic_rxmbuf_alloc(struct rte_mempool *mp)
534+static void
535+enic_rxmbuf_queue_release(struct enic *enic, struct vnic_rq *rq)
536 {
537- struct rte_mbuf *m;
538+ uint16_t i;
539
540- m = __rte_mbuf_raw_alloc(mp);
541- __rte_mbuf_sanity_check_raw(m, 0);
542- return m;
543+ if (!rq || !rq->mbuf_ring) {
544+ dev_debug(enic, "Pointer to rq or mbuf_ring is NULL");
545+ return;
546+ }
547+
548+ for (i = 0; i < enic->config.rq_desc_count; i++) {
549+ if (rq->mbuf_ring[i]) {
550+ rte_pktmbuf_free_seg(rq->mbuf_ring[i]);
551+ rq->mbuf_ring[i] = NULL;
552+ }
553+ }
554 }
555
556+
557 void enic_set_hdr_split_size(struct enic *enic, u16 split_hdr_size)
558 {
559 vnic_set_hdr_split_size(enic->vdev, split_hdr_size);
560@@ -262,13 +282,13 @@ void enic_set_mac_address(struct enic *enic, uint8_t *mac_addr)
561 }
562
563 static void
564-enic_free_rq_buf(__rte_unused struct vnic_rq *rq, struct vnic_rq_buf *buf)
565+enic_free_rq_buf(struct rte_mbuf **mbuf)
566 {
567- if (!buf->os_buf)
568+ if (*mbuf == NULL)
569 return;
570
571- rte_pktmbuf_free((struct rte_mbuf *)buf->os_buf);
572- buf->os_buf = NULL;
573+ rte_pktmbuf_free(*mbuf);
574+ mbuf = NULL;
575 }
576
577 void enic_init_vnic_resources(struct enic *enic)
578@@ -314,221 +334,47 @@ void enic_init_vnic_resources(struct enic *enic)
579 }
580
581
582-static int enic_rq_alloc_buf(struct vnic_rq *rq)
583+static int
584+enic_alloc_rx_queue_mbufs(struct enic *enic, struct vnic_rq *rq)
585 {
586- struct enic *enic = vnic_dev_priv(rq->vdev);
587+ struct rte_mbuf *mb;
588+ struct rq_enet_desc *rqd = rq->ring.descs;
589+ unsigned i;
590 dma_addr_t dma_addr;
591- struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
592- uint8_t type = RQ_ENET_TYPE_ONLY_SOP;
593- u16 split_hdr_size = vnic_get_hdr_split_size(enic->vdev);
594- struct rte_mbuf *mbuf = enic_rxmbuf_alloc(rq->mp);
595- struct rte_mbuf *hdr_mbuf = NULL;
596-
597- if (!mbuf) {
598- dev_err(enic, "mbuf alloc in enic_rq_alloc_buf failed\n");
599- return -1;
600- }
601-
602- if (unlikely(split_hdr_size)) {
603- if (vnic_rq_desc_avail(rq) < 2) {
604- rte_mempool_put(mbuf->pool, mbuf);
605- return -1;
606- }
607- hdr_mbuf = enic_rxmbuf_alloc(rq->mp);
608- if (!hdr_mbuf) {
609- rte_mempool_put(mbuf->pool, mbuf);
610- dev_err(enic,
611- "hdr_mbuf alloc in enic_rq_alloc_buf failed\n");
612- return -1;
613- }
614-
615- hdr_mbuf->data_off = RTE_PKTMBUF_HEADROOM;
616-
617- hdr_mbuf->nb_segs = 2;
618- hdr_mbuf->port = enic->port_id;
619- hdr_mbuf->next = mbuf;
620-
621- dma_addr = (dma_addr_t)
622- (hdr_mbuf->buf_physaddr + hdr_mbuf->data_off);
623-
624- rq_enet_desc_enc(desc, dma_addr, type, split_hdr_size);
625
626- vnic_rq_post(rq, (void *)hdr_mbuf, 0 /*os_buf_index*/, dma_addr,
627- (unsigned int)split_hdr_size, 0 /*wrid*/);
628+ dev_debug(enic, "queue %u, allocating %u rx queue mbufs", rq->index,
629+ rq->ring.desc_count);
630
631- desc = vnic_rq_next_desc(rq);
632- type = RQ_ENET_TYPE_NOT_SOP;
633- } else {
634- mbuf->nb_segs = 1;
635- mbuf->port = enic->port_id;
636- }
637-
638- mbuf->data_off = RTE_PKTMBUF_HEADROOM;
639- mbuf->next = NULL;
640-
641- dma_addr = (dma_addr_t)
642- (mbuf->buf_physaddr + mbuf->data_off);
643-
644- rq_enet_desc_enc(desc, dma_addr, type, mbuf->buf_len);
645-
646- vnic_rq_post(rq, (void *)mbuf, 0 /*os_buf_index*/, dma_addr,
647- (unsigned int)mbuf->buf_len, 0 /*wrid*/);
648-
649- return 0;
650-}
651-
652-static int enic_rq_indicate_buf(struct vnic_rq *rq,
653- struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
654- int skipped, void *opaque)
655-{
656- struct enic *enic = vnic_dev_priv(rq->vdev);
657- struct rte_mbuf **rx_pkt_bucket = (struct rte_mbuf **)opaque;
658- struct rte_mbuf *rx_pkt = NULL;
659- struct rte_mbuf *hdr_rx_pkt = NULL;
660-
661- u8 type, color, eop, sop, ingress_port, vlan_stripped;
662- u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof;
663- u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
664- u8 ipv6, ipv4, ipv4_fragment, fcs_ok, rss_type, csum_not_calc;
665- u8 packet_error;
666- u16 q_number, completed_index, bytes_written, vlan_tci, checksum;
667- u32 rss_hash;
668-
669- cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc,
670- &type, &color, &q_number, &completed_index,
671- &ingress_port, &fcoe, &eop, &sop, &rss_type,
672- &csum_not_calc, &rss_hash, &bytes_written,
673- &packet_error, &vlan_stripped, &vlan_tci, &checksum,
674- &fcoe_sof, &fcoe_fc_crc_ok, &fcoe_enc_error,
675- &fcoe_eof, &tcp_udp_csum_ok, &udp, &tcp,
676- &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment,
677- &fcs_ok);
678-
679- rx_pkt = (struct rte_mbuf *)buf->os_buf;
680- buf->os_buf = NULL;
681-
682- if (unlikely(packet_error)) {
683- dev_err(enic, "packet error\n");
684- rx_pkt->data_len = 0;
685- return 0;
686- }
687-
688- if (unlikely(skipped)) {
689- rx_pkt->data_len = 0;
690- return 0;
691- }
692-
693- if (likely(!vnic_get_hdr_split_size(enic->vdev))) {
694- /* No header split configured */
695- *rx_pkt_bucket = rx_pkt;
696- rx_pkt->pkt_len = bytes_written;
697-
698- if (ipv4) {
699- rx_pkt->packet_type = RTE_PTYPE_L3_IPV4;
700- if (!csum_not_calc) {
701- if (unlikely(!ipv4_csum_ok))
702- rx_pkt->ol_flags |= PKT_RX_IP_CKSUM_BAD;
703-
704- if ((tcp || udp) && (!tcp_udp_csum_ok))
705- rx_pkt->ol_flags |= PKT_RX_L4_CKSUM_BAD;
706- }
707- } else if (ipv6)
708- rx_pkt->packet_type = RTE_PTYPE_L3_IPV6;
709- } else {
710- /* Header split */
711- if (sop && !eop) {
712- /* This piece is header */
713- *rx_pkt_bucket = rx_pkt;
714- rx_pkt->pkt_len = bytes_written;
715- } else {
716- if (sop && eop) {
717- /* The packet is smaller than split_hdr_size */
718- *rx_pkt_bucket = rx_pkt;
719- rx_pkt->pkt_len = bytes_written;
720- if (ipv4) {
721- rx_pkt->packet_type = RTE_PTYPE_L3_IPV4;
722- if (!csum_not_calc) {
723- if (unlikely(!ipv4_csum_ok))
724- rx_pkt->ol_flags |=
725- PKT_RX_IP_CKSUM_BAD;
726-
727- if ((tcp || udp) &&
728- (!tcp_udp_csum_ok))
729- rx_pkt->ol_flags |=
730- PKT_RX_L4_CKSUM_BAD;
731- }
732- } else if (ipv6)
733- rx_pkt->packet_type = RTE_PTYPE_L3_IPV6;
734- } else {
735- /* Payload */
736- hdr_rx_pkt = *rx_pkt_bucket;
737- hdr_rx_pkt->pkt_len += bytes_written;
738- if (ipv4) {
739- hdr_rx_pkt->packet_type =
740- RTE_PTYPE_L3_IPV4;
741- if (!csum_not_calc) {
742- if (unlikely(!ipv4_csum_ok))
743- hdr_rx_pkt->ol_flags |=
744- PKT_RX_IP_CKSUM_BAD;
745-
746- if ((tcp || udp) &&
747- (!tcp_udp_csum_ok))
748- hdr_rx_pkt->ol_flags |=
749- PKT_RX_L4_CKSUM_BAD;
750- }
751- } else if (ipv6)
752- hdr_rx_pkt->packet_type =
753- RTE_PTYPE_L3_IPV6;
754- }
755+ for (i = 0; i < rq->ring.desc_count; i++, rqd++) {
756+ mb = rte_rxmbuf_alloc(rq->mp);
757+ if (mb == NULL) {
758+ dev_err(enic, "RX mbuf alloc failed queue_id=%u",
759+ (unsigned)rq->index);
760+ return -ENOMEM;
761 }
762- }
763
764- rx_pkt->data_len = bytes_written;
765+ dma_addr = (dma_addr_t)(mb->buf_physaddr + mb->data_off);
766
767- if (rss_hash) {
768- rx_pkt->ol_flags |= PKT_RX_RSS_HASH;
769- rx_pkt->hash.rss = rss_hash;
770+ rq_enet_desc_enc(rqd, dma_addr, RQ_ENET_TYPE_ONLY_SOP,
771+ mb->buf_len);
772+ rq->mbuf_ring[i] = mb;
773 }
774
775- if (vlan_tci) {
776- rx_pkt->ol_flags |= PKT_RX_VLAN_PKT;
777- rx_pkt->vlan_tci = vlan_tci;
778- }
779+ /* make sure all prior writes are complete before doing the PIO write */
780+ rte_rmb();
781
782- return eop;
783-}
784+ /* Post all but the last 2 cache lines' worth of descriptors */
785+ rq->posted_index = rq->ring.desc_count - (2 * RTE_CACHE_LINE_SIZE
786+ / sizeof(struct rq_enet_desc));
787+ rq->rx_nb_hold = 0;
788
789-static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
790- __rte_unused u8 type, u16 q_number, u16 completed_index, void *opaque)
791-{
792- struct enic *enic = vnic_dev_priv(vdev);
793-
794- return vnic_rq_service(&enic->rq[q_number], cq_desc,
795- completed_index, VNIC_RQ_RETURN_DESC,
796- enic_rq_indicate_buf, opaque);
797-
798-}
799+ dev_debug(enic, "port=%u, qidx=%u, Write %u posted idx, %u sw held\n",
800+ enic->port_id, rq->index, rq->posted_index, rq->rx_nb_hold);
801+ iowrite32(rq->posted_index, &rq->ctrl->posted_index);
802+ rte_rmb();
803
804-int enic_poll(struct vnic_rq *rq, struct rte_mbuf **rx_pkts,
805- unsigned int budget, unsigned int *work_done)
806-{
807- struct enic *enic = vnic_dev_priv(rq->vdev);
808- unsigned int cq = enic_cq_rq(enic, rq->index);
809- int err = 0;
810-
811- *work_done = vnic_cq_service(&enic->cq[cq],
812- budget, enic_rq_service, (void *)rx_pkts);
813-
814- if (*work_done) {
815- vnic_rq_fill(rq, enic_rq_alloc_buf);
816+ return 0;
817
818- /* Need at least one buffer on ring to get going */
819- if (vnic_rq_desc_used(rq) == 0) {
820- dev_err(enic, "Unable to alloc receive buffers\n");
821- err = -1;
822- }
823- }
824- return err;
825 }
826
827 static void *
828@@ -576,6 +422,7 @@ enic_intr_handler(__rte_unused struct rte_intr_handle *handle,
829 int enic_enable(struct enic *enic)
830 {
831 unsigned int index;
832+ int err;
833 struct rte_eth_dev *eth_dev = enic->rte_dev;
834
835 eth_dev->data->dev_link.link_speed = vnic_dev_port_speed(enic->vdev);
836@@ -586,15 +433,11 @@ int enic_enable(struct enic *enic)
837 dev_warning(enic, "Init of hash table for clsf failed."\
838 "Flow director feature will not work\n");
839
840- /* Fill RQ bufs */
841 for (index = 0; index < enic->rq_count; index++) {
842- vnic_rq_fill(&enic->rq[index], enic_rq_alloc_buf);
843-
844- /* Need at least one buffer on ring to get going
845- */
846- if (vnic_rq_desc_used(&enic->rq[index]) == 0) {
847- dev_err(enic, "Unable to alloc receive buffers\n");
848- return -1;
849+ err = enic_alloc_rx_queue_mbufs(enic, &enic->rq[index]);
850+ if (err) {
851+ dev_err(enic, "Failed to alloc RX queue mbufs\n");
852+ return err;
853 }
854 }
855
856@@ -636,6 +479,9 @@ void enic_free_rq(void *rxq)
857 struct vnic_rq *rq = (struct vnic_rq *)rxq;
858 struct enic *enic = vnic_dev_priv(rq->vdev);
859
860+ enic_rxmbuf_queue_release(enic, rq);
861+ rte_free(rq->mbuf_ring);
862+ rq->mbuf_ring = NULL;
863 vnic_rq_free(rq);
864 vnic_cq_free(&enic->cq[rq->index]);
865 }
866@@ -664,7 +510,7 @@ int enic_alloc_rq(struct enic *enic, uint16_t queue_idx,
867 unsigned int socket_id, struct rte_mempool *mp,
868 uint16_t nb_desc)
869 {
870- int err;
871+ int rc;
872 struct vnic_rq *rq = &enic->rq[queue_idx];
873
874 rq->socket_id = socket_id;
875@@ -687,23 +533,35 @@ int enic_alloc_rq(struct enic *enic, uint16_t queue_idx,
876 }
877
878 /* Allocate queue resources */
879- err = vnic_rq_alloc(enic->vdev, &enic->rq[queue_idx], queue_idx,
880- enic->config.rq_desc_count,
881- sizeof(struct rq_enet_desc));
882- if (err) {
883+ rc = vnic_rq_alloc(enic->vdev, rq, queue_idx,
884+ enic->config.rq_desc_count, sizeof(struct rq_enet_desc));
885+ if (rc) {
886 dev_err(enic, "error in allocation of rq\n");
887- return err;
888+ goto err_exit;
889 }
890
891- err = vnic_cq_alloc(enic->vdev, &enic->cq[queue_idx], queue_idx,
892+ rc = vnic_cq_alloc(enic->vdev, &enic->cq[queue_idx], queue_idx,
893 socket_id, enic->config.rq_desc_count,
894 sizeof(struct cq_enet_rq_desc));
895- if (err) {
896- vnic_rq_free(rq);
897+ if (rc) {
898 dev_err(enic, "error in allocation of cq for rq\n");
899+ goto err_free_rq_exit;
900 }
901
902- return err;
903+ /* Allocate the mbuf ring */
904+ rq->mbuf_ring = (struct rte_mbuf **)rte_zmalloc_socket("rq->mbuf_ring",
905+ sizeof(struct rte_mbuf *) * enic->config.rq_desc_count,
906+ RTE_CACHE_LINE_SIZE, rq->socket_id);
907+
908+ if (rq->mbuf_ring != NULL)
909+ return 0;
910+
911+ /* cleanup on error */
912+ vnic_cq_free(&enic->cq[queue_idx]);
913+err_free_rq_exit:
914+ vnic_rq_free(rq);
915+err_exit:
916+ return -ENOMEM;
917 }
918
919 void enic_free_wq(void *txq)
920@@ -790,6 +648,7 @@ int enic_disable(struct enic *enic)
921
922 for (i = 0; i < enic->wq_count; i++)
923 vnic_wq_clean(&enic->wq[i], enic_free_wq_buf);
924+
925 for (i = 0; i < enic->rq_count; i++)
926 vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
927 for (i = 0; i < enic->cq_count; i++)
928@@ -1074,7 +933,7 @@ int enic_probe(struct enic *enic)
929
930 /* Set ingress vlan rewrite mode before vnic initialization */
931 err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
932- IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN);
933+ IG_VLAN_REWRITE_MODE_PASS_THRU);
934 if (err) {
935 dev_err(enic,
936 "Failed to set ingress vlan rewrite mode, aborting.\n");
937diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h
938index 49f7e22..33f2e84 100644
939--- a/drivers/net/enic/enic_res.h
940+++ b/drivers/net/enic/enic_res.h
941@@ -52,6 +52,7 @@
942 #define ENIC_UNICAST_PERFECT_FILTERS 32
943
944 #define ENIC_NON_TSO_MAX_DESC 16
945+#define ENIC_DEFAULT_RX_FREE_THRESH 32
946
947 #define ENIC_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0)
948
949@@ -133,21 +134,6 @@ static inline void enic_queue_wq_desc_tso(struct vnic_wq *wq,
950 WQ_ENET_OFFLOAD_MODE_TSO,
951 eop, 1 /* SOP */, eop, loopback);
952 }
953-static inline void enic_queue_rq_desc(struct vnic_rq *rq,
954- void *os_buf, unsigned int os_buf_index,
955- dma_addr_t dma_addr, unsigned int len)
956-{
957- struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
958- u64 wrid = 0;
959- u8 type = os_buf_index ?
960- RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP;
961-
962- rq_enet_desc_enc(desc,
963- (u64)dma_addr | VNIC_PADDR_TARGET,
964- type, (u16)len);
965-
966- vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len, wrid);
967-}
968
969 struct enic;
970
971diff --git a/drivers/net/enic/enic_rx.c b/drivers/net/enic/enic_rx.c
972new file mode 100644
John Lo23650e62016-03-29 16:14:35 -0400973index 0000000..945a60f
John Loa6a8bfd2016-03-08 22:15:20 -0500974--- /dev/null
975+++ b/drivers/net/enic/enic_rx.c
John Lo23650e62016-03-29 16:14:35 -0400976@@ -0,0 +1,370 @@
John Loa6a8bfd2016-03-08 22:15:20 -0500977+/*
978+ * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved.
979+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
980+ *
981+ * Copyright (c) 2014, Cisco Systems, Inc.
982+ * All rights reserved.
983+ *
984+ * Redistribution and use in source and binary forms, with or without
985+ * modification, are permitted provided that the following conditions
986+ * are met:
987+ *
988+ * 1. Redistributions of source code must retain the above copyright
989+ * notice, this list of conditions and the following disclaimer.
990+ *
991+ * 2. Redistributions in binary form must reproduce the above copyright
992+ * notice, this list of conditions and the following disclaimer in
993+ * the documentation and/or other materials provided with the
994+ * distribution.
995+ *
996+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
997+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
998+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
999+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1000+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1001+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
1002+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1003+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1004+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1005+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
1006+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1007+ * POSSIBILITY OF SUCH DAMAGE.
1008+ *
1009+ */
1010+
1011+#include <rte_mbuf.h>
1012+#include <rte_ethdev.h>
1013+#include <rte_prefetch.h>
1014+
1015+#include "enic_compat.h"
1016+#include "rq_enet_desc.h"
1017+#include "enic.h"
1018+
1019+#define RTE_PMD_USE_PREFETCH
1020+
1021+#ifdef RTE_PMD_USE_PREFETCH
1022+/*
1023+ * Prefetch a cache line into all cache levels.
1024+ */
1025+#define rte_enic_prefetch(p) rte_prefetch0(p)
1026+#else
1027+#define rte_enic_prefetch(p) do {} while (0)
1028+#endif
1029+
1030+#ifdef RTE_PMD_PACKET_PREFETCH
1031+#define rte_packet_prefetch(p) rte_prefetch1(p)
1032+#else
1033+#define rte_packet_prefetch(p) do {} while (0)
1034+#endif
1035+
1036+static inline struct rte_mbuf *
1037+rte_rxmbuf_alloc(struct rte_mempool *mp)
1038+{
1039+ struct rte_mbuf *m;
1040+
1041+ m = __rte_mbuf_raw_alloc(mp);
1042+ __rte_mbuf_sanity_check_raw(m, 0);
1043+ return m;
1044+}
1045+
1046+static inline uint16_t
1047+enic_cq_rx_desc_ciflags(struct cq_enet_rq_desc *crd)
1048+{
1049+ return le16_to_cpu(crd->completed_index_flags) & ~CQ_DESC_COMP_NDX_MASK;
1050+}
1051+
1052+static inline uint16_t
1053+enic_cq_rx_desc_bwflags(struct cq_enet_rq_desc *crd)
1054+{
1055+ return(le16_to_cpu(crd->bytes_written_flags) &
1056+ ~CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK);
1057+}
1058+
1059+static inline uint8_t
1060+enic_cq_rx_desc_packet_error(uint16_t bwflags)
1061+{
1062+ return((bwflags & CQ_ENET_RQ_DESC_FLAGS_TRUNCATED) ==
1063+ CQ_ENET_RQ_DESC_FLAGS_TRUNCATED);
1064+}
1065+
1066+static inline uint8_t
1067+enic_cq_rx_desc_eop(uint16_t ciflags)
1068+{
1069+ return (ciflags & CQ_ENET_RQ_DESC_FLAGS_EOP)
1070+ == CQ_ENET_RQ_DESC_FLAGS_EOP;
1071+}
1072+
1073+static inline uint8_t
1074+enic_cq_rx_desc_csum_not_calc(struct cq_enet_rq_desc *cqrd)
1075+{
1076+ return ((le16_to_cpu(cqrd->q_number_rss_type_flags) &
1077+ CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC) ==
1078+ CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC);
1079+}
1080+
1081+static inline uint8_t
1082+enic_cq_rx_desc_ipv4_csum_ok(struct cq_enet_rq_desc *cqrd)
1083+{
1084+ return ((cqrd->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK) ==
1085+ CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK);
1086+}
1087+
1088+static inline uint8_t
1089+enic_cq_rx_desc_tcp_udp_csum_ok(struct cq_enet_rq_desc *cqrd)
1090+{
1091+ return((cqrd->flags & CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK) ==
1092+ CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK);
1093+}
1094+
1095+static inline uint8_t
1096+enic_cq_rx_desc_rss_type(struct cq_enet_rq_desc *cqrd)
1097+{
1098+ return (uint8_t)((le16_to_cpu(cqrd->q_number_rss_type_flags) >>
1099+ CQ_DESC_Q_NUM_BITS) & CQ_ENET_RQ_DESC_RSS_TYPE_MASK);
1100+}
1101+
1102+static inline uint32_t
1103+enic_cq_rx_desc_rss_hash(struct cq_enet_rq_desc *cqrd)
1104+{
1105+ return le32_to_cpu(cqrd->rss_hash);
1106+}
1107+
1108+static inline uint8_t
1109+enic_cq_rx_desc_fcs_ok(struct cq_enet_rq_desc *cqrd)
1110+{
1111+ return ((cqrd->flags & CQ_ENET_RQ_DESC_FLAGS_FCS_OK) ==
1112+ CQ_ENET_RQ_DESC_FLAGS_FCS_OK);
1113+}
1114+
1115+static inline uint16_t
1116+enic_cq_rx_desc_vlan(struct cq_enet_rq_desc *cqrd)
1117+{
1118+ return le16_to_cpu(cqrd->vlan);
1119+}
1120+
1121+static inline uint16_t
1122+enic_cq_rx_desc_n_bytes(struct cq_desc *cqd)
1123+{
1124+ struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd;
1125+ return le16_to_cpu(cqrd->bytes_written_flags) &
1126+ CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK;
1127+}
1128+
1129+static inline uint64_t
1130+enic_cq_rx_to_pkt_err_flags(struct cq_desc *cqd)
1131+{
1132+ struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd;
1133+ uint16_t bwflags;
1134+ uint64_t pkt_err_flags = 0;
1135+
1136+ bwflags = enic_cq_rx_desc_bwflags(cqrd);
1137+
1138+ /* Check for packet error. Can't be more specific than MAC error */
1139+ if (enic_cq_rx_desc_packet_error(bwflags)) {
John Loa6a8bfd2016-03-08 22:15:20 -05001140+ pkt_err_flags |= PKT_RX_MAC_ERR;
John Loa6a8bfd2016-03-08 22:15:20 -05001141+ }
1142+
1143+ /* Check for bad FCS. MAC error isn't quite, but no other choice */
1144+ if (!enic_cq_rx_desc_fcs_ok(cqrd)) {
John Loa6a8bfd2016-03-08 22:15:20 -05001145+ pkt_err_flags |= PKT_RX_MAC_ERR;
John Loa6a8bfd2016-03-08 22:15:20 -05001146+ }
1147+ return pkt_err_flags;
1148+}
1149+
1150+/*
1151+ * Lookup table to translate RX CQ flags to mbuf flags.
1152+ */
1153+static inline uint32_t
1154+enic_cq_rx_flags_to_pkt_type(struct cq_desc *cqd)
1155+{
1156+ struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd;
1157+ uint8_t cqrd_flags = cqrd->flags;
1158+ static const uint32_t cq_type_table[128] __rte_cache_aligned = {
1159+ [32] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4,
1160+ [34] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4
1161+ | RTE_PTYPE_L4_UDP,
1162+ [36] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4
1163+ | RTE_PTYPE_L4_TCP,
1164+ [96] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4
1165+ | RTE_PTYPE_L4_FRAG,
1166+ [16] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6,
1167+ [18] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6
1168+ | RTE_PTYPE_L4_UDP,
1169+ [20] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6
1170+ | RTE_PTYPE_L4_TCP,
1171+ [80] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6
1172+ | RTE_PTYPE_L4_FRAG,
1173+ /* All others reserved */
1174+ };
1175+ cqrd_flags &= CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT
1176+ | CQ_ENET_RQ_DESC_FLAGS_IPV4 | CQ_ENET_RQ_DESC_FLAGS_IPV6
1177+ | CQ_ENET_RQ_DESC_FLAGS_TCP | CQ_ENET_RQ_DESC_FLAGS_UDP;
1178+ return cq_type_table[cqrd_flags];
1179+}
1180+
1181+static inline void
1182+enic_cq_rx_to_pkt_flags(struct cq_desc *cqd, struct rte_mbuf *mbuf)
1183+{
1184+ struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd;
1185+ uint16_t ciflags, bwflags, pkt_flags = 0;
1186+ ciflags = enic_cq_rx_desc_ciflags(cqrd);
1187+ bwflags = enic_cq_rx_desc_bwflags(cqrd);
1188+
1189+ ASSERT(mbuf->ol_flags == 0);
1190+
1191+ /* flags are meaningless if !EOP */
1192+ if (unlikely(!enic_cq_rx_desc_eop(ciflags)))
1193+ goto mbuf_flags_done;
1194+
1195+ /* VLAN stripping */
1196+ if (bwflags & CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED) {
1197+ pkt_flags |= PKT_RX_VLAN_PKT;
1198+ mbuf->vlan_tci = enic_cq_rx_desc_vlan(cqrd);
1199+ } else {
1200+ mbuf->vlan_tci = 0;
1201+ }
1202+
1203+ /* RSS flag */
1204+ if (enic_cq_rx_desc_rss_type(cqrd)) {
1205+ pkt_flags |= PKT_RX_RSS_HASH;
1206+ mbuf->hash.rss = enic_cq_rx_desc_rss_hash(cqrd);
1207+ }
1208+
1209+ /* checksum flags */
1210+ if (!enic_cq_rx_desc_csum_not_calc(cqrd) &&
1211+ (mbuf->packet_type & RTE_PTYPE_L3_IPV4)) {
1212+ if (unlikely(!enic_cq_rx_desc_ipv4_csum_ok(cqrd)))
1213+ pkt_flags |= PKT_RX_IP_CKSUM_BAD;
1214+ if (mbuf->packet_type & (RTE_PTYPE_L4_UDP | RTE_PTYPE_L4_TCP)) {
1215+ if (unlikely(!enic_cq_rx_desc_tcp_udp_csum_ok(cqrd)))
1216+ pkt_flags |= PKT_RX_L4_CKSUM_BAD;
1217+ }
1218+ }
1219+
1220+ mbuf_flags_done:
1221+ mbuf->ol_flags = pkt_flags;
1222+}
1223+
1224+static inline uint32_t
1225+enic_ring_add(uint32_t n_descriptors, uint32_t i0, uint32_t i1)
1226+{
1227+ uint32_t d = i0 + i1;
1228+ ASSERT(i0 < n_descriptors);
1229+ ASSERT(i1 < n_descriptors);
1230+ d -= (d >= n_descriptors) ? n_descriptors : 0;
1231+ return d;
1232+}
1233+
1234+
1235+uint16_t
1236+enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
1237+ uint16_t nb_pkts)
1238+{
1239+ struct vnic_rq *rq = rx_queue;
1240+ struct enic *enic = vnic_dev_priv(rq->vdev);
1241+ unsigned int rx_id;
1242+ struct rte_mbuf *nmb, *rxmb;
1243+ uint16_t nb_rx = 0;
1244+ uint16_t nb_hold;
1245+ struct vnic_cq *cq;
1246+ volatile struct cq_desc *cqd_ptr;
1247+ uint8_t color;
1248+
1249+ cq = &enic->cq[enic_cq_rq(enic, rq->index)];
1250+ rx_id = cq->to_clean; /* index of cqd, rqd, mbuf_table */
1251+ cqd_ptr = (struct cq_desc *)(cq->ring.descs) + rx_id;
1252+
1253+ nb_hold = rq->rx_nb_hold; /* mbufs held by software */
1254+
1255+ while (nb_rx < nb_pkts) {
1256+ uint16_t rx_pkt_len;
1257+ volatile struct rq_enet_desc *rqd_ptr;
1258+ dma_addr_t dma_addr;
1259+ struct cq_desc cqd;
1260+ uint64_t ol_err_flags;
1261+
1262+ /* Check for pkts available */
1263+ color = (cqd_ptr->type_color >> CQ_DESC_COLOR_SHIFT)
1264+ & CQ_DESC_COLOR_MASK;
1265+ if (color == cq->last_color)
1266+ break;
1267+
1268+ /* Get the cq descriptor and rq pointer */
1269+ cqd = *cqd_ptr;
1270+ rqd_ptr = (struct rq_enet_desc *)(rq->ring.descs) + rx_id;
1271+
1272+ /* allocate a new mbuf */
1273+ nmb = rte_rxmbuf_alloc(rq->mp);
1274+ if (nmb == NULL) {
1275+ dev_err(enic, "RX mbuf alloc failed port=%u qid=%u",
1276+ enic->port_id, (unsigned)rq->index);
1277+ rte_eth_devices[enic->port_id].
1278+ data->rx_mbuf_alloc_failed++;
1279+ break;
1280+ }
1281+
1282+ /* Check for FCS or packet errors */
1283+ ol_err_flags = enic_cq_rx_to_pkt_err_flags(&cqd);
1284+ if (ol_err_flags == 0)
1285+ rx_pkt_len = enic_cq_rx_desc_n_bytes(&cqd);
1286+ else
1287+ rx_pkt_len = 0;
1288+
1289+ /* Get the mbuf to return and replace with one just allocated */
1290+ rxmb = rq->mbuf_ring[rx_id];
1291+ rq->mbuf_ring[rx_id] = nmb;
1292+
1293+ /* Increment cqd, rqd, mbuf_table index */
1294+ rx_id++;
1295+ if (unlikely(rx_id == rq->ring.desc_count)) {
1296+ rx_id = 0;
1297+ cq->last_color = cq->last_color ? 0 : 1;
1298+ }
1299+
1300+ /* Prefetch next mbuf & desc while processing current one */
1301+ cqd_ptr = (struct cq_desc *)(cq->ring.descs) + rx_id;
1302+ rte_enic_prefetch(cqd_ptr);
1303+ rte_enic_prefetch(rq->mbuf_ring[rx_id]);
1304+ rte_enic_prefetch((struct rq_enet_desc *)(rq->ring.descs)
1305+ + rx_id);
1306+
1307+ /* Push descriptor for newly allocated mbuf */
1308+ dma_addr = (dma_addr_t)(nmb->buf_physaddr + nmb->data_off);
1309+ rqd_ptr->address = rte_cpu_to_le_64(dma_addr);
1310+ rqd_ptr->length_type = cpu_to_le16(nmb->buf_len);
1311+
1312+ /* Fill in the rest of the mbuf */
1313+ rxmb->data_off = RTE_PKTMBUF_HEADROOM;
1314+ rxmb->nb_segs = 1;
1315+ rxmb->next = NULL;
1316+ rxmb->pkt_len = rx_pkt_len;
1317+ rxmb->data_len = rx_pkt_len;
1318+ rxmb->port = enic->port_id;
1319+ rxmb->ol_flags = ol_err_flags;
1320+ if (!ol_err_flags)
1321+ enic_cq_rx_to_pkt_flags(&cqd, rxmb);
1322+ rxmb->packet_type = enic_cq_rx_flags_to_pkt_type(&cqd);
1323+
1324+ /* prefetch mbuf data for caller */
1325+ rte_packet_prefetch(RTE_PTR_ADD(rxmb->buf_addr,
1326+ RTE_PKTMBUF_HEADROOM));
1327+
1328+ /* store the mbuf address into the next entry of the array */
1329+ rx_pkts[nb_rx++] = rxmb;
1330+ }
1331+
1332+ nb_hold += nb_rx;
1333+ cq->to_clean = rx_id;
1334+
1335+ if (nb_hold > rq->rx_free_thresh) {
1336+ rq->posted_index = enic_ring_add(rq->ring.desc_count,
1337+ rq->posted_index, nb_hold);
1338+ nb_hold = 0;
1339+ rte_mb();
1340+ iowrite32(rq->posted_index, &rq->ctrl->posted_index);
1341+ }
1342+
1343+ rq->rx_nb_hold = nb_hold;
1344+
1345+ return nb_rx;
1346+}
Todd Foggoaa292c8c2016-04-06 09:57:01 -04001347--
13481.9.1
1349