Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
3 : : * Copyright(c) 2018 Synopsys, Inc. All rights reserved.
4 : : */
5 : :
6 : : #include "axgbe_ethdev.h"
7 : : #include "axgbe_common.h"
8 : : #include "axgbe_phy.h"
9 : : #include "axgbe_rxtx.h"
10 : :
11 : 0 : static uint32_t bitrev32(uint32_t x)
12 : : {
13 : 0 : x = (x >> 16) | (x << 16);
14 : 0 : x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
15 : 0 : x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
16 : 0 : x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
17 : 0 : x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
18 : 0 : return x;
19 : : }
20 : :
21 : : /*MSB set bit from 32 to 1*/
22 : 0 : static int get_lastbit_set(int x)
23 : : {
24 : : int r = 32;
25 : :
26 [ # # ]: 0 : if (!x)
27 : : return 0;
28 [ # # ]: 0 : if (!(x & 0xffff0000)) {
29 : 0 : x <<= 16;
30 : : r -= 16;
31 : : }
32 [ # # ]: 0 : if (!(x & 0xff000000)) {
33 : 0 : x <<= 8;
34 : 0 : r -= 8;
35 : : }
36 [ # # ]: 0 : if (!(x & 0xf0000000)) {
37 : 0 : x <<= 4;
38 : 0 : r -= 4;
39 : : }
40 [ # # ]: 0 : if (!(x & 0xc0000000)) {
41 : 0 : x <<= 2;
42 : 0 : r -= 2;
43 : : }
44 [ # # ]: 0 : if (!(x & 0x80000000)) {
45 : : x <<= 1;
46 : 0 : r -= 1;
47 : : }
48 : : return r;
49 : : }
50 : :
51 : : static inline unsigned int axgbe_get_max_frame(struct axgbe_port *pdata)
52 : : {
53 : 0 : return pdata->eth_dev->data->mtu + RTE_ETHER_HDR_LEN +
54 : : RTE_ETHER_CRC_LEN + RTE_VLAN_HLEN;
55 : : }
56 : :
57 : : /* query busy bit */
58 : : static int mdio_complete(struct axgbe_port *pdata)
59 : : {
60 [ # # # # ]: 0 : if (!AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, BUSY))
61 : : return 1;
62 : :
63 : : return 0;
64 : : }
65 : :
66 : 0 : static int axgbe_write_ext_mii_regs(struct axgbe_port *pdata, int addr,
67 : : int reg, u16 val)
68 : : {
69 : : unsigned int mdio_sca, mdio_sccd;
70 : : uint64_t timeout;
71 : :
72 : : mdio_sca = 0;
73 : 0 : AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
74 : 0 : AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
75 : 0 : AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
76 : :
77 : : mdio_sccd = 0;
78 : 0 : AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, val);
79 : : AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 1);
80 : 0 : AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
81 : 0 : AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
82 : :
83 : 0 : timeout = rte_get_timer_cycles() + rte_get_timer_hz();
84 [ # # ]: 0 : while (time_before(rte_get_timer_cycles(), timeout)) {
85 : 0 : rte_delay_us(100);
86 : : if (mdio_complete(pdata))
87 : : return 0;
88 : : }
89 : :
90 : 0 : PMD_DRV_LOG(ERR, "Mdio write operation timed out\n");
91 : 0 : return -ETIMEDOUT;
92 : : }
93 : :
94 : 0 : static int axgbe_read_ext_mii_regs(struct axgbe_port *pdata, int addr,
95 : : int reg)
96 : : {
97 : : unsigned int mdio_sca, mdio_sccd;
98 : : uint64_t timeout;
99 : :
100 : : mdio_sca = 0;
101 : 0 : AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
102 : 0 : AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
103 : 0 : AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
104 : :
105 : : mdio_sccd = 0;
106 : : AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 3);
107 : : AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
108 : 0 : AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
109 : :
110 : 0 : timeout = rte_get_timer_cycles() + rte_get_timer_hz();
111 : :
112 [ # # ]: 0 : while (time_before(rte_get_timer_cycles(), timeout)) {
113 : 0 : rte_delay_us(100);
114 : : if (mdio_complete(pdata))
115 : 0 : goto success;
116 : : }
117 : :
118 : 0 : PMD_DRV_LOG(ERR, "Mdio read operation timed out\n");
119 : 0 : return -ETIMEDOUT;
120 : :
121 : : success:
122 : 0 : return AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA);
123 : : }
124 : :
125 : 0 : static int axgbe_set_ext_mii_mode(struct axgbe_port *pdata, unsigned int port,
126 : : enum axgbe_mdio_mode mode)
127 : : {
128 : : unsigned int reg_val = 0;
129 : :
130 [ # # # ]: 0 : switch (mode) {
131 : 0 : case AXGBE_MDIO_MODE_CL22:
132 [ # # ]: 0 : if (port > AXGMAC_MAX_C22_PORT)
133 : : return -EINVAL;
134 : 0 : reg_val |= (1 << port);
135 : 0 : break;
136 : : case AXGBE_MDIO_MODE_CL45:
137 : : break;
138 : : default:
139 : : return -EINVAL;
140 : : }
141 : 0 : AXGMAC_IOWRITE(pdata, MAC_MDIOCL22R, reg_val);
142 : :
143 : 0 : return 0;
144 : : }
145 : :
146 : 0 : static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
147 : : int prtad __rte_unused, int mmd_reg)
148 : : {
149 : : unsigned int mmd_address, index, offset;
150 : : int mmd_data;
151 : :
152 [ # # ]: 0 : if (mmd_reg & MII_ADDR_C45)
153 : 0 : mmd_address = mmd_reg & ~MII_ADDR_C45;
154 : : else
155 : 0 : mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
156 : :
157 : : /* The PCS registers are accessed using mmio. The underlying
158 : : * management interface uses indirect addressing to access the MMD
159 : : * register sets. This requires accessing of the PCS register in two
160 : : * phases, an address phase and a data phase.
161 : : *
162 : : * The mmio interface is based on 16-bit offsets and values. All
163 : : * register offsets must therefore be adjusted by left shifting the
164 : : * offset 1 bit and reading 16 bits of data.
165 : : */
166 : 0 : mmd_address <<= 1;
167 : 0 : index = mmd_address & ~pdata->xpcs_window_mask;
168 : 0 : offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
169 : :
170 : 0 : pthread_mutex_lock(&pdata->xpcs_mutex);
171 : :
172 : 0 : XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
173 : 0 : mmd_data = XPCS16_IOREAD(pdata, offset);
174 : :
175 : 0 : pthread_mutex_unlock(&pdata->xpcs_mutex);
176 : :
177 : 0 : return mmd_data;
178 : : }
179 : :
180 : 0 : static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
181 : : int prtad __rte_unused,
182 : : int mmd_reg, int mmd_data)
183 : : {
184 : : unsigned int mmd_address, index, offset;
185 : :
186 [ # # ]: 0 : if (mmd_reg & MII_ADDR_C45)
187 : 0 : mmd_address = mmd_reg & ~MII_ADDR_C45;
188 : : else
189 : 0 : mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
190 : :
191 : : /* The PCS registers are accessed using mmio. The underlying
192 : : * management interface uses indirect addressing to access the MMD
193 : : * register sets. This requires accessing of the PCS register in two
194 : : * phases, an address phase and a data phase.
195 : : *
196 : : * The mmio interface is based on 16-bit offsets and values. All
197 : : * register offsets must therefore be adjusted by left shifting the
198 : : * offset 1 bit and writing 16 bits of data.
199 : : */
200 : 0 : mmd_address <<= 1;
201 : 0 : index = mmd_address & ~pdata->xpcs_window_mask;
202 : 0 : offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
203 : :
204 : 0 : pthread_mutex_lock(&pdata->xpcs_mutex);
205 : :
206 : 0 : XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
207 : 0 : XPCS16_IOWRITE(pdata, offset, mmd_data);
208 : :
209 : 0 : pthread_mutex_unlock(&pdata->xpcs_mutex);
210 : 0 : }
211 : :
212 : 0 : static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
213 : : int mmd_reg)
214 : : {
215 [ # # ]: 0 : switch (pdata->vdata->xpcs_access) {
216 : 0 : case AXGBE_XPCS_ACCESS_V1:
217 : 0 : PMD_DRV_LOG(ERR, "PHY_Version 1 is not supported\n");
218 : 0 : return -1;
219 : 0 : case AXGBE_XPCS_ACCESS_V2:
220 : : default:
221 : 0 : return axgbe_read_mmd_regs_v2(pdata, prtad, mmd_reg);
222 : : }
223 : : }
224 : :
225 : 0 : static void axgbe_write_mmd_regs(struct axgbe_port *pdata, int prtad,
226 : : int mmd_reg, int mmd_data)
227 : : {
228 [ # # ]: 0 : switch (pdata->vdata->xpcs_access) {
229 : 0 : case AXGBE_XPCS_ACCESS_V1:
230 : 0 : PMD_DRV_LOG(ERR, "PHY_Version 1 is not supported\n");
231 : 0 : return;
232 : 0 : case AXGBE_XPCS_ACCESS_V2:
233 : : default:
234 : 0 : return axgbe_write_mmd_regs_v2(pdata, prtad, mmd_reg, mmd_data);
235 : : }
236 : : }
237 : :
238 : 0 : static int axgbe_set_speed(struct axgbe_port *pdata, int speed)
239 : : {
240 : : unsigned int ss;
241 : :
242 [ # # # # ]: 0 : switch (speed) {
243 : : case SPEED_1000:
244 : : ss = 0x03;
245 : : break;
246 : 0 : case SPEED_2500:
247 : : ss = 0x02;
248 : 0 : break;
249 : 0 : case SPEED_10000:
250 : : ss = 0x00;
251 : 0 : break;
252 : : default:
253 : : return -EINVAL;
254 : : }
255 : :
256 [ # # ]: 0 : if (AXGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) != ss)
257 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, ss);
258 : :
259 : : return 0;
260 : : }
261 : :
262 : 0 : static int axgbe_disable_tx_flow_control(struct axgbe_port *pdata)
263 : : {
264 : : unsigned int max_q_count, q_count;
265 : : unsigned int reg, reg_val;
266 : : unsigned int i;
267 : :
268 : : /* Clear MTL flow control */
269 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count; i++)
270 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
271 : :
272 : : /* Clear MAC flow control */
273 : : max_q_count = AXGMAC_MAX_FLOW_CONTROL_QUEUES;
274 : 0 : q_count = RTE_MIN(pdata->tx_q_count,
275 : : max_q_count);
276 : : reg = MAC_Q0TFCR;
277 [ # # ]: 0 : for (i = 0; i < q_count; i++) {
278 : 0 : reg_val = AXGMAC_IOREAD(pdata, reg);
279 : 0 : AXGMAC_SET_BITS(reg_val, MAC_Q0TFCR, TFE, 0);
280 : 0 : AXGMAC_IOWRITE(pdata, reg, reg_val);
281 : :
282 : 0 : reg += MAC_QTFCR_INC;
283 : : }
284 : :
285 : 0 : return 0;
286 : : }
287 : :
288 : 0 : static int axgbe_enable_tx_flow_control(struct axgbe_port *pdata)
289 : : {
290 : : unsigned int max_q_count, q_count;
291 : : unsigned int reg, reg_val;
292 : : unsigned int i;
293 : :
294 : : /* Set MTL flow control */
295 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count; i++) {
296 : : unsigned int ehfc = 0;
297 : :
298 : : /* Flow control thresholds are established */
299 [ # # ]: 0 : if (pdata->rx_rfd[i])
300 : : ehfc = 1;
301 : :
302 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, ehfc);
303 : :
304 [ # # ]: 0 : PMD_DRV_LOG(DEBUG, "flow control %s for RXq%u\n",
305 : : ehfc ? "enabled" : "disabled", i);
306 : : }
307 : :
308 : : /* Set MAC flow control */
309 : : max_q_count = AXGMAC_MAX_FLOW_CONTROL_QUEUES;
310 : 0 : q_count = RTE_MIN(pdata->tx_q_count,
311 : : max_q_count);
312 : : reg = MAC_Q0TFCR;
313 [ # # ]: 0 : for (i = 0; i < q_count; i++) {
314 : 0 : reg_val = AXGMAC_IOREAD(pdata, reg);
315 : :
316 : : /* Enable transmit flow control */
317 : : AXGMAC_SET_BITS(reg_val, MAC_Q0TFCR, TFE, 1);
318 : : /* Set pause time */
319 : 0 : AXGMAC_SET_BITS(reg_val, MAC_Q0TFCR, PT, 0xffff);
320 : :
321 : 0 : AXGMAC_IOWRITE(pdata, reg, reg_val);
322 : :
323 : 0 : reg += MAC_QTFCR_INC;
324 : : }
325 : :
326 : 0 : return 0;
327 : : }
328 : :
329 : : static int axgbe_disable_rx_flow_control(struct axgbe_port *pdata)
330 : : {
331 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RFCR, RFE, 0);
332 : :
333 : 0 : return 0;
334 : : }
335 : :
336 : : static int axgbe_enable_rx_flow_control(struct axgbe_port *pdata)
337 : : {
338 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RFCR, RFE, 1);
339 : :
340 : 0 : return 0;
341 : : }
342 : :
343 : 0 : static int axgbe_config_tx_flow_control(struct axgbe_port *pdata)
344 : : {
345 [ # # ]: 0 : if (pdata->tx_pause)
346 : 0 : axgbe_enable_tx_flow_control(pdata);
347 : : else
348 : 0 : axgbe_disable_tx_flow_control(pdata);
349 : :
350 : 0 : return 0;
351 : : }
352 : :
353 : 0 : static int axgbe_config_rx_flow_control(struct axgbe_port *pdata)
354 : : {
355 [ # # # # ]: 0 : if (pdata->rx_pause)
356 : : axgbe_enable_rx_flow_control(pdata);
357 : : else
358 : : axgbe_disable_rx_flow_control(pdata);
359 : :
360 : 0 : return 0;
361 : : }
362 : :
363 : 0 : static void axgbe_config_flow_control(struct axgbe_port *pdata)
364 : : {
365 : 0 : axgbe_config_tx_flow_control(pdata);
366 : : axgbe_config_rx_flow_control(pdata);
367 : :
368 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RFCR, PFCE, 0);
369 : 0 : }
370 : :
371 : 0 : static void axgbe_queue_flow_control_threshold(struct axgbe_port *pdata,
372 : : unsigned int queue,
373 : : unsigned int q_fifo_size)
374 : : {
375 : : unsigned int frame_fifo_size;
376 : : unsigned int rfa, rfd;
377 : :
378 : 0 : frame_fifo_size = AXGMAC_FLOW_CONTROL_ALIGN(axgbe_get_max_frame(pdata));
379 : :
380 : : /* This path deals with just maximum frame sizes which are
381 : : * limited to a jumbo frame of 9,000 (plus headers, etc.)
382 : : * so we can never exceed the maximum allowable RFA/RFD
383 : : * values.
384 : : */
385 [ # # ]: 0 : if (q_fifo_size <= 2048) {
386 : : /* rx_rfd to zero to signal no flow control */
387 : 0 : pdata->rx_rfa[queue] = 0;
388 : 0 : pdata->rx_rfd[queue] = 0;
389 : 0 : return;
390 : : }
391 : :
392 [ # # ]: 0 : if (q_fifo_size <= 4096) {
393 : : /* Between 2048 and 4096 */
394 : 0 : pdata->rx_rfa[queue] = 0; /* Full - 1024 bytes */
395 : 0 : pdata->rx_rfd[queue] = 1; /* Full - 1536 bytes */
396 : 0 : return;
397 : : }
398 : :
399 [ # # ]: 0 : if (q_fifo_size <= frame_fifo_size) {
400 : : /* Between 4096 and max-frame */
401 : 0 : pdata->rx_rfa[queue] = 2; /* Full - 2048 bytes */
402 : 0 : pdata->rx_rfd[queue] = 5; /* Full - 3584 bytes */
403 : 0 : return;
404 : : }
405 : :
406 [ # # ]: 0 : if (q_fifo_size <= (frame_fifo_size * 3)) {
407 : : /* Between max-frame and 3 max-frames,
408 : : * trigger if we get just over a frame of data and
409 : : * resume when we have just under half a frame left.
410 : : */
411 : 0 : rfa = q_fifo_size - frame_fifo_size;
412 : 0 : rfd = rfa + (frame_fifo_size / 2);
413 : : } else {
414 : : /* Above 3 max-frames - trigger when just over
415 : : * 2 frames of space available
416 : : */
417 : 0 : rfa = frame_fifo_size * 2;
418 : 0 : rfa += AXGMAC_FLOW_CONTROL_UNIT;
419 : 0 : rfd = rfa + frame_fifo_size;
420 : : }
421 : :
422 [ # # ]: 0 : pdata->rx_rfa[queue] = AXGMAC_FLOW_CONTROL_VALUE(rfa);
423 [ # # ]: 0 : pdata->rx_rfd[queue] = AXGMAC_FLOW_CONTROL_VALUE(rfd);
424 : : }
425 : :
426 : 0 : static void axgbe_calculate_flow_control_threshold(struct axgbe_port *pdata)
427 : : {
428 : : unsigned int q_fifo_size;
429 : : unsigned int i;
430 : :
431 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count; i++) {
432 : 0 : q_fifo_size = (pdata->fifo + 1) * AXGMAC_FIFO_UNIT;
433 : :
434 : 0 : axgbe_queue_flow_control_threshold(pdata, i, q_fifo_size);
435 : : }
436 : 0 : }
437 : :
438 : 0 : static void axgbe_config_flow_control_threshold(struct axgbe_port *pdata)
439 : : {
440 : : unsigned int i;
441 : :
442 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count; i++) {
443 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFA,
444 : : pdata->rx_rfa[i]);
445 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFD,
446 : : pdata->rx_rfd[i]);
447 : : }
448 : 0 : }
449 : :
450 : 0 : static int axgbe_enable_rx_vlan_stripping(struct axgbe_port *pdata)
451 : : {
452 : : /* Put the VLAN tag in the Rx descriptor */
453 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLRXS, 1);
454 : :
455 : : /* Don't check the VLAN type */
456 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, DOVLTC, 1);
457 : :
458 : : /* Check only C-TAG (0x8100) packets */
459 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ERSVLM, 0);
460 : :
461 : : /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */
462 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ESVL, 0);
463 : :
464 : : /* Enable VLAN tag stripping */
465 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0x3);
466 : 0 : return 0;
467 : : }
468 : :
469 : 0 : static int axgbe_disable_rx_vlan_stripping(struct axgbe_port *pdata)
470 : : {
471 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0);
472 : 0 : return 0;
473 : : }
474 : :
475 : 0 : static int axgbe_enable_rx_vlan_filtering(struct axgbe_port *pdata)
476 : : {
477 : : /* Enable VLAN filtering */
478 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1);
479 : :
480 : : /* Enable VLAN Hash Table filtering */
481 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1);
482 : :
483 : : /* Disable VLAN tag inverse matching */
484 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0);
485 : :
486 : : /* Only filter on the lower 12-bits of the VLAN tag */
487 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1);
488 : :
489 : : /* In order for the VLAN Hash Table filtering to be effective,
490 : : * the VLAN tag identifier in the VLAN Tag Register must not
491 : : * be zero. Set the VLAN tag identifier to "1" to enable the
492 : : * VLAN Hash Table filtering. This implies that a VLAN tag of
493 : : * 1 will always pass filtering.
494 : : */
495 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1);
496 : 0 : return 0;
497 : : }
498 : :
499 : 0 : static int axgbe_disable_rx_vlan_filtering(struct axgbe_port *pdata)
500 : : {
501 : : /* Disable VLAN filtering */
502 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0);
503 : 0 : return 0;
504 : : }
505 : :
506 : 0 : static u32 axgbe_vid_crc32_le(__le16 vid_le)
507 : : {
508 : : u32 poly = 0xedb88320; /* CRCPOLY_LE */
509 : : u32 crc = ~0;
510 : : u32 temp = 0;
511 : : unsigned char *data = (unsigned char *)&vid_le;
512 : : unsigned char data_byte = 0;
513 : : int i, bits;
514 : :
515 : 0 : bits = get_lastbit_set(VLAN_VID_MASK);
516 [ # # ]: 0 : for (i = 0; i < bits; i++) {
517 [ # # ]: 0 : if ((i % 8) == 0)
518 : 0 : data_byte = data[i / 8];
519 : :
520 : 0 : temp = ((crc & 1) ^ data_byte) & 1;
521 : 0 : crc >>= 1;
522 : 0 : data_byte >>= 1;
523 : :
524 [ # # ]: 0 : if (temp)
525 : 0 : crc ^= poly;
526 : : }
527 : 0 : return crc;
528 : : }
529 : :
530 : 0 : static int axgbe_update_vlan_hash_table(struct axgbe_port *pdata)
531 : : {
532 : : u32 crc = 0;
533 : : u16 vid;
534 : : __le16 vid_le = 0;
535 : : u16 vlan_hash_table = 0;
536 : : unsigned int reg = 0;
537 : : unsigned long vid_idx, vid_valid;
538 : :
539 : : /* Generate the VLAN Hash Table value */
540 [ # # ]: 0 : for (vid = 0; vid < VLAN_N_VID; vid++) {
541 : 0 : vid_idx = VLAN_TABLE_IDX(vid);
542 : 0 : vid_valid = pdata->active_vlans[vid_idx];
543 : 0 : vid_valid = (unsigned long)vid_valid >> (vid - (64 * vid_idx));
544 [ # # ]: 0 : if (vid_valid & 1)
545 : 0 : PMD_DRV_LOG(DEBUG,
546 : : "vid:%d pdata->active_vlans[%ld]=0x%lx\n",
547 : : vid, vid_idx, pdata->active_vlans[vid_idx]);
548 : : else
549 : 0 : continue;
550 : :
551 : : vid_le = rte_cpu_to_le_16(vid);
552 : 0 : crc = bitrev32(~axgbe_vid_crc32_le(vid_le)) >> 28;
553 : 0 : vlan_hash_table |= (1 << crc);
554 : 0 : PMD_DRV_LOG(DEBUG, "crc = %d vlan_hash_table = 0x%x\n",
555 : : crc, vlan_hash_table);
556 : : }
557 : : /* Set the VLAN Hash Table filtering register */
558 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table);
559 : 0 : reg = AXGMAC_IOREAD(pdata, MAC_VLANHTR);
560 : 0 : PMD_DRV_LOG(DEBUG, "vlan_hash_table reg val = 0x%x\n", reg);
561 : 0 : return 0;
562 : : }
563 : :
564 : 0 : static int __axgbe_exit(struct axgbe_port *pdata)
565 : : {
566 : : unsigned int count = 2000;
567 : :
568 : : /* Issue a software reset */
569 : 0 : AXGMAC_IOWRITE_BITS(pdata, DMA_MR, SWR, 1);
570 : 0 : rte_delay_us(10);
571 : :
572 : : /* Poll Until Poll Condition */
573 [ # # # # ]: 0 : while (--count && AXGMAC_IOREAD_BITS(pdata, DMA_MR, SWR))
574 : 0 : rte_delay_us(500);
575 : :
576 [ # # ]: 0 : if (!count)
577 : 0 : return -EBUSY;
578 : :
579 : : return 0;
580 : : }
581 : :
582 : 0 : static int axgbe_exit(struct axgbe_port *pdata)
583 : : {
584 : : int ret;
585 : :
586 : : /* To guard against possible incorrectly generated interrupts,
587 : : * issue the software reset twice.
588 : : */
589 : 0 : ret = __axgbe_exit(pdata);
590 [ # # ]: 0 : if (ret)
591 : : return ret;
592 : :
593 : 0 : return __axgbe_exit(pdata);
594 : : }
595 : :
596 : 0 : static int axgbe_flush_tx_queues(struct axgbe_port *pdata)
597 : : {
598 : : unsigned int i, count;
599 : :
600 [ # # ]: 0 : if (AXGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) < 0x21)
601 : : return 0;
602 : :
603 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++)
604 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, FTQ, 1);
605 : :
606 : : /* Poll Until Poll Condition */
607 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++) {
608 : : count = 2000;
609 [ # # # # ]: 0 : while (--count && AXGMAC_MTL_IOREAD_BITS(pdata, i,
610 : : MTL_Q_TQOMR, FTQ))
611 : 0 : rte_delay_us(500);
612 : :
613 [ # # ]: 0 : if (!count)
614 : : return -EBUSY;
615 : : }
616 : :
617 : : return 0;
618 : : }
619 : :
620 : 0 : static void axgbe_config_dma_bus(struct axgbe_port *pdata)
621 : : {
622 : : /* Set enhanced addressing mode */
623 : 0 : AXGMAC_IOWRITE_BITS(pdata, DMA_SBMR, EAME, 1);
624 : :
625 : : /* Out standing read/write requests*/
626 : 0 : AXGMAC_IOWRITE_BITS(pdata, DMA_SBMR, RD_OSR, 0x3f);
627 : 0 : AXGMAC_IOWRITE_BITS(pdata, DMA_SBMR, WR_OSR, 0x3f);
628 : :
629 : : /* Set the System Bus mode */
630 : 0 : AXGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1);
631 : 0 : AXGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN_32, 1);
632 : 0 : AXGMAC_IOWRITE_BITS(pdata, DMA_SBMR, AAL, 1);
633 : 0 : }
634 : :
635 : : static void axgbe_config_dma_cache(struct axgbe_port *pdata)
636 : : {
637 : : unsigned int arcache, awcache, arwcache;
638 : :
639 : : arcache = 0;
640 : : AXGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, 0x3);
641 : 0 : AXGMAC_IOWRITE(pdata, DMA_AXIARCR, arcache);
642 : :
643 : : awcache = 0;
644 : : AXGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, 0x3);
645 : : AXGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, 0x3);
646 : : AXGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, 0x1);
647 : : AXGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, 0x3);
648 : : AXGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, 0x1);
649 : : AXGMAC_SET_BITS(awcache, DMA_AXIAWCR, RDC, 0x3);
650 : : AXGMAC_SET_BITS(awcache, DMA_AXIAWCR, RDD, 0x1);
651 : 0 : AXGMAC_IOWRITE(pdata, DMA_AXIAWCR, awcache);
652 : :
653 : : arwcache = 0;
654 : : AXGMAC_SET_BITS(arwcache, DMA_AXIAWRCR, TDWD, 0x1);
655 : : AXGMAC_SET_BITS(arwcache, DMA_AXIAWRCR, TDWC, 0x3);
656 : : AXGMAC_SET_BITS(arwcache, DMA_AXIAWRCR, RDRC, 0x3);
657 : 0 : AXGMAC_IOWRITE(pdata, DMA_AXIAWRCR, arwcache);
658 : : }
659 : :
660 : : static void axgbe_config_edma_control(struct axgbe_port *pdata)
661 : : {
662 : 0 : AXGMAC_IOWRITE(pdata, EDMA_TX_CONTROL, 0x5);
663 : 0 : AXGMAC_IOWRITE(pdata, EDMA_RX_CONTROL, 0x5);
664 : : }
665 : :
666 : 0 : static int axgbe_config_osp_mode(struct axgbe_port *pdata)
667 : : {
668 : : /* Force DMA to operate on second packet before closing descriptors
669 : : * of first packet
670 : : */
671 : : struct axgbe_tx_queue *txq;
672 : : unsigned int i;
673 : :
674 [ # # ]: 0 : for (i = 0; i < pdata->eth_dev->data->nb_tx_queues; i++) {
675 : 0 : txq = pdata->eth_dev->data->tx_queues[i];
676 : 0 : AXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, OSP,
677 : : pdata->tx_osp_mode);
678 : : }
679 : :
680 : 0 : return 0;
681 : : }
682 : :
683 : 0 : static int axgbe_config_pblx8(struct axgbe_port *pdata)
684 : : {
685 : : struct axgbe_tx_queue *txq;
686 : : unsigned int i;
687 : :
688 [ # # ]: 0 : for (i = 0; i < pdata->eth_dev->data->nb_tx_queues; i++) {
689 : 0 : txq = pdata->eth_dev->data->tx_queues[i];
690 : 0 : AXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_CR, PBLX8,
691 : : pdata->pblx8);
692 : : }
693 : 0 : return 0;
694 : : }
695 : :
696 : 0 : static int axgbe_config_tx_pbl_val(struct axgbe_port *pdata)
697 : : {
698 : : struct axgbe_tx_queue *txq;
699 : : unsigned int i;
700 : :
701 [ # # ]: 0 : for (i = 0; i < pdata->eth_dev->data->nb_tx_queues; i++) {
702 : 0 : txq = pdata->eth_dev->data->tx_queues[i];
703 : 0 : AXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, PBL,
704 : : pdata->tx_pbl);
705 : : }
706 : :
707 : 0 : return 0;
708 : : }
709 : :
710 : 0 : static int axgbe_config_rx_pbl_val(struct axgbe_port *pdata)
711 : : {
712 : : struct axgbe_rx_queue *rxq;
713 : : unsigned int i;
714 : :
715 [ # # ]: 0 : for (i = 0; i < pdata->eth_dev->data->nb_rx_queues; i++) {
716 : 0 : rxq = pdata->eth_dev->data->rx_queues[i];
717 : 0 : AXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, PBL,
718 : : pdata->rx_pbl);
719 : : }
720 : :
721 : 0 : return 0;
722 : : }
723 : :
724 : 0 : static void axgbe_config_rx_buffer_size(struct axgbe_port *pdata)
725 : : {
726 : : struct axgbe_rx_queue *rxq;
727 : : unsigned int i;
728 : :
729 [ # # ]: 0 : for (i = 0; i < pdata->eth_dev->data->nb_rx_queues; i++) {
730 : 0 : rxq = pdata->eth_dev->data->rx_queues[i];
731 : :
732 [ # # ]: 0 : rxq->buf_size = rte_pktmbuf_data_room_size(rxq->mb_pool) -
733 : : RTE_PKTMBUF_HEADROOM;
734 : 0 : rxq->buf_size = (rxq->buf_size + AXGBE_RX_BUF_ALIGN - 1) &
735 : : ~(AXGBE_RX_BUF_ALIGN - 1);
736 : :
737 [ # # ]: 0 : if (rxq->buf_size > pdata->rx_buf_size)
738 : 0 : pdata->rx_buf_size = rxq->buf_size;
739 : :
740 : 0 : AXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, RBSZ,
741 : : rxq->buf_size);
742 : : }
743 : 0 : }
744 : :
745 : 0 : static int axgbe_write_rss_reg(struct axgbe_port *pdata, unsigned int type,
746 : : unsigned int index, unsigned int val)
747 : : {
748 : : unsigned int wait;
749 : :
750 [ # # ]: 0 : if (AXGMAC_IOREAD_BITS(pdata, MAC_RSSAR, OB))
751 : : return -EBUSY;
752 : :
753 : 0 : AXGMAC_IOWRITE(pdata, MAC_RSSDR, val);
754 : :
755 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, RSSIA, index);
756 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, ADDRT, type);
757 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, CT, 0);
758 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, OB, 1);
759 : :
760 : : wait = 1000;
761 [ # # ]: 0 : while (wait--) {
762 [ # # ]: 0 : if (!AXGMAC_IOREAD_BITS(pdata, MAC_RSSAR, OB))
763 : : return 0;
764 : :
765 : 0 : rte_delay_us(1500);
766 : : }
767 : :
768 : : return -EBUSY;
769 : : }
770 : :
771 : 0 : int axgbe_write_rss_hash_key(struct axgbe_port *pdata)
772 : : {
773 : : struct rte_eth_rss_conf *rss_conf;
774 : : unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32);
775 : : unsigned int *key;
776 : : int ret;
777 : :
778 : 0 : rss_conf = &pdata->eth_dev->data->dev_conf.rx_adv_conf.rss_conf;
779 : :
780 [ # # ]: 0 : if (!rss_conf->rss_key)
781 : 0 : key = (unsigned int *)&pdata->rss_key;
782 : : else
783 : 0 : key = (unsigned int *)&rss_conf->rss_key;
784 : :
785 [ # # ]: 0 : while (key_regs--) {
786 : 0 : ret = axgbe_write_rss_reg(pdata, AXGBE_RSS_HASH_KEY_TYPE,
787 : 0 : key_regs, *key++);
788 [ # # ]: 0 : if (ret)
789 : 0 : return ret;
790 : : }
791 : :
792 : : return 0;
793 : : }
794 : :
795 : 0 : int axgbe_write_rss_lookup_table(struct axgbe_port *pdata)
796 : : {
797 : : unsigned int i;
798 : : int ret;
799 : :
800 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) {
801 : 0 : ret = axgbe_write_rss_reg(pdata,
802 : : AXGBE_RSS_LOOKUP_TABLE_TYPE, i,
803 : : pdata->rss_table[i]);
804 [ # # ]: 0 : if (ret)
805 : 0 : return ret;
806 : : }
807 : :
808 : : return 0;
809 : : }
810 : :
811 : 0 : static int axgbe_enable_rss(struct axgbe_port *pdata)
812 : : {
813 : : int ret;
814 : :
815 : : /* Program the hash key */
816 : 0 : ret = axgbe_write_rss_hash_key(pdata);
817 [ # # ]: 0 : if (ret)
818 : : return ret;
819 : :
820 : : /* Program the lookup table */
821 : 0 : ret = axgbe_write_rss_lookup_table(pdata);
822 [ # # ]: 0 : if (ret)
823 : : return ret;
824 : :
825 : : /* Set the RSS options */
826 : 0 : AXGMAC_IOWRITE(pdata, MAC_RSSCR, pdata->rss_options);
827 : :
828 : : /* Enable RSS */
829 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RSSCR, RSSE, 1);
830 : :
831 : 0 : return 0;
832 : : }
833 : :
834 : 0 : static void axgbe_rss_options(struct axgbe_port *pdata)
835 : : {
836 : : struct rte_eth_rss_conf *rss_conf;
837 : : uint64_t rss_hf;
838 : :
839 : 0 : rss_conf = &pdata->eth_dev->data->dev_conf.rx_adv_conf.rss_conf;
840 : 0 : pdata->rss_hf = rss_conf->rss_hf;
841 : : rss_hf = rss_conf->rss_hf;
842 : :
843 [ # # ]: 0 : if (rss_hf & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_IPV6))
844 : 0 : AXGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1);
845 [ # # ]: 0 : if (rss_hf & (RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_NONFRAG_IPV6_TCP))
846 : 0 : AXGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1);
847 [ # # ]: 0 : if (rss_hf & (RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_NONFRAG_IPV6_UDP))
848 : 0 : AXGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
849 : 0 : }
850 : :
851 : 0 : static int axgbe_config_rss(struct axgbe_port *pdata)
852 : : {
853 : : uint32_t i;
854 : :
855 [ # # ]: 0 : if (pdata->rss_enable) {
856 : : /* Initialize RSS hash key and lookup table */
857 : 0 : uint32_t *key = (uint32_t *)pdata->rss_key;
858 : :
859 [ # # ]: 0 : for (i = 0; i < sizeof(pdata->rss_key) / 4; i++)
860 : 0 : *key++ = (uint32_t)rte_rand();
861 [ # # ]: 0 : for (i = 0; i < AXGBE_RSS_MAX_TABLE_SIZE; i++)
862 : 0 : AXGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH,
863 : : i % pdata->eth_dev->data->nb_rx_queues);
864 : 0 : axgbe_rss_options(pdata);
865 [ # # ]: 0 : if (axgbe_enable_rss(pdata)) {
866 : 0 : PMD_DRV_LOG(ERR, "Error in enabling RSS support\n");
867 : 0 : return -1;
868 : : }
869 : : } else {
870 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RSSCR, RSSE, 0);
871 : : }
872 : :
873 : : return 0;
874 : : }
875 : :
876 : 0 : static void axgbe_enable_dma_interrupts(struct axgbe_port *pdata)
877 : : {
878 : : struct axgbe_tx_queue *txq;
879 : : unsigned int dma_ch_isr, dma_ch_ier;
880 : : unsigned int i;
881 : :
882 [ # # ]: 0 : for (i = 0; i < pdata->eth_dev->data->nb_tx_queues; i++) {
883 : 0 : txq = pdata->eth_dev->data->tx_queues[i];
884 : :
885 : : /* Clear all the interrupts which are set */
886 : 0 : dma_ch_isr = AXGMAC_DMA_IOREAD(txq, DMA_CH_SR);
887 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_SR, dma_ch_isr);
888 : :
889 : : /* Clear all interrupt enable bits */
890 : : dma_ch_ier = 0;
891 : :
892 : : /* Enable following interrupts
893 : : * NIE - Normal Interrupt Summary Enable
894 : : * AIE - Abnormal Interrupt Summary Enable
895 : : * FBEE - Fatal Bus Error Enable
896 : : */
897 : : AXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, NIE, 0);
898 : : AXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, AIE, 1);
899 : : AXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1);
900 : :
901 : : /* Enable following Rx interrupts
902 : : * RBUE - Receive Buffer Unavailable Enable
903 : : * RIE - Receive Interrupt Enable (unless using
904 : : * per channel interrupts in edge triggered
905 : : * mode)
906 : : */
907 : : AXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 0);
908 : :
909 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_IER, dma_ch_ier);
910 : : }
911 : 0 : }
912 : :
913 : 0 : static void wrapper_tx_desc_init(struct axgbe_port *pdata)
914 : : {
915 : : struct axgbe_tx_queue *txq;
916 : : unsigned int i;
917 : :
918 [ # # ]: 0 : for (i = 0; i < pdata->eth_dev->data->nb_tx_queues; i++) {
919 : 0 : txq = pdata->eth_dev->data->tx_queues[i];
920 : 0 : txq->cur = 0;
921 : 0 : txq->dirty = 0;
922 : : /* Update the total number of Tx descriptors */
923 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_TDRLR, txq->nb_desc - 1);
924 : : /* Update the starting address of descriptor ring */
925 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_TDLR_HI,
926 : : high32_value(txq->ring_phys_addr));
927 : 0 : AXGMAC_DMA_IOWRITE(txq, DMA_CH_TDLR_LO,
928 : : low32_value(txq->ring_phys_addr));
929 : : }
930 : 0 : }
931 : :
932 : 0 : static int wrapper_rx_desc_init(struct axgbe_port *pdata)
933 : : {
934 : : struct axgbe_rx_queue *rxq;
935 : : struct rte_mbuf *mbuf;
936 : : volatile union axgbe_rx_desc *desc;
937 : : unsigned int i, j;
938 : :
939 [ # # ]: 0 : for (i = 0; i < pdata->eth_dev->data->nb_rx_queues; i++) {
940 : 0 : rxq = pdata->eth_dev->data->rx_queues[i];
941 : :
942 : : /* Initialize software ring entries */
943 : 0 : rxq->mbuf_alloc = 0;
944 : 0 : rxq->cur = 0;
945 : 0 : rxq->dirty = 0;
946 : 0 : desc = AXGBE_GET_DESC_PT(rxq, 0);
947 : :
948 [ # # ]: 0 : for (j = 0; j < rxq->nb_desc; j++) {
949 : 0 : mbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
950 [ # # ]: 0 : if (mbuf == NULL) {
951 : 0 : PMD_DRV_LOG(ERR, "RX mbuf alloc failed queue_id = %u, idx = %d\n",
952 : : (unsigned int)rxq->queue_id, j);
953 : 0 : axgbe_dev_rx_queue_release(pdata->eth_dev, i);
954 : 0 : return -ENOMEM;
955 : : }
956 : 0 : rxq->sw_ring[j] = mbuf;
957 : : /* Mbuf populate */
958 : 0 : mbuf->next = NULL;
959 : 0 : mbuf->data_off = RTE_PKTMBUF_HEADROOM;
960 : 0 : mbuf->nb_segs = 1;
961 : 0 : mbuf->port = rxq->port_id;
962 : 0 : desc->read.baddr =
963 : : rte_cpu_to_le_64(
964 : : rte_mbuf_data_iova_default(mbuf));
965 : : rte_wmb();
966 : 0 : AXGMAC_SET_BITS_LE(desc->read.desc3,
967 : : RX_NORMAL_DESC3, OWN, 1);
968 : : rte_wmb();
969 : 0 : rxq->mbuf_alloc++;
970 : 0 : desc++;
971 : : }
972 : : /* Update the total number of Rx descriptors */
973 : 0 : AXGMAC_DMA_IOWRITE(rxq, DMA_CH_RDRLR,
974 : : rxq->nb_desc - 1);
975 : : /* Update the starting address of descriptor ring */
976 : 0 : AXGMAC_DMA_IOWRITE(rxq, DMA_CH_RDLR_HI,
977 : : high32_value(rxq->ring_phys_addr));
978 : 0 : AXGMAC_DMA_IOWRITE(rxq, DMA_CH_RDLR_LO,
979 : : low32_value(rxq->ring_phys_addr));
980 : : /* Update the Rx Descriptor Tail Pointer */
981 : 0 : AXGMAC_DMA_IOWRITE(rxq, DMA_CH_RDTR_LO,
982 : : low32_value(rxq->ring_phys_addr +
983 : : (rxq->nb_desc - 1) *
984 : : sizeof(union axgbe_rx_desc)));
985 : : }
986 : : return 0;
987 : : }
988 : :
989 : 0 : static void axgbe_config_mtl_mode(struct axgbe_port *pdata)
990 : : {
991 : : unsigned int i;
992 : :
993 : : /* Set Tx to weighted round robin scheduling algorithm */
994 : 0 : AXGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_WRR);
995 : :
996 : : /* Set Tx traffic classes to use WRR algorithm with equal weights */
997 [ # # ]: 0 : for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
998 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
999 : : MTL_TSA_ETS);
1000 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW, 1);
1001 : : }
1002 : :
1003 : : /* Set Rx to strict priority algorithm */
1004 : 0 : AXGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP);
1005 : 0 : }
1006 : :
1007 : : static int axgbe_config_tsf_mode(struct axgbe_port *pdata, unsigned int val)
1008 : : {
1009 : : unsigned int i;
1010 : :
1011 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++)
1012 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TSF, val);
1013 : :
1014 : : return 0;
1015 : : }
1016 : :
1017 : : static int axgbe_config_rsf_mode(struct axgbe_port *pdata, unsigned int val)
1018 : : {
1019 : : unsigned int i;
1020 : :
1021 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count; i++)
1022 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RSF, val);
1023 : :
1024 : : return 0;
1025 : : }
1026 : :
1027 : : static int axgbe_config_tx_threshold(struct axgbe_port *pdata,
1028 : : unsigned int val)
1029 : : {
1030 : : unsigned int i;
1031 : :
1032 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++)
1033 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TTC, val);
1034 : :
1035 : : return 0;
1036 : : }
1037 : :
1038 : : static int axgbe_config_rx_threshold(struct axgbe_port *pdata,
1039 : : unsigned int val)
1040 : : {
1041 : : unsigned int i;
1042 : :
1043 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count; i++)
1044 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RTC, val);
1045 : :
1046 : : return 0;
1047 : : }
1048 : :
1049 : : /* Distributing FIFO size */
1050 : 0 : static void axgbe_config_rx_fifo_size(struct axgbe_port *pdata)
1051 : : {
1052 : : unsigned int fifo_size;
1053 : : unsigned int q_fifo_size;
1054 : : unsigned int p_fifo, i;
1055 : :
1056 : 0 : fifo_size = RTE_MIN(pdata->rx_max_fifo_size,
1057 : : pdata->hw_feat.rx_fifo_size);
1058 : 0 : q_fifo_size = fifo_size / pdata->rx_q_count;
1059 : :
1060 : : /* Calculate the fifo setting by dividing the queue's fifo size
1061 : : * by the fifo allocation increment (with 0 representing the
1062 : : * base allocation increment so decrement the result
1063 : : * by 1).
1064 : : */
1065 : 0 : p_fifo = q_fifo_size / AXGMAC_FIFO_UNIT;
1066 [ # # ]: 0 : if (p_fifo)
1067 : 0 : p_fifo--;
1068 : :
1069 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count; i++)
1070 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, p_fifo);
1071 : 0 : pdata->fifo = p_fifo;
1072 : :
1073 : : /*Calculate and config Flow control threshold*/
1074 : 0 : axgbe_calculate_flow_control_threshold(pdata);
1075 : 0 : axgbe_config_flow_control_threshold(pdata);
1076 : :
1077 : 0 : PMD_DRV_LOG(DEBUG, "%d Rx hardware queues, %d byte fifo per queue\n",
1078 : : pdata->rx_q_count, q_fifo_size);
1079 : 0 : }
1080 : :
1081 : 0 : static void axgbe_config_tx_fifo_size(struct axgbe_port *pdata)
1082 : : {
1083 : : unsigned int fifo_size;
1084 : : unsigned int q_fifo_size;
1085 : : unsigned int p_fifo, i;
1086 : :
1087 : 0 : fifo_size = RTE_MIN(pdata->tx_max_fifo_size,
1088 : : pdata->hw_feat.tx_fifo_size);
1089 : 0 : q_fifo_size = fifo_size / pdata->tx_q_count;
1090 : :
1091 : : /* Calculate the fifo setting by dividing the queue's fifo size
1092 : : * by the fifo allocation increment (with 0 representing the
1093 : : * base allocation increment so decrement the result
1094 : : * by 1).
1095 : : */
1096 : 0 : p_fifo = q_fifo_size / AXGMAC_FIFO_UNIT;
1097 [ # # ]: 0 : if (p_fifo)
1098 : 0 : p_fifo--;
1099 : :
1100 [ # # ]: 0 : for (i = 0; i < pdata->tx_q_count; i++)
1101 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, p_fifo);
1102 : :
1103 : 0 : PMD_DRV_LOG(DEBUG, "%d Tx hardware queues, %d byte fifo per queue\n",
1104 : : pdata->tx_q_count, q_fifo_size);
1105 : 0 : }
1106 : :
1107 : 0 : static void axgbe_config_queue_mapping(struct axgbe_port *pdata)
1108 : : {
1109 : : unsigned int qptc, qptc_extra, queue;
1110 : : unsigned int i, j, reg, reg_val;
1111 : :
1112 : : /* Map the MTL Tx Queues to Traffic Classes
1113 : : * Note: Tx Queues >= Traffic Classes
1114 : : */
1115 : 0 : qptc = pdata->tx_q_count / pdata->hw_feat.tc_cnt;
1116 : 0 : qptc_extra = pdata->tx_q_count % pdata->hw_feat.tc_cnt;
1117 : :
1118 [ # # ]: 0 : for (i = 0, queue = 0; i < pdata->hw_feat.tc_cnt; i++) {
1119 [ # # ]: 0 : for (j = 0; j < qptc; j++) {
1120 : 0 : PMD_DRV_LOG(DEBUG, "TXq%u mapped to TC%u\n", queue, i);
1121 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, queue, MTL_Q_TQOMR,
1122 : : Q2TCMAP, i);
1123 : : }
1124 [ # # ]: 0 : if (i < qptc_extra) {
1125 : 0 : PMD_DRV_LOG(DEBUG, "TXq%u mapped to TC%u\n", queue, i);
1126 : 0 : AXGMAC_MTL_IOWRITE_BITS(pdata, queue, MTL_Q_TQOMR,
1127 : : Q2TCMAP, i);
1128 : : }
1129 : : }
1130 : :
1131 [ # # ]: 0 : if (pdata->rss_enable) {
1132 : : /* Select dynamic mapping of MTL Rx queue to DMA Rx channel */
1133 : : reg = MTL_RQDCM0R;
1134 : : reg_val = 0;
1135 [ # # ]: 0 : for (i = 0; i < pdata->rx_q_count;) {
1136 : 0 : reg_val |= (0x80 << ((i++ % MTL_RQDCM_Q_PER_REG) << 3));
1137 : :
1138 [ # # # # ]: 0 : if ((i % MTL_RQDCM_Q_PER_REG) &&
1139 : : (i != pdata->rx_q_count))
1140 : 0 : continue;
1141 : :
1142 : 0 : AXGMAC_IOWRITE(pdata, reg, reg_val);
1143 : :
1144 : 0 : reg += MTL_RQDCM_INC;
1145 : : reg_val = 0;
1146 : : }
1147 : : }
1148 : 0 : }
1149 : :
1150 : 0 : static void axgbe_enable_mtl_interrupts(struct axgbe_port *pdata)
1151 : : {
1152 : : unsigned int mtl_q_isr;
1153 : : unsigned int q_count, i;
1154 : :
1155 : 0 : q_count = RTE_MAX(pdata->hw_feat.tx_q_cnt, pdata->hw_feat.rx_q_cnt);
1156 [ # # ]: 0 : for (i = 0; i < q_count; i++) {
1157 : : /* Clear all the interrupts which are set */
1158 : 0 : mtl_q_isr = AXGMAC_MTL_IOREAD(pdata, i, MTL_Q_ISR);
1159 : 0 : AXGMAC_MTL_IOWRITE(pdata, i, MTL_Q_ISR, mtl_q_isr);
1160 : :
1161 : : /* No MTL interrupts to be enabled */
1162 : 0 : AXGMAC_MTL_IOWRITE(pdata, i, MTL_Q_IER, 0);
1163 : : }
1164 : 0 : }
1165 : :
1166 : : static uint32_t crc32_le(uint32_t crc, uint8_t *p, uint32_t len)
1167 : : {
1168 : : int i;
1169 [ # # ]: 0 : while (len--) {
1170 : 0 : crc ^= *p++;
1171 [ # # ]: 0 : for (i = 0; i < 8; i++)
1172 [ # # ]: 0 : crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
1173 : : }
1174 : : return crc;
1175 : : }
1176 : :
1177 : 0 : void axgbe_set_mac_hash_table(struct axgbe_port *pdata, u8 *addr, bool add)
1178 : : {
1179 : : uint32_t crc, htable_index, htable_bitmask;
1180 : :
1181 : 0 : crc = bitrev32(~crc32_le(~0, addr, RTE_ETHER_ADDR_LEN));
1182 : 0 : crc >>= pdata->hash_table_shift;
1183 : 0 : htable_index = crc >> 5;
1184 : 0 : htable_bitmask = 1 << (crc & 0x1f);
1185 : :
1186 [ # # ]: 0 : if (add) {
1187 : 0 : pdata->uc_hash_table[htable_index] |= htable_bitmask;
1188 : 0 : pdata->uc_hash_mac_addr++;
1189 : : } else {
1190 : 0 : pdata->uc_hash_table[htable_index] &= ~htable_bitmask;
1191 : 0 : pdata->uc_hash_mac_addr--;
1192 : : }
1193 [ # # ]: 0 : PMD_DRV_LOG(DEBUG, "%s MAC hash table Bit %d at Index %#x\n",
1194 : : add ? "set" : "clear", (crc & 0x1f), htable_index);
1195 : :
1196 : 0 : AXGMAC_IOWRITE(pdata, MAC_HTR(htable_index),
1197 : : pdata->uc_hash_table[htable_index]);
1198 : 0 : }
1199 : :
1200 : 0 : void axgbe_set_mac_addn_addr(struct axgbe_port *pdata, u8 *addr, uint32_t index)
1201 : : {
1202 : : unsigned int mac_addr_hi, mac_addr_lo;
1203 : : u8 *mac_addr;
1204 : :
1205 : 0 : mac_addr_lo = 0;
1206 : 0 : mac_addr_hi = 0;
1207 : :
1208 [ # # ]: 0 : if (addr) {
1209 : : mac_addr = (u8 *)&mac_addr_lo;
1210 : 0 : mac_addr[0] = addr[0];
1211 : 0 : mac_addr[1] = addr[1];
1212 : 0 : mac_addr[2] = addr[2];
1213 : 0 : mac_addr[3] = addr[3];
1214 : : mac_addr = (u8 *)&mac_addr_hi;
1215 : 0 : mac_addr[0] = addr[4];
1216 : 0 : mac_addr[1] = addr[5];
1217 : :
1218 : : /*Address Enable: Use this Addr for Perfect Filtering */
1219 : 0 : AXGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1);
1220 : : }
1221 : :
1222 [ # # ]: 0 : PMD_DRV_LOG(DEBUG, "%s mac address at %#x\n",
1223 : : addr ? "set" : "clear", index);
1224 : :
1225 : 0 : AXGMAC_IOWRITE(pdata, MAC_MACAHR(index), mac_addr_hi);
1226 : 0 : AXGMAC_IOWRITE(pdata, MAC_MACALR(index), mac_addr_lo);
1227 : 0 : }
1228 : :
1229 : : static int axgbe_set_mac_address(struct axgbe_port *pdata, u8 *addr)
1230 : : {
1231 : : unsigned int mac_addr_hi, mac_addr_lo;
1232 : :
1233 : 0 : mac_addr_hi = (addr[5] << 8) | (addr[4] << 0);
1234 : 0 : mac_addr_lo = (addr[3] << 24) | (addr[2] << 16) |
1235 : 0 : (addr[1] << 8) | (addr[0] << 0);
1236 : :
1237 : 0 : AXGMAC_IOWRITE(pdata, MAC_MACA0HR, mac_addr_hi);
1238 : 0 : AXGMAC_IOWRITE(pdata, MAC_MACA0LR, mac_addr_lo);
1239 : :
1240 : : return 0;
1241 : : }
1242 : :
1243 : 0 : static void axgbe_config_mac_hash_table(struct axgbe_port *pdata)
1244 : : {
1245 : : struct axgbe_hw_features *hw_feat = &pdata->hw_feat;
1246 : :
1247 : 0 : pdata->hash_table_shift = 0;
1248 : 0 : pdata->hash_table_count = 0;
1249 : 0 : pdata->uc_hash_mac_addr = 0;
1250 [ # # ]: 0 : memset(pdata->uc_hash_table, 0, sizeof(pdata->uc_hash_table));
1251 : :
1252 [ # # ]: 0 : if (hw_feat->hash_table_size) {
1253 : 0 : pdata->hash_table_shift = 26 - (hw_feat->hash_table_size >> 7);
1254 : 0 : pdata->hash_table_count = hw_feat->hash_table_size / 32;
1255 : : }
1256 : 0 : }
1257 : :
1258 : : static void axgbe_config_mac_address(struct axgbe_port *pdata)
1259 : : {
1260 : : axgbe_set_mac_address(pdata, pdata->mac_addr.addr_bytes);
1261 : : }
1262 : :
1263 : : static void axgbe_config_jumbo_enable(struct axgbe_port *pdata)
1264 : : {
1265 : : unsigned int val;
1266 : :
1267 : 0 : val = (pdata->rx_buf_size > AXGMAC_STD_PACKET_MTU) ? 1 : 0;
1268 : :
1269 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, JE, val);
1270 : : }
1271 : :
1272 : : static void axgbe_config_mac_speed(struct axgbe_port *pdata)
1273 : : {
1274 : 0 : axgbe_set_speed(pdata, pdata->phy_speed);
1275 : : }
1276 : :
1277 : : static void axgbe_config_checksum_offload(struct axgbe_port *pdata)
1278 : : {
1279 [ # # ]: 0 : if (pdata->rx_csum_enable)
1280 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, IPC, 1);
1281 : : else
1282 : 0 : AXGMAC_IOWRITE_BITS(pdata, MAC_RCR, IPC, 0);
1283 : : }
1284 : :
1285 : 0 : static void axgbe_config_mmc(struct axgbe_port *pdata)
1286 : : {
1287 : 0 : struct axgbe_mmc_stats *stats = &pdata->mmc_stats;
1288 : :
1289 : : /* Reset stats */
1290 : : memset(stats, 0, sizeof(*stats));
1291 : :
1292 : : /* Set counters to reset on read */
1293 : 0 : AXGMAC_IOWRITE_BITS(pdata, MMC_CR, ROR, 1);
1294 : :
1295 : : /* Reset the counters */
1296 : 0 : AXGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1);
1297 : 0 : }
1298 : :
1299 : 0 : static int axgbe_init(struct axgbe_port *pdata)
1300 : : {
1301 : : int ret;
1302 : :
1303 : : /* Flush Tx queues */
1304 : 0 : ret = axgbe_flush_tx_queues(pdata);
1305 [ # # ]: 0 : if (ret)
1306 : : return ret;
1307 : : /* Initialize DMA related features */
1308 : 0 : axgbe_config_dma_bus(pdata);
1309 : : axgbe_config_dma_cache(pdata);
1310 : : axgbe_config_edma_control(pdata);
1311 : 0 : axgbe_config_osp_mode(pdata);
1312 : 0 : axgbe_config_pblx8(pdata);
1313 : 0 : axgbe_config_tx_pbl_val(pdata);
1314 : 0 : axgbe_config_rx_pbl_val(pdata);
1315 : 0 : axgbe_config_rx_buffer_size(pdata);
1316 : 0 : axgbe_config_rss(pdata);
1317 : 0 : wrapper_tx_desc_init(pdata);
1318 : 0 : ret = wrapper_rx_desc_init(pdata);
1319 [ # # ]: 0 : if (ret)
1320 : : return ret;
1321 : 0 : axgbe_enable_dma_interrupts(pdata);
1322 : :
1323 : : /* Initialize MTL related features */
1324 : 0 : axgbe_config_mtl_mode(pdata);
1325 : 0 : axgbe_config_queue_mapping(pdata);
1326 : 0 : axgbe_config_tsf_mode(pdata, pdata->tx_sf_mode);
1327 : 0 : axgbe_config_rsf_mode(pdata, pdata->rx_sf_mode);
1328 : 0 : axgbe_config_tx_threshold(pdata, pdata->tx_threshold);
1329 : 0 : axgbe_config_rx_threshold(pdata, pdata->rx_threshold);
1330 : 0 : axgbe_config_tx_fifo_size(pdata);
1331 : 0 : axgbe_config_rx_fifo_size(pdata);
1332 : :
1333 : 0 : axgbe_enable_mtl_interrupts(pdata);
1334 : :
1335 : : /* Initialize MAC related features */
1336 : 0 : axgbe_config_mac_hash_table(pdata);
1337 : : axgbe_config_mac_address(pdata);
1338 : : axgbe_config_jumbo_enable(pdata);
1339 : 0 : axgbe_config_flow_control(pdata);
1340 : : axgbe_config_mac_speed(pdata);
1341 : : axgbe_config_checksum_offload(pdata);
1342 : 0 : axgbe_config_mmc(pdata);
1343 : :
1344 : 0 : return 0;
1345 : : }
1346 : :
1347 : 0 : void axgbe_init_function_ptrs_dev(struct axgbe_hw_if *hw_if)
1348 : : {
1349 : 0 : hw_if->exit = axgbe_exit;
1350 : 0 : hw_if->config_flow_control = axgbe_config_flow_control;
1351 : :
1352 : 0 : hw_if->init = axgbe_init;
1353 : :
1354 : 0 : hw_if->read_mmd_regs = axgbe_read_mmd_regs;
1355 : 0 : hw_if->write_mmd_regs = axgbe_write_mmd_regs;
1356 : :
1357 : 0 : hw_if->set_speed = axgbe_set_speed;
1358 : :
1359 : 0 : hw_if->set_ext_mii_mode = axgbe_set_ext_mii_mode;
1360 : 0 : hw_if->read_ext_mii_regs = axgbe_read_ext_mii_regs;
1361 : 0 : hw_if->write_ext_mii_regs = axgbe_write_ext_mii_regs;
1362 : : /* For FLOW ctrl */
1363 : 0 : hw_if->config_tx_flow_control = axgbe_config_tx_flow_control;
1364 : 0 : hw_if->config_rx_flow_control = axgbe_config_rx_flow_control;
1365 : :
1366 : : /*vlan*/
1367 : 0 : hw_if->enable_rx_vlan_stripping = axgbe_enable_rx_vlan_stripping;
1368 : 0 : hw_if->disable_rx_vlan_stripping = axgbe_disable_rx_vlan_stripping;
1369 : 0 : hw_if->enable_rx_vlan_filtering = axgbe_enable_rx_vlan_filtering;
1370 : 0 : hw_if->disable_rx_vlan_filtering = axgbe_disable_rx_vlan_filtering;
1371 : 0 : hw_if->update_vlan_hash_table = axgbe_update_vlan_hash_table;
1372 : 0 : }
|