1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell RVU Physical Function ethernet driver
4 * Copyright (C) 2023 Marvell.
8 #include <linux/netdevice.h>
13 #include "otx2_common.h"
14 #include "otx2_txrx.h"
15 #include "otx2_struct.h"
17 #define OTX2_QOS_MAX_LEAF_NODES 16
19 static void otx2_qos_aura_pool_free(struct otx2_nic *pfvf, int pool_id)
21 struct otx2_pool *pool;
26 pool = &pfvf->qset.pool[pool_id];
27 qmem_free(pfvf->dev, pool->stack);
28 qmem_free(pfvf->dev, pool->fc_addr);
33 static int otx2_qos_sq_aura_pool_init(struct otx2_nic *pfvf, int qidx)
35 struct otx2_qset *qset = &pfvf->qset;
36 int pool_id, stack_pages, num_sqbs;
37 struct otx2_hw *hw = &pfvf->hw;
38 struct otx2_snd_queue *sq;
39 struct otx2_pool *pool;
44 /* Calculate number of SQBs needed.
46 * For a 128byte SQE, and 4K size SQB, 31 SQEs will fit in one SQB.
47 * Last SQE is used for pointing to next SQB.
49 num_sqbs = (hw->sqb_size / 128) - 1;
50 num_sqbs = (qset->sqe_cnt + num_sqbs) / num_sqbs;
52 /* Get no of stack pages needed */
54 (num_sqbs + hw->stack_pg_ptrs - 1) / hw->stack_pg_ptrs;
56 pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
57 pool = &pfvf->qset.pool[pool_id];
59 /* Initialize aura context */
60 err = otx2_aura_init(pfvf, pool_id, pool_id, num_sqbs);
64 /* Initialize pool context */
65 err = otx2_pool_init(pfvf, pool_id, stack_pages,
66 num_sqbs, hw->sqb_size, AURA_NIX_SQ);
70 /* Flush accumulated messages */
71 err = otx2_sync_mbox_msg(&pfvf->mbox);
75 /* Allocate pointers and free them to aura/pool */
78 sq->sqb_ptrs = kcalloc(num_sqbs, sizeof(*sq->sqb_ptrs), GFP_KERNEL);
84 for (ptr = 0; ptr < num_sqbs; ptr++) {
85 err = otx2_alloc_rbuf(pfvf, pool, &bufptr);
88 pfvf->hw_ops->aura_freeptr(pfvf, pool_id, bufptr);
89 sq->sqb_ptrs[sq->sqb_count++] = (u64)bufptr;
96 if (!sq->sqb_ptrs[ptr])
98 iova = sq->sqb_ptrs[ptr];
99 pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
100 dma_unmap_page_attrs(pfvf->dev, iova, hw->sqb_size,
102 DMA_ATTR_SKIP_CPU_SYNC);
103 put_page(virt_to_page(phys_to_virt(pa)));
104 otx2_aura_allocptr(pfvf, pool_id);
109 qmem_free(pfvf->dev, pool->stack);
111 qmem_free(pfvf->dev, pool->fc_addr);
112 otx2_mbox_reset(&pfvf->mbox.mbox, 0);
116 static void otx2_qos_sq_free_sqbs(struct otx2_nic *pfvf, int qidx)
118 struct otx2_qset *qset = &pfvf->qset;
119 struct otx2_hw *hw = &pfvf->hw;
120 struct otx2_snd_queue *sq;
124 sq = &qset->sq[qidx];
127 for (sqb = 0; sqb < sq->sqb_count; sqb++) {
128 if (!sq->sqb_ptrs[sqb])
130 iova = sq->sqb_ptrs[sqb];
131 pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
132 dma_unmap_page_attrs(pfvf->dev, iova, hw->sqb_size,
134 DMA_ATTR_SKIP_CPU_SYNC);
135 put_page(virt_to_page(phys_to_virt(pa)));
140 sq = &qset->sq[qidx];
141 qmem_free(pfvf->dev, sq->sqe);
142 qmem_free(pfvf->dev, sq->tso_hdrs);
145 qmem_free(pfvf->dev, sq->timestamps);
147 memset((void *)sq, 0, sizeof(*sq));
151 static void otx2_qos_sqb_flush(struct otx2_nic *pfvf, int qidx)
153 int sqe_tail, sqe_head;
156 ptr = (__force u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS);
157 incr = (u64)qidx << 32;
158 val = otx2_atomic64_add(incr, ptr);
159 sqe_head = (val >> 20) & 0x3F;
160 sqe_tail = (val >> 28) & 0x3F;
161 if (sqe_head != sqe_tail)
162 usleep_range(50, 60);
165 static int otx2_qos_ctx_disable(struct otx2_nic *pfvf, u16 qidx, int aura_id)
167 struct nix_cn10k_aq_enq_req *cn10k_sq_aq;
168 struct npa_aq_enq_req *aura_aq;
169 struct npa_aq_enq_req *pool_aq;
170 struct nix_aq_enq_req *sq_aq;
172 if (test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) {
173 cn10k_sq_aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
176 cn10k_sq_aq->qidx = qidx;
177 cn10k_sq_aq->sq.ena = 0;
178 cn10k_sq_aq->sq_mask.ena = 1;
179 cn10k_sq_aq->ctype = NIX_AQ_CTYPE_SQ;
180 cn10k_sq_aq->op = NIX_AQ_INSTOP_WRITE;
182 sq_aq = otx2_mbox_alloc_msg_nix_aq_enq(&pfvf->mbox);
187 sq_aq->sq_mask.ena = 1;
188 sq_aq->ctype = NIX_AQ_CTYPE_SQ;
189 sq_aq->op = NIX_AQ_INSTOP_WRITE;
192 aura_aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
194 otx2_mbox_reset(&pfvf->mbox.mbox, 0);
198 aura_aq->aura_id = aura_id;
199 aura_aq->aura.ena = 0;
200 aura_aq->aura_mask.ena = 1;
201 aura_aq->ctype = NPA_AQ_CTYPE_AURA;
202 aura_aq->op = NPA_AQ_INSTOP_WRITE;
204 pool_aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
206 otx2_mbox_reset(&pfvf->mbox.mbox, 0);
210 pool_aq->aura_id = aura_id;
211 pool_aq->pool.ena = 0;
212 pool_aq->pool_mask.ena = 1;
214 pool_aq->ctype = NPA_AQ_CTYPE_POOL;
215 pool_aq->op = NPA_AQ_INSTOP_WRITE;
217 return otx2_sync_mbox_msg(&pfvf->mbox);
220 int otx2_qos_get_qid(struct otx2_nic *pfvf)
224 qidx = find_first_zero_bit(pfvf->qos.qos_sq_bmap,
225 pfvf->hw.tc_tx_queues);
227 return qidx == pfvf->hw.tc_tx_queues ? -ENOSPC : qidx;
230 void otx2_qos_free_qid(struct otx2_nic *pfvf, int qidx)
232 clear_bit(qidx, pfvf->qos.qos_sq_bmap);
235 int otx2_qos_enable_sq(struct otx2_nic *pfvf, int qidx)
237 struct otx2_hw *hw = &pfvf->hw;
238 int pool_id, sq_idx, err;
240 if (pfvf->flags & OTX2_FLAG_INTF_DOWN)
243 sq_idx = hw->non_qos_queues + qidx;
245 mutex_lock(&pfvf->mbox.lock);
246 err = otx2_qos_sq_aura_pool_init(pfvf, sq_idx);
250 pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, sq_idx);
251 err = otx2_sq_init(pfvf, sq_idx, pool_id);
255 mutex_unlock(&pfvf->mbox.lock);
259 void otx2_qos_disable_sq(struct otx2_nic *pfvf, int qidx)
261 struct otx2_qset *qset = &pfvf->qset;
262 struct otx2_hw *hw = &pfvf->hw;
263 struct otx2_snd_queue *sq;
264 struct otx2_cq_queue *cq;
267 sq_idx = hw->non_qos_queues + qidx;
269 /* If the DOWN flag is set SQs are already freed */
270 if (pfvf->flags & OTX2_FLAG_INTF_DOWN)
273 sq = &pfvf->qset.sq[sq_idx];
277 if (sq_idx < hw->non_qos_queues ||
278 sq_idx >= otx2_get_total_tx_queues(pfvf)) {
279 netdev_err(pfvf->netdev, "Send Queue is not a QoS queue\n");
283 cq = &qset->cq[pfvf->hw.rx_queues + sq_idx];
284 pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, sq_idx);
286 otx2_qos_sqb_flush(pfvf, sq_idx);
287 otx2_smq_flush(pfvf, otx2_get_smq_idx(pfvf, sq_idx));
288 otx2_cleanup_tx_cqes(pfvf, cq);
290 mutex_lock(&pfvf->mbox.lock);
291 otx2_qos_ctx_disable(pfvf, sq_idx, pool_id);
292 mutex_unlock(&pfvf->mbox.lock);
294 otx2_qos_sq_free_sqbs(pfvf, sq_idx);
295 otx2_qos_aura_pool_free(pfvf, pool_id);