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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 /* 29 * Driver interconnect for the N2 PIU performance counter driver. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/ddi.h> 34 #include <sys/modctl.h> 35 #include <sys/hsvc.h> 36 #include <n2piupc_tables.h> 37 #include <n2piupc.h> 38 39 /* Debugging level. */ 40 #ifdef DEBUG 41 int n2piupc_debug = 0; 42 #endif /* DEBUG */ 43 44 /* State structure anchor. */ 45 void *n2piupc_state_p; 46 47 static int n2piupc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 48 static int n2piupc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 49 50 /* 51 * Support for hypervisor versioning. 52 * Need to negotiate for the N2PIU_PERF_COUNTER_GROUP 53 */ 54 55 #define N2PIUPC_REQ_MAJOR_VER 1 56 #define N2PIUPC_REQ_MINOR_VER 0 57 58 static hsvc_info_t n2piupc_hsvc = { 59 HSVC_REV_1, 60 NULL, 61 N2PIU_PERF_COUNTER_GROUP_ID, 62 N2PIUPC_REQ_MAJOR_VER, 63 N2PIUPC_REQ_MINOR_VER, 64 MODULE_NAME /* Passed in as a #define from Makefile */ 65 }; 66 67 static uint64_t n2piupc_sup_minor; 68 69 /* Driver boilerplate stuff. Having no minor nodes keep things very simple. */ 70 71 static struct dev_ops n2piupc_ops = { 72 DEVO_REV, 73 0, 74 nulldev, 75 nulldev, 76 nulldev, 77 n2piupc_attach, 78 n2piupc_detach, 79 nodev, 80 NULL, 81 NULL, 82 nodev, 83 ddi_quiesce_not_needed, 84 }; 85 86 extern struct mod_ops mod_driverops; 87 88 static struct modldrv md = { 89 &mod_driverops, 90 "N2 PIU Perf Counter", 91 &n2piupc_ops, 92 }; 93 94 static struct modlinkage ml = { 95 MODREV_1, 96 (void *)&md, 97 NULL 98 }; 99 100 101 /* 102 * One-time module-wide initialization. 103 */ 104 int 105 _init(void) 106 { 107 int rval; 108 109 /* Negotiate for hypervisor support. */ 110 if ((rval = hsvc_register(&n2piupc_hsvc, &n2piupc_sup_minor)) != 111 DDI_SUCCESS) { 112 N2PIUPC_DBG1("%s: Could not hsvc_register: %d\n", 113 MODULE_NAME, rval); 114 goto bad_hv_register; 115 } 116 117 /* Initialize per-leaf soft state pointer. */ 118 if ((rval = ddi_soft_state_init(&n2piupc_state_p, 119 sizeof (n2piupc_t), 1)) != DDI_SUCCESS) 120 goto bad_softstate_init; 121 122 /* Initialize one-time kstat structures. */ 123 if ((rval = n2piupc_kstat_init()) != DDI_SUCCESS) 124 goto bad_kstat_init; 125 126 /* If all checks out, install the module. */ 127 if ((rval = mod_install(&ml)) == DDI_SUCCESS) 128 129 return (DDI_SUCCESS); 130 131 bad_mod_install: 132 n2piupc_kstat_fini(); 133 bad_kstat_init: 134 ddi_soft_state_fini(&n2piupc_state_p); 135 bad_softstate_init: 136 (void) hsvc_unregister(&n2piupc_hsvc); 137 bad_hv_register: 138 return (rval); 139 } 140 141 /* 142 * One-time module-wide cleanup, after last detach is done. 143 */ 144 int 145 _fini(void) 146 { 147 int rval; 148 149 /* 150 * Remove the module first as this operation is the only thing here 151 * which can fail. 152 */ 153 rval = mod_remove(&ml); 154 if (rval != DDI_SUCCESS) 155 return (rval); 156 157 /* One-shot kstat data structure cleanup. */ 158 n2piupc_kstat_fini(); 159 160 /* Free px soft state */ 161 ddi_soft_state_fini(&n2piupc_state_p); 162 163 /* Unregister with hypervisor. */ 164 (void) hsvc_unregister(&n2piupc_hsvc); 165 166 return (rval); 167 } 168 169 int 170 _info(struct modinfo *modinfop) 171 { 172 return (mod_info(&ml, modinfop)); 173 } 174 175 /* 176 * Per-instance initialization. Suspend/resume not supported. 177 */ 178 static int 179 n2piupc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 180 { 181 n2piupc_t *n2piupc_p; 182 uint32_t regprop[4]; 183 int len; 184 int instance = ddi_get_instance(dip); 185 186 switch (cmd) { 187 case DDI_RESUME: 188 case DDI_ATTACH: 189 if (ddi_soft_state_zalloc(n2piupc_state_p, instance) != 190 DDI_SUCCESS) { 191 cmn_err(CE_WARN, "%s%d: Can't allocate softstate.\n", 192 NAMEINST(dip)); 193 goto bad_softstate; 194 } 195 196 n2piupc_p = (n2piupc_t *)ddi_get_soft_state(n2piupc_state_p, 197 instance); 198 199 n2piupc_p->n2piupc_dip = dip; 200 201 /* Get handle for hypervisor access of performance counters. */ 202 len = sizeof (regprop); 203 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 204 "reg", (caddr_t)regprop, &len) != DDI_SUCCESS) { 205 206 cmn_err(CE_WARN, 207 "%s%d: Cannot get reg property\n", 208 NAMEINST(dip)); 209 goto bad_handle; 210 } 211 212 /* Look only at the lower 28 bits of the highest cell. */ 213 n2piupc_p->n2piupc_handle = regprop[0] & 0xfffffff; 214 215 /* Set up kstats. */ 216 if (n2piupc_kstat_attach(n2piupc_p) != DDI_SUCCESS) 217 goto bad_kstat_attach; 218 219 return (DDI_SUCCESS); 220 221 bad_kstat_attach: 222 bad_handle: 223 (void) ddi_soft_state_free(n2piupc_state_p, instance); 224 bad_softstate: 225 return (DDI_FAILURE); 226 227 default: 228 return (DDI_FAILURE); 229 } 230 } 231 232 /* 233 * Per-instance cleanup. Suspend/resume not supported. 234 */ 235 static int 236 n2piupc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 237 { 238 int instance = ddi_get_instance(dip); 239 240 n2piupc_t *n2piupc_p = (n2piupc_t *)ddi_get_soft_state( 241 n2piupc_state_p, instance); 242 243 switch (cmd) { 244 case DDI_SUSPEND: 245 case DDI_DETACH: 246 n2piupc_kstat_detach(n2piupc_p); 247 (void) ddi_soft_state_free(n2piupc_state_p, instance); 248 249 return (DDI_SUCCESS); 250 251 default: 252 return (DDI_FAILURE); 253 } 254 } 255