netfilter: netns: shrink netns_ct struct
[linux-2.6-microblaze.git] / drivers / net / ethernet / netronome / nfp / abm / ctrl.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2018 Netronome Systems, Inc. */
3
4 #include <linux/kernel.h>
5
6 #include "../nfpcore/nfp_cpp.h"
7 #include "../nfpcore/nfp_nffw.h"
8 #include "../nfp_app.h"
9 #include "../nfp_abi.h"
10 #include "../nfp_main.h"
11 #include "../nfp_net.h"
12 #include "main.h"
13
14 #define NFP_QLVL_SYM_NAME       "_abi_nfd_out_q_lvls_%u"
15 #define NFP_QLVL_STRIDE         16
16 #define NFP_QLVL_BLOG_BYTES     0
17 #define NFP_QLVL_BLOG_PKTS      4
18 #define NFP_QLVL_THRS           8
19
20 #define NFP_QMSTAT_SYM_NAME     "_abi_nfdqm%u_stats"
21 #define NFP_QMSTAT_STRIDE       32
22 #define NFP_QMSTAT_NON_STO      0
23 #define NFP_QMSTAT_STO          8
24 #define NFP_QMSTAT_DROP         16
25 #define NFP_QMSTAT_ECN          24
26
27 static int
28 nfp_abm_ctrl_stat(struct nfp_abm_link *alink, const struct nfp_rtsym *sym,
29                   unsigned int stride, unsigned int offset, unsigned int i,
30                   bool is_u64, u64 *res)
31 {
32         struct nfp_cpp *cpp = alink->abm->app->cpp;
33         u64 val, sym_offset;
34         u32 val32;
35         int err;
36
37         sym_offset = (alink->queue_base + i) * stride + offset;
38         if (is_u64)
39                 err = __nfp_rtsym_readq(cpp, sym, 3, 0, sym_offset, &val);
40         else
41                 err = __nfp_rtsym_readl(cpp, sym, 3, 0, sym_offset, &val32);
42         if (err) {
43                 nfp_err(cpp,
44                         "RED offload reading stat failed on vNIC %d queue %d\n",
45                         alink->id, i);
46                 return err;
47         }
48
49         *res = is_u64 ? val : val32;
50         return 0;
51 }
52
53 static int
54 nfp_abm_ctrl_stat_all(struct nfp_abm_link *alink, const struct nfp_rtsym *sym,
55                       unsigned int stride, unsigned int offset, bool is_u64,
56                       u64 *res)
57 {
58         u64 val, sum = 0;
59         unsigned int i;
60         int err;
61
62         for (i = 0; i < alink->vnic->max_rx_rings; i++) {
63                 err = nfp_abm_ctrl_stat(alink, sym, stride, offset, i,
64                                         is_u64, &val);
65                 if (err)
66                         return err;
67                 sum += val;
68         }
69
70         *res = sum;
71         return 0;
72 }
73
74 int nfp_abm_ctrl_set_q_lvl(struct nfp_abm_link *alink, unsigned int i, u32 val)
75 {
76         struct nfp_cpp *cpp = alink->abm->app->cpp;
77         u64 sym_offset;
78         int err;
79
80         sym_offset = (alink->queue_base + i) * NFP_QLVL_STRIDE + NFP_QLVL_THRS;
81         err = __nfp_rtsym_writel(cpp, alink->abm->q_lvls, 4, 0,
82                                  sym_offset, val);
83         if (err) {
84                 nfp_err(cpp, "RED offload setting level failed on vNIC %d queue %d\n",
85                         alink->id, i);
86                 return err;
87         }
88
89         return 0;
90 }
91
92 int nfp_abm_ctrl_set_all_q_lvls(struct nfp_abm_link *alink, u32 val)
93 {
94         int i, err;
95
96         for (i = 0; i < alink->vnic->max_rx_rings; i++) {
97                 err = nfp_abm_ctrl_set_q_lvl(alink, i, val);
98                 if (err)
99                         return err;
100         }
101
102         return 0;
103 }
104
105 u64 nfp_abm_ctrl_stat_non_sto(struct nfp_abm_link *alink, unsigned int i)
106 {
107         u64 val;
108
109         if (nfp_abm_ctrl_stat(alink, alink->abm->qm_stats, NFP_QMSTAT_STRIDE,
110                               NFP_QMSTAT_NON_STO, i, true, &val))
111                 return 0;
112         return val;
113 }
114
115 u64 nfp_abm_ctrl_stat_sto(struct nfp_abm_link *alink, unsigned int i)
116 {
117         u64 val;
118
119         if (nfp_abm_ctrl_stat(alink, alink->abm->qm_stats, NFP_QMSTAT_STRIDE,
120                               NFP_QMSTAT_STO, i, true, &val))
121                 return 0;
122         return val;
123 }
124
125 int nfp_abm_ctrl_read_q_stats(struct nfp_abm_link *alink, unsigned int i,
126                               struct nfp_alink_stats *stats)
127 {
128         int err;
129
130         stats->tx_pkts = nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i));
131         stats->tx_bytes = nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i) + 8);
132
133         err = nfp_abm_ctrl_stat(alink, alink->abm->q_lvls,
134                                 NFP_QLVL_STRIDE, NFP_QLVL_BLOG_BYTES,
135                                 i, false, &stats->backlog_bytes);
136         if (err)
137                 return err;
138
139         err = nfp_abm_ctrl_stat(alink, alink->abm->q_lvls,
140                                 NFP_QLVL_STRIDE, NFP_QLVL_BLOG_PKTS,
141                                 i, false, &stats->backlog_pkts);
142         if (err)
143                 return err;
144
145         err = nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
146                                 NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
147                                 i, true, &stats->drops);
148         if (err)
149                 return err;
150
151         return nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
152                                  NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
153                                  i, true, &stats->overlimits);
154 }
155
156 int nfp_abm_ctrl_read_stats(struct nfp_abm_link *alink,
157                             struct nfp_alink_stats *stats)
158 {
159         u64 pkts = 0, bytes = 0;
160         int i, err;
161
162         for (i = 0; i < alink->vnic->max_rx_rings; i++) {
163                 pkts += nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i));
164                 bytes += nn_readq(alink->vnic, NFP_NET_CFG_RXR_STATS(i) + 8);
165         }
166         stats->tx_pkts = pkts;
167         stats->tx_bytes = bytes;
168
169         err = nfp_abm_ctrl_stat_all(alink, alink->abm->q_lvls,
170                                     NFP_QLVL_STRIDE, NFP_QLVL_BLOG_BYTES,
171                                     false, &stats->backlog_bytes);
172         if (err)
173                 return err;
174
175         err = nfp_abm_ctrl_stat_all(alink, alink->abm->q_lvls,
176                                     NFP_QLVL_STRIDE, NFP_QLVL_BLOG_PKTS,
177                                     false, &stats->backlog_pkts);
178         if (err)
179                 return err;
180
181         err = nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
182                                     NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
183                                     true, &stats->drops);
184         if (err)
185                 return err;
186
187         return nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
188                                      NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
189                                      true, &stats->overlimits);
190 }
191
192 int nfp_abm_ctrl_read_q_xstats(struct nfp_abm_link *alink, unsigned int i,
193                                struct nfp_alink_xstats *xstats)
194 {
195         int err;
196
197         err = nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
198                                 NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
199                                 i, true, &xstats->pdrop);
200         if (err)
201                 return err;
202
203         return nfp_abm_ctrl_stat(alink, alink->abm->qm_stats,
204                                  NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
205                                  i, true, &xstats->ecn_marked);
206 }
207
208 int nfp_abm_ctrl_read_xstats(struct nfp_abm_link *alink,
209                              struct nfp_alink_xstats *xstats)
210 {
211         int err;
212
213         err = nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
214                                     NFP_QMSTAT_STRIDE, NFP_QMSTAT_DROP,
215                                     true, &xstats->pdrop);
216         if (err)
217                 return err;
218
219         return nfp_abm_ctrl_stat_all(alink, alink->abm->qm_stats,
220                                      NFP_QMSTAT_STRIDE, NFP_QMSTAT_ECN,
221                                      true, &xstats->ecn_marked);
222 }
223
224 int nfp_abm_ctrl_qm_enable(struct nfp_abm *abm)
225 {
226         return nfp_mbox_cmd(abm->app->pf, NFP_MBOX_PCIE_ABM_ENABLE,
227                             NULL, 0, NULL, 0);
228 }
229
230 int nfp_abm_ctrl_qm_disable(struct nfp_abm *abm)
231 {
232         return nfp_mbox_cmd(abm->app->pf, NFP_MBOX_PCIE_ABM_DISABLE,
233                             NULL, 0, NULL, 0);
234 }
235
236 void nfp_abm_ctrl_read_params(struct nfp_abm_link *alink)
237 {
238         alink->queue_base = nn_readl(alink->vnic, NFP_NET_CFG_START_RXQ);
239         alink->queue_base /= alink->vnic->stride_rx;
240 }
241
242 static const struct nfp_rtsym *
243 nfp_abm_ctrl_find_rtsym(struct nfp_pf *pf, const char *name, unsigned int size)
244 {
245         const struct nfp_rtsym *sym;
246
247         sym = nfp_rtsym_lookup(pf->rtbl, name);
248         if (!sym) {
249                 nfp_err(pf->cpp, "Symbol '%s' not found\n", name);
250                 return ERR_PTR(-ENOENT);
251         }
252         if (nfp_rtsym_size(sym) != size) {
253                 nfp_err(pf->cpp,
254                         "Symbol '%s' wrong size: expected %u got %llu\n",
255                         name, size, nfp_rtsym_size(sym));
256                 return ERR_PTR(-EINVAL);
257         }
258
259         return sym;
260 }
261
262 static const struct nfp_rtsym *
263 nfp_abm_ctrl_find_q_rtsym(struct nfp_pf *pf, const char *name,
264                           unsigned int size)
265 {
266         return nfp_abm_ctrl_find_rtsym(pf, name, size * NFP_NET_MAX_RX_RINGS);
267 }
268
269 int nfp_abm_ctrl_find_addrs(struct nfp_abm *abm)
270 {
271         struct nfp_pf *pf = abm->app->pf;
272         const struct nfp_rtsym *sym;
273         unsigned int pf_id;
274         char pf_symbol[64];
275
276         pf_id = nfp_cppcore_pcie_unit(pf->cpp);
277         abm->pf_id = pf_id;
278
279         snprintf(pf_symbol, sizeof(pf_symbol), NFP_QLVL_SYM_NAME, pf_id);
280         sym = nfp_abm_ctrl_find_q_rtsym(pf, pf_symbol, NFP_QLVL_STRIDE);
281         if (IS_ERR(sym))
282                 return PTR_ERR(sym);
283         abm->q_lvls = sym;
284
285         snprintf(pf_symbol, sizeof(pf_symbol), NFP_QMSTAT_SYM_NAME, pf_id);
286         sym = nfp_abm_ctrl_find_q_rtsym(pf, pf_symbol, NFP_QMSTAT_STRIDE);
287         if (IS_ERR(sym))
288                 return PTR_ERR(sym);
289         abm->qm_stats = sym;
290
291         return 0;
292 }