xref: /openbmc/linux/drivers/net/ethernet/netronome/nfp/abm/ctrl.c (revision dd2934a95701576203b2f61e8ded4e4a2f9183ea)
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2 /*
3  * Copyright (C) 2018 Netronome Systems, Inc.
4  *
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.
9  *
10  * The BSD 2-Clause License:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      1. Redistributions of source code must retain the above
17  *         copyright notice, this list of conditions and the following
18  *         disclaimer.
19  *
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.
24  *
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
32  * SOFTWARE.
33  */
34 
35 #include <linux/kernel.h>
36 
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"
43 #include "main.h"
44 
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
50 
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
57 
58 static int
59 nfp_abm_ctrl_stat(struct nfp_abm_link *alink, const struct nfp_rtsym *sym,
60 		  unsigned int stride, unsigned int offset, unsigned int i,
61 		  bool is_u64, u64 *res)
62 {
63 	struct nfp_cpp *cpp = alink->abm->app->cpp;
64 	u64 val, sym_offset;
65 	u32 val32;
66 	int err;
67 
68 	sym_offset = (alink->queue_base + i) * stride + offset;
69 	if (is_u64)
70 		err = __nfp_rtsym_readq(cpp, sym, 3, 0, sym_offset, &val);
71 	else
72 		err = __nfp_rtsym_readl(cpp, sym, 3, 0, sym_offset, &val32);
73 	if (err) {
74 		nfp_err(cpp,
75 			"RED offload reading stat failed on vNIC %d queue %d\n",
76 			alink->id, i);
77 		return err;
78 	}
79 
80 	*res = is_u64 ? val : val32;
81 	return 0;
82 }
83 
84 static int
85 nfp_abm_ctrl_stat_all(struct nfp_abm_link *alink, const struct nfp_rtsym *sym,
86 		      unsigned int stride, unsigned int offset, bool is_u64,
87 		      u64 *res)
88 {
89 	u64 val, sum = 0;
90 	unsigned int i;
91 	int err;
92 
93 	for (i = 0; i < alink->vnic->max_rx_rings; i++) {
94 		err = nfp_abm_ctrl_stat(alink, sym, stride, offset, i,
95 					is_u64, &val);
96 		if (err)
97 			return err;
98 		sum += val;
99 	}
100 
101 	*res = sum;
102 	return 0;
103 }
104 
105 int nfp_abm_ctrl_set_q_lvl(struct nfp_abm_link *alink, unsigned int i, u32 val)
106 {
107 	struct nfp_cpp *cpp = alink->abm->app->cpp;
108 	u64 sym_offset;
109 	int err;
110 
111 	sym_offset = (alink->queue_base + i) * NFP_QLVL_STRIDE + NFP_QLVL_THRS;
112 	err = __nfp_rtsym_writel(cpp, alink->abm->q_lvls, 4, 0,
113 				 sym_offset, val);
114 	if (err) {
115 		nfp_err(cpp, "RED offload setting level failed on vNIC %d queue %d\n",
116 			alink->id, i);
117 		return err;
118 	}
119 
120 	return 0;
121 }
122 
123 int nfp_abm_ctrl_set_all_q_lvls(struct nfp_abm_link *alink, u32 val)
124 {
125 	int i, err;
126 
127 	for (i = 0; i < alink->vnic->max_rx_rings; i++) {
128 		err = nfp_abm_ctrl_set_q_lvl(alink, i, val);
129 		if (err)
130 			return err;
131 	}
132 
133 	return 0;
134 }
135 
136 u64 nfp_abm_ctrl_stat_non_sto(struct nfp_abm_link *alink, unsigned int i)
137 {
138 	u64 val;
139 
140 	if (nfp_abm_ctrl_stat(alink, alink->abm->qm_stats, NFP_QMSTAT_STRIDE,
141 			      NFP_QMSTAT_NON_STO, i, true, &val))
142 		return 0;
143 	return val;
144 }
145 
146 u64 nfp_abm_ctrl_stat_sto(struct nfp_abm_link *alink, unsigned int i)
147 {
148 	u64 val;
149 
150 	if (nfp_abm_ctrl_stat(alink, alink->abm->qm_stats, NFP_QMSTAT_STRIDE,
151 			      NFP_QMSTAT_STO, i, true, &val))
152 		return 0;
153 	return val;
154 }
155 
156 int nfp_abm_ctrl_read_q_stats(struct nfp_abm_link *alink, unsigned int i,
157 			      struct nfp_alink_stats *stats)
158 {
159 	int err;
160 
161 	stats->tx_pkts = nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i));
162 	stats->tx_bytes = nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i) + 8);
163 
164 	err = nfp_abm_ctrl_stat(alink, alink->abm->q_lvls,
165 				NFP_QLVL_STRIDE, NFP_QLVL_BLOG_BYTES,
166 				i, false, &stats->backlog_bytes);
167 	if (err)
168 		return err;
169 
170 	err = nfp_abm_ctrl_stat(alink, alink->abm->q_lvls,
171 				NFP_QLVL_STRIDE, NFP_QLVL_BLOG_PKTS,
172 				i, false, &stats->backlog_pkts);
173 	if (err)
174 		return err;
175 
176 	err = nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
177 				NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
178 				i, true, &stats->drops);
179 	if (err)
180 		return err;
181 
182 	return nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
183 				 NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
184 				 i, true, &stats->overlimits);
185 }
186 
187 int nfp_abm_ctrl_read_stats(struct nfp_abm_link *alink,
188 			    struct nfp_alink_stats *stats)
189 {
190 	u64 pkts = 0, bytes = 0;
191 	int i, err;
192 
193 	for (i = 0; i < alink->vnic->max_rx_rings; i++) {
194 		pkts += nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i));
195 		bytes += nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i) + 8);
196 	}
197 	stats->tx_pkts = pkts;
198 	stats->tx_bytes = bytes;
199 
200 	err = nfp_abm_ctrl_stat_all(alink, alink->abm->q_lvls,
201 				    NFP_QLVL_STRIDE, NFP_QLVL_BLOG_BYTES,
202 				    false, &stats->backlog_bytes);
203 	if (err)
204 		return err;
205 
206 	err = nfp_abm_ctrl_stat_all(alink, alink->abm->q_lvls,
207 				    NFP_QLVL_STRIDE, NFP_QLVL_BLOG_PKTS,
208 				    false, &stats->backlog_pkts);
209 	if (err)
210 		return err;
211 
212 	err = nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
213 				    NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
214 				    true, &stats->drops);
215 	if (err)
216 		return err;
217 
218 	return nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
219 				     NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
220 				     true, &stats->overlimits);
221 }
222 
223 int nfp_abm_ctrl_read_q_xstats(struct nfp_abm_link *alink, unsigned int i,
224 			       struct nfp_alink_xstats *xstats)
225 {
226 	int err;
227 
228 	err = nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
229 				NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
230 				i, true, &xstats->pdrop);
231 	if (err)
232 		return err;
233 
234 	return nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
235 				 NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
236 				 i, true, &xstats->ecn_marked);
237 }
238 
239 int nfp_abm_ctrl_read_xstats(struct nfp_abm_link *alink,
240 			     struct nfp_alink_xstats *xstats)
241 {
242 	int err;
243 
244 	err = nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
245 				    NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
246 				    true, &xstats->pdrop);
247 	if (err)
248 		return err;
249 
250 	return nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
251 				     NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
252 				     true, &xstats->ecn_marked);
253 }
254 
255 int nfp_abm_ctrl_qm_enable(struct nfp_abm *abm)
256 {
257 	return nfp_mbox_cmd(abm->app->pf, NFP_MBOX_PCIE_ABM_ENABLE,
258 			    NULL, 0, NULL, 0);
259 }
260 
261 int nfp_abm_ctrl_qm_disable(struct nfp_abm *abm)
262 {
263 	return nfp_mbox_cmd(abm->app->pf, NFP_MBOX_PCIE_ABM_DISABLE,
264 			    NULL, 0, NULL, 0);
265 }
266 
267 void nfp_abm_ctrl_read_params(struct nfp_abm_link *alink)
268 {
269 	alink->queue_base = nn_readl(alink->vnic, NFP_NET_CFG_START_RXQ);
270 	alink->queue_base /= alink->vnic->stride_rx;
271 }
272 
273 static const struct nfp_rtsym *
274 nfp_abm_ctrl_find_rtsym(struct nfp_pf *pf, const char *name, unsigned int size)
275 {
276 	const struct nfp_rtsym *sym;
277 
278 	sym = nfp_rtsym_lookup(pf->rtbl, name);
279 	if (!sym) {
280 		nfp_err(pf->cpp, "Symbol '%s' not found\n", name);
281 		return ERR_PTR(-ENOENT);
282 	}
283 	if (nfp_rtsym_size(sym) != size) {
284 		nfp_err(pf->cpp,
285 			"Symbol '%s' wrong size: expected %u got %llu\n",
286 			name, size, nfp_rtsym_size(sym));
287 		return ERR_PTR(-EINVAL);
288 	}
289 
290 	return sym;
291 }
292 
293 static const struct nfp_rtsym *
294 nfp_abm_ctrl_find_q_rtsym(struct nfp_pf *pf, const char *name,
295 			  unsigned int size)
296 {
297 	return nfp_abm_ctrl_find_rtsym(pf, name, size * NFP_NET_MAX_RX_RINGS);
298 }
299 
300 int nfp_abm_ctrl_find_addrs(struct nfp_abm *abm)
301 {
302 	struct nfp_pf *pf = abm->app->pf;
303 	const struct nfp_rtsym *sym;
304 	unsigned int pf_id;
305 	char pf_symbol[64];
306 
307 	pf_id =	nfp_cppcore_pcie_unit(pf->cpp);
308 	abm->pf_id = pf_id;
309 
310 	snprintf(pf_symbol, sizeof(pf_symbol), NFP_QLVL_SYM_NAME, pf_id);
311 	sym = nfp_abm_ctrl_find_q_rtsym(pf, pf_symbol, NFP_QLVL_STRIDE);
312 	if (IS_ERR(sym))
313 		return PTR_ERR(sym);
314 	abm->q_lvls = sym;
315 
316 	snprintf(pf_symbol, sizeof(pf_symbol), NFP_QMSTAT_SYM_NAME, pf_id);
317 	sym = nfp_abm_ctrl_find_q_rtsym(pf, pf_symbol, NFP_QMSTAT_STRIDE);
318 	if (IS_ERR(sym))
319 		return PTR_ERR(sym);
320 	abm->qm_stats = sym;
321 
322 	return 0;
323 }
324