1 // SPDX-License-Identifier: GPL-2.0 2 /* Marvell OcteonTx2 RVU Admin Function driver 3 * 4 * Copyright (C) 2018 Marvell International Ltd. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #include <linux/types.h> 12 #include <linux/module.h> 13 #include <linux/pci.h> 14 15 #include "rvu.h" 16 #include "cgx.h" 17 #include "lmac_common.h" 18 #include "rvu_reg.h" 19 #include "rvu_trace.h" 20 21 struct cgx_evq_entry { 22 struct list_head evq_node; 23 struct cgx_link_event link_event; 24 }; 25 26 #define M(_name, _id, _fn_name, _req_type, _rsp_type) \ 27 static struct _req_type __maybe_unused \ 28 *otx2_mbox_alloc_msg_ ## _fn_name(struct rvu *rvu, int devid) \ 29 { \ 30 struct _req_type *req; \ 31 \ 32 req = (struct _req_type *)otx2_mbox_alloc_msg_rsp( \ 33 &rvu->afpf_wq_info.mbox_up, devid, sizeof(struct _req_type), \ 34 sizeof(struct _rsp_type)); \ 35 if (!req) \ 36 return NULL; \ 37 req->hdr.sig = OTX2_MBOX_REQ_SIG; \ 38 req->hdr.id = _id; \ 39 trace_otx2_msg_alloc(rvu->pdev, _id, sizeof(*req)); \ 40 return req; \ 41 } 42 43 MBOX_UP_CGX_MESSAGES 44 #undef M 45 46 bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature) 47 { 48 u8 cgx_id, lmac_id; 49 void *cgxd; 50 51 if (!is_pf_cgxmapped(rvu, pf)) 52 return 0; 53 54 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 55 cgxd = rvu_cgx_pdata(cgx_id, rvu); 56 57 return (cgx_features_get(cgxd) & feature); 58 } 59 60 /* Returns bitmap of mapped PFs */ 61 static u16 cgxlmac_to_pfmap(struct rvu *rvu, u8 cgx_id, u8 lmac_id) 62 { 63 return rvu->cgxlmac2pf_map[CGX_OFFSET(cgx_id) + lmac_id]; 64 } 65 66 static int cgxlmac_to_pf(struct rvu *rvu, int cgx_id, int lmac_id) 67 { 68 unsigned long pfmap; 69 70 pfmap = cgxlmac_to_pfmap(rvu, cgx_id, lmac_id); 71 72 /* Assumes only one pf mapped to a cgx lmac port */ 73 if (!pfmap) 74 return -ENODEV; 75 else 76 return find_first_bit(&pfmap, 16); 77 } 78 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 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 /* Based on P2X connectivity find mapped NIX block for a PF */ 93 static void rvu_map_cgx_nix_block(struct rvu *rvu, int pf, 94 int cgx_id, int lmac_id) 95 { 96 struct rvu_pfvf *pfvf = &rvu->pf[pf]; 97 u8 p2x; 98 99 p2x = cgx_lmac_get_p2x(cgx_id, lmac_id); 100 /* Firmware sets P2X_SELECT as either NIX0 or NIX1 */ 101 pfvf->nix_blkaddr = BLKADDR_NIX0; 102 if (p2x == CMR_P2X_SEL_NIX1) 103 pfvf->nix_blkaddr = BLKADDR_NIX1; 104 } 105 106 static int rvu_map_cgx_lmac_pf(struct rvu *rvu) 107 { 108 struct npc_pkind *pkind = &rvu->hw->pkind; 109 int cgx_cnt_max = rvu->cgx_cnt_max; 110 int pf = PF_CGXMAP_BASE; 111 unsigned long lmac_bmap; 112 int size, free_pkind; 113 int cgx, lmac, iter; 114 115 if (!cgx_cnt_max) 116 return 0; 117 118 if (cgx_cnt_max > 0xF || MAX_LMAC_PER_CGX > 0xF) 119 return -EINVAL; 120 121 /* Alloc map table 122 * An additional entry is required since PF id starts from 1 and 123 * hence entry at offset 0 is invalid. 124 */ 125 size = (cgx_cnt_max * MAX_LMAC_PER_CGX + 1) * sizeof(u8); 126 rvu->pf2cgxlmac_map = devm_kmalloc(rvu->dev, size, GFP_KERNEL); 127 if (!rvu->pf2cgxlmac_map) 128 return -ENOMEM; 129 130 /* Initialize all entries with an invalid cgx and lmac id */ 131 memset(rvu->pf2cgxlmac_map, 0xFF, size); 132 133 /* Reverse map table */ 134 rvu->cgxlmac2pf_map = devm_kzalloc(rvu->dev, 135 cgx_cnt_max * MAX_LMAC_PER_CGX * sizeof(u16), 136 GFP_KERNEL); 137 if (!rvu->cgxlmac2pf_map) 138 return -ENOMEM; 139 140 rvu->cgx_mapped_pfs = 0; 141 for (cgx = 0; cgx < cgx_cnt_max; cgx++) { 142 if (!rvu_cgx_pdata(cgx, rvu)) 143 continue; 144 lmac_bmap = cgx_get_lmac_bmap(rvu_cgx_pdata(cgx, rvu)); 145 for_each_set_bit(iter, &lmac_bmap, MAX_LMAC_PER_CGX) { 146 lmac = cgx_get_lmacid(rvu_cgx_pdata(cgx, rvu), 147 iter); 148 rvu->pf2cgxlmac_map[pf] = cgxlmac_id_to_bmap(cgx, lmac); 149 rvu->cgxlmac2pf_map[CGX_OFFSET(cgx) + lmac] = 1 << pf; 150 free_pkind = rvu_alloc_rsrc(&pkind->rsrc); 151 pkind->pfchan_map[free_pkind] = ((pf) & 0x3F) << 16; 152 rvu_map_cgx_nix_block(rvu, pf, cgx, lmac); 153 rvu->cgx_mapped_pfs++; 154 pf++; 155 } 156 } 157 return 0; 158 } 159 160 static int rvu_cgx_send_link_info(int cgx_id, int lmac_id, struct rvu *rvu) 161 { 162 struct cgx_evq_entry *qentry; 163 unsigned long flags; 164 int err; 165 166 qentry = kmalloc(sizeof(*qentry), GFP_KERNEL); 167 if (!qentry) 168 return -ENOMEM; 169 170 /* Lock the event queue before we read the local link status */ 171 spin_lock_irqsave(&rvu->cgx_evq_lock, flags); 172 err = cgx_get_link_info(rvu_cgx_pdata(cgx_id, rvu), lmac_id, 173 &qentry->link_event.link_uinfo); 174 qentry->link_event.cgx_id = cgx_id; 175 qentry->link_event.lmac_id = lmac_id; 176 if (err) { 177 kfree(qentry); 178 goto skip_add; 179 } 180 list_add_tail(&qentry->evq_node, &rvu->cgx_evq_head); 181 skip_add: 182 spin_unlock_irqrestore(&rvu->cgx_evq_lock, flags); 183 184 /* start worker to process the events */ 185 queue_work(rvu->cgx_evh_wq, &rvu->cgx_evh_work); 186 187 return 0; 188 } 189 190 /* This is called from interrupt context and is expected to be atomic */ 191 static int cgx_lmac_postevent(struct cgx_link_event *event, void *data) 192 { 193 struct cgx_evq_entry *qentry; 194 struct rvu *rvu = data; 195 196 /* post event to the event queue */ 197 qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC); 198 if (!qentry) 199 return -ENOMEM; 200 qentry->link_event = *event; 201 spin_lock(&rvu->cgx_evq_lock); 202 list_add_tail(&qentry->evq_node, &rvu->cgx_evq_head); 203 spin_unlock(&rvu->cgx_evq_lock); 204 205 /* start worker to process the events */ 206 queue_work(rvu->cgx_evh_wq, &rvu->cgx_evh_work); 207 208 return 0; 209 } 210 211 static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu) 212 { 213 struct cgx_link_user_info *linfo; 214 struct cgx_link_info_msg *msg; 215 unsigned long pfmap; 216 int err, pfid; 217 218 linfo = &event->link_uinfo; 219 pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id); 220 221 do { 222 pfid = find_first_bit(&pfmap, 16); 223 clear_bit(pfid, &pfmap); 224 225 /* check if notification is enabled */ 226 if (!test_bit(pfid, &rvu->pf_notify_bmap)) { 227 dev_info(rvu->dev, "cgx %d: lmac %d Link status %s\n", 228 event->cgx_id, event->lmac_id, 229 linfo->link_up ? "UP" : "DOWN"); 230 continue; 231 } 232 233 /* Send mbox message to PF */ 234 msg = otx2_mbox_alloc_msg_cgx_link_event(rvu, pfid); 235 if (!msg) 236 continue; 237 msg->link_info = *linfo; 238 otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, pfid); 239 err = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, pfid); 240 if (err) 241 dev_warn(rvu->dev, "notification to pf %d failed\n", 242 pfid); 243 } while (pfmap); 244 } 245 246 static void cgx_evhandler_task(struct work_struct *work) 247 { 248 struct rvu *rvu = container_of(work, struct rvu, cgx_evh_work); 249 struct cgx_evq_entry *qentry; 250 struct cgx_link_event *event; 251 unsigned long flags; 252 253 do { 254 /* Dequeue an event */ 255 spin_lock_irqsave(&rvu->cgx_evq_lock, flags); 256 qentry = list_first_entry_or_null(&rvu->cgx_evq_head, 257 struct cgx_evq_entry, 258 evq_node); 259 if (qentry) 260 list_del(&qentry->evq_node); 261 spin_unlock_irqrestore(&rvu->cgx_evq_lock, flags); 262 if (!qentry) 263 break; /* nothing more to process */ 264 265 event = &qentry->link_event; 266 267 /* process event */ 268 cgx_notify_pfs(event, rvu); 269 kfree(qentry); 270 } while (1); 271 } 272 273 static int cgx_lmac_event_handler_init(struct rvu *rvu) 274 { 275 unsigned long lmac_bmap; 276 struct cgx_event_cb cb; 277 int cgx, lmac, err; 278 void *cgxd; 279 280 spin_lock_init(&rvu->cgx_evq_lock); 281 INIT_LIST_HEAD(&rvu->cgx_evq_head); 282 INIT_WORK(&rvu->cgx_evh_work, cgx_evhandler_task); 283 rvu->cgx_evh_wq = alloc_workqueue("rvu_evh_wq", 0, 0); 284 if (!rvu->cgx_evh_wq) { 285 dev_err(rvu->dev, "alloc workqueue failed"); 286 return -ENOMEM; 287 } 288 289 cb.notify_link_chg = cgx_lmac_postevent; /* link change call back */ 290 cb.data = rvu; 291 292 for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) { 293 cgxd = rvu_cgx_pdata(cgx, rvu); 294 if (!cgxd) 295 continue; 296 lmac_bmap = cgx_get_lmac_bmap(cgxd); 297 for_each_set_bit(lmac, &lmac_bmap, MAX_LMAC_PER_CGX) { 298 err = cgx_lmac_evh_register(&cb, cgxd, lmac); 299 if (err) 300 dev_err(rvu->dev, 301 "%d:%d handler register failed\n", 302 cgx, lmac); 303 } 304 } 305 306 return 0; 307 } 308 309 static void rvu_cgx_wq_destroy(struct rvu *rvu) 310 { 311 if (rvu->cgx_evh_wq) { 312 flush_workqueue(rvu->cgx_evh_wq); 313 destroy_workqueue(rvu->cgx_evh_wq); 314 rvu->cgx_evh_wq = NULL; 315 } 316 } 317 318 int rvu_cgx_init(struct rvu *rvu) 319 { 320 int cgx, err; 321 void *cgxd; 322 323 /* CGX port id starts from 0 and are not necessarily contiguous 324 * Hence we allocate resources based on the maximum port id value. 325 */ 326 rvu->cgx_cnt_max = cgx_get_cgxcnt_max(); 327 if (!rvu->cgx_cnt_max) { 328 dev_info(rvu->dev, "No CGX devices found!\n"); 329 return -ENODEV; 330 } 331 332 rvu->cgx_idmap = devm_kzalloc(rvu->dev, rvu->cgx_cnt_max * 333 sizeof(void *), GFP_KERNEL); 334 if (!rvu->cgx_idmap) 335 return -ENOMEM; 336 337 /* Initialize the cgxdata table */ 338 for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++) 339 rvu->cgx_idmap[cgx] = cgx_get_pdata(cgx); 340 341 /* Map CGX LMAC interfaces to RVU PFs */ 342 err = rvu_map_cgx_lmac_pf(rvu); 343 if (err) 344 return err; 345 346 /* Register for CGX events */ 347 err = cgx_lmac_event_handler_init(rvu); 348 if (err) 349 return err; 350 351 mutex_init(&rvu->cgx_cfg_lock); 352 353 /* Ensure event handler registration is completed, before 354 * we turn on the links 355 */ 356 mb(); 357 358 /* Do link up for all CGX ports */ 359 for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) { 360 cgxd = rvu_cgx_pdata(cgx, rvu); 361 if (!cgxd) 362 continue; 363 err = cgx_lmac_linkup_start(cgxd); 364 if (err) 365 dev_err(rvu->dev, 366 "Link up process failed to start on cgx %d\n", 367 cgx); 368 } 369 370 return 0; 371 } 372 373 int rvu_cgx_exit(struct rvu *rvu) 374 { 375 unsigned long lmac_bmap; 376 int cgx, lmac; 377 void *cgxd; 378 379 for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) { 380 cgxd = rvu_cgx_pdata(cgx, rvu); 381 if (!cgxd) 382 continue; 383 lmac_bmap = cgx_get_lmac_bmap(cgxd); 384 for_each_set_bit(lmac, &lmac_bmap, MAX_LMAC_PER_CGX) 385 cgx_lmac_evh_unregister(cgxd, lmac); 386 } 387 388 /* Ensure event handler unregister is completed */ 389 mb(); 390 391 rvu_cgx_wq_destroy(rvu); 392 return 0; 393 } 394 395 /* Most of the CGX configuration is restricted to the mapped PF only, 396 * VF's of mapped PF and other PFs are not allowed. This fn() checks 397 * whether a PFFUNC is permitted to do the config or not. 398 */ 399 static bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc) 400 { 401 if ((pcifunc & RVU_PFVF_FUNC_MASK) || 402 !is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) 403 return false; 404 return true; 405 } 406 407 void rvu_cgx_enadis_rx_bp(struct rvu *rvu, int pf, bool enable) 408 { 409 struct mac_ops *mac_ops; 410 u8 cgx_id, lmac_id; 411 void *cgxd; 412 413 if (!is_pf_cgxmapped(rvu, pf)) 414 return; 415 416 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 417 cgxd = rvu_cgx_pdata(cgx_id, rvu); 418 419 mac_ops = get_mac_ops(cgxd); 420 /* Set / clear CTL_BCK to control pause frame forwarding to NIX */ 421 if (enable) 422 mac_ops->mac_enadis_rx_pause_fwding(cgxd, lmac_id, true); 423 else 424 mac_ops->mac_enadis_rx_pause_fwding(cgxd, lmac_id, false); 425 } 426 427 int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start) 428 { 429 int pf = rvu_get_pf(pcifunc); 430 u8 cgx_id, lmac_id; 431 432 if (!is_cgx_config_permitted(rvu, pcifunc)) 433 return -EPERM; 434 435 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 436 437 cgx_lmac_rx_tx_enable(rvu_cgx_pdata(cgx_id, rvu), lmac_id, start); 438 439 return 0; 440 } 441 442 int rvu_mbox_handler_cgx_start_rxtx(struct rvu *rvu, struct msg_req *req, 443 struct msg_rsp *rsp) 444 { 445 rvu_cgx_config_rxtx(rvu, req->hdr.pcifunc, true); 446 return 0; 447 } 448 449 int rvu_mbox_handler_cgx_stop_rxtx(struct rvu *rvu, struct msg_req *req, 450 struct msg_rsp *rsp) 451 { 452 rvu_cgx_config_rxtx(rvu, req->hdr.pcifunc, false); 453 return 0; 454 } 455 456 static int rvu_lmac_get_stats(struct rvu *rvu, struct msg_req *req, 457 void *rsp) 458 { 459 int pf = rvu_get_pf(req->hdr.pcifunc); 460 struct mac_ops *mac_ops; 461 int stat = 0, err = 0; 462 u64 tx_stat, rx_stat; 463 u8 cgx_idx, lmac; 464 void *cgxd; 465 466 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) 467 return -ENODEV; 468 469 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac); 470 cgxd = rvu_cgx_pdata(cgx_idx, rvu); 471 mac_ops = get_mac_ops(cgxd); 472 473 /* Rx stats */ 474 while (stat < mac_ops->rx_stats_cnt) { 475 err = mac_ops->mac_get_rx_stats(cgxd, lmac, stat, &rx_stat); 476 if (err) 477 return err; 478 if (mac_ops->rx_stats_cnt == RPM_RX_STATS_COUNT) 479 ((struct rpm_stats_rsp *)rsp)->rx_stats[stat] = rx_stat; 480 else 481 ((struct cgx_stats_rsp *)rsp)->rx_stats[stat] = rx_stat; 482 stat++; 483 } 484 485 /* Tx stats */ 486 stat = 0; 487 while (stat < mac_ops->tx_stats_cnt) { 488 err = mac_ops->mac_get_tx_stats(cgxd, lmac, stat, &tx_stat); 489 if (err) 490 return err; 491 if (mac_ops->tx_stats_cnt == RPM_TX_STATS_COUNT) 492 ((struct rpm_stats_rsp *)rsp)->tx_stats[stat] = tx_stat; 493 else 494 ((struct cgx_stats_rsp *)rsp)->tx_stats[stat] = tx_stat; 495 stat++; 496 } 497 return 0; 498 } 499 500 int rvu_mbox_handler_cgx_stats(struct rvu *rvu, struct msg_req *req, 501 struct cgx_stats_rsp *rsp) 502 { 503 return rvu_lmac_get_stats(rvu, req, (void *)rsp); 504 } 505 506 int rvu_mbox_handler_rpm_stats(struct rvu *rvu, struct msg_req *req, 507 struct rpm_stats_rsp *rsp) 508 { 509 return rvu_lmac_get_stats(rvu, req, (void *)rsp); 510 } 511 512 int rvu_mbox_handler_cgx_fec_stats(struct rvu *rvu, 513 struct msg_req *req, 514 struct cgx_fec_stats_rsp *rsp) 515 { 516 int pf = rvu_get_pf(req->hdr.pcifunc); 517 u8 cgx_idx, lmac; 518 void *cgxd; 519 520 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) 521 return -EPERM; 522 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac); 523 524 cgxd = rvu_cgx_pdata(cgx_idx, rvu); 525 return cgx_get_fec_stats(cgxd, lmac, rsp); 526 } 527 528 int rvu_mbox_handler_cgx_mac_addr_set(struct rvu *rvu, 529 struct cgx_mac_addr_set_or_get *req, 530 struct cgx_mac_addr_set_or_get *rsp) 531 { 532 int pf = rvu_get_pf(req->hdr.pcifunc); 533 u8 cgx_id, lmac_id; 534 535 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) 536 return -EPERM; 537 538 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 539 540 cgx_lmac_addr_set(cgx_id, lmac_id, req->mac_addr); 541 542 return 0; 543 } 544 545 int rvu_mbox_handler_cgx_mac_addr_get(struct rvu *rvu, 546 struct cgx_mac_addr_set_or_get *req, 547 struct cgx_mac_addr_set_or_get *rsp) 548 { 549 int pf = rvu_get_pf(req->hdr.pcifunc); 550 u8 cgx_id, lmac_id; 551 int rc = 0, i; 552 u64 cfg; 553 554 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) 555 return -EPERM; 556 557 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 558 559 rsp->hdr.rc = rc; 560 cfg = cgx_lmac_addr_get(cgx_id, lmac_id); 561 /* copy 48 bit mac address to req->mac_addr */ 562 for (i = 0; i < ETH_ALEN; i++) 563 rsp->mac_addr[i] = cfg >> (ETH_ALEN - 1 - i) * 8; 564 return 0; 565 } 566 567 int rvu_mbox_handler_cgx_promisc_enable(struct rvu *rvu, struct msg_req *req, 568 struct msg_rsp *rsp) 569 { 570 u16 pcifunc = req->hdr.pcifunc; 571 int pf = rvu_get_pf(pcifunc); 572 u8 cgx_id, lmac_id; 573 574 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) 575 return -EPERM; 576 577 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 578 579 cgx_lmac_promisc_config(cgx_id, lmac_id, true); 580 return 0; 581 } 582 583 int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req, 584 struct msg_rsp *rsp) 585 { 586 int pf = rvu_get_pf(req->hdr.pcifunc); 587 u8 cgx_id, lmac_id; 588 589 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) 590 return -EPERM; 591 592 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 593 594 cgx_lmac_promisc_config(cgx_id, lmac_id, false); 595 return 0; 596 } 597 598 static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) 599 { 600 int pf = rvu_get_pf(pcifunc); 601 u8 cgx_id, lmac_id; 602 void *cgxd; 603 604 if (!is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_PTP)) 605 return 0; 606 607 /* This msg is expected only from PFs that are mapped to CGX LMACs, 608 * if received from other PF/VF simply ACK, nothing to do. 609 */ 610 if ((pcifunc & RVU_PFVF_FUNC_MASK) || 611 !is_pf_cgxmapped(rvu, pf)) 612 return -ENODEV; 613 614 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 615 cgxd = rvu_cgx_pdata(cgx_id, rvu); 616 617 cgx_lmac_ptp_config(cgxd, lmac_id, enable); 618 /* If PTP is enabled then inform NPC that packets to be 619 * parsed by this PF will have their data shifted by 8 bytes 620 * and if PTP is disabled then no shift is required 621 */ 622 if (npc_config_ts_kpuaction(rvu, pf, pcifunc, enable)) 623 return -EINVAL; 624 625 return 0; 626 } 627 628 int rvu_mbox_handler_cgx_ptp_rx_enable(struct rvu *rvu, struct msg_req *req, 629 struct msg_rsp *rsp) 630 { 631 return rvu_cgx_ptp_rx_cfg(rvu, req->hdr.pcifunc, true); 632 } 633 634 int rvu_mbox_handler_cgx_ptp_rx_disable(struct rvu *rvu, struct msg_req *req, 635 struct msg_rsp *rsp) 636 { 637 return rvu_cgx_ptp_rx_cfg(rvu, req->hdr.pcifunc, false); 638 } 639 640 static int rvu_cgx_config_linkevents(struct rvu *rvu, u16 pcifunc, bool en) 641 { 642 int pf = rvu_get_pf(pcifunc); 643 u8 cgx_id, lmac_id; 644 645 if (!is_cgx_config_permitted(rvu, pcifunc)) 646 return -EPERM; 647 648 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 649 650 if (en) { 651 set_bit(pf, &rvu->pf_notify_bmap); 652 /* Send the current link status to PF */ 653 rvu_cgx_send_link_info(cgx_id, lmac_id, rvu); 654 } else { 655 clear_bit(pf, &rvu->pf_notify_bmap); 656 } 657 658 return 0; 659 } 660 661 int rvu_mbox_handler_cgx_start_linkevents(struct rvu *rvu, struct msg_req *req, 662 struct msg_rsp *rsp) 663 { 664 rvu_cgx_config_linkevents(rvu, req->hdr.pcifunc, true); 665 return 0; 666 } 667 668 int rvu_mbox_handler_cgx_stop_linkevents(struct rvu *rvu, struct msg_req *req, 669 struct msg_rsp *rsp) 670 { 671 rvu_cgx_config_linkevents(rvu, req->hdr.pcifunc, false); 672 return 0; 673 } 674 675 int rvu_mbox_handler_cgx_get_linkinfo(struct rvu *rvu, struct msg_req *req, 676 struct cgx_link_info_msg *rsp) 677 { 678 u8 cgx_id, lmac_id; 679 int pf, err; 680 681 pf = rvu_get_pf(req->hdr.pcifunc); 682 683 if (!is_pf_cgxmapped(rvu, pf)) 684 return -ENODEV; 685 686 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 687 688 err = cgx_get_link_info(rvu_cgx_pdata(cgx_id, rvu), lmac_id, 689 &rsp->link_info); 690 return err; 691 } 692 693 int rvu_mbox_handler_cgx_features_get(struct rvu *rvu, 694 struct msg_req *req, 695 struct cgx_features_info_msg *rsp) 696 { 697 int pf = rvu_get_pf(req->hdr.pcifunc); 698 u8 cgx_idx, lmac; 699 void *cgxd; 700 701 if (!is_pf_cgxmapped(rvu, pf)) 702 return 0; 703 704 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac); 705 cgxd = rvu_cgx_pdata(cgx_idx, rvu); 706 rsp->lmac_features = cgx_features_get(cgxd); 707 708 return 0; 709 } 710 711 u32 rvu_cgx_get_fifolen(struct rvu *rvu) 712 { 713 struct mac_ops *mac_ops; 714 int rvu_def_cgx_id = 0; 715 u32 fifo_len; 716 717 mac_ops = get_mac_ops(rvu_cgx_pdata(rvu_def_cgx_id, rvu)); 718 fifo_len = mac_ops ? mac_ops->fifo_len : 0; 719 720 return fifo_len; 721 } 722 723 static int rvu_cgx_config_intlbk(struct rvu *rvu, u16 pcifunc, bool en) 724 { 725 struct mac_ops *mac_ops; 726 u8 cgx_id, lmac_id; 727 728 if (!is_cgx_config_permitted(rvu, pcifunc)) 729 return -EPERM; 730 731 mac_ops = get_mac_ops(rvu_cgx_pdata(cgx_id, rvu)); 732 733 return mac_ops->mac_lmac_intl_lbk(rvu_cgx_pdata(cgx_id, rvu), 734 lmac_id, en); 735 } 736 737 int rvu_mbox_handler_cgx_intlbk_enable(struct rvu *rvu, struct msg_req *req, 738 struct msg_rsp *rsp) 739 { 740 rvu_cgx_config_intlbk(rvu, req->hdr.pcifunc, true); 741 return 0; 742 } 743 744 int rvu_mbox_handler_cgx_intlbk_disable(struct rvu *rvu, struct msg_req *req, 745 struct msg_rsp *rsp) 746 { 747 rvu_cgx_config_intlbk(rvu, req->hdr.pcifunc, false); 748 return 0; 749 } 750 751 int rvu_mbox_handler_cgx_cfg_pause_frm(struct rvu *rvu, 752 struct cgx_pause_frm_cfg *req, 753 struct cgx_pause_frm_cfg *rsp) 754 { 755 int pf = rvu_get_pf(req->hdr.pcifunc); 756 struct mac_ops *mac_ops; 757 u8 cgx_id, lmac_id; 758 void *cgxd; 759 760 if (!is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_FC)) 761 return 0; 762 763 /* This msg is expected only from PF/VFs that are mapped to CGX LMACs, 764 * if received from other PF/VF simply ACK, nothing to do. 765 */ 766 if (!is_pf_cgxmapped(rvu, pf)) 767 return -ENODEV; 768 769 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 770 cgxd = rvu_cgx_pdata(cgx_id, rvu); 771 mac_ops = get_mac_ops(cgxd); 772 773 if (req->set) 774 mac_ops->mac_enadis_pause_frm(cgxd, lmac_id, 775 req->tx_pause, req->rx_pause); 776 else 777 mac_ops->mac_get_pause_frm_status(cgxd, lmac_id, 778 &rsp->tx_pause, 779 &rsp->rx_pause); 780 return 0; 781 } 782 783 int rvu_mbox_handler_cgx_get_phy_fec_stats(struct rvu *rvu, struct msg_req *req, 784 struct msg_rsp *rsp) 785 { 786 int pf = rvu_get_pf(req->hdr.pcifunc); 787 u8 cgx_id, lmac_id; 788 789 if (!is_pf_cgxmapped(rvu, pf)) 790 return -EPERM; 791 792 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 793 return cgx_get_phy_fec_stats(rvu_cgx_pdata(cgx_id, rvu), lmac_id); 794 } 795 796 /* Finds cumulative status of NIX rx/tx counters from LF of a PF and those 797 * from its VFs as well. ie. NIX rx/tx counters at the CGX port level 798 */ 799 int rvu_cgx_nix_cuml_stats(struct rvu *rvu, void *cgxd, int lmac_id, 800 int index, int rxtxflag, u64 *stat) 801 { 802 struct rvu_block *block; 803 int blkaddr; 804 u16 pcifunc; 805 int pf, lf; 806 807 *stat = 0; 808 809 if (!cgxd || !rvu) 810 return -EINVAL; 811 812 pf = cgxlmac_to_pf(rvu, cgx_get_cgxid(cgxd), lmac_id); 813 if (pf < 0) 814 return pf; 815 816 /* Assumes LF of a PF and all of its VF belongs to the same 817 * NIX block 818 */ 819 pcifunc = pf << RVU_PFVF_PF_SHIFT; 820 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); 821 if (blkaddr < 0) 822 return 0; 823 block = &rvu->hw->block[blkaddr]; 824 825 for (lf = 0; lf < block->lf.max; lf++) { 826 /* Check if a lf is attached to this PF or one of its VFs */ 827 if (!((block->fn_map[lf] & ~RVU_PFVF_FUNC_MASK) == (pcifunc & 828 ~RVU_PFVF_FUNC_MASK))) 829 continue; 830 if (rxtxflag == NIX_STATS_RX) 831 *stat += rvu_read64(rvu, blkaddr, 832 NIX_AF_LFX_RX_STATX(lf, index)); 833 else 834 *stat += rvu_read64(rvu, blkaddr, 835 NIX_AF_LFX_TX_STATX(lf, index)); 836 } 837 838 return 0; 839 } 840 841 int rvu_cgx_start_stop_io(struct rvu *rvu, u16 pcifunc, bool start) 842 { 843 struct rvu_pfvf *parent_pf, *pfvf; 844 int cgx_users, err = 0; 845 846 if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) 847 return 0; 848 849 parent_pf = &rvu->pf[rvu_get_pf(pcifunc)]; 850 pfvf = rvu_get_pfvf(rvu, pcifunc); 851 852 mutex_lock(&rvu->cgx_cfg_lock); 853 854 if (start && pfvf->cgx_in_use) 855 goto exit; /* CGX is already started hence nothing to do */ 856 if (!start && !pfvf->cgx_in_use) 857 goto exit; /* CGX is already stopped hence nothing to do */ 858 859 if (start) { 860 cgx_users = parent_pf->cgx_users; 861 parent_pf->cgx_users++; 862 } else { 863 parent_pf->cgx_users--; 864 cgx_users = parent_pf->cgx_users; 865 } 866 867 /* Start CGX when first of all NIXLFs is started. 868 * Stop CGX when last of all NIXLFs is stopped. 869 */ 870 if (!cgx_users) { 871 err = rvu_cgx_config_rxtx(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK, 872 start); 873 if (err) { 874 dev_err(rvu->dev, "Unable to %s CGX\n", 875 start ? "start" : "stop"); 876 /* Revert the usage count in case of error */ 877 parent_pf->cgx_users = start ? parent_pf->cgx_users - 1 878 : parent_pf->cgx_users + 1; 879 goto exit; 880 } 881 } 882 pfvf->cgx_in_use = start; 883 exit: 884 mutex_unlock(&rvu->cgx_cfg_lock); 885 return err; 886 } 887 888 int rvu_mbox_handler_cgx_set_fec_param(struct rvu *rvu, 889 struct fec_mode *req, 890 struct fec_mode *rsp) 891 { 892 int pf = rvu_get_pf(req->hdr.pcifunc); 893 u8 cgx_id, lmac_id; 894 895 if (!is_pf_cgxmapped(rvu, pf)) 896 return -EPERM; 897 898 if (req->fec == OTX2_FEC_OFF) 899 req->fec = OTX2_FEC_NONE; 900 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 901 rsp->fec = cgx_set_fec(req->fec, cgx_id, lmac_id); 902 return 0; 903 } 904 905 int rvu_mbox_handler_cgx_get_aux_link_info(struct rvu *rvu, struct msg_req *req, 906 struct cgx_fw_data *rsp) 907 { 908 int pf = rvu_get_pf(req->hdr.pcifunc); 909 u8 cgx_id, lmac_id; 910 911 if (!rvu->fwdata) 912 return -ENXIO; 913 914 if (!is_pf_cgxmapped(rvu, pf)) 915 return -EPERM; 916 917 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); 918 919 memcpy(&rsp->fwdata, &rvu->fwdata->cgx_fw_data[cgx_id][lmac_id], 920 sizeof(struct cgx_lmac_fwdata_s)); 921 return 0; 922 } 923 924 int rvu_mbox_handler_cgx_set_link_mode(struct rvu *rvu, 925 struct cgx_set_link_mode_req *req, 926 struct cgx_set_link_mode_rsp *rsp) 927 { 928 int pf = rvu_get_pf(req->hdr.pcifunc); 929 u8 cgx_idx, lmac; 930 void *cgxd; 931 932 if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) 933 return -EPERM; 934 935 rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac); 936 cgxd = rvu_cgx_pdata(cgx_idx, rvu); 937 rsp->status = cgx_set_link_mode(cgxd, req->args, cgx_idx, lmac); 938 return 0; 939 } 940