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