New upstream version 18.11.2
[deb_dpdk.git] / drivers / net / enetc / enetc_rxtx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2018 NXP
3  */
4
5 #include <stdbool.h>
6 #include <stdint.h>
7 #include <unistd.h>
8
9 #include "rte_ethdev.h"
10 #include "rte_malloc.h"
11 #include "rte_memzone.h"
12
13 #include "base/enetc_hw.h"
14 #include "enetc.h"
15 #include "enetc_logs.h"
16
17 #define ENETC_RXBD_BUNDLE 8 /* Number of BDs to update at once */
18
19 static int
20 enetc_clean_tx_ring(struct enetc_bdr *tx_ring)
21 {
22         int tx_frm_cnt = 0;
23         struct enetc_swbd *tx_swbd;
24         int i;
25
26         i = tx_ring->next_to_clean;
27         tx_swbd = &tx_ring->q_swbd[i];
28         while ((int)(enetc_rd_reg(tx_ring->tcisr) &
29                ENETC_TBCISR_IDX_MASK) != i) {
30                 rte_pktmbuf_free(tx_swbd->buffer_addr);
31                 tx_swbd->buffer_addr = NULL;
32                 tx_swbd++;
33                 i++;
34                 if (unlikely(i == tx_ring->bd_count)) {
35                         i = 0;
36                         tx_swbd = &tx_ring->q_swbd[0];
37                 }
38
39                 tx_frm_cnt++;
40         }
41
42         tx_ring->next_to_clean = i;
43         return tx_frm_cnt++;
44 }
45
46 uint16_t
47 enetc_xmit_pkts(void *tx_queue,
48                 struct rte_mbuf **tx_pkts,
49                 uint16_t nb_pkts)
50 {
51         struct enetc_swbd *tx_swbd;
52         int i, start, bds_to_use;
53         struct enetc_tx_bd *txbd;
54         struct enetc_bdr *tx_ring = (struct enetc_bdr *)tx_queue;
55
56         i = tx_ring->next_to_use;
57
58         bds_to_use = enetc_bd_unused(tx_ring);
59         if (bds_to_use < nb_pkts)
60                 nb_pkts = bds_to_use;
61
62         start = 0;
63         while (nb_pkts--) {
64                 enetc_clean_tx_ring(tx_ring);
65                 tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
66                 txbd = ENETC_TXBD(*tx_ring, i);
67                 tx_swbd = &tx_ring->q_swbd[i];
68                 txbd->frm_len = tx_pkts[start]->pkt_len;
69                 txbd->buf_len = txbd->frm_len;
70                 txbd->flags = rte_cpu_to_le_16(ENETC_TXBD_FLAGS_F);
71                 txbd->addr = (uint64_t)(uintptr_t)
72                 rte_cpu_to_le_64((size_t)tx_swbd->buffer_addr->buf_addr +
73                                  tx_swbd->buffer_addr->data_off);
74                 i++;
75                 start++;
76                 if (unlikely(i == tx_ring->bd_count))
77                         i = 0;
78         }
79
80         tx_ring->next_to_use = i;
81         enetc_wr_reg(tx_ring->tcir, i);
82         return start;
83 }
84
85 int
86 enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
87 {
88         struct enetc_swbd *rx_swbd;
89         union enetc_rx_bd *rxbd;
90         int i, j;
91
92         i = rx_ring->next_to_use;
93         rx_swbd = &rx_ring->q_swbd[i];
94         rxbd = ENETC_RXBD(*rx_ring, i);
95         for (j = 0; j < buff_cnt; j++) {
96                 rx_swbd->buffer_addr = (void *)(uintptr_t)
97                         rte_cpu_to_le_64((uint64_t)(uintptr_t)
98                                         rte_pktmbuf_alloc(rx_ring->mb_pool));
99                 rxbd->w.addr = (uint64_t)(uintptr_t)
100                                rx_swbd->buffer_addr->buf_addr +
101                                rx_swbd->buffer_addr->data_off;
102                 /* clear 'R" as well */
103                 rxbd->r.lstatus = 0;
104                 rx_swbd++;
105                 rxbd++;
106                 i++;
107                 if (unlikely(i == rx_ring->bd_count)) {
108                         i = 0;
109                         rxbd = ENETC_RXBD(*rx_ring, 0);
110                         rx_swbd = &rx_ring->q_swbd[i];
111                 }
112         }
113
114         if (likely(j)) {
115                 rx_ring->next_to_alloc = i;
116                 rx_ring->next_to_use = i;
117                 enetc_wr_reg(rx_ring->rcir, i);
118         }
119
120         return j;
121 }
122
123
124 static inline void __attribute__((hot))
125 enetc_dev_rx_parse(struct rte_mbuf *m, uint16_t parse_results)
126 {
127         ENETC_PMD_DP_DEBUG("parse summary = 0x%x   ", parse_results);
128
129         m->packet_type = RTE_PTYPE_UNKNOWN;
130         switch (parse_results) {
131         case ENETC_PKT_TYPE_ETHER:
132                 m->packet_type = RTE_PTYPE_L2_ETHER;
133                 break;
134         case ENETC_PKT_TYPE_IPV4:
135                 m->packet_type = RTE_PTYPE_L2_ETHER |
136                                  RTE_PTYPE_L3_IPV4;
137                 break;
138         case ENETC_PKT_TYPE_IPV6:
139                 m->packet_type = RTE_PTYPE_L2_ETHER |
140                                  RTE_PTYPE_L3_IPV6;
141                 break;
142         case ENETC_PKT_TYPE_IPV4_TCP:
143                 m->packet_type = RTE_PTYPE_L2_ETHER |
144                                  RTE_PTYPE_L3_IPV4 |
145                                  RTE_PTYPE_L4_TCP;
146                 break;
147         case ENETC_PKT_TYPE_IPV6_TCP:
148                 m->packet_type = RTE_PTYPE_L2_ETHER |
149                                  RTE_PTYPE_L3_IPV6 |
150                                  RTE_PTYPE_L4_TCP;
151                 break;
152         case ENETC_PKT_TYPE_IPV4_UDP:
153                 m->packet_type = RTE_PTYPE_L2_ETHER |
154                                  RTE_PTYPE_L3_IPV4 |
155                                  RTE_PTYPE_L4_UDP;
156                 break;
157         case ENETC_PKT_TYPE_IPV6_UDP:
158                 m->packet_type = RTE_PTYPE_L2_ETHER |
159                                  RTE_PTYPE_L3_IPV6 |
160                                  RTE_PTYPE_L4_UDP;
161                 break;
162         case ENETC_PKT_TYPE_IPV4_SCTP:
163                 m->packet_type = RTE_PTYPE_L2_ETHER |
164                                  RTE_PTYPE_L3_IPV4 |
165                                  RTE_PTYPE_L4_SCTP;
166                 break;
167         case ENETC_PKT_TYPE_IPV6_SCTP:
168                 m->packet_type = RTE_PTYPE_L2_ETHER |
169                                  RTE_PTYPE_L3_IPV6 |
170                                  RTE_PTYPE_L4_SCTP;
171                 break;
172         case ENETC_PKT_TYPE_IPV4_ICMP:
173                 m->packet_type = RTE_PTYPE_L2_ETHER |
174                                  RTE_PTYPE_L3_IPV4 |
175                                  RTE_PTYPE_L4_ICMP;
176                 break;
177         case ENETC_PKT_TYPE_IPV6_ICMP:
178                 m->packet_type = RTE_PTYPE_L2_ETHER |
179                                  RTE_PTYPE_L3_IPV6 |
180                                  RTE_PTYPE_L4_ICMP;
181                 break;
182         /* More switch cases can be added */
183         default:
184                 m->packet_type = RTE_PTYPE_UNKNOWN;
185         }
186 }
187
188 static int
189 enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
190                     struct rte_mbuf **rx_pkts,
191                     int work_limit)
192 {
193         int rx_frm_cnt = 0;
194         int cleaned_cnt, i;
195         struct enetc_swbd *rx_swbd;
196
197         cleaned_cnt = enetc_bd_unused(rx_ring);
198         /* next descriptor to process */
199         i = rx_ring->next_to_clean;
200         rx_swbd = &rx_ring->q_swbd[i];
201         while (likely(rx_frm_cnt < work_limit)) {
202                 union enetc_rx_bd *rxbd;
203                 uint32_t bd_status;
204
205                 if (cleaned_cnt >= ENETC_RXBD_BUNDLE) {
206                         int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt);
207
208                         cleaned_cnt -= count;
209                 }
210
211                 rxbd = ENETC_RXBD(*rx_ring, i);
212                 bd_status = rte_le_to_cpu_32(rxbd->r.lstatus);
213                 if (!bd_status)
214                         break;
215
216                 rx_swbd->buffer_addr->pkt_len = rxbd->r.buf_len;
217                 rx_swbd->buffer_addr->data_len = rxbd->r.buf_len;
218                 rx_swbd->buffer_addr->hash.rss = rxbd->r.rss_hash;
219                 rx_swbd->buffer_addr->ol_flags = 0;
220                 enetc_dev_rx_parse(rx_swbd->buffer_addr,
221                                    rxbd->r.parse_summary);
222                 rx_pkts[rx_frm_cnt] = rx_swbd->buffer_addr;
223                 cleaned_cnt++;
224                 rx_swbd++;
225                 i++;
226                 if (unlikely(i == rx_ring->bd_count)) {
227                         i = 0;
228                         rx_swbd = &rx_ring->q_swbd[i];
229                 }
230
231                 rx_ring->next_to_clean = i;
232                 rx_frm_cnt++;
233         }
234
235         return rx_frm_cnt;
236 }
237
238 uint16_t
239 enetc_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
240                 uint16_t nb_pkts)
241 {
242         struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
243
244         return enetc_clean_rx_ring(rx_ring, rx_pkts, nb_pkts);
245 }