xref: /freebsd/sys/dev/mana/mana_sysctl.c (revision 9b8701b81f14f0fa0787425eb9761b765d5faab0)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2021 Microsoft Corp.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include <sys/cdefs.h>
31 #include "mana_sysctl.h"
32 
33 static int mana_sysctl_cleanup_thread_cpu(SYSCTL_HANDLER_ARGS);
34 
35 int mana_log_level = MANA_ALERT | MANA_WARNING | MANA_INFO;
36 
37 unsigned int mana_tx_req_size;
38 unsigned int mana_rx_req_size;
39 unsigned int mana_rx_refill_threshold;
40 
41 SYSCTL_NODE(_hw, OID_AUTO, mana, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
42     "MANA driver parameters");
43 
44 SYSCTL_UINT(_hw_mana, OID_AUTO, tx_req_size, CTLFLAG_RWTUN,
45     &mana_tx_req_size, 0, "requested number of unit of tx queue");
46 SYSCTL_UINT(_hw_mana, OID_AUTO, rx_req_size, CTLFLAG_RWTUN,
47     &mana_rx_req_size, 0, "requested number of unit of rx queue");
48 SYSCTL_UINT(_hw_mana, OID_AUTO, rx_refill_thresh, CTLFLAG_RWTUN,
49     &mana_rx_refill_threshold, 0,
50     "number of rx slots before starting the refill");
51 
52 /*
53  * Logging level for changing verbosity of the output
54  */
55 SYSCTL_INT(_hw_mana, OID_AUTO, log_level, CTLFLAG_RWTUN,
56     &mana_log_level, 0, "Logging level indicating verbosity of the logs");
57 
58 SYSCTL_CONST_STRING(_hw_mana, OID_AUTO, driver_version, CTLFLAG_RD,
59     DRV_MODULE_VERSION, "MANA driver version");
60 
61 static int
mana_sysctl_rx_stat_agg_u64(SYSCTL_HANDLER_ARGS)62 mana_sysctl_rx_stat_agg_u64(SYSCTL_HANDLER_ARGS)
63 {
64 	struct mana_port_context *apc = arg1;
65 	int offset = arg2, i, err;
66 	struct mana_rxq *rxq;
67 	uint64_t stat;
68 
69 	stat = 0;
70 	for (i = 0; i < apc->num_queues; i++) {
71 		rxq = apc->rxqs[i];
72 		stat += *((uint64_t *)((uint8_t *)rxq + offset));
73 	}
74 
75 	err = sysctl_handle_64(oidp, &stat, 0, req);
76 	if (err || req->newptr == NULL)
77 		return err;
78 
79 	for (i = 0; i < apc->num_queues; i++) {
80 		rxq = apc->rxqs[i];
81 		*((uint64_t *)((uint8_t *)rxq + offset)) = 0;
82 	}
83 	return 0;
84 }
85 
86 static int
mana_sysctl_rx_stat_u16(SYSCTL_HANDLER_ARGS)87 mana_sysctl_rx_stat_u16(SYSCTL_HANDLER_ARGS)
88 {
89 	struct mana_port_context *apc = arg1;
90 	int offset = arg2, err;
91 	struct mana_rxq *rxq;
92 	uint64_t stat;
93 	uint16_t val;
94 
95 	rxq = apc->rxqs[0];
96 	val = *((uint16_t *)((uint8_t *)rxq + offset));
97 	stat = val;
98 
99 	err = sysctl_handle_64(oidp, &stat, 0, req);
100 	if (err || req->newptr == NULL)
101 		return err;
102 	else
103 		return 0;
104 }
105 
106 static int
mana_sysctl_rx_stat_u32(SYSCTL_HANDLER_ARGS)107 mana_sysctl_rx_stat_u32(SYSCTL_HANDLER_ARGS)
108 {
109 	struct mana_port_context *apc = arg1;
110 	int offset = arg2, err;
111 	struct mana_rxq *rxq;
112 	uint64_t stat;
113 	uint32_t val;
114 
115 	rxq = apc->rxqs[0];
116 	val = *((uint32_t *)((uint8_t *)rxq + offset));
117 	stat = val;
118 
119 	err = sysctl_handle_64(oidp, &stat, 0, req);
120 	if (err || req->newptr == NULL)
121 		return err;
122 	else
123 		return 0;
124 }
125 
126 static int
mana_sysctl_tx_stat_agg_u64(SYSCTL_HANDLER_ARGS)127 mana_sysctl_tx_stat_agg_u64(SYSCTL_HANDLER_ARGS)
128 {
129 	struct mana_port_context *apc = arg1;
130 	int offset = arg2, i, err;
131 	struct mana_txq *txq;
132 	uint64_t stat;
133 
134 	stat = 0;
135 	for (i = 0; i < apc->num_queues; i++) {
136 		txq = &apc->tx_qp[i].txq;
137 		stat += *((uint64_t *)((uint8_t *)txq + offset));
138 	}
139 
140 	err = sysctl_handle_64(oidp, &stat, 0, req);
141 	if (err || req->newptr == NULL)
142 		return err;
143 
144 	for (i = 0; i < apc->num_queues; i++) {
145 		txq = &apc->tx_qp[i].txq;
146 		*((uint64_t *)((uint8_t *)txq + offset)) = 0;
147 	}
148 	return 0;
149 }
150 
151 void
mana_sysctl_add_port(struct mana_port_context * apc)152 mana_sysctl_add_port(struct mana_port_context *apc)
153 {
154 	struct gdma_context *gc = apc->ac->gdma_dev->gdma_context;
155 	device_t dev = gc->dev;
156 	struct sysctl_ctx_list *ctx;
157 	struct sysctl_oid *tree;
158 	struct sysctl_oid_list *child;
159 	struct mana_port_stats *port_stats;
160 	char node_name[32];
161 
162 	struct sysctl_oid *port_node, *stats_node;
163 	struct sysctl_oid_list *stats_list;
164 
165 	ctx = device_get_sysctl_ctx(dev);
166 	tree = device_get_sysctl_tree(dev);
167 	child = SYSCTL_CHILDREN(tree);
168 
169 	port_stats = &apc->port_stats;
170 
171 	snprintf(node_name, 32, "port%d", apc->port_idx);
172 
173 	port_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO,
174 	    node_name, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Port Name");
175 	apc->port_list = SYSCTL_CHILDREN(port_node);
176 
177 	SYSCTL_ADD_BOOL(ctx, apc->port_list, OID_AUTO,
178 	    "enable_altq", CTLFLAG_RW, &apc->enable_tx_altq, 0,
179 	    "Choose alternative txq under heavy load");
180 
181 	SYSCTL_ADD_UINT(ctx, apc->port_list, OID_AUTO,
182 	    "tx_queue_size", CTLFLAG_RD, &apc->tx_queue_size, 0,
183 	    "number of unit of tx queue");
184 
185 	SYSCTL_ADD_UINT(ctx, apc->port_list, OID_AUTO,
186 	    "rx_queue_size", CTLFLAG_RD, &apc->rx_queue_size, 0,
187 	    "number of unit of rx queue");
188 
189 	SYSCTL_ADD_PROC(ctx, apc->port_list, OID_AUTO,
190 	    "bind_cleanup_thread_cpu",
191 	    CTLTYPE_U8 | CTLFLAG_RW | CTLFLAG_MPSAFE,
192 	    apc, 0, mana_sysctl_cleanup_thread_cpu, "I",
193 	    "Bind cleanup thread to a cpu. 0 disables it.");
194 
195 	stats_node = SYSCTL_ADD_NODE(ctx, apc->port_list, OID_AUTO,
196 	    "port_stats", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
197 	    "Statistics of port");
198 	stats_list = SYSCTL_CHILDREN(stats_node);
199 
200 	SYSCTL_ADD_COUNTER_U64(ctx, stats_list, OID_AUTO, "rx_packets",
201 	    CTLFLAG_RD, &port_stats->rx_packets, "Packets received");
202 	SYSCTL_ADD_COUNTER_U64(ctx, stats_list, OID_AUTO, "tx_packets",
203 	    CTLFLAG_RD, &port_stats->tx_packets, "Packets transmitted");
204 	SYSCTL_ADD_COUNTER_U64(ctx, stats_list, OID_AUTO, "rx_bytes",
205 	    CTLFLAG_RD, &port_stats->rx_bytes, "Bytes received");
206 	SYSCTL_ADD_COUNTER_U64(ctx, stats_list, OID_AUTO, "tx_bytes",
207 	    CTLFLAG_RD, &port_stats->tx_bytes, "Bytes transmitted");
208 	SYSCTL_ADD_COUNTER_U64(ctx, stats_list, OID_AUTO, "rx_drops",
209 	    CTLFLAG_RD, &port_stats->rx_drops, "Receive packet drops");
210 	SYSCTL_ADD_COUNTER_U64(ctx, stats_list, OID_AUTO, "tx_drops",
211 	    CTLFLAG_RD, &port_stats->tx_drops, "Transmit packet drops");
212 
213 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "rx_lro_queued",
214 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_STATS, apc,
215 	    __offsetof(struct mana_rxq, lro.lro_queued),
216 	    mana_sysctl_rx_stat_agg_u64, "LU", "LRO queued");
217 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "rx_lro_flushed",
218 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_STATS, apc,
219 	    __offsetof(struct mana_rxq, lro.lro_flushed),
220 	    mana_sysctl_rx_stat_agg_u64, "LU", "LRO flushed");
221 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "rx_lro_bad_csum",
222 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_STATS, apc,
223 	    __offsetof(struct mana_rxq, lro.lro_bad_csum),
224 	    mana_sysctl_rx_stat_agg_u64, "LU", "LRO bad checksum");
225 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "rx_lro_tried",
226 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, apc,
227 	    __offsetof(struct mana_rxq, lro_tried),
228 	    mana_sysctl_rx_stat_agg_u64, "LU", "LRO tried");
229 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "rx_lro_failed",
230 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, apc,
231 	    __offsetof(struct mana_rxq, lro_failed),
232 	    mana_sysctl_rx_stat_agg_u64, "LU", "LRO failed");
233 
234 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "lro_ackcnt_lim",
235 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, apc,
236 	    __offsetof(struct mana_rxq, lro.lro_ackcnt_lim),
237 	    mana_sysctl_rx_stat_u16,
238 	    "LU", "Max # of ACKs to be aggregated by LRO");
239 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "lro_length_lim",
240 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, apc,
241 	    __offsetof(struct mana_rxq, lro.lro_length_lim),
242 	    mana_sysctl_rx_stat_u32,
243 	    "LU", "Max len of aggregated data in byte by LRO");
244 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "lro_cnt",
245 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, apc,
246 	    __offsetof(struct mana_rxq, lro.lro_cnt),
247 	    mana_sysctl_rx_stat_u32,
248 	    "LU", "Max # or LRO packet count");
249 
250 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "tx_tso_packets",
251 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, apc,
252 	    __offsetof(struct mana_txq, tso_pkts),
253 	    mana_sysctl_tx_stat_agg_u64, "LU", "TSO packets");
254 	SYSCTL_ADD_PROC(ctx, stats_list, OID_AUTO, "tx_tso_bytes",
255 	    CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, apc,
256 	    __offsetof(struct mana_txq, tso_bytes),
257 	    mana_sysctl_tx_stat_agg_u64, "LU", "TSO bytes");
258 }
259 
260 void
mana_sysctl_add_queues(struct mana_port_context * apc)261 mana_sysctl_add_queues(struct mana_port_context *apc)
262 {
263 	struct sysctl_ctx_list *ctx = &apc->que_sysctl_ctx;
264 	struct sysctl_oid_list *child = apc->port_list;
265 
266 	struct sysctl_oid *queue_node, *tx_node, *rx_node;
267 	struct sysctl_oid_list *queue_list, *tx_list, *rx_list;
268 	struct mana_txq *txq;
269 	struct mana_rxq *rxq;
270 	struct mana_stats *tx_stats, *rx_stats;
271 	char que_name[32];
272 	int i;
273 
274 	sysctl_ctx_init(ctx);
275 
276 	for (i = 0; i < apc->num_queues; i++) {
277 		rxq = apc->rxqs[i];
278 		txq = &apc->tx_qp[i].txq;
279 
280 		snprintf(que_name, 32, "queue%d", i);
281 
282 		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO,
283 		    que_name, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name");
284 		queue_list = SYSCTL_CHILDREN(queue_node);
285 
286 		/* TX stats */
287 		tx_node = SYSCTL_ADD_NODE(ctx, queue_list, OID_AUTO,
288 		    "txq", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "TX queue");
289 		tx_list = SYSCTL_CHILDREN(tx_node);
290 
291 		tx_stats = &txq->stats;
292 
293 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO, "count",
294 		    CTLFLAG_RD, &tx_stats->packets, "Packets sent");
295 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO, "bytes",
296 		    CTLFLAG_RD, &tx_stats->bytes, "Bytes sent");
297 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO, "queue_wakeups",
298 		    CTLFLAG_RD, &tx_stats->wakeup, "Queue wakeups");
299 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO, "queue_stops",
300 		    CTLFLAG_RD, &tx_stats->stop, "Queue stops");
301 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO, "mbuf_collapse",
302 		    CTLFLAG_RD, &tx_stats->collapse, "Mbuf collapse count");
303 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
304 		    "mbuf_collapse_err", CTLFLAG_RD,
305 		    &tx_stats->collapse_err, "Mbuf collapse failures");
306 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
307 		    "dma_mapping_err", CTLFLAG_RD,
308 		    &tx_stats->dma_mapping_err, "DMA mapping failures");
309 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
310 		    "alt_chg", CTLFLAG_RD,
311 		    &tx_stats->alt_chg, "Switch to alternative txq");
312 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
313 		    "alt_reset", CTLFLAG_RD,
314 		    &tx_stats->alt_reset, "Reset to self txq");
315 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
316 		    "cqe_err", CTLFLAG_RD,
317 		    &tx_stats->cqe_err, "Error CQE count");
318 		SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
319 		    "cqe_unknown_type", CTLFLAG_RD,
320 		    &tx_stats->cqe_unknown_type, "Unknown CQE count");
321 
322 		/* RX stats */
323 		rx_node = SYSCTL_ADD_NODE(ctx, queue_list, OID_AUTO,
324 		    "rxq", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "RX queue");
325 		rx_list = SYSCTL_CHILDREN(rx_node);
326 
327 		rx_stats = &rxq->stats;
328 
329 		SYSCTL_ADD_COUNTER_U64(ctx, rx_list, OID_AUTO, "count",
330 		    CTLFLAG_RD, &rx_stats->packets, "Packets received");
331 		SYSCTL_ADD_COUNTER_U64(ctx, rx_list, OID_AUTO, "bytes",
332 		    CTLFLAG_RD, &rx_stats->bytes, "Bytes received");
333 		SYSCTL_ADD_COUNTER_U64(ctx, rx_list, OID_AUTO,
334 		    "mbuf_alloc_fail", CTLFLAG_RD,
335 		    &rx_stats->mbuf_alloc_fail, "Failed mbuf allocs");
336 		SYSCTL_ADD_COUNTER_U64(ctx, rx_list, OID_AUTO,
337 		    "partial_refill", CTLFLAG_RD,
338 		    &rx_stats->partial_refill, "Partially refilled mbuf");
339 		SYSCTL_ADD_COUNTER_U64(ctx, rx_list, OID_AUTO,
340 		    "dma_mapping_err", CTLFLAG_RD,
341 		    &rx_stats->dma_mapping_err, "DMA mapping errors");
342 	}
343 }
344 
345 /*
346  * Free all queues' sysctl trees attached to the port's tree.
347  */
348 void
mana_sysctl_free_queues(struct mana_port_context * apc)349 mana_sysctl_free_queues(struct mana_port_context *apc)
350 {
351 	sysctl_ctx_free(&apc->que_sysctl_ctx);
352 }
353 
354 static int
mana_sysctl_cleanup_thread_cpu(SYSCTL_HANDLER_ARGS)355 mana_sysctl_cleanup_thread_cpu(SYSCTL_HANDLER_ARGS)
356 {
357 	struct mana_port_context *apc = arg1;
358 	bool bind_cpu = false;
359 	uint8_t val;
360 	int err;
361 
362 	val = 0;
363 	err = sysctl_wire_old_buffer(req, sizeof(val));
364 	if (err == 0) {
365 		val = apc->bind_cleanup_thread_cpu;
366 		err = sysctl_handle_8(oidp, &val, 0, req);
367 	}
368 
369 	if (err != 0 || req->newptr == NULL)
370 		return (err);
371 
372 	if (val != 0)
373 		bind_cpu = true;
374 
375 	if (bind_cpu != apc->bind_cleanup_thread_cpu) {
376 		apc->bind_cleanup_thread_cpu = bind_cpu;
377 		err = mana_restart(apc);
378 	}
379 
380 	return (err);
381 }
382