1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell RVU Admin Function driver
3 *
4 * Copyright (C) 2018 Marvell.
5 *
6 */
7
8 #include <linux/types.h>
9 #include <linux/module.h>
10 #include <linux/pci.h>
11
12 #include "rvu.h"
13 #include "cgx.h"
14 #include "lmac_common.h"
15 #include "rvu_reg.h"
16 #include "rvu_trace.h"
17 #include "rvu_npc_hash.h"
18
19 struct cgx_evq_entry {
20 struct list_head evq_node;
21 struct cgx_link_event link_event;
22 };
23
24 #define M(_name, _id, _fn_name, _req_type, _rsp_type) \
25 static struct _req_type __maybe_unused \
26 *otx2_mbox_alloc_msg_ ## _fn_name(struct rvu *rvu, int devid) \
27 { \
28 struct _req_type *req; \
29 \
30 req = (struct _req_type *)otx2_mbox_alloc_msg_rsp( \
31 &rvu->afpf_wq_info.mbox_up, devid, sizeof(struct _req_type), \
32 sizeof(struct _rsp_type)); \
33 if (!req) \
34 return NULL; \
35 req->hdr.sig = OTX2_MBOX_REQ_SIG; \
36 req->hdr.id = _id; \
37 trace_otx2_msg_alloc(rvu->pdev, _id, sizeof(*req)); \
38 return req; \
39 }
40
41 MBOX_UP_CGX_MESSAGES
42 #undef M
43
is_mac_feature_supported(struct rvu * rvu,int pf,int feature)44 bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature)
45 {
46 u8 cgx_id, lmac_id;
47 void *cgxd;
48
49 if (!is_pf_cgxmapped(rvu, pf))
50 return 0;
51
52 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
53 cgxd = rvu_cgx_pdata(cgx_id, rvu);
54
55 return (cgx_features_get(cgxd) & feature);
56 }
57
58 #define CGX_OFFSET(x) ((x) * rvu->hw->lmac_per_cgx)
59 /* Returns bitmap of mapped PFs */
cgxlmac_to_pfmap(struct rvu * rvu,u8 cgx_id,u8 lmac_id)60 static u64 cgxlmac_to_pfmap(struct rvu *rvu, u8 cgx_id, u8 lmac_id)
61 {
62 return rvu->cgxlmac2pf_map[CGX_OFFSET(cgx_id) + lmac_id];
63 }
64
cgxlmac_to_pf(struct rvu * rvu,int cgx_id,int lmac_id)65 int cgxlmac_to_pf(struct rvu *rvu, int cgx_id, int lmac_id)
66 {
67 unsigned long pfmap;
68
69 pfmap = cgxlmac_to_pfmap(rvu, cgx_id, lmac_id);
70
71 /* Assumes only one pf mapped to a cgx lmac port */
72 if (!pfmap)
73 return -ENODEV;
74 else
75 return find_first_bit(&pfmap,
76 rvu->cgx_cnt_max * rvu->hw->lmac_per_cgx);
77 }
78
cgxlmac_id_to_bmap(u8 cgx_id,u8 lmac_id)79 static u8 cgxlmac_id_to_bmap(u8 cgx_id, u8 lmac_id)
80 {
81 return ((cgx_id & 0xF) << 4) | (lmac_id & 0xF);
82 }
83
rvu_cgx_pdata(u8 cgx_id,struct rvu * rvu)84 void *rvu_cgx_pdata(u8 cgx_id, struct rvu *rvu)
85 {
86 if (cgx_id >= rvu->cgx_cnt_max)
87 return NULL;
88
89 return rvu->cgx_idmap[cgx_id];
90 }
91
92 /* Return first enabled CGX instance if none are enabled then return NULL */
rvu_first_cgx_pdata(struct rvu * rvu)93 void *rvu_first_cgx_pdata(struct rvu *rvu)
94 {
95 int first_enabled_cgx = 0;
96 void *cgxd = NULL;
97
98 for (; first_enabled_cgx < rvu->cgx_cnt_max; first_enabled_cgx++) {
99 cgxd = rvu_cgx_pdata(first_enabled_cgx, rvu);
100 if (cgxd)
101 break;
102 }
103
104 return cgxd;
105 }
106
107 /* Based on P2X connectivity find mapped NIX block for a PF */
rvu_map_cgx_nix_block(struct rvu * rvu,int pf,int cgx_id,int lmac_id)108 static void rvu_map_cgx_nix_block(struct rvu *rvu, int pf,
109 int cgx_id, int lmac_id)
110 {
111 struct rvu_pfvf *pfvf = &rvu->pf[pf];
112 u8 p2x;
113
114 p2x = cgx_lmac_get_p2x(cgx_id, lmac_id);
115 /* Firmware sets P2X_SELECT as either NIX0 or NIX1 */
116 pfvf->nix_blkaddr = BLKADDR_NIX0;
117 if (is_rvu_supports_nix1(rvu) && p2x == CMR_P2X_SEL_NIX1)
118 pfvf->nix_blkaddr = BLKADDR_NIX1;
119 }
120
rvu_map_cgx_lmac_pf(struct rvu * rvu)121 static int rvu_map_cgx_lmac_pf(struct rvu *rvu)
122 {
123 struct npc_pkind *pkind = &rvu->hw->pkind;
124 int cgx_cnt_max = rvu->cgx_cnt_max;
125 int pf = PF_CGXMAP_BASE;
126 unsigned long lmac_bmap;
127 int size, free_pkind;
128 int cgx, lmac, iter;
129 int numvfs, hwvfs;
130
131 if (!cgx_cnt_max)
132 return 0;
133
134 if (cgx_cnt_max > 0xF || rvu->hw->lmac_per_cgx > 0xF)
135 return -EINVAL;
136
137 /* Alloc map table
138 * An additional entry is required since PF id starts from 1 and
139 * hence entry at offset 0 is invalid.
140 */
141 size = (cgx_cnt_max * rvu->hw->lmac_per_cgx + 1) * sizeof(u8);
142 rvu->pf2cgxlmac_map = devm_kmalloc(rvu->dev, size, GFP_KERNEL);
143 if (!rvu->pf2cgxlmac_map)
144 return -ENOMEM;
145
146 /* Initialize all entries with an invalid cgx and lmac id */
147 memset(rvu->pf2cgxlmac_map, 0xFF, size);
148
149 /* Reverse map table */
150 rvu->cgxlmac2pf_map =
151 devm_kzalloc(rvu->dev,
152 cgx_cnt_max * rvu->hw->lmac_per_cgx * sizeof(u64),
153 GFP_KERNEL);
154 if (!rvu->cgxlmac2pf_map)
155 return -ENOMEM;
156
157 rvu->cgx_mapped_pfs = 0;
158 for (cgx = 0; cgx < cgx_cnt_max; cgx++) {
159 if (!rvu_cgx_pdata(cgx, rvu))
160 continue;
161 lmac_bmap = cgx_get_lmac_bmap(rvu_cgx_pdata(cgx, rvu));
162 for_each_set_bit(iter, &lmac_bmap, rvu->hw->lmac_per_cgx) {
163 lmac = cgx_get_lmacid(rvu_cgx_pdata(cgx, rvu),
164 iter);
165 rvu->pf2cgxlmac_map[pf] = cgxlmac_id_to_bmap(cgx, lmac);
166 rvu->cgxlmac2pf_map[CGX_OFFSET(cgx) + lmac] = 1 << pf;
167 free_pkind = rvu_alloc_rsrc(&pkind->rsrc);
168 pkind->pfchan_map[free_pkind] = ((pf) & 0x3F) << 16;
169 rvu_map_cgx_nix_block(rvu, pf, cgx, lmac);
170 rvu->cgx_mapped_pfs++;
171 rvu_get_pf_numvfs(rvu, pf, &numvfs, &hwvfs);
172 rvu->cgx_mapped_vfs += numvfs;
173 pf++;
174 }
175 }
176 return 0;
177 }
178
rvu_cgx_send_link_info(int cgx_id,int lmac_id,struct rvu * rvu)179 static int rvu_cgx_send_link_info(int cgx_id, int lmac_id, struct rvu *rvu)
180 {
181 struct cgx_evq_entry *qentry;
182 unsigned long flags;
183 int err;
184
185 qentry = kmalloc(sizeof(*qentry), GFP_KERNEL);
186 if (!qentry)
187 return -ENOMEM;
188
189 /* Lock the event queue before we read the local link status */
190 spin_lock_irqsave(&rvu->cgx_evq_lock, flags);
191 err = cgx_get_link_info(rvu_cgx_pdata(cgx_id, rvu), lmac_id,
192 &qentry->link_event.link_uinfo);
193 qentry->link_event.cgx_id = cgx_id;
194 qentry->link_event.lmac_id = lmac_id;
195 if (err) {
196 kfree(qentry);
197 goto skip_add;
198 }
199 list_add_tail(&qentry->evq_node, &rvu->cgx_evq_head);
200 skip_add:
201 spin_unlock_irqrestore(&rvu->cgx_evq_lock, flags);
202
203 /* start worker to process the events */
204 queue_work(rvu->cgx_evh_wq, &rvu->cgx_evh_work);
205
206 return 0;
207 }
208
209 /* This is called from interrupt context and is expected to be atomic */
cgx_lmac_postevent(struct cgx_link_event * event,void * data)210 static int cgx_lmac_postevent(struct cgx_link_event *event, void *data)
211 {
212 struct cgx_evq_entry *qentry;
213 struct rvu *rvu = data;
214
215 /* post event to the event queue */
216 qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC);
217 if (!qentry)
218 return -ENOMEM;
219 qentry->link_event = *event;
220 spin_lock(&rvu->cgx_evq_lock);
221 list_add_tail(&qentry->evq_node, &rvu->cgx_evq_head);
222 spin_unlock(&rvu->cgx_evq_lock);
223
224 /* start worker to process the events */
225 queue_work(rvu->cgx_evh_wq, &rvu->cgx_evh_work);
226
227 return 0;
228 }
229
cgx_notify_pfs(struct cgx_link_event * event,struct rvu * rvu)230 static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)
231 {
232 struct cgx_link_user_info *linfo;
233 struct cgx_link_info_msg *msg;
234 unsigned long pfmap;
235 int err, pfid;
236
237 linfo = &event->link_uinfo;
238 pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id);
239 if (!pfmap) {
240 dev_err(rvu->dev, "CGX port%d:%d not mapped with PF\n",
241 event->cgx_id, event->lmac_id);
242 return;
243 }
244
245 do {
246 pfid = find_first_bit(&pfmap,
247 rvu->cgx_cnt_max * rvu->hw->lmac_per_cgx);
248 clear_bit(pfid, &pfmap);
249
250 /* check if notification is enabled */
251 if (!test_bit(pfid, &rvu->pf_notify_bmap)) {
252 dev_info(rvu->dev, "cgx %d: lmac %d Link status %s\n",
253 event->cgx_id, event->lmac_id,
254 linfo->link_up ? "UP" : "DOWN");
255 continue;
256 }
257
258 /* Send mbox message to PF */
259 msg = otx2_mbox_alloc_msg_cgx_link_event(rvu, pfid);
260 if (!msg)
261 continue;
262 msg->link_info = *linfo;
263 otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, pfid);
264 err = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, pfid);
265 if (err)
266 dev_warn(rvu->dev, "notification to pf %d failed\n",
267 pfid);
268 } while (pfmap);
269 }
270
cgx_evhandler_task(struct work_struct * work)271 static void cgx_evhandler_task(struct work_struct *work)
272 {
273 struct rvu *rvu = container_of(work, struct rvu, cgx_evh_work);
274 struct cgx_evq_entry *qentry;
275 struct cgx_link_event *event;
276 unsigned long flags;
277
278 do {
279 /* Dequeue an event */
280 spin_lock_irqsave(&rvu->cgx_evq_lock, flags);
281 qentry = list_first_entry_or_null(&rvu->cgx_evq_head,
282 struct cgx_evq_entry,
283 evq_node);
284 if (qentry)
285 list_del(&qentry->evq_node);
286 spin_unlock_irqrestore(&rvu->cgx_evq_lock, flags);
287 if (!qentry)
288 break; /* nothing more to process */
289
290 event = &qentry->link_event;
291
292 /* process event */
293 cgx_notify_pfs(event, rvu);
294 kfree(qentry);
295 } while (1);
296 }
297
cgx_lmac_event_handler_init(struct rvu * rvu)298 static int cgx_lmac_event_handler_init(struct rvu *rvu)
299 {
300 unsigned long lmac_bmap;
301 struct cgx_event_cb cb;
302 int cgx, lmac, err;
303 void *cgxd;
304
305 spin_lock_init(&rvu->cgx_evq_lock);
306 INIT_LIST_HEAD(&rvu->cgx_evq_head);
307 INIT_WORK(&rvu->cgx_evh_work, cgx_evhandler_task);
308 rvu->cgx_evh_wq = alloc_workqueue("rvu_evh_wq", 0, 0);
309 if (!rvu->cgx_evh_wq) {
310 dev_err(rvu->dev, "alloc workqueue failed");
311 return -ENOMEM;
312 }
313
314 cb.notify_link_chg = cgx_lmac_postevent; /* link change call back */
315 cb.data = rvu;
316
317 for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
318 cgxd = rvu_cgx_pdata(cgx, rvu);
319 if (!cgxd)
320 continue;
321 lmac_bmap = cgx_get_lmac_bmap(cgxd);
322 for_each_set_bit(lmac, &lmac_bmap, rvu->hw->lmac_per_cgx) {
323 err = cgx_lmac_evh_register(&cb, cgxd, lmac);
324 if (err)
325 dev_err(rvu->dev,
326 "%d:%d handler register failed\n",
327 cgx, lmac);
328 }
329 }
330
331 return 0;
332 }
333
rvu_cgx_wq_destroy(struct rvu * rvu)334 static void rvu_cgx_wq_destroy(struct rvu *rvu)
335 {
336 if (rvu->cgx_evh_wq) {
337 destroy_workqueue(rvu->cgx_evh_wq);
338 rvu->cgx_evh_wq = NULL;
339 }
340 }
341
rvu_cgx_init(struct rvu * rvu)342 int rvu_cgx_init(struct rvu *rvu)
343 {
344 int cgx, err;
345 void *cgxd;
346
347 /* CGX port id starts from 0 and are not necessarily contiguous
348 * Hence we allocate resources based on the maximum port id value.
349 */
350 rvu->cgx_cnt_max = cgx_get_cgxcnt_max();
351 if (!rvu->cgx_cnt_max) {
352 dev_info(rvu->dev, "No CGX devices found!\n");
353 return 0;
354 }
355
356 rvu->cgx_idmap = devm_kzalloc(rvu->dev, rvu->cgx_cnt_max *
357 sizeof(void *), GFP_KERNEL);
358 if (!rvu->cgx_idmap)
359 return -ENOMEM;
360
361 /* Initialize the cgxdata table */
362 for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++)
363 rvu->cgx_idmap[cgx] = cgx_get_pdata(cgx);
364
365 /* Map CGX LMAC interfaces to RVU PFs */
366 err = rvu_map_cgx_lmac_pf(rvu);
367 if (err)
368 return err;
369
370 /* Register for CGX events */
371 err = cgx_lmac_event_handler_init(rvu);
372 if (err)
373 return err;
374
375 mutex_init(&rvu->cgx_cfg_lock);
376
377 /* Ensure event handler registration is completed, before
378 * we turn on the links
379 */
380 mb();
381
382 /* Do link up for all CGX ports */
383 for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
384 cgxd = rvu_cgx_pdata(cgx, rvu);
385 if (!cgxd)
386 continue;
387 err = cgx_lmac_linkup_start(cgxd);
388 if (err)
389 dev_err(rvu->dev,
390 "Link up process failed to start on cgx %d\n",
391 cgx);
392 }
393
394 return 0;
395 }
396
rvu_cgx_exit(struct rvu * rvu)397 int rvu_cgx_exit(struct rvu *rvu)
398 {
399 unsigned long lmac_bmap;
400 int cgx, lmac;
401 void *cgxd;
402
403 for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
404 cgxd = rvu_cgx_pdata(cgx, rvu);
405 if (!cgxd)
406 continue;
407 lmac_bmap = cgx_get_lmac_bmap(cgxd);
408 for_each_set_bit(lmac, &lmac_bmap, rvu->hw->lmac_per_cgx)
409 cgx_lmac_evh_unregister(cgxd, lmac);
410 }
411
412 /* Ensure event handler unregister is completed */
413 mb();
414
415 rvu_cgx_wq_destroy(rvu);
416 return 0;
417 }
418
419 /* Most of the CGX configuration is restricted to the mapped PF only,
420 * VF's of mapped PF and other PFs are not allowed. This fn() checks
421 * whether a PFFUNC is permitted to do the config or not.
422 */
is_cgx_config_permitted(struct rvu * rvu,u16 pcifunc)423 inline bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc)
424 {
425 if ((pcifunc & RVU_PFVF_FUNC_MASK) ||
426 !is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc)))
427 return false;
428 return true;
429 }
430
rvu_cgx_enadis_rx_bp(struct rvu * rvu,int pf,bool enable)431 void rvu_cgx_enadis_rx_bp(struct rvu *rvu, int pf, bool enable)
432 {
433 struct mac_ops *mac_ops;
434 u8 cgx_id, lmac_id;
435 void *cgxd;
436
437 if (!is_pf_cgxmapped(rvu, pf))
438 return;
439
440 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
441 cgxd = rvu_cgx_pdata(cgx_id, rvu);
442
443 mac_ops = get_mac_ops(cgxd);
444 /* Set / clear CTL_BCK to control pause frame forwarding to NIX */
445 if (enable)
446 mac_ops->mac_enadis_rx_pause_fwding(cgxd, lmac_id, true);
447 else
448 mac_ops->mac_enadis_rx_pause_fwding(cgxd, lmac_id, false);
449 }
450
rvu_cgx_config_rxtx(struct rvu * rvu,u16 pcifunc,bool start)451 int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start)
452 {
453 int pf = rvu_get_pf(pcifunc);
454 struct mac_ops *mac_ops;
455 u8 cgx_id, lmac_id;
456 void *cgxd;
457
458 if (!is_cgx_config_permitted(rvu, pcifunc))
459 return LMAC_AF_ERR_PERM_DENIED;
460
461 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
462 cgxd = rvu_cgx_pdata(cgx_id, rvu);
463 mac_ops = get_mac_ops(cgxd);
464
465 return mac_ops->mac_rx_tx_enable(cgxd, lmac_id, start);
466 }
467
rvu_cgx_config_tx(void * cgxd,int lmac_id,bool enable)468 int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable)
469 {
470 struct mac_ops *mac_ops;
471
472 mac_ops = get_mac_ops(cgxd);
473 return mac_ops->mac_tx_enable(cgxd, lmac_id, enable);
474 }
475
rvu_cgx_disable_dmac_entries(struct rvu * rvu,u16 pcifunc)476 void rvu_cgx_disable_dmac_entries(struct rvu *rvu, u16 pcifunc)
477 {
478 int pf = rvu_get_pf(pcifunc);
479 int i = 0, lmac_count = 0;
480 struct mac_ops *mac_ops;
481 u8 max_dmac_filters;
482 u8 cgx_id, lmac_id;
483 void *cgx_dev;
484
485 if (!is_cgx_config_permitted(rvu, pcifunc))
486 return;
487
488 if (rvu_npc_exact_has_match_table(rvu)) {
489 rvu_npc_exact_reset(rvu, pcifunc);
490 return;
491 }
492
493 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
494 cgx_dev = cgx_get_pdata(cgx_id);
495 lmac_count = cgx_get_lmac_cnt(cgx_dev);
496
497 mac_ops = get_mac_ops(cgx_dev);
498 if (!mac_ops)
499 return;
500
501 max_dmac_filters = mac_ops->dmac_filter_count / lmac_count;
502
503 for (i = 0; i < max_dmac_filters; i++)
504 cgx_lmac_addr_del(cgx_id, lmac_id, i);
505
506 /* As cgx_lmac_addr_del does not clear entry for index 0
507 * so it needs to be done explicitly
508 */
509 cgx_lmac_addr_reset(cgx_id, lmac_id);
510 }
511
rvu_mbox_handler_cgx_start_rxtx(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)512 int rvu_mbox_handler_cgx_start_rxtx(struct rvu *rvu, struct msg_req *req,
513 struct msg_rsp *rsp)
514 {
515 rvu_cgx_config_rxtx(rvu, req->hdr.pcifunc, true);
516 return 0;
517 }
518
rvu_mbox_handler_cgx_stop_rxtx(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)519 int rvu_mbox_handler_cgx_stop_rxtx(struct rvu *rvu, struct msg_req *req,
520 struct msg_rsp *rsp)
521 {
522 rvu_cgx_config_rxtx(rvu, req->hdr.pcifunc, false);
523 return 0;
524 }
525
rvu_lmac_get_stats(struct rvu * rvu,struct msg_req * req,void * rsp)526 static int rvu_lmac_get_stats(struct rvu *rvu, struct msg_req *req,
527 void *rsp)
528 {
529 int pf = rvu_get_pf(req->hdr.pcifunc);
530 struct mac_ops *mac_ops;
531 int stat = 0, err = 0;
532 u64 tx_stat, rx_stat;
533 u8 cgx_idx, lmac;
534 void *cgxd;
535
536 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
537 return LMAC_AF_ERR_PERM_DENIED;
538
539 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac);
540 cgxd = rvu_cgx_pdata(cgx_idx, rvu);
541 mac_ops = get_mac_ops(cgxd);
542
543 /* Rx stats */
544 while (stat < mac_ops->rx_stats_cnt) {
545 err = mac_ops->mac_get_rx_stats(cgxd, lmac, stat, &rx_stat);
546 if (err)
547 return err;
548 if (mac_ops->rx_stats_cnt == RPM_RX_STATS_COUNT)
549 ((struct rpm_stats_rsp *)rsp)->rx_stats[stat] = rx_stat;
550 else
551 ((struct cgx_stats_rsp *)rsp)->rx_stats[stat] = rx_stat;
552 stat++;
553 }
554
555 /* Tx stats */
556 stat = 0;
557 while (stat < mac_ops->tx_stats_cnt) {
558 err = mac_ops->mac_get_tx_stats(cgxd, lmac, stat, &tx_stat);
559 if (err)
560 return err;
561 if (mac_ops->tx_stats_cnt == RPM_TX_STATS_COUNT)
562 ((struct rpm_stats_rsp *)rsp)->tx_stats[stat] = tx_stat;
563 else
564 ((struct cgx_stats_rsp *)rsp)->tx_stats[stat] = tx_stat;
565 stat++;
566 }
567 return 0;
568 }
569
rvu_mbox_handler_cgx_stats(struct rvu * rvu,struct msg_req * req,struct cgx_stats_rsp * rsp)570 int rvu_mbox_handler_cgx_stats(struct rvu *rvu, struct msg_req *req,
571 struct cgx_stats_rsp *rsp)
572 {
573 return rvu_lmac_get_stats(rvu, req, (void *)rsp);
574 }
575
rvu_mbox_handler_rpm_stats(struct rvu * rvu,struct msg_req * req,struct rpm_stats_rsp * rsp)576 int rvu_mbox_handler_rpm_stats(struct rvu *rvu, struct msg_req *req,
577 struct rpm_stats_rsp *rsp)
578 {
579 return rvu_lmac_get_stats(rvu, req, (void *)rsp);
580 }
581
rvu_mbox_handler_cgx_fec_stats(struct rvu * rvu,struct msg_req * req,struct cgx_fec_stats_rsp * rsp)582 int rvu_mbox_handler_cgx_fec_stats(struct rvu *rvu,
583 struct msg_req *req,
584 struct cgx_fec_stats_rsp *rsp)
585 {
586 int pf = rvu_get_pf(req->hdr.pcifunc);
587 struct mac_ops *mac_ops;
588 u8 cgx_idx, lmac;
589 void *cgxd;
590
591 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
592 return LMAC_AF_ERR_PERM_DENIED;
593 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac);
594
595 cgxd = rvu_cgx_pdata(cgx_idx, rvu);
596 mac_ops = get_mac_ops(cgxd);
597 return mac_ops->get_fec_stats(cgxd, lmac, rsp);
598 }
599
rvu_mbox_handler_cgx_mac_addr_set(struct rvu * rvu,struct cgx_mac_addr_set_or_get * req,struct cgx_mac_addr_set_or_get * rsp)600 int rvu_mbox_handler_cgx_mac_addr_set(struct rvu *rvu,
601 struct cgx_mac_addr_set_or_get *req,
602 struct cgx_mac_addr_set_or_get *rsp)
603 {
604 int pf = rvu_get_pf(req->hdr.pcifunc);
605 u8 cgx_id, lmac_id;
606
607 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
608 return -EPERM;
609
610 if (rvu_npc_exact_has_match_table(rvu))
611 return rvu_npc_exact_mac_addr_set(rvu, req, rsp);
612
613 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
614
615 cgx_lmac_addr_set(cgx_id, lmac_id, req->mac_addr);
616
617 return 0;
618 }
619
rvu_mbox_handler_cgx_mac_addr_add(struct rvu * rvu,struct cgx_mac_addr_add_req * req,struct cgx_mac_addr_add_rsp * rsp)620 int rvu_mbox_handler_cgx_mac_addr_add(struct rvu *rvu,
621 struct cgx_mac_addr_add_req *req,
622 struct cgx_mac_addr_add_rsp *rsp)
623 {
624 int pf = rvu_get_pf(req->hdr.pcifunc);
625 u8 cgx_id, lmac_id;
626 int rc = 0;
627
628 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
629 return -EPERM;
630
631 if (rvu_npc_exact_has_match_table(rvu))
632 return rvu_npc_exact_mac_addr_add(rvu, req, rsp);
633
634 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
635 rc = cgx_lmac_addr_add(cgx_id, lmac_id, req->mac_addr);
636 if (rc >= 0) {
637 rsp->index = rc;
638 return 0;
639 }
640
641 return rc;
642 }
643
rvu_mbox_handler_cgx_mac_addr_del(struct rvu * rvu,struct cgx_mac_addr_del_req * req,struct msg_rsp * rsp)644 int rvu_mbox_handler_cgx_mac_addr_del(struct rvu *rvu,
645 struct cgx_mac_addr_del_req *req,
646 struct msg_rsp *rsp)
647 {
648 int pf = rvu_get_pf(req->hdr.pcifunc);
649 u8 cgx_id, lmac_id;
650
651 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
652 return -EPERM;
653
654 if (rvu_npc_exact_has_match_table(rvu))
655 return rvu_npc_exact_mac_addr_del(rvu, req, rsp);
656
657 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
658 return cgx_lmac_addr_del(cgx_id, lmac_id, req->index);
659 }
660
rvu_mbox_handler_cgx_mac_max_entries_get(struct rvu * rvu,struct msg_req * req,struct cgx_max_dmac_entries_get_rsp * rsp)661 int rvu_mbox_handler_cgx_mac_max_entries_get(struct rvu *rvu,
662 struct msg_req *req,
663 struct cgx_max_dmac_entries_get_rsp
664 *rsp)
665 {
666 int pf = rvu_get_pf(req->hdr.pcifunc);
667 u8 cgx_id, lmac_id;
668
669 /* If msg is received from PFs(which are not mapped to CGX LMACs)
670 * or VF then no entries are allocated for DMAC filters at CGX level.
671 * So returning zero.
672 */
673 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) {
674 rsp->max_dmac_filters = 0;
675 return 0;
676 }
677
678 if (rvu_npc_exact_has_match_table(rvu)) {
679 rsp->max_dmac_filters = rvu_npc_exact_get_max_entries(rvu);
680 return 0;
681 }
682
683 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
684 rsp->max_dmac_filters = cgx_lmac_addr_max_entries_get(cgx_id, lmac_id);
685 return 0;
686 }
687
rvu_mbox_handler_cgx_mac_addr_get(struct rvu * rvu,struct cgx_mac_addr_set_or_get * req,struct cgx_mac_addr_set_or_get * rsp)688 int rvu_mbox_handler_cgx_mac_addr_get(struct rvu *rvu,
689 struct cgx_mac_addr_set_or_get *req,
690 struct cgx_mac_addr_set_or_get *rsp)
691 {
692 int pf = rvu_get_pf(req->hdr.pcifunc);
693 u8 cgx_id, lmac_id;
694 int rc = 0;
695 u64 cfg;
696
697 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
698 return -EPERM;
699
700 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
701
702 rsp->hdr.rc = rc;
703 cfg = cgx_lmac_addr_get(cgx_id, lmac_id);
704 /* copy 48 bit mac address to req->mac_addr */
705 u64_to_ether_addr(cfg, rsp->mac_addr);
706 return 0;
707 }
708
rvu_mbox_handler_cgx_promisc_enable(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)709 int rvu_mbox_handler_cgx_promisc_enable(struct rvu *rvu, struct msg_req *req,
710 struct msg_rsp *rsp)
711 {
712 u16 pcifunc = req->hdr.pcifunc;
713 int pf = rvu_get_pf(pcifunc);
714 u8 cgx_id, lmac_id;
715
716 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
717 return -EPERM;
718
719 /* Disable drop on non hit rule */
720 if (rvu_npc_exact_has_match_table(rvu))
721 return rvu_npc_exact_promisc_enable(rvu, req->hdr.pcifunc);
722
723 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
724
725 cgx_lmac_promisc_config(cgx_id, lmac_id, true);
726 return 0;
727 }
728
rvu_mbox_handler_cgx_promisc_disable(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)729 int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req,
730 struct msg_rsp *rsp)
731 {
732 int pf = rvu_get_pf(req->hdr.pcifunc);
733 u8 cgx_id, lmac_id;
734
735 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
736 return -EPERM;
737
738 /* Disable drop on non hit rule */
739 if (rvu_npc_exact_has_match_table(rvu))
740 return rvu_npc_exact_promisc_disable(rvu, req->hdr.pcifunc);
741
742 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
743
744 cgx_lmac_promisc_config(cgx_id, lmac_id, false);
745 return 0;
746 }
747
rvu_cgx_ptp_rx_cfg(struct rvu * rvu,u16 pcifunc,bool enable)748 static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
749 {
750 struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
751 int pf = rvu_get_pf(pcifunc);
752 struct mac_ops *mac_ops;
753 u8 cgx_id, lmac_id;
754 void *cgxd;
755
756 if (!is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_PTP))
757 return 0;
758
759 /* This msg is expected only from PFs that are mapped to CGX LMACs,
760 * if received from other PF/VF simply ACK, nothing to do.
761 */
762 if ((pcifunc & RVU_PFVF_FUNC_MASK) ||
763 !is_pf_cgxmapped(rvu, pf))
764 return -ENODEV;
765
766 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
767 cgxd = rvu_cgx_pdata(cgx_id, rvu);
768
769 mac_ops = get_mac_ops(cgxd);
770 mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, enable);
771 /* If PTP is enabled then inform NPC that packets to be
772 * parsed by this PF will have their data shifted by 8 bytes
773 * and if PTP is disabled then no shift is required
774 */
775 if (npc_config_ts_kpuaction(rvu, pf, pcifunc, enable))
776 return -EINVAL;
777 /* This flag is required to clean up CGX conf if app gets killed */
778 pfvf->hw_rx_tstamp_en = enable;
779
780 /* Inform MCS about 8B RX header */
781 rvu_mcs_ptp_cfg(rvu, cgx_id, lmac_id, enable);
782 return 0;
783 }
784
rvu_mbox_handler_cgx_ptp_rx_enable(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)785 int rvu_mbox_handler_cgx_ptp_rx_enable(struct rvu *rvu, struct msg_req *req,
786 struct msg_rsp *rsp)
787 {
788 if (!is_pf_cgxmapped(rvu, rvu_get_pf(req->hdr.pcifunc)))
789 return -EPERM;
790
791 return rvu_cgx_ptp_rx_cfg(rvu, req->hdr.pcifunc, true);
792 }
793
rvu_mbox_handler_cgx_ptp_rx_disable(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)794 int rvu_mbox_handler_cgx_ptp_rx_disable(struct rvu *rvu, struct msg_req *req,
795 struct msg_rsp *rsp)
796 {
797 return rvu_cgx_ptp_rx_cfg(rvu, req->hdr.pcifunc, false);
798 }
799
rvu_cgx_config_linkevents(struct rvu * rvu,u16 pcifunc,bool en)800 static int rvu_cgx_config_linkevents(struct rvu *rvu, u16 pcifunc, bool en)
801 {
802 int pf = rvu_get_pf(pcifunc);
803 u8 cgx_id, lmac_id;
804
805 if (!is_cgx_config_permitted(rvu, pcifunc))
806 return -EPERM;
807
808 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
809
810 if (en) {
811 set_bit(pf, &rvu->pf_notify_bmap);
812 /* Send the current link status to PF */
813 rvu_cgx_send_link_info(cgx_id, lmac_id, rvu);
814 } else {
815 clear_bit(pf, &rvu->pf_notify_bmap);
816 }
817
818 return 0;
819 }
820
rvu_mbox_handler_cgx_start_linkevents(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)821 int rvu_mbox_handler_cgx_start_linkevents(struct rvu *rvu, struct msg_req *req,
822 struct msg_rsp *rsp)
823 {
824 rvu_cgx_config_linkevents(rvu, req->hdr.pcifunc, true);
825 return 0;
826 }
827
rvu_mbox_handler_cgx_stop_linkevents(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)828 int rvu_mbox_handler_cgx_stop_linkevents(struct rvu *rvu, struct msg_req *req,
829 struct msg_rsp *rsp)
830 {
831 rvu_cgx_config_linkevents(rvu, req->hdr.pcifunc, false);
832 return 0;
833 }
834
rvu_mbox_handler_cgx_get_linkinfo(struct rvu * rvu,struct msg_req * req,struct cgx_link_info_msg * rsp)835 int rvu_mbox_handler_cgx_get_linkinfo(struct rvu *rvu, struct msg_req *req,
836 struct cgx_link_info_msg *rsp)
837 {
838 u8 cgx_id, lmac_id;
839 int pf, err;
840
841 pf = rvu_get_pf(req->hdr.pcifunc);
842
843 if (!is_pf_cgxmapped(rvu, pf))
844 return -ENODEV;
845
846 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
847
848 err = cgx_get_link_info(rvu_cgx_pdata(cgx_id, rvu), lmac_id,
849 &rsp->link_info);
850 return err;
851 }
852
rvu_mbox_handler_cgx_features_get(struct rvu * rvu,struct msg_req * req,struct cgx_features_info_msg * rsp)853 int rvu_mbox_handler_cgx_features_get(struct rvu *rvu,
854 struct msg_req *req,
855 struct cgx_features_info_msg *rsp)
856 {
857 int pf = rvu_get_pf(req->hdr.pcifunc);
858 u8 cgx_idx, lmac;
859 void *cgxd;
860
861 if (!is_pf_cgxmapped(rvu, pf))
862 return 0;
863
864 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac);
865 cgxd = rvu_cgx_pdata(cgx_idx, rvu);
866 rsp->lmac_features = cgx_features_get(cgxd);
867
868 return 0;
869 }
870
rvu_cgx_get_fifolen(struct rvu * rvu)871 u32 rvu_cgx_get_fifolen(struct rvu *rvu)
872 {
873 struct mac_ops *mac_ops;
874 u32 fifo_len;
875
876 mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu));
877 fifo_len = mac_ops ? mac_ops->fifo_len : 0;
878
879 return fifo_len;
880 }
881
rvu_cgx_get_lmac_fifolen(struct rvu * rvu,int cgx,int lmac)882 u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac)
883 {
884 struct mac_ops *mac_ops;
885 void *cgxd;
886
887 cgxd = rvu_cgx_pdata(cgx, rvu);
888 if (!cgxd)
889 return 0;
890
891 mac_ops = get_mac_ops(cgxd);
892 if (!mac_ops->lmac_fifo_len)
893 return 0;
894
895 return mac_ops->lmac_fifo_len(cgxd, lmac);
896 }
897
rvu_cgx_config_intlbk(struct rvu * rvu,u16 pcifunc,bool en)898 static int rvu_cgx_config_intlbk(struct rvu *rvu, u16 pcifunc, bool en)
899 {
900 int pf = rvu_get_pf(pcifunc);
901 struct mac_ops *mac_ops;
902 u8 cgx_id, lmac_id;
903
904 if (!is_cgx_config_permitted(rvu, pcifunc))
905 return -EPERM;
906
907 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
908 mac_ops = get_mac_ops(rvu_cgx_pdata(cgx_id, rvu));
909
910 return mac_ops->mac_lmac_intl_lbk(rvu_cgx_pdata(cgx_id, rvu),
911 lmac_id, en);
912 }
913
rvu_mbox_handler_cgx_intlbk_enable(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)914 int rvu_mbox_handler_cgx_intlbk_enable(struct rvu *rvu, struct msg_req *req,
915 struct msg_rsp *rsp)
916 {
917 rvu_cgx_config_intlbk(rvu, req->hdr.pcifunc, true);
918 return 0;
919 }
920
rvu_mbox_handler_cgx_intlbk_disable(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)921 int rvu_mbox_handler_cgx_intlbk_disable(struct rvu *rvu, struct msg_req *req,
922 struct msg_rsp *rsp)
923 {
924 rvu_cgx_config_intlbk(rvu, req->hdr.pcifunc, false);
925 return 0;
926 }
927
rvu_cgx_cfg_pause_frm(struct rvu * rvu,u16 pcifunc,u8 tx_pause,u8 rx_pause)928 int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause)
929 {
930 int pf = rvu_get_pf(pcifunc);
931 u8 rx_pfc = 0, tx_pfc = 0;
932 struct mac_ops *mac_ops;
933 u8 cgx_id, lmac_id;
934 void *cgxd;
935
936 if (!is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_FC))
937 return 0;
938
939 /* This msg is expected only from PF/VFs that are mapped to CGX LMACs,
940 * if received from other PF/VF simply ACK, nothing to do.
941 */
942 if (!is_pf_cgxmapped(rvu, pf))
943 return LMAC_AF_ERR_PF_NOT_MAPPED;
944
945 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
946 cgxd = rvu_cgx_pdata(cgx_id, rvu);
947 mac_ops = get_mac_ops(cgxd);
948
949 mac_ops->mac_get_pfc_frm_cfg(cgxd, lmac_id, &tx_pfc, &rx_pfc);
950 if (tx_pfc || rx_pfc) {
951 dev_warn(rvu->dev,
952 "Can not configure 802.3X flow control as PFC frames are enabled");
953 return LMAC_AF_ERR_8023PAUSE_ENADIS_PERM_DENIED;
954 }
955
956 mutex_lock(&rvu->rsrc_lock);
957 if (verify_lmac_fc_cfg(cgxd, lmac_id, tx_pause, rx_pause,
958 pcifunc & RVU_PFVF_FUNC_MASK)) {
959 mutex_unlock(&rvu->rsrc_lock);
960 return LMAC_AF_ERR_PERM_DENIED;
961 }
962 mutex_unlock(&rvu->rsrc_lock);
963
964 return mac_ops->mac_enadis_pause_frm(cgxd, lmac_id, tx_pause, rx_pause);
965 }
966
rvu_mbox_handler_cgx_cfg_pause_frm(struct rvu * rvu,struct cgx_pause_frm_cfg * req,struct cgx_pause_frm_cfg * rsp)967 int rvu_mbox_handler_cgx_cfg_pause_frm(struct rvu *rvu,
968 struct cgx_pause_frm_cfg *req,
969 struct cgx_pause_frm_cfg *rsp)
970 {
971 int pf = rvu_get_pf(req->hdr.pcifunc);
972 struct mac_ops *mac_ops;
973 u8 cgx_id, lmac_id;
974 int err = 0;
975 void *cgxd;
976
977 /* This msg is expected only from PF/VFs that are mapped to CGX LMACs,
978 * if received from other PF/VF simply ACK, nothing to do.
979 */
980 if (!is_pf_cgxmapped(rvu, pf))
981 return -ENODEV;
982
983 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
984 cgxd = rvu_cgx_pdata(cgx_id, rvu);
985 mac_ops = get_mac_ops(cgxd);
986
987 if (req->set)
988 err = rvu_cgx_cfg_pause_frm(rvu, req->hdr.pcifunc, req->tx_pause, req->rx_pause);
989 else
990 mac_ops->mac_get_pause_frm_status(cgxd, lmac_id, &rsp->tx_pause, &rsp->rx_pause);
991
992 return err;
993 }
994
rvu_mbox_handler_cgx_get_phy_fec_stats(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)995 int rvu_mbox_handler_cgx_get_phy_fec_stats(struct rvu *rvu, struct msg_req *req,
996 struct msg_rsp *rsp)
997 {
998 int pf = rvu_get_pf(req->hdr.pcifunc);
999 u8 cgx_id, lmac_id;
1000
1001 if (!is_pf_cgxmapped(rvu, pf))
1002 return LMAC_AF_ERR_PF_NOT_MAPPED;
1003
1004 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1005 return cgx_get_phy_fec_stats(rvu_cgx_pdata(cgx_id, rvu), lmac_id);
1006 }
1007
1008 /* Finds cumulative status of NIX rx/tx counters from LF of a PF and those
1009 * from its VFs as well. ie. NIX rx/tx counters at the CGX port level
1010 */
rvu_cgx_nix_cuml_stats(struct rvu * rvu,void * cgxd,int lmac_id,int index,int rxtxflag,u64 * stat)1011 int rvu_cgx_nix_cuml_stats(struct rvu *rvu, void *cgxd, int lmac_id,
1012 int index, int rxtxflag, u64 *stat)
1013 {
1014 struct rvu_block *block;
1015 int blkaddr;
1016 u16 pcifunc;
1017 int pf, lf;
1018
1019 *stat = 0;
1020
1021 if (!cgxd || !rvu)
1022 return -EINVAL;
1023
1024 pf = cgxlmac_to_pf(rvu, cgx_get_cgxid(cgxd), lmac_id);
1025 if (pf < 0)
1026 return pf;
1027
1028 /* Assumes LF of a PF and all of its VF belongs to the same
1029 * NIX block
1030 */
1031 pcifunc = pf << RVU_PFVF_PF_SHIFT;
1032 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
1033 if (blkaddr < 0)
1034 return 0;
1035 block = &rvu->hw->block[blkaddr];
1036
1037 for (lf = 0; lf < block->lf.max; lf++) {
1038 /* Check if a lf is attached to this PF or one of its VFs */
1039 if (!((block->fn_map[lf] & ~RVU_PFVF_FUNC_MASK) == (pcifunc &
1040 ~RVU_PFVF_FUNC_MASK)))
1041 continue;
1042 if (rxtxflag == NIX_STATS_RX)
1043 *stat += rvu_read64(rvu, blkaddr,
1044 NIX_AF_LFX_RX_STATX(lf, index));
1045 else
1046 *stat += rvu_read64(rvu, blkaddr,
1047 NIX_AF_LFX_TX_STATX(lf, index));
1048 }
1049
1050 return 0;
1051 }
1052
rvu_cgx_start_stop_io(struct rvu * rvu,u16 pcifunc,bool start)1053 int rvu_cgx_start_stop_io(struct rvu *rvu, u16 pcifunc, bool start)
1054 {
1055 struct rvu_pfvf *parent_pf, *pfvf;
1056 int cgx_users, err = 0;
1057
1058 if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc)))
1059 return 0;
1060
1061 parent_pf = &rvu->pf[rvu_get_pf(pcifunc)];
1062 pfvf = rvu_get_pfvf(rvu, pcifunc);
1063
1064 mutex_lock(&rvu->cgx_cfg_lock);
1065
1066 if (start && pfvf->cgx_in_use)
1067 goto exit; /* CGX is already started hence nothing to do */
1068 if (!start && !pfvf->cgx_in_use)
1069 goto exit; /* CGX is already stopped hence nothing to do */
1070
1071 if (start) {
1072 cgx_users = parent_pf->cgx_users;
1073 parent_pf->cgx_users++;
1074 } else {
1075 parent_pf->cgx_users--;
1076 cgx_users = parent_pf->cgx_users;
1077 }
1078
1079 /* Start CGX when first of all NIXLFs is started.
1080 * Stop CGX when last of all NIXLFs is stopped.
1081 */
1082 if (!cgx_users) {
1083 err = rvu_cgx_config_rxtx(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK,
1084 start);
1085 if (err) {
1086 dev_err(rvu->dev, "Unable to %s CGX\n",
1087 start ? "start" : "stop");
1088 /* Revert the usage count in case of error */
1089 parent_pf->cgx_users = start ? parent_pf->cgx_users - 1
1090 : parent_pf->cgx_users + 1;
1091 goto exit;
1092 }
1093 }
1094 pfvf->cgx_in_use = start;
1095 exit:
1096 mutex_unlock(&rvu->cgx_cfg_lock);
1097 return err;
1098 }
1099
rvu_mbox_handler_cgx_set_fec_param(struct rvu * rvu,struct fec_mode * req,struct fec_mode * rsp)1100 int rvu_mbox_handler_cgx_set_fec_param(struct rvu *rvu,
1101 struct fec_mode *req,
1102 struct fec_mode *rsp)
1103 {
1104 int pf = rvu_get_pf(req->hdr.pcifunc);
1105 u8 cgx_id, lmac_id;
1106
1107 if (!is_pf_cgxmapped(rvu, pf))
1108 return -EPERM;
1109
1110 if (req->fec == OTX2_FEC_OFF)
1111 req->fec = OTX2_FEC_NONE;
1112 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1113 rsp->fec = cgx_set_fec(req->fec, cgx_id, lmac_id);
1114 return 0;
1115 }
1116
rvu_mbox_handler_cgx_get_aux_link_info(struct rvu * rvu,struct msg_req * req,struct cgx_fw_data * rsp)1117 int rvu_mbox_handler_cgx_get_aux_link_info(struct rvu *rvu, struct msg_req *req,
1118 struct cgx_fw_data *rsp)
1119 {
1120 int pf = rvu_get_pf(req->hdr.pcifunc);
1121 u8 cgx_id, lmac_id;
1122
1123 if (!rvu->fwdata)
1124 return LMAC_AF_ERR_FIRMWARE_DATA_NOT_MAPPED;
1125
1126 if (!is_pf_cgxmapped(rvu, pf))
1127 return -EPERM;
1128
1129 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1130
1131 if (rvu->hw->lmac_per_cgx == CGX_LMACS_USX)
1132 memcpy(&rsp->fwdata,
1133 &rvu->fwdata->cgx_fw_data_usx[cgx_id][lmac_id],
1134 sizeof(struct cgx_lmac_fwdata_s));
1135 else
1136 memcpy(&rsp->fwdata,
1137 &rvu->fwdata->cgx_fw_data[cgx_id][lmac_id],
1138 sizeof(struct cgx_lmac_fwdata_s));
1139
1140 return 0;
1141 }
1142
rvu_mbox_handler_cgx_set_link_mode(struct rvu * rvu,struct cgx_set_link_mode_req * req,struct cgx_set_link_mode_rsp * rsp)1143 int rvu_mbox_handler_cgx_set_link_mode(struct rvu *rvu,
1144 struct cgx_set_link_mode_req *req,
1145 struct cgx_set_link_mode_rsp *rsp)
1146 {
1147 int pf = rvu_get_pf(req->hdr.pcifunc);
1148 u8 cgx_idx, lmac;
1149 void *cgxd;
1150
1151 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
1152 return -EPERM;
1153
1154 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac);
1155 cgxd = rvu_cgx_pdata(cgx_idx, rvu);
1156 rsp->status = cgx_set_link_mode(cgxd, req->args, cgx_idx, lmac);
1157 return 0;
1158 }
1159
rvu_mbox_handler_cgx_mac_addr_reset(struct rvu * rvu,struct cgx_mac_addr_reset_req * req,struct msg_rsp * rsp)1160 int rvu_mbox_handler_cgx_mac_addr_reset(struct rvu *rvu, struct cgx_mac_addr_reset_req *req,
1161 struct msg_rsp *rsp)
1162 {
1163 int pf = rvu_get_pf(req->hdr.pcifunc);
1164 u8 cgx_id, lmac_id;
1165
1166 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
1167 return LMAC_AF_ERR_PERM_DENIED;
1168
1169 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1170
1171 if (rvu_npc_exact_has_match_table(rvu))
1172 return rvu_npc_exact_mac_addr_reset(rvu, req, rsp);
1173
1174 return cgx_lmac_addr_reset(cgx_id, lmac_id);
1175 }
1176
rvu_mbox_handler_cgx_mac_addr_update(struct rvu * rvu,struct cgx_mac_addr_update_req * req,struct cgx_mac_addr_update_rsp * rsp)1177 int rvu_mbox_handler_cgx_mac_addr_update(struct rvu *rvu,
1178 struct cgx_mac_addr_update_req *req,
1179 struct cgx_mac_addr_update_rsp *rsp)
1180 {
1181 int pf = rvu_get_pf(req->hdr.pcifunc);
1182 u8 cgx_id, lmac_id;
1183
1184 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
1185 return LMAC_AF_ERR_PERM_DENIED;
1186
1187 if (rvu_npc_exact_has_match_table(rvu))
1188 return rvu_npc_exact_mac_addr_update(rvu, req, rsp);
1189
1190 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1191 return cgx_lmac_addr_update(cgx_id, lmac_id, req->mac_addr, req->index);
1192 }
1193
rvu_cgx_prio_flow_ctrl_cfg(struct rvu * rvu,u16 pcifunc,u8 tx_pause,u8 rx_pause,u16 pfc_en)1194 int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause,
1195 u8 rx_pause, u16 pfc_en)
1196 {
1197 int pf = rvu_get_pf(pcifunc);
1198 u8 rx_8023 = 0, tx_8023 = 0;
1199 struct mac_ops *mac_ops;
1200 u8 cgx_id, lmac_id;
1201 void *cgxd;
1202
1203 /* This msg is expected only from PF/VFs that are mapped to CGX LMACs,
1204 * if received from other PF/VF simply ACK, nothing to do.
1205 */
1206 if (!is_pf_cgxmapped(rvu, pf))
1207 return -ENODEV;
1208
1209 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1210 cgxd = rvu_cgx_pdata(cgx_id, rvu);
1211 mac_ops = get_mac_ops(cgxd);
1212
1213 mac_ops->mac_get_pause_frm_status(cgxd, lmac_id, &tx_8023, &rx_8023);
1214 if (tx_8023 || rx_8023) {
1215 dev_warn(rvu->dev,
1216 "Can not configure PFC as 802.3X pause frames are enabled");
1217 return LMAC_AF_ERR_PFC_ENADIS_PERM_DENIED;
1218 }
1219
1220 mutex_lock(&rvu->rsrc_lock);
1221 if (verify_lmac_fc_cfg(cgxd, lmac_id, tx_pause, rx_pause,
1222 pcifunc & RVU_PFVF_FUNC_MASK)) {
1223 mutex_unlock(&rvu->rsrc_lock);
1224 return LMAC_AF_ERR_PERM_DENIED;
1225 }
1226 mutex_unlock(&rvu->rsrc_lock);
1227
1228 return mac_ops->pfc_config(cgxd, lmac_id, tx_pause, rx_pause, pfc_en);
1229 }
1230
rvu_mbox_handler_cgx_prio_flow_ctrl_cfg(struct rvu * rvu,struct cgx_pfc_cfg * req,struct cgx_pfc_rsp * rsp)1231 int rvu_mbox_handler_cgx_prio_flow_ctrl_cfg(struct rvu *rvu,
1232 struct cgx_pfc_cfg *req,
1233 struct cgx_pfc_rsp *rsp)
1234 {
1235 int pf = rvu_get_pf(req->hdr.pcifunc);
1236 struct mac_ops *mac_ops;
1237 u8 cgx_id, lmac_id;
1238 void *cgxd;
1239 int err;
1240
1241 /* This msg is expected only from PF/VFs that are mapped to CGX LMACs,
1242 * if received from other PF/VF simply ACK, nothing to do.
1243 */
1244 if (!is_pf_cgxmapped(rvu, pf))
1245 return -ENODEV;
1246
1247 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1248 cgxd = rvu_cgx_pdata(cgx_id, rvu);
1249 mac_ops = get_mac_ops(cgxd);
1250
1251 err = rvu_cgx_prio_flow_ctrl_cfg(rvu, req->hdr.pcifunc, req->tx_pause,
1252 req->rx_pause, req->pfc_en);
1253
1254 mac_ops->mac_get_pfc_frm_cfg(cgxd, lmac_id, &rsp->tx_pause, &rsp->rx_pause);
1255 return err;
1256 }
1257
rvu_mac_reset(struct rvu * rvu,u16 pcifunc)1258 void rvu_mac_reset(struct rvu *rvu, u16 pcifunc)
1259 {
1260 int pf = rvu_get_pf(pcifunc);
1261 struct mac_ops *mac_ops;
1262 struct cgx *cgxd;
1263 u8 cgx, lmac;
1264
1265 if (!is_pf_cgxmapped(rvu, pf))
1266 return;
1267
1268 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx, &lmac);
1269 cgxd = rvu_cgx_pdata(cgx, rvu);
1270 mac_ops = get_mac_ops(cgxd);
1271
1272 if (mac_ops->mac_reset(cgxd, lmac, !is_vf(pcifunc)))
1273 dev_err(rvu->dev, "Failed to reset MAC\n");
1274 }
1275