common/mlx5: move to formal ASO action API
[dpdk.git] / drivers / net / nfb / nfb_rx.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Cesnet
3  * Copyright(c) 2019 Netcope Technologies, a.s. <info@netcope.com>
4  * All rights reserved.
5  */
6
7 #ifndef _NFB_RX_H_
8 #define _NFB_RX_H_
9
10 #include <nfb/nfb.h>
11 #include <nfb/ndp.h>
12
13 #include <rte_mbuf.h>
14 #include <rte_ethdev.h>
15
16 #define NFB_TIMESTAMP_FLAG (1 << 0)
17
18 extern uint64_t nfb_timestamp_rx_dynflag;
19 extern int nfb_timestamp_dynfield_offset;
20
21 static inline rte_mbuf_timestamp_t *
22 nfb_timestamp_dynfield(struct rte_mbuf *mbuf)
23 {
24         return RTE_MBUF_DYNFIELD(mbuf,
25                 nfb_timestamp_dynfield_offset, rte_mbuf_timestamp_t *);
26 }
27
28 struct ndp_rx_queue {
29         struct nfb_device *nfb;      /* nfb dev structure */
30         struct ndp_queue *queue;     /* rx queue */
31         uint16_t rx_queue_id;        /* index */
32         uint8_t in_port;             /* port */
33         uint8_t flags;               /* setup flags */
34
35         struct rte_mempool *mb_pool; /* memory pool to allocate packets */
36         uint16_t buf_size;           /* mbuf size */
37
38         volatile uint64_t rx_pkts;   /* packets read */
39         volatile uint64_t rx_bytes;  /* bytes read */
40         volatile uint64_t err_pkts;  /* erroneous packets */
41 };
42
43 /**
44  * Initialize ndp_rx_queue structure
45  *
46  * @param nfb
47  *   Pointer to nfb device structure.
48  * @param rx_queue_id
49  *   RX queue index.
50  * @param port_id
51  *   Device [external] port identifier.
52  * @param mb_pool
53  *   Memory pool for buffer allocations.
54  * @param[out] rxq
55  *   Pointer to ndp_rx_queue output structure
56  * @return
57  *   0 on success, a negative errno value otherwise.
58  */
59 int
60 nfb_eth_rx_queue_init(struct nfb_device *nfb,
61         uint16_t rx_queue_id,
62         uint16_t port_id,
63         struct rte_mempool *mb_pool,
64         struct ndp_rx_queue *rxq);
65
66 /**
67  * DPDK callback to setup a RX queue for use.
68  *
69  * @param dev
70  *   Pointer to Ethernet device structure.
71  * @param idx
72  *   RX queue index.
73  * @param desc
74  *   Number of descriptors to configure in queue.
75  * @param socket
76  *   NUMA socket on which memory must be allocated.
77  * @param[in] conf
78  *   Thresholds parameters.
79  * @param mb_pool
80  *   Memory pool for buffer allocations.
81  *
82  * @return
83  *   0 on success, a negative errno value otherwise.
84  */
85 int
86 nfb_eth_rx_queue_setup(struct rte_eth_dev *dev,
87         uint16_t rx_queue_id,
88         uint16_t nb_rx_desc __rte_unused,
89         unsigned int socket_id,
90         const struct rte_eth_rxconf *rx_conf __rte_unused,
91         struct rte_mempool *mb_pool);
92
93 /**
94  * DPDK callback to release a RX queue.
95  *
96  * @param dpdk_rxq
97  *   Generic RX queue pointer.
98  */
99 void
100 nfb_eth_rx_queue_release(void *q);
101
102 /**
103  * Start traffic on Rx queue.
104  *
105  * @param dev
106  *   Pointer to Ethernet device structure.
107  * @param txq_id
108  *   RX queue index.
109  * @return
110  *   0 on success, a negative errno value otherwise.
111  */
112 int
113 nfb_eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rxq_id);
114
115 /**
116  * Stop traffic on Rx queue.
117  *
118  * @param dev
119  *   Pointer to Ethernet device structure.
120  * @param txq_id
121  *   RX queue index.
122  */
123 int
124 nfb_eth_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rxq_id);
125
126 /**
127  * DPDK callback for RX.
128  *
129  * @param dpdk_rxq
130  *   Generic pointer to RX queue structure.
131  * @param[out] bufs
132  *   Array to store received packets.
133  * @param nb_pkts
134  *   Maximum number of packets in array.
135  *
136  * @return
137  *   Number of packets successfully received (<= nb_pkts).
138  */
139 static __rte_always_inline uint16_t
140 nfb_eth_ndp_rx(void *queue,
141         struct rte_mbuf **bufs,
142         uint16_t nb_pkts)
143 {
144         struct ndp_rx_queue *ndp = queue;
145         uint8_t timestamping_enabled;
146         uint16_t packet_size;
147         uint64_t num_bytes = 0;
148         uint16_t num_rx;
149         unsigned int i;
150
151         const uint16_t buf_size = ndp->buf_size;
152
153         struct rte_mbuf *mbuf;
154         struct ndp_packet packets[nb_pkts];
155
156         struct rte_mbuf *mbufs[nb_pkts];
157
158         if (unlikely(ndp->queue == NULL || nb_pkts == 0)) {
159                 RTE_LOG(ERR, PMD, "RX invalid arguments!\n");
160                 return 0;
161         }
162
163         timestamping_enabled = ndp->flags & NFB_TIMESTAMP_FLAG;
164
165         /* returns either all or nothing */
166         i = rte_pktmbuf_alloc_bulk(ndp->mb_pool, mbufs, nb_pkts);
167         if (unlikely(i != 0))
168                 return 0;
169
170         num_rx = ndp_rx_burst_get(ndp->queue, packets, nb_pkts);
171
172         if (unlikely(num_rx != nb_pkts)) {
173                 for (i = num_rx; i < nb_pkts; i++)
174                         rte_pktmbuf_free(mbufs[i]);
175         }
176
177         nb_pkts = num_rx;
178
179         num_rx = 0;
180         /*
181          * Reads the given number of packets from NDP queue given
182          * by queue and copies the packet data into a newly allocated mbuf
183          * to return.
184          */
185         for (i = 0; i < nb_pkts; ++i) {
186                 mbuf = mbufs[i];
187
188                 /* get the space available for data in the mbuf */
189                 packet_size = packets[i].data_length;
190
191                 if (likely(packet_size <= buf_size)) {
192                         /* NDP packet will fit in one mbuf, go ahead and copy */
193                         rte_memcpy(rte_pktmbuf_mtod(mbuf, void *),
194                                 packets[i].data, packet_size);
195
196                         mbuf->data_len = (uint16_t)packet_size;
197
198                         mbuf->pkt_len = packet_size;
199                         mbuf->port = ndp->in_port;
200                         mbuf->ol_flags = 0;
201
202                         if (timestamping_enabled) {
203                                 rte_mbuf_timestamp_t timestamp;
204
205                                 /* nanoseconds */
206                                 timestamp =
207                                         rte_le_to_cpu_32(*((uint32_t *)
208                                         (packets[i].header + 4)));
209                                 timestamp <<= 32;
210                                 /* seconds */
211                                 timestamp |=
212                                         rte_le_to_cpu_32(*((uint32_t *)
213                                         (packets[i].header + 8)));
214                                 *nfb_timestamp_dynfield(mbuf) = timestamp;
215                                 mbuf->ol_flags |= nfb_timestamp_rx_dynflag;
216                         }
217
218                         bufs[num_rx++] = mbuf;
219                         num_bytes += packet_size;
220                 } else {
221                         /*
222                          * NDP packet will not fit in one mbuf,
223                          * scattered mode is not enabled, drop packet
224                          */
225                         rte_pktmbuf_free(mbuf);
226                 }
227         }
228
229         ndp_rx_burst_put(ndp->queue);
230
231         ndp->rx_pkts += num_rx;
232         ndp->rx_bytes += num_bytes;
233         return num_rx;
234 }
235
236 #endif /* _NFB_RX_H_ */