1/* SPDX-License-Identifier: BSD-3-Clause */
2/* Copyright(c) 2007-2022 Intel Corporation */
3#include "adf_accel_devices.h"
4#include "adf_common_drv.h"
5#include "adf_dev_err.h"
6#include "adf_freebsd_pfvf_ctrs_dbg.h"
7
8#define MAX_REPORT_LINES (14)
9#define MAX_REPORT_LINE_LEN (64)
10#define MAX_REPORT_SIZE (MAX_REPORT_LINES * MAX_REPORT_LINE_LEN)
11
12static void
13adf_pfvf_ctrs_prepare_report(char *rep, struct pfvf_stats *pfvf_counters)
14{
15	unsigned int value = 0;
16	char *string = "unknown";
17	unsigned int pos = 0;
18	char *ptr = rep;
19
20	for (pos = 0; pos < MAX_REPORT_LINES; pos++) {
21		switch (pos) {
22		case 0:
23			string = "Messages written to CSR";
24			value = pfvf_counters->tx;
25			break;
26		case 1:
27			string = "Messages read from CSR";
28			value = pfvf_counters->rx;
29			break;
30		case 2:
31			string = "Spurious Interrupt";
32			value = pfvf_counters->spurious;
33			break;
34		case 3:
35			string = "Block messages sent";
36			value = pfvf_counters->blk_tx;
37			break;
38		case 4:
39			string = "Block messages received";
40			value = pfvf_counters->blk_rx;
41			break;
42		case 5:
43			string = "Blocks received with CRC errors";
44			value = pfvf_counters->crc_err;
45			break;
46		case 6:
47			string = "CSR in use";
48			value = pfvf_counters->busy;
49			break;
50		case 7:
51			string = "No acknowledgment";
52			value = pfvf_counters->no_ack;
53			break;
54		case 8:
55			string = "Collisions";
56			value = pfvf_counters->collision;
57			break;
58		case 9:
59			string = "Put msg timeout";
60			value = pfvf_counters->tx_timeout;
61			break;
62		case 10:
63			string = "No response received";
64			value = pfvf_counters->rx_timeout;
65			break;
66		case 11:
67			string = "Responses received";
68			value = pfvf_counters->rx_rsp;
69			break;
70		case 12:
71			string = "Messages re-transmitted";
72			value = pfvf_counters->retry;
73			break;
74		case 13:
75			string = "Put event timeout";
76			value = pfvf_counters->event_timeout;
77			break;
78		default:
79			value = 0;
80		}
81		if (value)
82			ptr += snprintf(ptr,
83					(MAX_REPORT_SIZE - (ptr - rep)),
84					"%s %u\n",
85					string,
86					value);
87	}
88}
89
90static int adf_pfvf_ctrs_show(SYSCTL_HANDLER_ARGS)
91{
92	struct pfvf_stats *pfvf_counters = arg1;
93	char report[MAX_REPORT_SIZE];
94
95	if (!pfvf_counters)
96		return EINVAL;
97
98	explicit_bzero(report, sizeof(report));
99	adf_pfvf_ctrs_prepare_report(report, pfvf_counters);
100	sysctl_handle_string(oidp, report, sizeof(report), req);
101	return 0;
102}
103
104int
105adf_pfvf_ctrs_dbg_add(struct adf_accel_dev *accel_dev)
106{
107	struct sysctl_ctx_list *qat_sysctl_ctx;
108	struct sysctl_oid *qat_pfvf_ctrs_sysctl_tree;
109	struct sysctl_oid *oid_pfvf;
110	device_t dev;
111
112	if (!accel_dev || accel_dev->accel_id > ADF_MAX_DEVICES)
113		return EINVAL;
114
115	dev = GET_DEV(accel_dev);
116
117	qat_sysctl_ctx = device_get_sysctl_ctx(dev);
118	qat_pfvf_ctrs_sysctl_tree = device_get_sysctl_tree(dev);
119
120	oid_pfvf = SYSCTL_ADD_PROC(qat_sysctl_ctx,
121				   SYSCTL_CHILDREN(qat_pfvf_ctrs_sysctl_tree),
122				   OID_AUTO,
123				   "pfvf_counters",
124				   CTLTYPE_STRING | CTLFLAG_RD,
125				   &accel_dev->u1.vf.pfvf_counters,
126				   0,
127				   adf_pfvf_ctrs_show,
128				   "A",
129				   "QAT PFVF counters");
130
131	if (!oid_pfvf) {
132		device_printf(dev, "Failure creating PFVF counters sysctl\n");
133		return ENOMEM;
134	}
135	return 0;
136}
137