File Index
Files and directories
Sign in
FILE

rvu_cn10k.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Marvell RPM CN10K driver
  3 *
  4 * Copyright (C) 2020 Marvell.
  5 */
  6
  7#include <linux/bitfield.h>
  8#include <linux/pci.h>
  9#include "rvu.h"
 10#include "cgx.h"
 11#include "rvu_reg.h"
 12
 13/* RVU LMTST */
 14#define LMT_TBL_OP_READ		0
 15#define LMT_TBL_OP_WRITE	1
 16#define LMT_MAPTBL_ENTRY_SIZE	16
 17#define LMT_MAX_VFS		256
 18
 19#define LMT_MAP_ENTRY_ENA      BIT_ULL(20)
 20#define LMT_MAP_ENTRY_LINES    GENMASK_ULL(18, 16)
 21
 22/* Function to perform operations (read/write) on lmtst map table */
 23static int lmtst_map_table_ops(struct rvu *rvu, u32 index, u64 *val,
 24			       int lmt_tbl_op)
 25{
 26	void __iomem *lmt_map_base;
 27	u64 tbl_base, cfg;
 28	int pfs, vfs;
 29
 30	tbl_base = rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_MAP_BASE);
 31	cfg  = rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_CFG);
 32	vfs = 1 << (cfg & 0xF);
 33	pfs = 1 << ((cfg >> 4) & 0x7);
 34
 35	lmt_map_base = ioremap_wc(tbl_base, pfs * vfs * LMT_MAPTBL_ENTRY_SIZE);
 36	if (!lmt_map_base) {
 37		dev_err(rvu->dev, "Failed to setup lmt map table mapping!!\n");
 38		return -ENOMEM;
 39	}
 40
 41	if (lmt_tbl_op == LMT_TBL_OP_READ) {
 42		*val = readq(lmt_map_base + index);
 43	} else {
 44		writeq((*val), (lmt_map_base + index));
 45
 46		cfg = FIELD_PREP(LMT_MAP_ENTRY_ENA, 0x1);
 47		/* 2048 LMTLINES */
 48		cfg |= FIELD_PREP(LMT_MAP_ENTRY_LINES, 0x6);
 49
 50		writeq(cfg, (lmt_map_base + (index + 8)));
 51
 52		/* Flushing the AP interceptor cache to make APR_LMT_MAP_ENTRY_S
 53		 * changes effective. Write 1 for flush and read is being used as a
 54		 * barrier and sets up a data dependency. Write to 0 after a write
 55		 * to 1 to complete the flush.
 56		 */
 57		rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CTL, BIT_ULL(0));
 58		rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_CTL);
 59		rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CTL, 0x00);
 60	}
 61
 62	iounmap(lmt_map_base);
 63	return 0;
 64}
 65
 66#define LMT_MAP_TBL_W1_OFF  8
 67static u32 rvu_get_lmtst_tbl_index(struct rvu *rvu, u16 pcifunc)
 68{
 69	return ((rvu_get_pf(rvu->pdev, pcifunc) * LMT_MAX_VFS) +
 70		(pcifunc & RVU_PFVF_FUNC_MASK)) * LMT_MAPTBL_ENTRY_SIZE;
 71}
 72
 73static int rvu_get_lmtaddr(struct rvu *rvu, u16 pcifunc,
 74			   u64 iova, u64 *lmt_addr)
 75{
 76	u64 pa, val, pf;
 77	int err = 0;
 78
 79	if (!iova) {
 80		dev_err(rvu->dev, "%s Requested Null address for transulation\n", __func__);
 81		return -EINVAL;
 82	}
 83
 84	mutex_lock(&rvu->rsrc_lock);
 85	rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_REQ, iova);
 86	pf = rvu_get_pf(rvu->pdev, pcifunc) & RVU_OTX2_PFVF_PF_MASK;
 87	val = BIT_ULL(63) | BIT_ULL(14) | BIT_ULL(13) | pf << 8 |
 88	      ((pcifunc & RVU_PFVF_FUNC_MASK) & 0xFF);
 89	rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_TXN_REQ, val);
 90
 91	err = rvu_poll_reg(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_RSP_STS, BIT_ULL(0), false);
 92	if (err) {
 93		dev_err(rvu->dev, "%s LMTLINE iova transulation failed\n", __func__);
 94		goto exit;
 95	}
 96	val = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_RSP_STS);
 97	if (val & ~0x1ULL) {
 98		dev_err(rvu->dev, "%s LMTLINE iova transulation failed err:%llx\n", __func__, val);
 99		err = -EIO;
100		goto exit;
101	}
102	/* PA[51:12] = RVU_AF_SMMU_TLN_FLIT0[57:18]
103	 * PA[11:0] = IOVA[11:0]
104	 */
105	pa = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_TLN_FLIT0) >> 18;
106	pa &= GENMASK_ULL(39, 0);
107	*lmt_addr = (pa << 12) | (iova  & 0xFFF);
108exit:
109	mutex_unlock(&rvu->rsrc_lock);
110	return err;
111}
112
113static int rvu_update_lmtaddr(struct rvu *rvu, u16 pcifunc, u64 lmt_addr)
114{
115	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
116	u32 tbl_idx;
117	int err = 0;
118	u64 val;
119
120	/* Read the current lmt addr of pcifunc */
121	tbl_idx = rvu_get_lmtst_tbl_index(rvu, pcifunc);
122	err = lmtst_map_table_ops(rvu, tbl_idx, &val, LMT_TBL_OP_READ);
123	if (err) {
124		dev_err(rvu->dev,
125			"Failed to read LMT map table: index 0x%x err %d\n",
126			tbl_idx, err);
127		return err;
128	}
129
130	/* Storing the seondary's lmt base address as this needs to be
131	 * reverted in FLR. Also making sure this default value doesn't
132	 * get overwritten on multiple calls to this mailbox.
133	 */
134	if (!pfvf->lmt_base_addr)
135		pfvf->lmt_base_addr = val;
136
137	/* Update the LMT table with new addr */
138	err = lmtst_map_table_ops(rvu, tbl_idx, &lmt_addr, LMT_TBL_OP_WRITE);
139	if (err) {
140		dev_err(rvu->dev,
141			"Failed to update LMT map table: index 0x%x err %d\n",
142			tbl_idx, err);
143		return err;
144	}
145	return 0;
146}
147
148int rvu_mbox_handler_lmtst_tbl_setup(struct rvu *rvu,
149				     struct lmtst_tbl_setup_req *req,
150				     struct msg_rsp *rsp)
151{
152	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
153	u32 pri_tbl_idx, tbl_idx;
154	u64 lmt_addr;
155	int err = 0;
156	u64 val;
157
158	/* Check if PF_FUNC wants to use its own local memory as LMTLINE
159	 * region, if so, convert that IOVA to physical address and
160	 * populate LMT table with that address
161	 */
162	if (req->use_local_lmt_region) {
163		err = rvu_get_lmtaddr(rvu, req->hdr.pcifunc,
164				      req->lmt_iova, &lmt_addr);
165		if (err < 0)
166			return err;
167
168		/* Update the lmt addr for this PFFUNC in the LMT table */
169		err = rvu_update_lmtaddr(rvu, req->hdr.pcifunc, lmt_addr);
170		if (err)
171			return err;
172	}
173
174	/* Reconfiguring lmtst map table in lmt region shared mode i.e. make
175	 * multiple PF_FUNCs to share an LMTLINE region, so primary/base
176	 * pcifunc (which is passed as an argument to mailbox) is the one
177	 * whose lmt base address will be shared among other secondary
178	 * pcifunc (will be the one who is calling this mailbox).
179	 */
180	if (req->base_pcifunc) {
181		/* Calculating the LMT table index equivalent to primary
182		 * pcifunc.
183		 */
184		pri_tbl_idx = rvu_get_lmtst_tbl_index(rvu, req->base_pcifunc);
185
186		/* Read the base lmt addr of the primary pcifunc */
187		err = lmtst_map_table_ops(rvu, pri_tbl_idx, &val,
188					  LMT_TBL_OP_READ);
189		if (err) {
190			dev_err(rvu->dev,
191				"Failed to read LMT map table: index 0x%x err %d\n",
192				pri_tbl_idx, err);
193			goto error;
194		}
195
196		/* Update the base lmt addr of secondary with primary's base
197		 * lmt addr.
198		 */
199		err = rvu_update_lmtaddr(rvu, req->hdr.pcifunc, val);
200		if (err)
201			return err;
202	}
203
204	/* This mailbox can also be used to update word1 of APR_LMT_MAP_ENTRY_S
205	 * like enabling scheduled LMTST, disable LMTLINE prefetch, disable
206	 * early completion for ordered LMTST.
207	 */
208	if (req->sch_ena || req->dis_sched_early_comp || req->dis_line_pref) {
209		tbl_idx = rvu_get_lmtst_tbl_index(rvu, req->hdr.pcifunc);
210		err = lmtst_map_table_ops(rvu, tbl_idx + LMT_MAP_TBL_W1_OFF,
211					  &val, LMT_TBL_OP_READ);
212		if (err) {
213			dev_err(rvu->dev,
214				"Failed to read LMT map table: index 0x%x err %d\n",
215				tbl_idx + LMT_MAP_TBL_W1_OFF, err);
216			goto error;
217		}
218
219		/* Storing lmt map table entry word1 default value as this needs
220		 * to be reverted in FLR. Also making sure this default value
221		 * doesn't get overwritten on multiple calls to this mailbox.
222		 */
223		if (!pfvf->lmt_map_ent_w1)
224			pfvf->lmt_map_ent_w1 = val;
225
226		/* Disable early completion for Ordered LMTSTs. */
227		if (req->dis_sched_early_comp)
228			val |= (req->dis_sched_early_comp <<
229				APR_LMT_MAP_ENT_DIS_SCH_CMP_SHIFT);
230		/* Enable scheduled LMTST */
231		if (req->sch_ena)
232			val |= (req->sch_ena << APR_LMT_MAP_ENT_SCH_ENA_SHIFT) |
233				req->ssow_pf_func;
234		/* Disables LMTLINE prefetch before receiving store data. */
235		if (req->dis_line_pref)
236			val |= (req->dis_line_pref <<
237				APR_LMT_MAP_ENT_DIS_LINE_PREF_SHIFT);
238
239		err = lmtst_map_table_ops(rvu, tbl_idx + LMT_MAP_TBL_W1_OFF,
240					  &val, LMT_TBL_OP_WRITE);
241		if (err) {
242			dev_err(rvu->dev,
243				"Failed to update LMT map table: index 0x%x err %d\n",
244				tbl_idx + LMT_MAP_TBL_W1_OFF, err);
245			goto error;
246		}
247	}
248
249error:
250	return err;
251}
252
253/* Resetting the lmtst map table to original base addresses */
254void rvu_reset_lmt_map_tbl(struct rvu *rvu, u16 pcifunc)
255{
256	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
257	u32 tbl_idx;
258	int err;
259
260	if (is_rvu_otx2(rvu))
261		return;
262
263	if (pfvf->lmt_base_addr || pfvf->lmt_map_ent_w1) {
264		/* This corresponds to lmt map table index */
265		tbl_idx = rvu_get_lmtst_tbl_index(rvu, pcifunc);
266		/* Reverting back original lmt base addr for respective
267		 * pcifunc.
268		 */
269		if (pfvf->lmt_base_addr) {
270			err = lmtst_map_table_ops(rvu, tbl_idx,
271						  &pfvf->lmt_base_addr,
272						  LMT_TBL_OP_WRITE);
273			if (err)
274				dev_err(rvu->dev,
275					"Failed to update LMT map table: index 0x%x err %d\n",
276					tbl_idx, err);
277			pfvf->lmt_base_addr = 0;
278		}
279		/* Reverting back to orginal word1 val of lmtst map table entry
280		 * which underwent changes.
281		 */
282		if (pfvf->lmt_map_ent_w1) {
283			err = lmtst_map_table_ops(rvu,
284						  tbl_idx + LMT_MAP_TBL_W1_OFF,
285						  &pfvf->lmt_map_ent_w1,
286						  LMT_TBL_OP_WRITE);
287			if (err)
288				dev_err(rvu->dev,
289					"Failed to update LMT map table: index 0x%x err %d\n",
290					tbl_idx + LMT_MAP_TBL_W1_OFF, err);
291			pfvf->lmt_map_ent_w1 = 0;
292		}
293	}
294}
295
296int rvu_set_channels_base(struct rvu *rvu)
297{
298	u16 nr_lbk_chans, nr_sdp_chans, nr_cgx_chans, nr_cpt_chans;
299	u16 sdp_chan_base, cgx_chan_base, cpt_chan_base;
300	struct rvu_hwinfo *hw = rvu->hw;
301	u64 nix_const, nix_const1;
302	int blkaddr;
303
304	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
305	if (blkaddr < 0)
306		return blkaddr;
307
308	nix_const = rvu_read64(rvu, blkaddr, NIX_AF_CONST);
309	nix_const1 = rvu_read64(rvu, blkaddr, NIX_AF_CONST1);
310
311	hw->cgx = (nix_const >> 12) & 0xFULL;
312	hw->lmac_per_cgx = (nix_const >> 8) & 0xFULL;
313	hw->cgx_links = hw->cgx * hw->lmac_per_cgx;
314	hw->lbk_links = (nix_const >> 24) & 0xFULL;
315	hw->cpt_links = (nix_const >> 44) & 0xFULL;
316	hw->sdp_links = 1;
317
318	hw->cgx_chan_base = NIX_CHAN_CGX_LMAC_CHX(0, 0, 0);
319	hw->lbk_chan_base = NIX_CHAN_LBK_CHX(0, 0);
320	hw->sdp_chan_base = NIX_CHAN_SDP_CH_START;
321
322	/* No Programmable channels */
323	if (!(nix_const & BIT_ULL(60)))
324		return 0;
325
326	hw->cap.programmable_chans = true;
327
328	/* If programmable channels are present then configure
329	 * channels such that all channel numbers are contiguous
330	 * leaving no holes. This way the new CPT channels can be
331	 * accomodated. The order of channel numbers assigned is
332	 * LBK, SDP, CGX and CPT. Also the base channel number
333	 * of a block must be multiple of number of channels
334	 * of the block.
335	 */
336	nr_lbk_chans = (nix_const >> 16) & 0xFFULL;
337	nr_sdp_chans = nix_const1 & 0xFFFULL;
338	nr_cgx_chans = nix_const & 0xFFULL;
339	nr_cpt_chans = (nix_const >> 32) & 0xFFFULL;
340
341	sdp_chan_base = hw->lbk_chan_base + hw->lbk_links * nr_lbk_chans;
342	/* Round up base channel to multiple of number of channels */
343	hw->sdp_chan_base = ALIGN(sdp_chan_base, nr_sdp_chans);
344
345	cgx_chan_base = hw->sdp_chan_base + hw->sdp_links * nr_sdp_chans;
346	hw->cgx_chan_base = ALIGN(cgx_chan_base, nr_cgx_chans);
347
348	cpt_chan_base = hw->cgx_chan_base + hw->cgx_links * nr_cgx_chans;
349	hw->cpt_chan_base = ALIGN(cpt_chan_base, nr_cpt_chans);
350
351	/* Out of 4096 channels start CPT from 2048 so
352	 * that MSB for CPT channels is always set
353	 */
354	if (cpt_chan_base <= NIX_CHAN_CPT_CH_START) {
355		hw->cpt_chan_base = NIX_CHAN_CPT_CH_START;
356	} else {
357		dev_err(rvu->dev,
358			"CPT channels could not fit in the range 2048-4095\n");
359		return -EINVAL;
360	}
361
362	return 0;
363}
364
365#define LBK_CONNECT_NIXX(a)		(0x0 + (a))
366
367static void __rvu_lbk_set_chans(struct rvu *rvu, void __iomem *base,
368				u64 offset, int lbkid, u16 chans)
369{
370	struct rvu_hwinfo *hw = rvu->hw;
371	u64 cfg;
372
373	cfg = readq(base + offset);
374	cfg &= ~(LBK_LINK_CFG_RANGE_MASK |
375		 LBK_LINK_CFG_ID_MASK | LBK_LINK_CFG_BASE_MASK);
376	cfg |=	FIELD_PREP(LBK_LINK_CFG_RANGE_MASK, ilog2(chans));
377	cfg |=	FIELD_PREP(LBK_LINK_CFG_ID_MASK, lbkid);
378	cfg |=	FIELD_PREP(LBK_LINK_CFG_BASE_MASK, hw->lbk_chan_base);
379
380	writeq(cfg, base + offset);
381}
382
383static void rvu_lbk_set_channels(struct rvu *rvu)
384{
385	struct pci_dev *pdev = NULL;
386	void __iomem *base;
387	u64 lbk_const;
388	u8 src, dst;
389	u16 chans;
390
391	/* To loopback packets between multiple NIX blocks
392	 * mutliple LBK blocks are needed. With two NIX blocks,
393	 * four LBK blocks are needed and each LBK block
394	 * source and destination are as follows:
395	 * LBK0 - source NIX0 and destination NIX1
396	 * LBK1 - source NIX0 and destination NIX1
397	 * LBK2 - source NIX1 and destination NIX0
398	 * LBK3 - source NIX1 and destination NIX1
399	 * As per the HRM channel numbers should be programmed as:
400	 * P2X and X2P of LBK0 as same
401	 * P2X and X2P of LBK3 as same
402	 * P2X of LBK1 and X2P of LBK2 as same
403	 * P2X of LBK2 and X2P of LBK1 as same
404	 */
405	while (true) {
406		pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
407				      PCI_DEVID_OCTEONTX2_LBK, pdev);
408		if (!pdev)
409			return;
410
411		base = pci_ioremap_bar(pdev, 0);
412		if (!base)
413			goto err_put;
414
415		lbk_const = readq(base + LBK_CONST);
416		chans = FIELD_GET(LBK_CONST_CHANS, lbk_const);
417		dst = FIELD_GET(LBK_CONST_DST, lbk_const);
418		src = FIELD_GET(LBK_CONST_SRC, lbk_const);
419
420		if (src == dst) {
421			if (src == LBK_CONNECT_NIXX(0)) { /* LBK0 */
422				__rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_X2P,
423						    0, chans);
424				__rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_P2X,
425						    0, chans);
426			} else if (src == LBK_CONNECT_NIXX(1)) { /* LBK3 */
427				__rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_X2P,
428						    1, chans);
429				__rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_P2X,
430						    1, chans);
431			}
432		} else {
433			if (src == LBK_CONNECT_NIXX(0)) { /* LBK1 */
434				__rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_X2P,
435						    0, chans);
436				__rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_P2X,
437						    1, chans);
438			} else if (src == LBK_CONNECT_NIXX(1)) { /* LBK2 */
439				__rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_X2P,
440						    1, chans);
441				__rvu_lbk_set_chans(rvu, base, LBK_LINK_CFG_P2X,
442						    0, chans);
443			}
444		}
445		iounmap(base);
446	}
447err_put:
448	pci_dev_put(pdev);
449}
450
451static void __rvu_nix_set_channels(struct rvu *rvu, int blkaddr)
452{
453	u64 nix_const1 = rvu_read64(rvu, blkaddr, NIX_AF_CONST1);
454	u64 nix_const = rvu_read64(rvu, blkaddr, NIX_AF_CONST);
455	u16 cgx_chans, lbk_chans, sdp_chans, cpt_chans;
456	struct rvu_hwinfo *hw = rvu->hw;
457	int link, nix_link = 0;
458	u16 start;
459	u64 cfg;
460
461	cgx_chans = nix_const & 0xFFULL;
462	lbk_chans = (nix_const >> 16) & 0xFFULL;
463	sdp_chans = nix_const1 & 0xFFFULL;
464	cpt_chans = (nix_const >> 32) & 0xFFFULL;
465
466	start = hw->cgx_chan_base;
467	for (link = 0; link < hw->cgx_links; link++, nix_link++) {
468		cfg = rvu_read64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link));
469		cfg &= ~(NIX_AF_LINKX_BASE_MASK | NIX_AF_LINKX_RANGE_MASK);
470		cfg |=	FIELD_PREP(NIX_AF_LINKX_RANGE_MASK, ilog2(cgx_chans));
471		cfg |=	FIELD_PREP(NIX_AF_LINKX_BASE_MASK, start);
472		rvu_write64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link), cfg);
473		start += cgx_chans;
474	}
475
476	start = hw->lbk_chan_base;
477	for (link = 0; link < hw->lbk_links; link++, nix_link++) {
478		cfg = rvu_read64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link));
479		cfg &= ~(NIX_AF_LINKX_BASE_MASK | NIX_AF_LINKX_RANGE_MASK);
480		cfg |=	FIELD_PREP(NIX_AF_LINKX_RANGE_MASK, ilog2(lbk_chans));
481		cfg |=	FIELD_PREP(NIX_AF_LINKX_BASE_MASK, start);
482		rvu_write64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link), cfg);
483		start += lbk_chans;
484	}
485
486	start = hw->sdp_chan_base;
487	for (link = 0; link < hw->sdp_links; link++, nix_link++) {
488		cfg = rvu_read64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link));
489		cfg &= ~(NIX_AF_LINKX_BASE_MASK | NIX_AF_LINKX_RANGE_MASK);
490		cfg |=	FIELD_PREP(NIX_AF_LINKX_RANGE_MASK, ilog2(sdp_chans));
491		cfg |=	FIELD_PREP(NIX_AF_LINKX_BASE_MASK, start);
492		rvu_write64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link), cfg);
493		start += sdp_chans;
494	}
495
496	start = hw->cpt_chan_base;
497	for (link = 0; link < hw->cpt_links; link++, nix_link++) {
498		cfg = rvu_read64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link));
499		cfg &= ~(NIX_AF_LINKX_BASE_MASK | NIX_AF_LINKX_RANGE_MASK);
500		cfg |=	FIELD_PREP(NIX_AF_LINKX_RANGE_MASK, ilog2(cpt_chans));
501		cfg |=	FIELD_PREP(NIX_AF_LINKX_BASE_MASK, start);
502		rvu_write64(rvu, blkaddr, NIX_AF_LINKX_CFG(nix_link), cfg);
503		start += cpt_chans;
504	}
505}
506
507static void rvu_nix_set_channels(struct rvu *rvu)
508{
509	int blkaddr = 0;
510
511	blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
512	while (blkaddr) {
513		__rvu_nix_set_channels(rvu, blkaddr);
514		blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
515	}
516}
517
518static void __rvu_rpm_set_channels(int cgxid, int lmacid, u16 base)
519{
520	u64 cfg;
521
522	cfg = cgx_lmac_read(cgxid, lmacid, RPMX_CMRX_LINK_CFG);
523	cfg &= ~(RPMX_CMRX_LINK_BASE_MASK | RPMX_CMRX_LINK_RANGE_MASK);
524
525	/* There is no read-only constant register to read
526	 * the number of channels for LMAC and it is always 16.
527	 */
528	cfg |=	FIELD_PREP(RPMX_CMRX_LINK_RANGE_MASK, ilog2(16));
529	cfg |=	FIELD_PREP(RPMX_CMRX_LINK_BASE_MASK, base);
530	cgx_lmac_write(cgxid, lmacid, RPMX_CMRX_LINK_CFG, cfg);
531}
532
533static void rvu_rpm_set_channels(struct rvu *rvu)
534{
535	struct rvu_hwinfo *hw = rvu->hw;
536	u16 base = hw->cgx_chan_base;
537	int cgx, lmac;
538
539	for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++) {
540		for (lmac = 0; lmac < hw->lmac_per_cgx; lmac++) {
541			__rvu_rpm_set_channels(cgx, lmac, base);
542			base += 16;
543		}
544	}
545}
546
547void rvu_program_channels(struct rvu *rvu)
548{
549	struct rvu_hwinfo *hw = rvu->hw;
550
551	if (!hw->cap.programmable_chans)
552		return;
553
554	rvu_nix_set_channels(rvu);
555	rvu_lbk_set_channels(rvu);
556	rvu_rpm_set_channels(rvu);
557}
558
559void rvu_nix_block_cn10k_init(struct rvu *rvu, struct nix_hw *nix_hw)
560{
561	int blkaddr = nix_hw->blkaddr;
562	u64 cfg;
563
564	/* Set AF vWQE timer interval to a LF configurable range of
565	 * 6.4us to 1.632ms.
566	 */
567	rvu_write64(rvu, blkaddr, NIX_AF_VWQE_TIMER, 0x3FULL);
568
569	/* Enable NIX RX stream and global conditional clock to
570	 * avoild multiple free of NPA buffers.
571	 */
572	cfg = rvu_read64(rvu, blkaddr, NIX_AF_CFG);
573	cfg |= BIT_ULL(1) | BIT_ULL(2);
574	rvu_write64(rvu, blkaddr, NIX_AF_CFG, cfg);
575}
576
577void rvu_apr_block_cn10k_init(struct rvu *rvu)
578{
579	u64 reg;
580
581	reg = rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_CFG);
582	reg |=	FIELD_PREP(LMTST_THROTTLE_MASK, LMTST_WR_PEND_MAX);
583	rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CFG, reg);
584}
~/ Read-only file preview.