1
2
3
4
5
6
7
8
9
10#include <linux/types.h>
11#include <linux/skbuff.h>
12#include <linux/netdevice.h>
13#include <linux/interrupt.h>
14#include <linux/ip.h>
15#include <linux/dma-mapping.h>
16
17#include "sparx5_main_regs.h"
18#include "sparx5_main.h"
19#include "sparx5_port.h"
20
21#define FDMA_XTR_CHANNEL 6
22#define FDMA_INJ_CHANNEL 0
23
24#define FDMA_DCB_INFO_DATAL(x) ((x) & GENMASK(15, 0))
25#define FDMA_DCB_INFO_TOKEN BIT(17)
26#define FDMA_DCB_INFO_INTR BIT(18)
27#define FDMA_DCB_INFO_SW(x) (((x) << 24) & GENMASK(31, 24))
28
29#define FDMA_DCB_STATUS_BLOCKL(x) ((x) & GENMASK(15, 0))
30#define FDMA_DCB_STATUS_SOF BIT(16)
31#define FDMA_DCB_STATUS_EOF BIT(17)
32#define FDMA_DCB_STATUS_INTR BIT(18)
33#define FDMA_DCB_STATUS_DONE BIT(19)
34#define FDMA_DCB_STATUS_BLOCKO(x) (((x) << 20) & GENMASK(31, 20))
35#define FDMA_DCB_INVALID_DATA 0x1
36
37#define FDMA_XTR_BUFFER_SIZE 2048
38#define FDMA_WEIGHT 4
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74struct sparx5_db {
75 struct list_head list;
76 void *cpu_addr;
77};
78
79static void sparx5_fdma_rx_add_dcb(struct sparx5_rx *rx,
80 struct sparx5_rx_dcb_hw *dcb,
81 u64 nextptr)
82{
83 int idx = 0;
84
85
86 for (idx = 0; idx < FDMA_RX_DCB_MAX_DBS; ++idx) {
87 struct sparx5_db_hw *db = &dcb->db[idx];
88
89 db->status = FDMA_DCB_STATUS_INTR;
90 }
91 dcb->nextptr = FDMA_DCB_INVALID_DATA;
92 dcb->info = FDMA_DCB_INFO_DATAL(FDMA_XTR_BUFFER_SIZE);
93 rx->last_entry->nextptr = nextptr;
94 rx->last_entry = dcb;
95}
96
97static void sparx5_fdma_tx_add_dcb(struct sparx5_tx *tx,
98 struct sparx5_tx_dcb_hw *dcb,
99 u64 nextptr)
100{
101 int idx = 0;
102
103
104 for (idx = 0; idx < FDMA_TX_DCB_MAX_DBS; ++idx) {
105 struct sparx5_db_hw *db = &dcb->db[idx];
106
107 db->status = FDMA_DCB_STATUS_DONE;
108 }
109 dcb->nextptr = FDMA_DCB_INVALID_DATA;
110 dcb->info = FDMA_DCB_INFO_DATAL(FDMA_XTR_BUFFER_SIZE);
111}
112
113static void sparx5_fdma_rx_activate(struct sparx5 *sparx5, struct sparx5_rx *rx)
114{
115
116 spx5_wr(((u64)rx->dma) & GENMASK(31, 0), sparx5,
117 FDMA_DCB_LLP(rx->channel_id));
118 spx5_wr(((u64)rx->dma) >> 32, sparx5, FDMA_DCB_LLP1(rx->channel_id));
119
120
121 spx5_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(FDMA_RX_DCB_MAX_DBS) |
122 FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(1) |
123 FDMA_CH_CFG_CH_INJ_PORT_SET(XTR_QUEUE),
124 sparx5, FDMA_CH_CFG(rx->channel_id));
125
126
127 spx5_rmw(FDMA_XTR_CFG_XTR_FIFO_WM_SET(31), FDMA_XTR_CFG_XTR_FIFO_WM,
128 sparx5,
129 FDMA_XTR_CFG);
130
131
132 spx5_rmw(FDMA_PORT_CTRL_XTR_STOP_SET(0), FDMA_PORT_CTRL_XTR_STOP,
133 sparx5, FDMA_PORT_CTRL(0));
134
135
136 spx5_rmw(BIT(rx->channel_id),
137 BIT(rx->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA,
138 sparx5, FDMA_INTR_DB_ENA);
139
140
141 spx5_wr(BIT(rx->channel_id), sparx5, FDMA_CH_ACTIVATE);
142}
143
144static void sparx5_fdma_rx_deactivate(struct sparx5 *sparx5, struct sparx5_rx *rx)
145{
146
147 spx5_rmw(0, BIT(rx->channel_id) & FDMA_CH_ACTIVATE_CH_ACTIVATE,
148 sparx5, FDMA_CH_ACTIVATE);
149
150
151 spx5_rmw(0, BIT(rx->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA,
152 sparx5, FDMA_INTR_DB_ENA);
153
154
155 spx5_rmw(FDMA_PORT_CTRL_XTR_STOP_SET(1), FDMA_PORT_CTRL_XTR_STOP,
156 sparx5, FDMA_PORT_CTRL(0));
157}
158
159static void sparx5_fdma_tx_activate(struct sparx5 *sparx5, struct sparx5_tx *tx)
160{
161
162 spx5_wr(((u64)tx->dma) & GENMASK(31, 0), sparx5,
163 FDMA_DCB_LLP(tx->channel_id));
164 spx5_wr(((u64)tx->dma) >> 32, sparx5, FDMA_DCB_LLP1(tx->channel_id));
165
166
167 spx5_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(FDMA_TX_DCB_MAX_DBS) |
168 FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(1) |
169 FDMA_CH_CFG_CH_INJ_PORT_SET(INJ_QUEUE),
170 sparx5, FDMA_CH_CFG(tx->channel_id));
171
172
173 spx5_rmw(FDMA_PORT_CTRL_INJ_STOP_SET(0), FDMA_PORT_CTRL_INJ_STOP,
174 sparx5, FDMA_PORT_CTRL(0));
175
176
177 spx5_wr(BIT(tx->channel_id), sparx5, FDMA_CH_ACTIVATE);
178}
179
180static void sparx5_fdma_tx_deactivate(struct sparx5 *sparx5, struct sparx5_tx *tx)
181{
182
183 spx5_rmw(0, BIT(tx->channel_id) & FDMA_CH_ACTIVATE_CH_ACTIVATE,
184 sparx5, FDMA_CH_ACTIVATE);
185}
186
187static void sparx5_fdma_rx_reload(struct sparx5 *sparx5, struct sparx5_rx *rx)
188{
189
190 spx5_wr(BIT(rx->channel_id), sparx5, FDMA_CH_RELOAD);
191}
192
193static void sparx5_fdma_tx_reload(struct sparx5 *sparx5, struct sparx5_tx *tx)
194{
195
196 spx5_wr(BIT(tx->channel_id), sparx5, FDMA_CH_RELOAD);
197}
198
199static struct sk_buff *sparx5_fdma_rx_alloc_skb(struct sparx5_rx *rx)
200{
201 return __netdev_alloc_skb(rx->ndev, FDMA_XTR_BUFFER_SIZE,
202 GFP_ATOMIC);
203}
204
205static bool sparx5_fdma_rx_get_frame(struct sparx5 *sparx5, struct sparx5_rx *rx)
206{
207 struct sparx5_db_hw *db_hw;
208 unsigned int packet_size;
209 struct sparx5_port *port;
210 struct sk_buff *new_skb;
211 struct frame_info fi;
212 struct sk_buff *skb;
213 dma_addr_t dma_addr;
214
215
216 db_hw = &rx->dcb_entries[rx->dcb_index].db[rx->db_index];
217 if (unlikely(!(db_hw->status & FDMA_DCB_STATUS_DONE)))
218 return false;
219 skb = rx->skb[rx->dcb_index][rx->db_index];
220
221 new_skb = sparx5_fdma_rx_alloc_skb(rx);
222 if (unlikely(!new_skb))
223 return false;
224
225 dma_addr = virt_to_phys(new_skb->data);
226 rx->skb[rx->dcb_index][rx->db_index] = new_skb;
227 db_hw->dataptr = dma_addr;
228 packet_size = FDMA_DCB_STATUS_BLOCKL(db_hw->status);
229 skb_put(skb, packet_size);
230
231 sparx5_ifh_parse((u32 *)skb->data, &fi);
232
233 port = fi.src_port < SPX5_PORTS ? sparx5->ports[fi.src_port] : NULL;
234 if (!port || !port->ndev) {
235 dev_err(sparx5->dev, "Data on inactive port %d\n", fi.src_port);
236 sparx5_xtr_flush(sparx5, XTR_QUEUE);
237 return false;
238 }
239 skb->dev = port->ndev;
240 skb_pull(skb, IFH_LEN * sizeof(u32));
241 if (likely(!(skb->dev->features & NETIF_F_RXFCS)))
242 skb_trim(skb, skb->len - ETH_FCS_LEN);
243 skb->protocol = eth_type_trans(skb, skb->dev);
244
245
246
247 if (test_bit(port->portno, sparx5->bridge_mask))
248 skb->offload_fwd_mark = 1;
249 skb->dev->stats.rx_bytes += skb->len;
250 skb->dev->stats.rx_packets++;
251 rx->packets++;
252 netif_receive_skb(skb);
253 return true;
254}
255
256static int sparx5_fdma_napi_callback(struct napi_struct *napi, int weight)
257{
258 struct sparx5_rx *rx = container_of(napi, struct sparx5_rx, napi);
259 struct sparx5 *sparx5 = container_of(rx, struct sparx5, rx);
260 int counter = 0;
261
262 while (counter < weight && sparx5_fdma_rx_get_frame(sparx5, rx)) {
263 struct sparx5_rx_dcb_hw *old_dcb;
264
265 rx->db_index++;
266 counter++;
267
268 if (rx->db_index != FDMA_RX_DCB_MAX_DBS)
269 continue;
270
271
272
273 rx->db_index = 0;
274 old_dcb = &rx->dcb_entries[rx->dcb_index];
275 rx->dcb_index++;
276 rx->dcb_index &= FDMA_DCB_MAX - 1;
277 sparx5_fdma_rx_add_dcb(rx, old_dcb,
278 rx->dma +
279 ((unsigned long)old_dcb -
280 (unsigned long)rx->dcb_entries));
281 }
282 if (counter < weight) {
283 napi_complete_done(&rx->napi, counter);
284 spx5_rmw(BIT(rx->channel_id),
285 BIT(rx->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA,
286 sparx5, FDMA_INTR_DB_ENA);
287 }
288 if (counter)
289 sparx5_fdma_rx_reload(sparx5, rx);
290 return counter;
291}
292
293static struct sparx5_tx_dcb_hw *sparx5_fdma_next_dcb(struct sparx5_tx *tx,
294 struct sparx5_tx_dcb_hw *dcb)
295{
296 struct sparx5_tx_dcb_hw *next_dcb;
297
298 next_dcb = dcb;
299 next_dcb++;
300
301 if ((unsigned long)next_dcb >=
302 ((unsigned long)tx->first_entry + FDMA_DCB_MAX * sizeof(*dcb)))
303 next_dcb = tx->first_entry;
304 return next_dcb;
305}
306
307int sparx5_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb)
308{
309 struct sparx5_tx_dcb_hw *next_dcb_hw;
310 struct sparx5_tx *tx = &sparx5->tx;
311 static bool first_time = true;
312 struct sparx5_db_hw *db_hw;
313 struct sparx5_db *db;
314
315 next_dcb_hw = sparx5_fdma_next_dcb(tx, tx->curr_entry);
316 db_hw = &next_dcb_hw->db[0];
317 if (!(db_hw->status & FDMA_DCB_STATUS_DONE))
318 tx->dropped++;
319 db = list_first_entry(&tx->db_list, struct sparx5_db, list);
320 list_move_tail(&db->list, &tx->db_list);
321 next_dcb_hw->nextptr = FDMA_DCB_INVALID_DATA;
322 tx->curr_entry->nextptr = tx->dma +
323 ((unsigned long)next_dcb_hw -
324 (unsigned long)tx->first_entry);
325 tx->curr_entry = next_dcb_hw;
326 memset(db->cpu_addr, 0, FDMA_XTR_BUFFER_SIZE);
327 memcpy(db->cpu_addr, ifh, IFH_LEN * 4);
328 memcpy(db->cpu_addr + IFH_LEN * 4, skb->data, skb->len);
329 db_hw->status = FDMA_DCB_STATUS_SOF |
330 FDMA_DCB_STATUS_EOF |
331 FDMA_DCB_STATUS_BLOCKO(0) |
332 FDMA_DCB_STATUS_BLOCKL(skb->len + IFH_LEN * 4 + 4);
333 if (first_time) {
334 sparx5_fdma_tx_activate(sparx5, tx);
335 first_time = false;
336 } else {
337 sparx5_fdma_tx_reload(sparx5, tx);
338 }
339 return NETDEV_TX_OK;
340}
341
342static int sparx5_fdma_rx_alloc(struct sparx5 *sparx5)
343{
344 struct sparx5_rx *rx = &sparx5->rx;
345 struct sparx5_rx_dcb_hw *dcb;
346 int idx, jdx;
347 int size;
348
349 size = sizeof(struct sparx5_rx_dcb_hw) * FDMA_DCB_MAX;
350 size = ALIGN(size, PAGE_SIZE);
351 rx->dcb_entries = devm_kzalloc(sparx5->dev, size, GFP_KERNEL);
352 if (!rx->dcb_entries)
353 return -ENOMEM;
354 rx->dma = virt_to_phys(rx->dcb_entries);
355 rx->last_entry = rx->dcb_entries;
356 rx->db_index = 0;
357 rx->dcb_index = 0;
358
359 for (idx = 0; idx < FDMA_DCB_MAX; ++idx) {
360 dcb = &rx->dcb_entries[idx];
361 dcb->info = 0;
362
363
364
365
366 for (jdx = 0; jdx < FDMA_RX_DCB_MAX_DBS; ++jdx) {
367 struct sparx5_db_hw *db_hw = &dcb->db[jdx];
368 dma_addr_t dma_addr;
369 struct sk_buff *skb;
370
371 skb = sparx5_fdma_rx_alloc_skb(rx);
372 if (!skb)
373 return -ENOMEM;
374
375 dma_addr = virt_to_phys(skb->data);
376 db_hw->dataptr = dma_addr;
377 db_hw->status = 0;
378 rx->skb[idx][jdx] = skb;
379 }
380 sparx5_fdma_rx_add_dcb(rx, dcb, rx->dma + sizeof(*dcb) * idx);
381 }
382 netif_napi_add(rx->ndev, &rx->napi, sparx5_fdma_napi_callback, FDMA_WEIGHT);
383 napi_enable(&rx->napi);
384 sparx5_fdma_rx_activate(sparx5, rx);
385 return 0;
386}
387
388static int sparx5_fdma_tx_alloc(struct sparx5 *sparx5)
389{
390 struct sparx5_tx *tx = &sparx5->tx;
391 struct sparx5_tx_dcb_hw *dcb;
392 int idx, jdx;
393 int size;
394
395 size = sizeof(struct sparx5_tx_dcb_hw) * FDMA_DCB_MAX;
396 size = ALIGN(size, PAGE_SIZE);
397 tx->curr_entry = devm_kzalloc(sparx5->dev, size, GFP_KERNEL);
398 if (!tx->curr_entry)
399 return -ENOMEM;
400 tx->dma = virt_to_phys(tx->curr_entry);
401 tx->first_entry = tx->curr_entry;
402 INIT_LIST_HEAD(&tx->db_list);
403
404 for (idx = 0; idx < FDMA_DCB_MAX; ++idx) {
405 dcb = &tx->curr_entry[idx];
406 dcb->info = 0;
407
408 for (jdx = 0; jdx < FDMA_TX_DCB_MAX_DBS; ++jdx) {
409 struct sparx5_db_hw *db_hw = &dcb->db[jdx];
410 struct sparx5_db *db;
411 dma_addr_t phys;
412 void *cpu_addr;
413
414 cpu_addr = devm_kzalloc(sparx5->dev,
415 FDMA_XTR_BUFFER_SIZE,
416 GFP_KERNEL);
417 if (!cpu_addr)
418 return -ENOMEM;
419 phys = virt_to_phys(cpu_addr);
420 db_hw->dataptr = phys;
421 db_hw->status = 0;
422 db = devm_kzalloc(sparx5->dev, sizeof(*db), GFP_KERNEL);
423 db->cpu_addr = cpu_addr;
424 list_add_tail(&db->list, &tx->db_list);
425 }
426 sparx5_fdma_tx_add_dcb(tx, dcb, tx->dma + sizeof(*dcb) * idx);
427
428 if (idx == FDMA_DCB_MAX - 1)
429 tx->curr_entry = dcb;
430 }
431 return 0;
432}
433
434static void sparx5_fdma_rx_init(struct sparx5 *sparx5,
435 struct sparx5_rx *rx, int channel)
436{
437 int idx;
438
439 rx->channel_id = channel;
440
441 for (idx = 0; idx < SPX5_PORTS; ++idx) {
442 struct sparx5_port *port = sparx5->ports[idx];
443
444 if (port && port->ndev) {
445 rx->ndev = port->ndev;
446 break;
447 }
448 }
449}
450
451static void sparx5_fdma_tx_init(struct sparx5 *sparx5,
452 struct sparx5_tx *tx, int channel)
453{
454 tx->channel_id = channel;
455}
456
457irqreturn_t sparx5_fdma_handler(int irq, void *args)
458{
459 struct sparx5 *sparx5 = args;
460 u32 db = 0, err = 0;
461
462 db = spx5_rd(sparx5, FDMA_INTR_DB);
463 err = spx5_rd(sparx5, FDMA_INTR_ERR);
464
465 if (db) {
466 spx5_wr(0, sparx5, FDMA_INTR_DB_ENA);
467 spx5_wr(db, sparx5, FDMA_INTR_DB);
468 napi_schedule(&sparx5->rx.napi);
469 }
470 if (err) {
471 u32 err_type = spx5_rd(sparx5, FDMA_ERRORS);
472
473 dev_err_ratelimited(sparx5->dev,
474 "ERR: int: %#x, type: %#x\n",
475 err, err_type);
476 spx5_wr(err, sparx5, FDMA_INTR_ERR);
477 spx5_wr(err_type, sparx5, FDMA_ERRORS);
478 }
479 return IRQ_HANDLED;
480}
481
482static void sparx5_fdma_injection_mode(struct sparx5 *sparx5)
483{
484 const int byte_swap = 1;
485 int portno;
486 int urgency;
487
488
489 spx5_wr(QS_XTR_GRP_CFG_MODE_SET(2) |
490 QS_XTR_GRP_CFG_STATUS_WORD_POS_SET(1) |
491 QS_XTR_GRP_CFG_BYTE_SWAP_SET(byte_swap),
492 sparx5, QS_XTR_GRP_CFG(XTR_QUEUE));
493 spx5_wr(QS_INJ_GRP_CFG_MODE_SET(2) |
494 QS_INJ_GRP_CFG_BYTE_SWAP_SET(byte_swap),
495 sparx5, QS_INJ_GRP_CFG(INJ_QUEUE));
496
497
498 for (portno = SPX5_PORT_CPU_0; portno <= SPX5_PORT_CPU_1; portno++) {
499
500 spx5_wr(ASM_PORT_CFG_PAD_ENA_SET(1) |
501 ASM_PORT_CFG_NO_PREAMBLE_ENA_SET(1) |
502 ASM_PORT_CFG_INJ_FORMAT_CFG_SET(1),
503 sparx5, ASM_PORT_CFG(portno));
504
505
506 spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV_TX_CNT_CLR_SET(1),
507 DSM_DEV_TX_STOP_WM_CFG_DEV_TX_CNT_CLR,
508 sparx5,
509 DSM_DEV_TX_STOP_WM_CFG(portno));
510
511
512 spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM_SET(100),
513 DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM,
514 sparx5,
515 DSM_DEV_TX_STOP_WM_CFG(portno));
516
517
518 urgency = sparx5_port_fwd_urg(sparx5, SPEED_2500);
519 spx5_rmw(QFWD_SWITCH_PORT_MODE_PORT_ENA_SET(1) |
520 QFWD_SWITCH_PORT_MODE_FWD_URGENCY_SET(urgency),
521 QFWD_SWITCH_PORT_MODE_PORT_ENA |
522 QFWD_SWITCH_PORT_MODE_FWD_URGENCY,
523 sparx5,
524 QFWD_SWITCH_PORT_MODE(portno));
525
526
527
528
529 spx5_rmw(DSM_BUF_CFG_UNDERFLOW_WATCHDOG_DIS_SET(1),
530 DSM_BUF_CFG_UNDERFLOW_WATCHDOG_DIS,
531 sparx5,
532 DSM_BUF_CFG(portno));
533
534
535 spx5_rmw(HSCH_PORT_MODE_AGE_DIS_SET(1),
536 HSCH_PORT_MODE_AGE_DIS,
537 sparx5,
538 HSCH_PORT_MODE(portno));
539 }
540}
541
542int sparx5_fdma_start(struct sparx5 *sparx5)
543{
544 int err;
545
546
547 spx5_wr(FDMA_CTRL_NRESET_SET(0), sparx5, FDMA_CTRL);
548 spx5_wr(FDMA_CTRL_NRESET_SET(1), sparx5, FDMA_CTRL);
549
550
551 spx5_rmw(CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA_SET(1) |
552 CPU_PROC_CTRL_ACP_AWCACHE_SET(0) |
553 CPU_PROC_CTRL_ACP_ARCACHE_SET(0),
554 CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA |
555 CPU_PROC_CTRL_ACP_AWCACHE |
556 CPU_PROC_CTRL_ACP_ARCACHE,
557 sparx5, CPU_PROC_CTRL);
558
559 sparx5_fdma_injection_mode(sparx5);
560 sparx5_fdma_rx_init(sparx5, &sparx5->rx, FDMA_XTR_CHANNEL);
561 sparx5_fdma_tx_init(sparx5, &sparx5->tx, FDMA_INJ_CHANNEL);
562 err = sparx5_fdma_rx_alloc(sparx5);
563 if (err) {
564 dev_err(sparx5->dev, "Could not allocate RX buffers: %d\n", err);
565 return err;
566 }
567 err = sparx5_fdma_tx_alloc(sparx5);
568 if (err) {
569 dev_err(sparx5->dev, "Could not allocate TX buffers: %d\n", err);
570 return err;
571 }
572 return err;
573}
574
575static u32 sparx5_fdma_port_ctrl(struct sparx5 *sparx5)
576{
577 return spx5_rd(sparx5, FDMA_PORT_CTRL(0));
578}
579
580int sparx5_fdma_stop(struct sparx5 *sparx5)
581{
582 u32 val;
583
584 napi_disable(&sparx5->rx.napi);
585
586 sparx5_fdma_rx_deactivate(sparx5, &sparx5->rx);
587 sparx5_fdma_tx_deactivate(sparx5, &sparx5->tx);
588
589 read_poll_timeout(sparx5_fdma_port_ctrl, val,
590 FDMA_PORT_CTRL_XTR_BUF_IS_EMPTY_GET(val) == 0,
591 500, 10000, 0, sparx5);
592 return 0;
593}
594