New upstream version 18.11-rc1
[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;
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         start = 0;
58         while (nb_pkts--) {
59                 enetc_clean_tx_ring(tx_ring);
60                 tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
61                 txbd = ENETC_TXBD(*tx_ring, i);
62                 tx_swbd = &tx_ring->q_swbd[i];
63                 txbd->frm_len = tx_pkts[start]->pkt_len;
64                 txbd->buf_len = txbd->frm_len;
65                 txbd->flags = rte_cpu_to_le_16(ENETC_TXBD_FLAGS_F);
66                 txbd->addr = (uint64_t)(uintptr_t)
67                 rte_cpu_to_le_64((size_t)tx_swbd->buffer_addr->buf_addr +
68                                  tx_swbd->buffer_addr->data_off);
69                 i++;
70                 start++;
71                 if (unlikely(i == tx_ring->bd_count))
72                         i = 0;
73         }
74
75         tx_ring->next_to_use = i;
76         enetc_wr_reg(tx_ring->tcir, i);
77         return start;
78 }
79
80 int
81 enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
82 {
83         struct enetc_swbd *rx_swbd;
84         union enetc_rx_bd *rxbd;
85         int i, j;
86
87         i = rx_ring->next_to_use;
88         rx_swbd = &rx_ring->q_swbd[i];
89         rxbd = ENETC_RXBD(*rx_ring, i);
90         for (j = 0; j < buff_cnt; j++) {
91                 rx_swbd->buffer_addr =
92                         rte_cpu_to_le_64(rte_mbuf_raw_alloc(rx_ring->mb_pool));
93                 rxbd->w.addr = (uint64_t)(uintptr_t)
94                                rx_swbd->buffer_addr->buf_addr +
95                                rx_swbd->buffer_addr->data_off;
96                 /* clear 'R" as well */
97                 rxbd->r.lstatus = 0;
98                 rx_swbd++;
99                 rxbd++;
100                 i++;
101                 if (unlikely(i == rx_ring->bd_count)) {
102                         i = 0;
103                         rxbd = ENETC_RXBD(*rx_ring, 0);
104                         rx_swbd = &rx_ring->q_swbd[i];
105                 }
106         }
107
108         if (likely(j)) {
109                 rx_ring->next_to_alloc = i;
110                 rx_ring->next_to_use = i;
111                 enetc_wr_reg(rx_ring->rcir, i);
112         }
113
114         return j;
115 }
116
117
118 static inline void __attribute__((hot))
119 enetc_dev_rx_parse(struct rte_mbuf *m, uint16_t parse_results)
120 {
121         ENETC_PMD_DP_DEBUG("parse summary = 0x%x   ", parse_results);
122
123         m->packet_type = RTE_PTYPE_UNKNOWN;
124         switch (parse_results) {
125         case ENETC_PKT_TYPE_ETHER:
126                 m->packet_type = RTE_PTYPE_L2_ETHER;
127                 break;
128         case ENETC_PKT_TYPE_IPV4:
129                 m->packet_type = RTE_PTYPE_L2_ETHER |
130                                  RTE_PTYPE_L3_IPV4;
131                 break;
132         case ENETC_PKT_TYPE_IPV6:
133                 m->packet_type = RTE_PTYPE_L2_ETHER |
134                                  RTE_PTYPE_L3_IPV6;
135                 break;
136         case ENETC_PKT_TYPE_IPV4_TCP:
137                 m->packet_type = RTE_PTYPE_L2_ETHER |
138                                  RTE_PTYPE_L3_IPV4 |
139                                  RTE_PTYPE_L4_TCP;
140                 break;
141         case ENETC_PKT_TYPE_IPV6_TCP:
142                 m->packet_type = RTE_PTYPE_L2_ETHER |
143                                  RTE_PTYPE_L3_IPV6 |
144                                  RTE_PTYPE_L4_TCP;
145                 break;
146         case ENETC_PKT_TYPE_IPV4_UDP:
147                 m->packet_type = RTE_PTYPE_L2_ETHER |
148                                  RTE_PTYPE_L3_IPV4 |
149                                  RTE_PTYPE_L4_UDP;
150                 break;
151         case ENETC_PKT_TYPE_IPV6_UDP:
152                 m->packet_type = RTE_PTYPE_L2_ETHER |
153                                  RTE_PTYPE_L3_IPV6 |
154                                  RTE_PTYPE_L4_UDP;
155                 break;
156         case ENETC_PKT_TYPE_IPV4_SCTP:
157                 m->packet_type = RTE_PTYPE_L2_ETHER |
158                                  RTE_PTYPE_L3_IPV4 |
159                                  RTE_PTYPE_L4_SCTP;
160                 break;
161         case ENETC_PKT_TYPE_IPV6_SCTP:
162                 m->packet_type = RTE_PTYPE_L2_ETHER |
163                                  RTE_PTYPE_L3_IPV6 |
164                                  RTE_PTYPE_L4_SCTP;
165                 break;
166         case ENETC_PKT_TYPE_IPV4_ICMP:
167                 m->packet_type = RTE_PTYPE_L2_ETHER |
168                                  RTE_PTYPE_L3_IPV4 |
169                                  RTE_PTYPE_L4_ICMP;
170                 break;
171         case ENETC_PKT_TYPE_IPV6_ICMP:
172                 m->packet_type = RTE_PTYPE_L2_ETHER |
173                                  RTE_PTYPE_L3_IPV6 |
174                                  RTE_PTYPE_L4_ICMP;
175                 break;
176         /* More switch cases can be added */
177         default:
178                 m->packet_type = RTE_PTYPE_UNKNOWN;
179         }
180 }
181
182 static int
183 enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
184                     struct rte_mbuf **rx_pkts,
185                     int work_limit)
186 {
187         int rx_frm_cnt = 0;
188         int cleaned_cnt, i;
189         struct enetc_swbd *rx_swbd;
190
191         cleaned_cnt = enetc_bd_unused(rx_ring);
192         /* next descriptor to process */
193         i = rx_ring->next_to_clean;
194         rx_swbd = &rx_ring->q_swbd[i];
195         while (likely(rx_frm_cnt < work_limit)) {
196                 union enetc_rx_bd *rxbd;
197                 uint32_t bd_status;
198
199                 if (cleaned_cnt >= ENETC_RXBD_BUNDLE) {
200                         int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt);
201
202                         cleaned_cnt -= count;
203                 }
204
205                 rxbd = ENETC_RXBD(*rx_ring, i);
206                 bd_status = rte_le_to_cpu_32(rxbd->r.lstatus);
207                 if (!bd_status)
208                         break;
209
210                 rx_swbd->buffer_addr->pkt_len = rxbd->r.buf_len;
211                 rx_swbd->buffer_addr->data_len = rxbd->r.buf_len;
212                 rx_swbd->buffer_addr->hash.rss = rxbd->r.rss_hash;
213                 rx_swbd->buffer_addr->ol_flags = 0;
214                 enetc_dev_rx_parse(rx_swbd->buffer_addr,
215                                    rxbd->r.parse_summary);
216                 rx_pkts[rx_frm_cnt] = rx_swbd->buffer_addr;
217                 cleaned_cnt++;
218                 rx_swbd++;
219                 i++;
220                 if (unlikely(i == rx_ring->bd_count)) {
221                         i = 0;
222                         rx_swbd = &rx_ring->q_swbd[i];
223                 }
224
225                 rx_ring->next_to_clean = i;
226                 rx_frm_cnt++;
227         }
228
229         return rx_frm_cnt;
230 }
231
232 uint16_t
233 enetc_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
234                 uint16_t nb_pkts)
235 {
236         struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
237
238         return enetc_clean_rx_ring(rx_ring, rx_pkts, nb_pkts);
239 }