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