xref: /illumos-gate/usr/src/uts/common/crypto/io/dca_kstat.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Deimos - cryptographic acceleration based upon Broadcom 582x.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/ddi.h>
35 #include <sys/sunddi.h>
36 #include <sys/kstat.h>
37 #include <sys/crypto/dca.h>
38 
39 /*
40  * Kernel statistics.
41  */
42 static int dca_ksupdate(kstat_t *, int);
43 
44 /*
45  * Initialize Kstats.
46  */
47 void
48 dca_ksinit(dca_t *dca)
49 {
50 	char	buf[64];
51 	int	instance;
52 
53 	if (ddi_getprop(DDI_DEV_T_ANY, dca->dca_dip,
54 	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "nostats", 0) != 0) {
55 		/*
56 		 * sysadmin has explicity disabled stats to prevent
57 		 * covert channel.
58 		 */
59 		return;
60 	}
61 
62 	instance = ddi_get_instance(dca->dca_dip);
63 
64 	/*
65 	 * Interrupt kstats.
66 	 */
67 	(void) sprintf(buf, "%sc%d", DRIVER, instance);
68 	if ((dca->dca_intrstats = kstat_create(DRIVER, instance, buf,
69 	    "controller", KSTAT_TYPE_INTR, 1, 0)) == NULL) {
70 		dca_error(dca, "unable to create interrupt kstat");
71 	} else {
72 		kstat_install(dca->dca_intrstats);
73 	}
74 
75 	/*
76 	 * Named kstats.
77 	 */
78 	if ((dca->dca_ksp = kstat_create(DRIVER, instance, NULL, "misc",
79 	    KSTAT_TYPE_NAMED, sizeof (dca_stat_t) / sizeof (kstat_named_t),
80 	    KSTAT_FLAG_WRITABLE)) == NULL) {
81 		dca_error(dca, "unable to create kstats");
82 	} else {
83 		dca_stat_t *dkp = (dca_stat_t *)dca->dca_ksp->ks_data;
84 		kstat_named_init(&dkp->ds_status, "status", KSTAT_DATA_CHAR);
85 		kstat_named_init(&dkp->ds_mcr[0].ds_submit, "mcr1submit",
86 		    KSTAT_DATA_ULONGLONG);
87 		kstat_named_init(&dkp->ds_mcr[0].ds_flowctl, "mcr1flowctl",
88 		    KSTAT_DATA_ULONGLONG);
89 		kstat_named_init(&dkp->ds_mcr[0].ds_lowater, "mcr1lowater",
90 		    KSTAT_DATA_ULONGLONG);
91 		kstat_named_init(&dkp->ds_mcr[0].ds_hiwater, "mcr1hiwater",
92 		    KSTAT_DATA_ULONGLONG);
93 		kstat_named_init(&dkp->ds_mcr[0].ds_maxreqs, "mcr1maxreqs",
94 		    KSTAT_DATA_ULONGLONG);
95 		kstat_named_init(&dkp->ds_mcr[1].ds_submit, "mcr2submit",
96 		    KSTAT_DATA_ULONGLONG);
97 		kstat_named_init(&dkp->ds_mcr[1].ds_flowctl, "mcr2flowctl",
98 		    KSTAT_DATA_ULONGLONG);
99 		kstat_named_init(&dkp->ds_mcr[1].ds_lowater, "mcr2lowater",
100 		    KSTAT_DATA_ULONGLONG);
101 		kstat_named_init(&dkp->ds_mcr[1].ds_hiwater, "mcr2hiwater",
102 		    KSTAT_DATA_ULONGLONG);
103 		kstat_named_init(&dkp->ds_mcr[1].ds_maxreqs, "mcr2maxreqs",
104 		    KSTAT_DATA_ULONGLONG);
105 #ifdef	DS_RC4JOBS
106 		/* rc4 */
107 		kstat_named_init(&dkp->ds_algs[DS_RC4JOBS], "rc4jobs",
108 		    KSTAT_DATA_ULONGLONG);
109 #endif
110 #ifdef	DS_RC4BYTES
111 		kstat_named_init(&dkp->ds_algs[DS_RC4BYTES], "rc4bytes",
112 		    KSTAT_DATA_ULONGLONG);
113 #endif
114 		/* 3des */
115 		kstat_named_init(&dkp->ds_algs[DS_3DESJOBS], "3desjobs",
116 		    KSTAT_DATA_ULONGLONG);
117 		kstat_named_init(&dkp->ds_algs[DS_3DESBYTES], "3desbytes",
118 		    KSTAT_DATA_ULONGLONG);
119 		/* rsa */
120 		kstat_named_init(&dkp->ds_algs[DS_RSAPUBLIC], "rsapublic",
121 		    KSTAT_DATA_ULONGLONG);
122 		kstat_named_init(&dkp->ds_algs[DS_RSAPRIVATE], "rsaprivate",
123 		    KSTAT_DATA_ULONGLONG);
124 		/* dsa */
125 		kstat_named_init(&dkp->ds_algs[DS_DSASIGN], "dsasign",
126 		    KSTAT_DATA_ULONGLONG);
127 		kstat_named_init(&dkp->ds_algs[DS_DSAVERIFY], "dsaverify",
128 		    KSTAT_DATA_ULONGLONG);
129 #ifdef	DS_DHPUBLIC
130 		/* diffie-hellman */
131 		kstat_named_init(&dkp->ds_algs[DS_DHPUBLIC], "dhpublic",
132 		    KSTAT_DATA_ULONGLONG);
133 #endif
134 #ifdef	DS_DHSECRET
135 		kstat_named_init(&dkp->ds_algs[DS_DHSECRET], "dhsecret",
136 		    KSTAT_DATA_ULONGLONG);
137 #endif
138 		/* random number jobs */
139 		kstat_named_init(&dkp->ds_algs[DS_RNGJOBS], "rngjobs",
140 		    KSTAT_DATA_ULONGLONG);
141 		kstat_named_init(&dkp->ds_algs[DS_RNGBYTES], "rngbytes",
142 		    KSTAT_DATA_ULONGLONG);
143 		kstat_named_init(&dkp->ds_algs[DS_RNGSHA1JOBS], "rngsha1jobs",
144 		    KSTAT_DATA_ULONGLONG);
145 		kstat_named_init(&dkp->ds_algs[DS_RNGSHA1BYTES],
146 		    "rngsha1bytes", KSTAT_DATA_ULONGLONG);
147 		dca->dca_ksp->ks_update = dca_ksupdate;
148 		dca->dca_ksp->ks_private = dca;
149 		kstat_install(dca->dca_ksp);
150 	}
151 }
152 
153 /*
154  * Update Kstats.
155  */
156 int
157 dca_ksupdate(kstat_t *ksp, int rw)
158 {
159 	dca_t		*dca;
160 	dca_stat_t	*dkp;
161 	int		i;
162 
163 	dca = (dca_t *)ksp->ks_private;
164 	dkp = (dca_stat_t *)ksp->ks_data;
165 
166 	if (rw == KSTAT_WRITE) {
167 		for (i = 0; i < DS_MAX; i++) {
168 			dca->dca_stats[i] = dkp->ds_algs[i].value.ull;
169 		}
170 		for (i = MCR1; i <= MCR2; i++) {
171 			WORKLIST(dca, i)->dwl_submit =
172 			    dkp->ds_mcr[i - 1].ds_submit.value.ull;
173 			WORKLIST(dca, i)->dwl_flowctl =
174 			    dkp->ds_mcr[i - 1].ds_flowctl.value.ull;
175 			/* hiwater, lowater, and maxreqs are read only */
176 		}
177 	} else {
178 		/* handy status value */
179 		if (dca->dca_flags & DCA_FAILED) {
180 			/* device has failed */
181 			(void) strcpy(dkp->ds_status.value.c, "fail");
182 		} else if ((WORKLIST(dca, MCR1)->dwl_drain) ||
183 		    (WORKLIST(dca, MCR2)->dwl_drain)) {
184 			/* device is draining for DR */
185 			(void) strcpy(dkp->ds_status.value.c, "drain");
186 		} else {
187 			/* everything looks good */
188 			(void) strcpy(dkp->ds_status.value.c, "online");
189 		}
190 
191 		for (i = 0; i < DS_MAX; i++) {
192 			dkp->ds_algs[i].value.ull = dca->dca_stats[i];
193 		}
194 		for (i = MCR1; i <= MCR2; i++) {
195 			dkp->ds_mcr[i - 1].ds_submit.value.ull =
196 			    WORKLIST(dca, i)->dwl_submit;
197 			dkp->ds_mcr[i - 1].ds_flowctl.value.ull =
198 			    WORKLIST(dca, i)->dwl_flowctl;
199 			dkp->ds_mcr[i - 1].ds_lowater.value.ull =
200 			    WORKLIST(dca, i)->dwl_lowater;
201 			dkp->ds_mcr[i - 1].ds_hiwater.value.ull =
202 			    WORKLIST(dca, i)->dwl_hiwater;
203 			dkp->ds_mcr[i - 1].ds_maxreqs.value.ull =
204 			    WORKLIST(dca, i)->dwl_reqspermcr;
205 		}
206 	}
207 	return (0);
208 }
209