932 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell CN10K MCS driver3 *4 * Copyright (C) 2022 Marvell.5 */6 7#include <linux/types.h>8#include <linux/device.h>9#include <linux/module.h>10#include <linux/pci.h>11 12#include "mcs.h"13#include "rvu.h"14#include "mcs_reg.h"15#include "lmac_common.h"16 17#define M(_name, _id, _fn_name, _req_type, _rsp_type) \18static struct _req_type __maybe_unused \19*otx2_mbox_alloc_msg_ ## _fn_name(struct rvu *rvu, int devid) \20{ \21 struct _req_type *req; \22 \23 req = (struct _req_type *)otx2_mbox_alloc_msg_rsp( \24 &rvu->afpf_wq_info.mbox_up, devid, sizeof(struct _req_type), \25 sizeof(struct _rsp_type)); \26 if (!req) \27 return NULL; \28 req->hdr.sig = OTX2_MBOX_REQ_SIG; \29 req->hdr.id = _id; \30 return req; \31}32 33MBOX_UP_MCS_MESSAGES34#undef M35 36void rvu_mcs_ptp_cfg(struct rvu *rvu, u8 rpm_id, u8 lmac_id, bool ena)37{38 struct mcs *mcs;39 u64 cfg;40 u8 port;41 42 if (!rvu->mcs_blk_cnt)43 return;44 45 /* When ptp is enabled, RPM appends 8B header for all46 * RX packets. MCS PEX need to configure to skip 8B47 * during packet parsing.48 */49 50 /* CNF10K-B */51 if (rvu->mcs_blk_cnt > 1) {52 mcs = mcs_get_pdata(rpm_id);53 cfg = mcs_reg_read(mcs, MCSX_PEX_RX_SLAVE_PEX_CONFIGURATION);54 if (ena)55 cfg |= BIT_ULL(lmac_id);56 else57 cfg &= ~BIT_ULL(lmac_id);58 mcs_reg_write(mcs, MCSX_PEX_RX_SLAVE_PEX_CONFIGURATION, cfg);59 return;60 }61 /* CN10KB */62 mcs = mcs_get_pdata(0);63 port = (rpm_id * rvu->hw->lmac_per_cgx) + lmac_id;64 cfg = mcs_reg_read(mcs, MCSX_PEX_RX_SLAVE_PORT_CFGX(port));65 if (ena)66 cfg |= BIT_ULL(0);67 else68 cfg &= ~BIT_ULL(0);69 mcs_reg_write(mcs, MCSX_PEX_RX_SLAVE_PORT_CFGX(port), cfg);70}71 72int rvu_mbox_handler_mcs_set_lmac_mode(struct rvu *rvu,73 struct mcs_set_lmac_mode *req,74 struct msg_rsp *rsp)75{76 struct mcs *mcs;77 78 if (req->mcs_id >= rvu->mcs_blk_cnt)79 return MCS_AF_ERR_INVALID_MCSID;80 81 mcs = mcs_get_pdata(req->mcs_id);82 83 if (BIT_ULL(req->lmac_id) & mcs->hw->lmac_bmap)84 mcs_set_lmac_mode(mcs, req->lmac_id, req->mode);85 86 return 0;87}88 89int mcs_add_intr_wq_entry(struct mcs *mcs, struct mcs_intr_event *event)90{91 struct mcs_intrq_entry *qentry;92 u16 pcifunc = event->pcifunc;93 struct rvu *rvu = mcs->rvu;94 struct mcs_pfvf *pfvf;95 96 /* Check if it is PF or VF */97 if (pcifunc & RVU_PFVF_FUNC_MASK)98 pfvf = &mcs->vf[rvu_get_hwvf(rvu, pcifunc)];99 else100 pfvf = &mcs->pf[rvu_get_pf(pcifunc)];101 102 event->intr_mask &= pfvf->intr_mask;103 104 /* Check PF/VF interrupt notification is enabled */105 if (!(pfvf->intr_mask && event->intr_mask))106 return 0;107 108 qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC);109 if (!qentry)110 return -ENOMEM;111 112 qentry->intr_event = *event;113 spin_lock(&rvu->mcs_intrq_lock);114 list_add_tail(&qentry->node, &rvu->mcs_intrq_head);115 spin_unlock(&rvu->mcs_intrq_lock);116 queue_work(rvu->mcs_intr_wq, &rvu->mcs_intr_work);117 118 return 0;119}120 121static int mcs_notify_pfvf(struct mcs_intr_event *event, struct rvu *rvu)122{123 struct mcs_intr_info *req;124 int pf;125 126 pf = rvu_get_pf(event->pcifunc);127 128 mutex_lock(&rvu->mbox_lock);129 130 req = otx2_mbox_alloc_msg_mcs_intr_notify(rvu, pf);131 if (!req) {132 mutex_unlock(&rvu->mbox_lock);133 return -ENOMEM;134 }135 136 req->mcs_id = event->mcs_id;137 req->intr_mask = event->intr_mask;138 req->sa_id = event->sa_id;139 req->hdr.pcifunc = event->pcifunc;140 req->lmac_id = event->lmac_id;141 142 otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);143 144 otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);145 146 mutex_unlock(&rvu->mbox_lock);147 148 return 0;149}150 151static void mcs_intr_handler_task(struct work_struct *work)152{153 struct rvu *rvu = container_of(work, struct rvu, mcs_intr_work);154 struct mcs_intrq_entry *qentry;155 struct mcs_intr_event *event;156 unsigned long flags;157 158 do {159 spin_lock_irqsave(&rvu->mcs_intrq_lock, flags);160 qentry = list_first_entry_or_null(&rvu->mcs_intrq_head,161 struct mcs_intrq_entry,162 node);163 if (qentry)164 list_del(&qentry->node);165 166 spin_unlock_irqrestore(&rvu->mcs_intrq_lock, flags);167 if (!qentry)168 break; /* nothing more to process */169 170 event = &qentry->intr_event;171 172 mcs_notify_pfvf(event, rvu);173 kfree(qentry);174 } while (1);175}176 177int rvu_mbox_handler_mcs_intr_cfg(struct rvu *rvu,178 struct mcs_intr_cfg *req,179 struct msg_rsp *rsp)180{181 u16 pcifunc = req->hdr.pcifunc;182 struct mcs_pfvf *pfvf;183 struct mcs *mcs;184 185 if (req->mcs_id >= rvu->mcs_blk_cnt)186 return MCS_AF_ERR_INVALID_MCSID;187 188 mcs = mcs_get_pdata(req->mcs_id);189 190 /* Check if it is PF or VF */191 if (pcifunc & RVU_PFVF_FUNC_MASK)192 pfvf = &mcs->vf[rvu_get_hwvf(rvu, pcifunc)];193 else194 pfvf = &mcs->pf[rvu_get_pf(pcifunc)];195 196 mcs->pf_map[0] = pcifunc;197 pfvf->intr_mask = req->intr_mask;198 199 return 0;200}201 202int rvu_mbox_handler_mcs_get_hw_info(struct rvu *rvu,203 struct msg_req *req,204 struct mcs_hw_info *rsp)205{206 struct mcs *mcs;207 208 if (!rvu->mcs_blk_cnt)209 return MCS_AF_ERR_NOT_MAPPED;210 211 /* MCS resources are same across all blocks */212 mcs = mcs_get_pdata(0);213 rsp->num_mcs_blks = rvu->mcs_blk_cnt;214 rsp->tcam_entries = mcs->hw->tcam_entries;215 rsp->secy_entries = mcs->hw->secy_entries;216 rsp->sc_entries = mcs->hw->sc_entries;217 rsp->sa_entries = mcs->hw->sa_entries;218 return 0;219}220 221int rvu_mbox_handler_mcs_port_reset(struct rvu *rvu, struct mcs_port_reset_req *req,222 struct msg_rsp *rsp)223{224 struct mcs *mcs;225 226 if (req->mcs_id >= rvu->mcs_blk_cnt)227 return MCS_AF_ERR_INVALID_MCSID;228 229 mcs = mcs_get_pdata(req->mcs_id);230 231 mcs_reset_port(mcs, req->port_id, req->reset);232 233 return 0;234}235 236int rvu_mbox_handler_mcs_clear_stats(struct rvu *rvu,237 struct mcs_clear_stats *req,238 struct msg_rsp *rsp)239{240 u16 pcifunc = req->hdr.pcifunc;241 struct mcs *mcs;242 243 if (req->mcs_id >= rvu->mcs_blk_cnt)244 return MCS_AF_ERR_INVALID_MCSID;245 246 mcs = mcs_get_pdata(req->mcs_id);247 248 mutex_lock(&mcs->stats_lock);249 if (req->all)250 mcs_clear_all_stats(mcs, pcifunc, req->dir);251 else252 mcs_clear_stats(mcs, req->type, req->id, req->dir);253 254 mutex_unlock(&mcs->stats_lock);255 return 0;256}257 258int rvu_mbox_handler_mcs_get_flowid_stats(struct rvu *rvu,259 struct mcs_stats_req *req,260 struct mcs_flowid_stats *rsp)261{262 struct mcs *mcs;263 264 if (req->mcs_id >= rvu->mcs_blk_cnt)265 return MCS_AF_ERR_INVALID_MCSID;266 267 mcs = mcs_get_pdata(req->mcs_id);268 269 /* In CNF10K-B, before reading the statistics,270 * MCSX_MIL_GLOBAL.FORCE_CLK_EN_IP needs to be set271 * to get accurate statistics272 */273 if (mcs->hw->mcs_blks > 1)274 mcs_set_force_clk_en(mcs, true);275 276 mutex_lock(&mcs->stats_lock);277 mcs_get_flowid_stats(mcs, rsp, req->id, req->dir);278 mutex_unlock(&mcs->stats_lock);279 280 /* Clear MCSX_MIL_GLOBAL.FORCE_CLK_EN_IP after reading281 * the statistics282 */283 if (mcs->hw->mcs_blks > 1)284 mcs_set_force_clk_en(mcs, false);285 286 return 0;287}288 289int rvu_mbox_handler_mcs_get_secy_stats(struct rvu *rvu,290 struct mcs_stats_req *req,291 struct mcs_secy_stats *rsp)292{ struct mcs *mcs;293 294 if (req->mcs_id >= rvu->mcs_blk_cnt)295 return MCS_AF_ERR_INVALID_MCSID;296 297 mcs = mcs_get_pdata(req->mcs_id);298 299 if (mcs->hw->mcs_blks > 1)300 mcs_set_force_clk_en(mcs, true);301 302 mutex_lock(&mcs->stats_lock);303 304 if (req->dir == MCS_RX)305 mcs_get_rx_secy_stats(mcs, rsp, req->id);306 else307 mcs_get_tx_secy_stats(mcs, rsp, req->id);308 309 mutex_unlock(&mcs->stats_lock);310 311 if (mcs->hw->mcs_blks > 1)312 mcs_set_force_clk_en(mcs, false);313 314 return 0;315}316 317int rvu_mbox_handler_mcs_get_sc_stats(struct rvu *rvu,318 struct mcs_stats_req *req,319 struct mcs_sc_stats *rsp)320{321 struct mcs *mcs;322 323 if (req->mcs_id >= rvu->mcs_blk_cnt)324 return MCS_AF_ERR_INVALID_MCSID;325 326 mcs = mcs_get_pdata(req->mcs_id);327 328 if (mcs->hw->mcs_blks > 1)329 mcs_set_force_clk_en(mcs, true);330 331 mutex_lock(&mcs->stats_lock);332 mcs_get_sc_stats(mcs, rsp, req->id, req->dir);333 mutex_unlock(&mcs->stats_lock);334 335 if (mcs->hw->mcs_blks > 1)336 mcs_set_force_clk_en(mcs, false);337 338 return 0;339}340 341int rvu_mbox_handler_mcs_get_sa_stats(struct rvu *rvu,342 struct mcs_stats_req *req,343 struct mcs_sa_stats *rsp)344{345 struct mcs *mcs;346 347 if (req->mcs_id >= rvu->mcs_blk_cnt)348 return MCS_AF_ERR_INVALID_MCSID;349 350 mcs = mcs_get_pdata(req->mcs_id);351 352 if (mcs->hw->mcs_blks > 1)353 mcs_set_force_clk_en(mcs, true);354 355 mutex_lock(&mcs->stats_lock);356 mcs_get_sa_stats(mcs, rsp, req->id, req->dir);357 mutex_unlock(&mcs->stats_lock);358 359 if (mcs->hw->mcs_blks > 1)360 mcs_set_force_clk_en(mcs, false);361 362 return 0;363}364 365int rvu_mbox_handler_mcs_get_port_stats(struct rvu *rvu,366 struct mcs_stats_req *req,367 struct mcs_port_stats *rsp)368{369 struct mcs *mcs;370 371 if (req->mcs_id >= rvu->mcs_blk_cnt)372 return MCS_AF_ERR_INVALID_MCSID;373 374 mcs = mcs_get_pdata(req->mcs_id);375 376 if (mcs->hw->mcs_blks > 1)377 mcs_set_force_clk_en(mcs, true);378 379 mutex_lock(&mcs->stats_lock);380 mcs_get_port_stats(mcs, rsp, req->id, req->dir);381 mutex_unlock(&mcs->stats_lock);382 383 if (mcs->hw->mcs_blks > 1)384 mcs_set_force_clk_en(mcs, false);385 386 return 0;387}388 389int rvu_mbox_handler_mcs_set_active_lmac(struct rvu *rvu,390 struct mcs_set_active_lmac *req,391 struct msg_rsp *rsp)392{393 struct mcs *mcs;394 395 if (req->mcs_id >= rvu->mcs_blk_cnt)396 return MCS_AF_ERR_INVALID_MCSID;397 398 mcs = mcs_get_pdata(req->mcs_id);399 if (!mcs)400 return MCS_AF_ERR_NOT_MAPPED;401 402 mcs->hw->lmac_bmap = req->lmac_bmap;403 mcs_set_lmac_channels(req->mcs_id, req->chan_base);404 return 0;405}406 407int rvu_mbox_handler_mcs_port_cfg_set(struct rvu *rvu, struct mcs_port_cfg_set_req *req,408 struct msg_rsp *rsp)409{410 struct mcs *mcs;411 412 if (req->mcs_id >= rvu->mcs_blk_cnt)413 return MCS_AF_ERR_INVALID_MCSID;414 415 mcs = mcs_get_pdata(req->mcs_id);416 417 if (mcs->hw->lmac_cnt <= req->port_id || !(mcs->hw->lmac_bmap & BIT_ULL(req->port_id)))418 return -EINVAL;419 420 mcs_set_port_cfg(mcs, req);421 422 return 0;423}424 425int rvu_mbox_handler_mcs_port_cfg_get(struct rvu *rvu, struct mcs_port_cfg_get_req *req,426 struct mcs_port_cfg_get_rsp *rsp)427{428 struct mcs *mcs;429 430 if (req->mcs_id >= rvu->mcs_blk_cnt)431 return MCS_AF_ERR_INVALID_MCSID;432 433 mcs = mcs_get_pdata(req->mcs_id);434 435 if (mcs->hw->lmac_cnt <= req->port_id || !(mcs->hw->lmac_bmap & BIT_ULL(req->port_id)))436 return -EINVAL;437 438 mcs_get_port_cfg(mcs, req, rsp);439 440 return 0;441}442 443int rvu_mbox_handler_mcs_custom_tag_cfg_get(struct rvu *rvu, struct mcs_custom_tag_cfg_get_req *req,444 struct mcs_custom_tag_cfg_get_rsp *rsp)445{446 struct mcs *mcs;447 448 if (req->mcs_id >= rvu->mcs_blk_cnt)449 return MCS_AF_ERR_INVALID_MCSID;450 451 mcs = mcs_get_pdata(req->mcs_id);452 453 mcs_get_custom_tag_cfg(mcs, req, rsp);454 455 return 0;456}457 458int rvu_mcs_flr_handler(struct rvu *rvu, u16 pcifunc)459{460 struct mcs *mcs;461 int mcs_id;462 463 /* CNF10K-B mcs0-6 are mapped to RPM2-8*/464 if (rvu->mcs_blk_cnt > 1) {465 for (mcs_id = 0; mcs_id < rvu->mcs_blk_cnt; mcs_id++) {466 mcs = mcs_get_pdata(mcs_id);467 mcs_free_all_rsrc(mcs, MCS_RX, pcifunc);468 mcs_free_all_rsrc(mcs, MCS_TX, pcifunc);469 }470 } else {471 /* CN10K-B has only one mcs block */472 mcs = mcs_get_pdata(0);473 mcs_free_all_rsrc(mcs, MCS_RX, pcifunc);474 mcs_free_all_rsrc(mcs, MCS_TX, pcifunc);475 }476 return 0;477}478 479int rvu_mbox_handler_mcs_flowid_ena_entry(struct rvu *rvu,480 struct mcs_flowid_ena_dis_entry *req,481 struct msg_rsp *rsp)482{483 struct mcs *mcs;484 485 if (req->mcs_id >= rvu->mcs_blk_cnt)486 return MCS_AF_ERR_INVALID_MCSID;487 488 mcs = mcs_get_pdata(req->mcs_id);489 mcs_ena_dis_flowid_entry(mcs, req->flow_id, req->dir, req->ena);490 return 0;491}492 493int rvu_mbox_handler_mcs_pn_table_write(struct rvu *rvu,494 struct mcs_pn_table_write_req *req,495 struct msg_rsp *rsp)496{497 struct mcs *mcs;498 499 if (req->mcs_id >= rvu->mcs_blk_cnt)500 return MCS_AF_ERR_INVALID_MCSID;501 502 mcs = mcs_get_pdata(req->mcs_id);503 mcs_pn_table_write(mcs, req->pn_id, req->next_pn, req->dir);504 return 0;505}506 507int rvu_mbox_handler_mcs_set_pn_threshold(struct rvu *rvu,508 struct mcs_set_pn_threshold *req,509 struct msg_rsp *rsp)510{511 struct mcs *mcs;512 513 if (req->mcs_id >= rvu->mcs_blk_cnt)514 return MCS_AF_ERR_INVALID_MCSID;515 516 mcs = mcs_get_pdata(req->mcs_id);517 518 mcs_pn_threshold_set(mcs, req);519 520 return 0;521}522 523int rvu_mbox_handler_mcs_rx_sc_sa_map_write(struct rvu *rvu,524 struct mcs_rx_sc_sa_map *req,525 struct msg_rsp *rsp)526{527 struct mcs *mcs;528 529 if (req->mcs_id >= rvu->mcs_blk_cnt)530 return MCS_AF_ERR_INVALID_MCSID;531 532 mcs = mcs_get_pdata(req->mcs_id);533 mcs->mcs_ops->mcs_rx_sa_mem_map_write(mcs, req);534 return 0;535}536 537int rvu_mbox_handler_mcs_tx_sc_sa_map_write(struct rvu *rvu,538 struct mcs_tx_sc_sa_map *req,539 struct msg_rsp *rsp)540{541 struct mcs *mcs;542 543 if (req->mcs_id >= rvu->mcs_blk_cnt)544 return MCS_AF_ERR_INVALID_MCSID;545 546 mcs = mcs_get_pdata(req->mcs_id);547 mcs->mcs_ops->mcs_tx_sa_mem_map_write(mcs, req);548 mcs->tx_sa_active[req->sc_id] = req->tx_sa_active;549 550 return 0;551}552 553int rvu_mbox_handler_mcs_sa_plcy_write(struct rvu *rvu,554 struct mcs_sa_plcy_write_req *req,555 struct msg_rsp *rsp)556{557 struct mcs *mcs;558 int i;559 560 if (req->mcs_id >= rvu->mcs_blk_cnt)561 return MCS_AF_ERR_INVALID_MCSID;562 563 mcs = mcs_get_pdata(req->mcs_id);564 565 for (i = 0; i < req->sa_cnt; i++)566 mcs_sa_plcy_write(mcs, &req->plcy[i][0],567 req->sa_index[i], req->dir);568 return 0;569}570 571int rvu_mbox_handler_mcs_rx_sc_cam_write(struct rvu *rvu,572 struct mcs_rx_sc_cam_write_req *req,573 struct msg_rsp *rsp)574{575 struct mcs *mcs;576 577 if (req->mcs_id >= rvu->mcs_blk_cnt)578 return MCS_AF_ERR_INVALID_MCSID;579 580 mcs = mcs_get_pdata(req->mcs_id);581 mcs_rx_sc_cam_write(mcs, req->sci, req->secy_id, req->sc_id);582 return 0;583}584 585int rvu_mbox_handler_mcs_secy_plcy_write(struct rvu *rvu,586 struct mcs_secy_plcy_write_req *req,587 struct msg_rsp *rsp)588{ struct mcs *mcs;589 590 if (req->mcs_id >= rvu->mcs_blk_cnt)591 return MCS_AF_ERR_INVALID_MCSID;592 593 mcs = mcs_get_pdata(req->mcs_id);594 595 mcs_secy_plcy_write(mcs, req->plcy,596 req->secy_id, req->dir);597 return 0;598}599 600int rvu_mbox_handler_mcs_flowid_entry_write(struct rvu *rvu,601 struct mcs_flowid_entry_write_req *req,602 struct msg_rsp *rsp)603{604 struct secy_mem_map map;605 struct mcs *mcs;606 607 if (req->mcs_id >= rvu->mcs_blk_cnt)608 return MCS_AF_ERR_INVALID_MCSID;609 610 mcs = mcs_get_pdata(req->mcs_id);611 612 /* TODO validate the flowid */613 mcs_flowid_entry_write(mcs, req->data, req->mask,614 req->flow_id, req->dir);615 map.secy = req->secy_id;616 map.sc = req->sc_id;617 map.ctrl_pkt = req->ctrl_pkt;618 map.flow_id = req->flow_id;619 map.sci = req->sci;620 mcs->mcs_ops->mcs_flowid_secy_map(mcs, &map, req->dir);621 if (req->ena)622 mcs_ena_dis_flowid_entry(mcs, req->flow_id,623 req->dir, true);624 return 0;625}626 627int rvu_mbox_handler_mcs_free_resources(struct rvu *rvu,628 struct mcs_free_rsrc_req *req,629 struct msg_rsp *rsp)630{631 u16 pcifunc = req->hdr.pcifunc;632 struct mcs_rsrc_map *map;633 struct mcs *mcs;634 int rc = 0;635 636 if (req->mcs_id >= rvu->mcs_blk_cnt)637 return MCS_AF_ERR_INVALID_MCSID;638 639 mcs = mcs_get_pdata(req->mcs_id);640 641 if (req->dir == MCS_RX)642 map = &mcs->rx;643 else644 map = &mcs->tx;645 646 mutex_lock(&rvu->rsrc_lock);647 /* Free all the cam resources mapped to PF/VF */648 if (req->all) {649 rc = mcs_free_all_rsrc(mcs, req->dir, pcifunc);650 goto exit;651 }652 653 switch (req->rsrc_type) {654 case MCS_RSRC_TYPE_FLOWID:655 rc = mcs_free_rsrc(&map->flow_ids, map->flowid2pf_map, req->rsrc_id, pcifunc);656 mcs_ena_dis_flowid_entry(mcs, req->rsrc_id, req->dir, false);657 break;658 case MCS_RSRC_TYPE_SECY:659 rc = mcs_free_rsrc(&map->secy, map->secy2pf_map, req->rsrc_id, pcifunc);660 mcs_clear_secy_plcy(mcs, req->rsrc_id, req->dir);661 break;662 case MCS_RSRC_TYPE_SC:663 rc = mcs_free_rsrc(&map->sc, map->sc2pf_map, req->rsrc_id, pcifunc);664 /* Disable SC CAM only on RX side */665 if (req->dir == MCS_RX)666 mcs_ena_dis_sc_cam_entry(mcs, req->rsrc_id, false);667 break;668 case MCS_RSRC_TYPE_SA:669 rc = mcs_free_rsrc(&map->sa, map->sa2pf_map, req->rsrc_id, pcifunc);670 break;671 }672exit:673 mutex_unlock(&rvu->rsrc_lock);674 return rc;675}676 677int rvu_mbox_handler_mcs_alloc_resources(struct rvu *rvu,678 struct mcs_alloc_rsrc_req *req,679 struct mcs_alloc_rsrc_rsp *rsp)680{681 u16 pcifunc = req->hdr.pcifunc;682 struct mcs_rsrc_map *map;683 struct mcs *mcs;684 int rsrc_id, i;685 686 if (req->mcs_id >= rvu->mcs_blk_cnt)687 return MCS_AF_ERR_INVALID_MCSID;688 689 mcs = mcs_get_pdata(req->mcs_id);690 691 if (req->dir == MCS_RX)692 map = &mcs->rx;693 else694 map = &mcs->tx;695 696 mutex_lock(&rvu->rsrc_lock);697 698 if (req->all) {699 rsrc_id = mcs_alloc_all_rsrc(mcs, &rsp->flow_ids[0],700 &rsp->secy_ids[0],701 &rsp->sc_ids[0],702 &rsp->sa_ids[0],703 &rsp->sa_ids[1],704 pcifunc, req->dir);705 goto exit;706 }707 708 switch (req->rsrc_type) {709 case MCS_RSRC_TYPE_FLOWID:710 for (i = 0; i < req->rsrc_cnt; i++) {711 rsrc_id = mcs_alloc_rsrc(&map->flow_ids, map->flowid2pf_map, pcifunc);712 if (rsrc_id < 0)713 goto exit;714 rsp->flow_ids[i] = rsrc_id;715 rsp->rsrc_cnt++;716 }717 break;718 case MCS_RSRC_TYPE_SECY:719 for (i = 0; i < req->rsrc_cnt; i++) {720 rsrc_id = mcs_alloc_rsrc(&map->secy, map->secy2pf_map, pcifunc);721 if (rsrc_id < 0)722 goto exit;723 rsp->secy_ids[i] = rsrc_id;724 rsp->rsrc_cnt++;725 }726 break;727 case MCS_RSRC_TYPE_SC:728 for (i = 0; i < req->rsrc_cnt; i++) {729 rsrc_id = mcs_alloc_rsrc(&map->sc, map->sc2pf_map, pcifunc);730 if (rsrc_id < 0)731 goto exit;732 rsp->sc_ids[i] = rsrc_id;733 rsp->rsrc_cnt++;734 }735 break;736 case MCS_RSRC_TYPE_SA:737 for (i = 0; i < req->rsrc_cnt; i++) {738 rsrc_id = mcs_alloc_rsrc(&map->sa, map->sa2pf_map, pcifunc);739 if (rsrc_id < 0)740 goto exit;741 rsp->sa_ids[i] = rsrc_id;742 rsp->rsrc_cnt++;743 }744 break;745 }746 747 rsp->rsrc_type = req->rsrc_type;748 rsp->dir = req->dir;749 rsp->mcs_id = req->mcs_id;750 rsp->all = req->all;751 752exit:753 if (rsrc_id < 0)754 dev_err(rvu->dev, "Failed to allocate the mcs resources for PCIFUNC:%d\n", pcifunc);755 mutex_unlock(&rvu->rsrc_lock);756 return 0;757}758 759int rvu_mbox_handler_mcs_alloc_ctrl_pkt_rule(struct rvu *rvu,760 struct mcs_alloc_ctrl_pkt_rule_req *req,761 struct mcs_alloc_ctrl_pkt_rule_rsp *rsp)762{763 u16 pcifunc = req->hdr.pcifunc;764 struct mcs_rsrc_map *map;765 struct mcs *mcs;766 int rsrc_id;767 u16 offset;768 769 if (req->mcs_id >= rvu->mcs_blk_cnt)770 return MCS_AF_ERR_INVALID_MCSID;771 772 mcs = mcs_get_pdata(req->mcs_id);773 774 map = (req->dir == MCS_RX) ? &mcs->rx : &mcs->tx;775 776 mutex_lock(&rvu->rsrc_lock);777 778 switch (req->rule_type) {779 case MCS_CTRL_PKT_RULE_TYPE_ETH:780 offset = MCS_CTRLPKT_ETYPE_RULE_OFFSET;781 break;782 case MCS_CTRL_PKT_RULE_TYPE_DA:783 offset = MCS_CTRLPKT_DA_RULE_OFFSET;784 break;785 case MCS_CTRL_PKT_RULE_TYPE_RANGE:786 offset = MCS_CTRLPKT_DA_RANGE_RULE_OFFSET;787 break;788 case MCS_CTRL_PKT_RULE_TYPE_COMBO:789 offset = MCS_CTRLPKT_COMBO_RULE_OFFSET;790 break;791 case MCS_CTRL_PKT_RULE_TYPE_MAC:792 offset = MCS_CTRLPKT_MAC_EN_RULE_OFFSET;793 break;794 }795 796 rsrc_id = mcs_alloc_ctrlpktrule(&map->ctrlpktrule, map->ctrlpktrule2pf_map, offset,797 pcifunc);798 if (rsrc_id < 0)799 goto exit;800 801 rsp->rule_idx = rsrc_id;802 rsp->rule_type = req->rule_type;803 rsp->dir = req->dir;804 rsp->mcs_id = req->mcs_id;805 806 mutex_unlock(&rvu->rsrc_lock);807 return 0;808exit:809 if (rsrc_id < 0)810 dev_err(rvu->dev, "Failed to allocate the mcs ctrl pkt rule for PCIFUNC:%d\n",811 pcifunc);812 mutex_unlock(&rvu->rsrc_lock);813 return rsrc_id;814}815 816int rvu_mbox_handler_mcs_free_ctrl_pkt_rule(struct rvu *rvu,817 struct mcs_free_ctrl_pkt_rule_req *req,818 struct msg_rsp *rsp)819{820 struct mcs *mcs;821 int rc;822 823 if (req->mcs_id >= rvu->mcs_blk_cnt)824 return MCS_AF_ERR_INVALID_MCSID;825 826 mcs = mcs_get_pdata(req->mcs_id);827 828 mutex_lock(&rvu->rsrc_lock);829 830 rc = mcs_free_ctrlpktrule(mcs, req);831 832 mutex_unlock(&rvu->rsrc_lock);833 834 return rc;835}836 837int rvu_mbox_handler_mcs_ctrl_pkt_rule_write(struct rvu *rvu,838 struct mcs_ctrl_pkt_rule_write_req *req,839 struct msg_rsp *rsp)840{841 struct mcs *mcs;842 int rc;843 844 if (req->mcs_id >= rvu->mcs_blk_cnt)845 return MCS_AF_ERR_INVALID_MCSID;846 847 mcs = mcs_get_pdata(req->mcs_id);848 849 rc = mcs_ctrlpktrule_write(mcs, req);850 851 return rc;852}853 854static void rvu_mcs_set_lmac_bmap(struct rvu *rvu)855{856 struct mcs *mcs = mcs_get_pdata(0);857 unsigned long lmac_bmap;858 int cgx, lmac, port;859 860 for (port = 0; port < mcs->hw->lmac_cnt; port++) {861 cgx = port / rvu->hw->lmac_per_cgx;862 lmac = port % rvu->hw->lmac_per_cgx;863 if (!is_lmac_valid(rvu_cgx_pdata(cgx, rvu), lmac))864 continue;865 set_bit(port, &lmac_bmap);866 }867 mcs->hw->lmac_bmap = lmac_bmap;868}869 870int rvu_mcs_init(struct rvu *rvu)871{872 struct rvu_hwinfo *hw = rvu->hw;873 int lmac, err = 0, mcs_id;874 struct mcs *mcs;875 876 rvu->mcs_blk_cnt = mcs_get_blkcnt();877 878 if (!rvu->mcs_blk_cnt)879 return 0;880 881 /* Needed only for CN10K-B */882 if (rvu->mcs_blk_cnt == 1) {883 err = mcs_set_lmac_channels(0, hw->cgx_chan_base);884 if (err)885 return err;886 /* Set active lmacs */887 rvu_mcs_set_lmac_bmap(rvu);888 }889 890 /* Install default tcam bypass entry and set port to operational mode */891 for (mcs_id = 0; mcs_id < rvu->mcs_blk_cnt; mcs_id++) {892 mcs = mcs_get_pdata(mcs_id);893 mcs_install_flowid_bypass_entry(mcs);894 for (lmac = 0; lmac < mcs->hw->lmac_cnt; lmac++)895 mcs_set_lmac_mode(mcs, lmac, 0);896 897 mcs->rvu = rvu;898 899 /* Allocated memory for PFVF data */900 mcs->pf = devm_kcalloc(mcs->dev, hw->total_pfs,901 sizeof(struct mcs_pfvf), GFP_KERNEL);902 if (!mcs->pf)903 return -ENOMEM;904 905 mcs->vf = devm_kcalloc(mcs->dev, hw->total_vfs,906 sizeof(struct mcs_pfvf), GFP_KERNEL);907 if (!mcs->vf)908 return -ENOMEM;909 }910 911 /* Initialize the wq for handling mcs interrupts */912 INIT_LIST_HEAD(&rvu->mcs_intrq_head);913 INIT_WORK(&rvu->mcs_intr_work, mcs_intr_handler_task);914 rvu->mcs_intr_wq = alloc_workqueue("mcs_intr_wq", 0, 0);915 if (!rvu->mcs_intr_wq) {916 dev_err(rvu->dev, "mcs alloc workqueue failed\n");917 return -ENOMEM;918 }919 920 return err;921}922 923void rvu_mcs_exit(struct rvu *rvu)924{925 if (!rvu->mcs_intr_wq)926 return;927 928 flush_workqueue(rvu->mcs_intr_wq);929 destroy_workqueue(rvu->mcs_intr_wq);930 rvu->mcs_intr_wq = NULL;931}932