1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
3 * Copyright (C) 2018 Netronome Systems, Inc.
5 * This software is dual licensed under the GNU General License Version 2,
6 * June 1991 as shown in the file COPYING in the top-level directory of this
7 * source tree or the BSD 2-Clause License provided below. You have the
8 * option to license this software under the complete terms of either license.
10 * The BSD 2-Clause License:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * 1. Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * 2. Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 #include <linux/kernel.h>
37 #include "../nfpcore/nfp_cpp.h"
38 #include "../nfpcore/nfp_nffw.h"
39 #include "../nfp_app.h"
40 #include "../nfp_abi.h"
41 #include "../nfp_main.h"
42 #include "../nfp_net.h"
45 #define NFP_QLVL_SYM_NAME "_abi_nfd_out_q_lvls_%u"
46 #define NFP_QLVL_STRIDE 16
47 #define NFP_QLVL_BLOG_BYTES 0
48 #define NFP_QLVL_BLOG_PKTS 4
49 #define NFP_QLVL_THRS 8
51 #define NFP_QMSTAT_SYM_NAME "_abi_nfdqm%u_stats"
52 #define NFP_QMSTAT_STRIDE 32
53 #define NFP_QMSTAT_NON_STO 0
54 #define NFP_QMSTAT_STO 8
55 #define NFP_QMSTAT_DROP 16
56 #define NFP_QMSTAT_ECN 24
58 static unsigned long long
59 nfp_abm_q_lvl_thrs(struct nfp_abm_link *alink, unsigned int queue)
61 return alink->abm->q_lvls->addr +
62 (alink->queue_base + queue) * NFP_QLVL_STRIDE + NFP_QLVL_THRS;
66 nfp_abm_ctrl_stat(struct nfp_abm_link *alink, const struct nfp_rtsym *sym,
67 unsigned int stride, unsigned int offset, unsigned int i,
68 bool is_u64, u64 *res)
70 struct nfp_cpp *cpp = alink->abm->app->cpp;
75 mur = NFP_CPP_ATOMIC_RD(sym->target, sym->domain);
77 addr = sym->addr + (alink->queue_base + i) * stride + offset;
79 err = nfp_cpp_readq(cpp, mur, addr, &val);
81 err = nfp_cpp_readl(cpp, mur, addr, &val32);
84 "RED offload reading stat failed on vNIC %d queue %d\n",
89 *res = is_u64 ? val : val32;
94 nfp_abm_ctrl_stat_all(struct nfp_abm_link *alink, const struct nfp_rtsym *sym,
95 unsigned int stride, unsigned int offset, bool is_u64,
102 for (i = 0; i < alink->vnic->max_rx_rings; i++) {
103 err = nfp_abm_ctrl_stat(alink, sym, stride, offset, i,
114 int nfp_abm_ctrl_set_q_lvl(struct nfp_abm_link *alink, unsigned int i, u32 val)
116 struct nfp_cpp *cpp = alink->abm->app->cpp;
120 muw = NFP_CPP_ATOMIC_WR(alink->abm->q_lvls->target,
121 alink->abm->q_lvls->domain);
123 err = nfp_cpp_writel(cpp, muw, nfp_abm_q_lvl_thrs(alink, i), val);
125 nfp_err(cpp, "RED offload setting level failed on vNIC %d queue %d\n",
133 int nfp_abm_ctrl_set_all_q_lvls(struct nfp_abm_link *alink, u32 val)
137 for (i = 0; i < alink->vnic->max_rx_rings; i++) {
138 err = nfp_abm_ctrl_set_q_lvl(alink, i, val);
146 u64 nfp_abm_ctrl_stat_non_sto(struct nfp_abm_link *alink, unsigned int i)
150 if (nfp_abm_ctrl_stat(alink, alink->abm->qm_stats, NFP_QMSTAT_STRIDE,
151 NFP_QMSTAT_NON_STO, i, true, &val))
156 u64 nfp_abm_ctrl_stat_sto(struct nfp_abm_link *alink, unsigned int i)
160 if (nfp_abm_ctrl_stat(alink, alink->abm->qm_stats, NFP_QMSTAT_STRIDE,
161 NFP_QMSTAT_STO, i, true, &val))
166 int nfp_abm_ctrl_read_q_stats(struct nfp_abm_link *alink, unsigned int i,
167 struct nfp_alink_stats *stats)
171 stats->tx_pkts = nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i));
172 stats->tx_bytes = nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i) + 8);
174 err = nfp_abm_ctrl_stat(alink, alink->abm->q_lvls,
175 NFP_QLVL_STRIDE, NFP_QLVL_BLOG_BYTES,
176 i, false, &stats->backlog_bytes);
180 err = nfp_abm_ctrl_stat(alink, alink->abm->q_lvls,
181 NFP_QLVL_STRIDE, NFP_QLVL_BLOG_PKTS,
182 i, false, &stats->backlog_pkts);
186 err = nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
187 NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
188 i, true, &stats->drops);
192 return nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
193 NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
194 i, true, &stats->overlimits);
197 int nfp_abm_ctrl_read_stats(struct nfp_abm_link *alink,
198 struct nfp_alink_stats *stats)
200 u64 pkts = 0, bytes = 0;
203 for (i = 0; i < alink->vnic->max_rx_rings; i++) {
204 pkts += nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i));
205 bytes += nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i) + 8);
207 stats->tx_pkts = pkts;
208 stats->tx_bytes = bytes;
210 err = nfp_abm_ctrl_stat_all(alink, alink->abm->q_lvls,
211 NFP_QLVL_STRIDE, NFP_QLVL_BLOG_BYTES,
212 false, &stats->backlog_bytes);
216 err = nfp_abm_ctrl_stat_all(alink, alink->abm->q_lvls,
217 NFP_QLVL_STRIDE, NFP_QLVL_BLOG_PKTS,
218 false, &stats->backlog_pkts);
222 err = nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
223 NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
224 true, &stats->drops);
228 return nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
229 NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
230 true, &stats->overlimits);
233 int nfp_abm_ctrl_read_q_xstats(struct nfp_abm_link *alink, unsigned int i,
234 struct nfp_alink_xstats *xstats)
238 err = nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
239 NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
240 i, true, &xstats->pdrop);
244 return nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
245 NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
246 i, true, &xstats->ecn_marked);
249 int nfp_abm_ctrl_read_xstats(struct nfp_abm_link *alink,
250 struct nfp_alink_xstats *xstats)
254 err = nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
255 NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
256 true, &xstats->pdrop);
260 return nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
261 NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
262 true, &xstats->ecn_marked);
265 int nfp_abm_ctrl_qm_enable(struct nfp_abm *abm)
267 return nfp_mbox_cmd(abm->app->pf, NFP_MBOX_PCIE_ABM_ENABLE,
271 int nfp_abm_ctrl_qm_disable(struct nfp_abm *abm)
273 return nfp_mbox_cmd(abm->app->pf, NFP_MBOX_PCIE_ABM_DISABLE,
277 void nfp_abm_ctrl_read_params(struct nfp_abm_link *alink)
279 alink->queue_base = nn_readl(alink->vnic, NFP_NET_CFG_START_RXQ);
280 alink->queue_base /= alink->vnic->stride_rx;
283 static const struct nfp_rtsym *
284 nfp_abm_ctrl_find_rtsym(struct nfp_pf *pf, const char *name, unsigned int size)
286 const struct nfp_rtsym *sym;
288 sym = nfp_rtsym_lookup(pf->rtbl, name);
290 nfp_err(pf->cpp, "Symbol '%s' not found\n", name);
291 return ERR_PTR(-ENOENT);
293 if (sym->size != size) {
295 "Symbol '%s' wrong size: expected %u got %llu\n",
296 name, size, sym->size);
297 return ERR_PTR(-EINVAL);
303 static const struct nfp_rtsym *
304 nfp_abm_ctrl_find_q_rtsym(struct nfp_pf *pf, const char *name,
307 return nfp_abm_ctrl_find_rtsym(pf, name, size * NFP_NET_MAX_RX_RINGS);
310 int nfp_abm_ctrl_find_addrs(struct nfp_abm *abm)
312 struct nfp_pf *pf = abm->app->pf;
313 const struct nfp_rtsym *sym;
317 pf_id = nfp_cppcore_pcie_unit(pf->cpp);
320 snprintf(pf_symbol, sizeof(pf_symbol), NFP_QLVL_SYM_NAME, pf_id);
321 sym = nfp_abm_ctrl_find_q_rtsym(pf, pf_symbol, NFP_QLVL_STRIDE);
326 snprintf(pf_symbol, sizeof(pf_symbol), NFP_QMSTAT_SYM_NAME, pf_id);
327 sym = nfp_abm_ctrl_find_q_rtsym(pf, pf_symbol, NFP_QMSTAT_STRIDE);