1*2309Srsmaeda /* 2*2309Srsmaeda * CDDL HEADER START 3*2309Srsmaeda * 4*2309Srsmaeda * The contents of this file are subject to the terms of the 5*2309Srsmaeda * Common Development and Distribution License (the "License"). 6*2309Srsmaeda * You may not use this file except in compliance with the License. 7*2309Srsmaeda * 8*2309Srsmaeda * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2309Srsmaeda * or http://www.opensolaris.org/os/licensing. 10*2309Srsmaeda * See the License for the specific language governing permissions 11*2309Srsmaeda * and limitations under the License. 12*2309Srsmaeda * 13*2309Srsmaeda * When distributing Covered Code, include this CDDL HEADER in each 14*2309Srsmaeda * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2309Srsmaeda * If applicable, add the following below this CDDL HEADER, with the 16*2309Srsmaeda * fields enclosed by brackets "[]" replaced with your own identifying 17*2309Srsmaeda * information: Portions Copyright [yyyy] [name of copyright owner] 18*2309Srsmaeda * 19*2309Srsmaeda * CDDL HEADER END 20*2309Srsmaeda */ 21*2309Srsmaeda 22*2309Srsmaeda /* 23*2309Srsmaeda * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*2309Srsmaeda * Use is subject to license terms. 25*2309Srsmaeda */ 26*2309Srsmaeda 27*2309Srsmaeda #pragma ident "%Z%%M% %I% %E% SMI" 28*2309Srsmaeda 29*2309Srsmaeda /* 30*2309Srsmaeda * DR control module for LDoms 31*2309Srsmaeda */ 32*2309Srsmaeda 33*2309Srsmaeda #include <sys/sysmacros.h> 34*2309Srsmaeda #include <sys/modctl.h> 35*2309Srsmaeda #include <sys/conf.h> 36*2309Srsmaeda #include <sys/ddi.h> 37*2309Srsmaeda #include <sys/sunddi.h> 38*2309Srsmaeda #include <sys/ddi_impldefs.h> 39*2309Srsmaeda #include <sys/stat.h> 40*2309Srsmaeda #include <sys/door.h> 41*2309Srsmaeda #include <sys/open.h> 42*2309Srsmaeda #include <sys/note.h> 43*2309Srsmaeda #include <sys/ldoms.h> 44*2309Srsmaeda #include <sys/dr_util.h> 45*2309Srsmaeda #include <sys/drctl.h> 46*2309Srsmaeda #include <sys/drctl_impl.h> 47*2309Srsmaeda 48*2309Srsmaeda 49*2309Srsmaeda static int drctl_attach(dev_info_t *, ddi_attach_cmd_t); 50*2309Srsmaeda static int drctl_detach(dev_info_t *, ddi_detach_cmd_t); 51*2309Srsmaeda static int drctl_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 52*2309Srsmaeda 53*2309Srsmaeda static int drctl_open(dev_t *, int, int, cred_t *); 54*2309Srsmaeda static int drctl_close(dev_t, int, int, cred_t *); 55*2309Srsmaeda static int drctl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 56*2309Srsmaeda 57*2309Srsmaeda static void *pack_message(int, int, int, void *, size_t *); 58*2309Srsmaeda static int send_message(void *, size_t, void **, size_t *); 59*2309Srsmaeda 60*2309Srsmaeda 61*2309Srsmaeda /* 62*2309Srsmaeda * Configuration data structures 63*2309Srsmaeda */ 64*2309Srsmaeda static struct cb_ops drctl_cb_ops = { 65*2309Srsmaeda drctl_open, /* open */ 66*2309Srsmaeda drctl_close, /* close */ 67*2309Srsmaeda nodev, /* strategy */ 68*2309Srsmaeda nodev, /* print */ 69*2309Srsmaeda nodev, /* dump */ 70*2309Srsmaeda nodev, /* read */ 71*2309Srsmaeda nodev, /* write */ 72*2309Srsmaeda drctl_ioctl, /* ioctl */ 73*2309Srsmaeda nodev, /* devmap */ 74*2309Srsmaeda nodev, /* mmap */ 75*2309Srsmaeda nodev, /* segmap */ 76*2309Srsmaeda nochpoll, /* poll */ 77*2309Srsmaeda ddi_prop_op, /* prop_op */ 78*2309Srsmaeda NULL, /* streamtab */ 79*2309Srsmaeda D_MP | D_NEW, /* driver compatibility flag */ 80*2309Srsmaeda CB_REV, /* cb_ops revision */ 81*2309Srsmaeda nodev, /* async read */ 82*2309Srsmaeda nodev /* async write */ 83*2309Srsmaeda }; 84*2309Srsmaeda 85*2309Srsmaeda 86*2309Srsmaeda static struct dev_ops drctl_ops = { 87*2309Srsmaeda DEVO_REV, /* devo_rev */ 88*2309Srsmaeda 0, /* refcnt */ 89*2309Srsmaeda drctl_getinfo, /* info */ 90*2309Srsmaeda nulldev, /* identify */ 91*2309Srsmaeda nulldev, /* probe */ 92*2309Srsmaeda drctl_attach, /* attach */ 93*2309Srsmaeda drctl_detach, /* detach */ 94*2309Srsmaeda nodev, /* reset */ 95*2309Srsmaeda &drctl_cb_ops, /* driver operations */ 96*2309Srsmaeda NULL, /* bus operations */ 97*2309Srsmaeda NULL, /* power */ 98*2309Srsmaeda }; 99*2309Srsmaeda 100*2309Srsmaeda static struct modldrv modldrv = { 101*2309Srsmaeda &mod_driverops, /* type of module - driver */ 102*2309Srsmaeda "DR Control pseudo driver v%I%", 103*2309Srsmaeda &drctl_ops 104*2309Srsmaeda }; 105*2309Srsmaeda 106*2309Srsmaeda static struct modlinkage modlinkage = { 107*2309Srsmaeda MODREV_1, 108*2309Srsmaeda &modldrv, 109*2309Srsmaeda NULL 110*2309Srsmaeda }; 111*2309Srsmaeda 112*2309Srsmaeda 113*2309Srsmaeda /* 114*2309Srsmaeda * Locking strategy 115*2309Srsmaeda * 116*2309Srsmaeda * One of the reasons for this module's existence is to serialize 117*2309Srsmaeda * DR requests which might be coming from different sources. Only 118*2309Srsmaeda * one operation is allowed to be in progress at any given time. 119*2309Srsmaeda * 120*2309Srsmaeda * A single lock word (the 'drc_busy' element below) is NULL 121*2309Srsmaeda * when there is no operation in progress. When a client of this 122*2309Srsmaeda * module initiates an operation it grabs the mutex 'drc_lock' in 123*2309Srsmaeda * order to examine the lock word ('drc_busy'). If no other 124*2309Srsmaeda * operation is in progress, the lock word will be NULL. If so, 125*2309Srsmaeda * a cookie which uniquely identifies the requestor is stored in 126*2309Srsmaeda * the lock word, and the mutex is released. Attempts by other 127*2309Srsmaeda * clients to initiate an operation will fail. 128*2309Srsmaeda * 129*2309Srsmaeda * When the lock-holding client's operation is completed, the 130*2309Srsmaeda * client will call a "finalize" function in this module, providing 131*2309Srsmaeda * the cookie passed with the original request. Since the cookie 132*2309Srsmaeda * matches, the operation will succeed and the lock word will be 133*2309Srsmaeda * cleared. At this point, an new operation may be initiated. 134*2309Srsmaeda */ 135*2309Srsmaeda 136*2309Srsmaeda /* 137*2309Srsmaeda * Driver private data 138*2309Srsmaeda */ 139*2309Srsmaeda static struct drctl_unit { 140*2309Srsmaeda kmutex_t drc_lock; /* global driver lock */ 141*2309Srsmaeda dev_info_t *drc_dip; /* dev_info pointer */ 142*2309Srsmaeda kcondvar_t drc_busy_cv; /* block for !busy */ 143*2309Srsmaeda drctl_cookie_t drc_busy; /* NULL if free else a unique */ 144*2309Srsmaeda /* identifier for caller */ 145*2309Srsmaeda int drc_cmd; /* the cmd underway (or -1) */ 146*2309Srsmaeda int drc_flags; /* saved flag from above cmd */ 147*2309Srsmaeda int drc_inst; /* our single instance */ 148*2309Srsmaeda uint_t drc_state; /* driver state */ 149*2309Srsmaeda } drctl_state; 150*2309Srsmaeda 151*2309Srsmaeda static struct drctl_unit *drctlp = &drctl_state; 152*2309Srsmaeda 153*2309Srsmaeda int 154*2309Srsmaeda _init(void) 155*2309Srsmaeda { 156*2309Srsmaeda drctlp->drc_inst = -1; 157*2309Srsmaeda mutex_init(&drctlp->drc_lock, NULL, MUTEX_DRIVER, NULL); 158*2309Srsmaeda return (mod_install(&modlinkage)); 159*2309Srsmaeda } 160*2309Srsmaeda 161*2309Srsmaeda 162*2309Srsmaeda int 163*2309Srsmaeda _fini(void) 164*2309Srsmaeda { 165*2309Srsmaeda mutex_destroy(&drctlp->drc_lock); 166*2309Srsmaeda return (mod_remove(&modlinkage)); 167*2309Srsmaeda } 168*2309Srsmaeda 169*2309Srsmaeda 170*2309Srsmaeda int 171*2309Srsmaeda _info(struct modinfo *modinfop) 172*2309Srsmaeda { 173*2309Srsmaeda return (mod_info(&modlinkage, modinfop)); 174*2309Srsmaeda } 175*2309Srsmaeda 176*2309Srsmaeda 177*2309Srsmaeda /* 178*2309Srsmaeda * Do the attach work 179*2309Srsmaeda */ 180*2309Srsmaeda static int 181*2309Srsmaeda drctl_do_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 182*2309Srsmaeda { 183*2309Srsmaeda _NOTE(ARGUNUSED(cmd)) 184*2309Srsmaeda 185*2309Srsmaeda char *str = "drctl_do_attach"; 186*2309Srsmaeda int retval = DDI_SUCCESS; 187*2309Srsmaeda 188*2309Srsmaeda if (drctlp->drc_inst != -1) { 189*2309Srsmaeda cmn_err(CE_WARN, "%s: an instance is already attached!", str); 190*2309Srsmaeda return (DDI_FAILURE); 191*2309Srsmaeda } 192*2309Srsmaeda drctlp->drc_inst = ddi_get_instance(dip); 193*2309Srsmaeda 194*2309Srsmaeda retval = ddi_create_minor_node(dip, "drctl", S_IFCHR, 195*2309Srsmaeda drctlp->drc_inst, DDI_PSEUDO, 0); 196*2309Srsmaeda if (retval != DDI_SUCCESS) { 197*2309Srsmaeda cmn_err(CE_WARN, "%s: can't create minor node", str); 198*2309Srsmaeda drctlp->drc_inst = -1; 199*2309Srsmaeda return (retval); 200*2309Srsmaeda } 201*2309Srsmaeda 202*2309Srsmaeda drctlp->drc_dip = dip; 203*2309Srsmaeda ddi_report_dev(dip); 204*2309Srsmaeda 205*2309Srsmaeda return (retval); 206*2309Srsmaeda } 207*2309Srsmaeda 208*2309Srsmaeda 209*2309Srsmaeda static int 210*2309Srsmaeda drctl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 211*2309Srsmaeda { 212*2309Srsmaeda switch (cmd) { 213*2309Srsmaeda case DDI_ATTACH: 214*2309Srsmaeda return (drctl_do_attach(dip, cmd)); 215*2309Srsmaeda 216*2309Srsmaeda default: 217*2309Srsmaeda return (DDI_FAILURE); 218*2309Srsmaeda } 219*2309Srsmaeda } 220*2309Srsmaeda 221*2309Srsmaeda 222*2309Srsmaeda /* ARGSUSED */ 223*2309Srsmaeda static int 224*2309Srsmaeda drctl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 225*2309Srsmaeda { 226*2309Srsmaeda switch (cmd) { 227*2309Srsmaeda case DDI_DETACH: 228*2309Srsmaeda drctlp->drc_inst = -1; 229*2309Srsmaeda ddi_remove_minor_node(dip, "drctl"); 230*2309Srsmaeda return (DDI_SUCCESS); 231*2309Srsmaeda 232*2309Srsmaeda default: 233*2309Srsmaeda return (DDI_FAILURE); 234*2309Srsmaeda } 235*2309Srsmaeda } 236*2309Srsmaeda 237*2309Srsmaeda static int 238*2309Srsmaeda drctl_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) 239*2309Srsmaeda { 240*2309Srsmaeda _NOTE(ARGUNUSED(dip, cmd, arg, resultp)) 241*2309Srsmaeda 242*2309Srsmaeda return (0); 243*2309Srsmaeda } 244*2309Srsmaeda 245*2309Srsmaeda static int 246*2309Srsmaeda drctl_open(dev_t *devp, int flag, int otyp, cred_t *cred_p) 247*2309Srsmaeda { 248*2309Srsmaeda _NOTE(ARGUNUSED(devp, flag, cred_p)) 249*2309Srsmaeda 250*2309Srsmaeda if (otyp != OTYP_CHR) 251*2309Srsmaeda return (EINVAL); 252*2309Srsmaeda 253*2309Srsmaeda return (0); 254*2309Srsmaeda } 255*2309Srsmaeda 256*2309Srsmaeda static int 257*2309Srsmaeda drctl_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 258*2309Srsmaeda { 259*2309Srsmaeda _NOTE(ARGUNUSED(dev, flag, otyp, cred_p)) 260*2309Srsmaeda 261*2309Srsmaeda return (0); 262*2309Srsmaeda } 263*2309Srsmaeda 264*2309Srsmaeda /* 265*2309Srsmaeda * This driver guarantees that if drctl_config_init returns 0, 266*2309Srsmaeda * a valid response buffer will be passed back to the caller. This 267*2309Srsmaeda * routine can be used to generate that response in cases where the 268*2309Srsmaeda * upcall has not resulted in a response message from userland. 269*2309Srsmaeda */ 270*2309Srsmaeda static drctl_rsrc_t * 271*2309Srsmaeda drctl_generate_resp(drctl_rsrc_t *res, 272*2309Srsmaeda int count, size_t *rsize, drctl_status_t status) 273*2309Srsmaeda { 274*2309Srsmaeda int idx; 275*2309Srsmaeda size_t size; 276*2309Srsmaeda drctl_rsrc_t *rbuf; 277*2309Srsmaeda 278*2309Srsmaeda size = count * sizeof (*res); 279*2309Srsmaeda rbuf = kmem_alloc(size, KM_SLEEP); 280*2309Srsmaeda 281*2309Srsmaeda bcopy(res, rbuf, size); 282*2309Srsmaeda 283*2309Srsmaeda for (idx = 0; idx < count; idx++) { 284*2309Srsmaeda rbuf[idx].status = status; 285*2309Srsmaeda rbuf[idx].offset = 0; 286*2309Srsmaeda } 287*2309Srsmaeda 288*2309Srsmaeda *rsize = size; 289*2309Srsmaeda return (rbuf); 290*2309Srsmaeda } 291*2309Srsmaeda 292*2309Srsmaeda static int 293*2309Srsmaeda drctl_config_common(int cmd, int flags, drctl_rsrc_t *res, 294*2309Srsmaeda int count, drctl_rsrc_t **rbuf, size_t *rsize) 295*2309Srsmaeda { 296*2309Srsmaeda int rv = 0; 297*2309Srsmaeda size_t size; 298*2309Srsmaeda char *bufp; 299*2309Srsmaeda static const char me[] = "drctl_config_common"; 300*2309Srsmaeda 301*2309Srsmaeda switch (cmd) { 302*2309Srsmaeda case DRCTL_CPU_CONFIG_REQUEST: 303*2309Srsmaeda case DRCTL_CPU_CONFIG_NOTIFY: 304*2309Srsmaeda case DRCTL_CPU_UNCONFIG_REQUEST: 305*2309Srsmaeda case DRCTL_CPU_UNCONFIG_NOTIFY: 306*2309Srsmaeda rv = 0; 307*2309Srsmaeda break; 308*2309Srsmaeda case DRCTL_MEM_CONFIG_REQUEST: 309*2309Srsmaeda case DRCTL_MEM_CONFIG_NOTIFY: 310*2309Srsmaeda case DRCTL_MEM_UNCONFIG_REQUEST: 311*2309Srsmaeda case DRCTL_MEM_UNCONFIG_NOTIFY: 312*2309Srsmaeda case DRCTL_IO_CONFIG_REQUEST: 313*2309Srsmaeda case DRCTL_IO_CONFIG_NOTIFY: 314*2309Srsmaeda case DRCTL_IO_UNCONFIG_REQUEST: 315*2309Srsmaeda case DRCTL_IO_UNCONFIG_NOTIFY: 316*2309Srsmaeda rv = ENOTSUP; 317*2309Srsmaeda break; 318*2309Srsmaeda } 319*2309Srsmaeda 320*2309Srsmaeda if (rv != 0) { 321*2309Srsmaeda DR_DBG_CTL("%s: invalid cmd %d\n", me, cmd); 322*2309Srsmaeda return (rv); 323*2309Srsmaeda } 324*2309Srsmaeda 325*2309Srsmaeda /* 326*2309Srsmaeda * If the operation is a FORCE, we don't send a message to 327*2309Srsmaeda * the daemon. But, the upstream clients still expect a 328*2309Srsmaeda * response, so generate a response with all ops 'allowed'. 329*2309Srsmaeda */ 330*2309Srsmaeda if (flags == DRCTL_FLAG_FORCE) { 331*2309Srsmaeda if (rbuf != NULL) { 332*2309Srsmaeda *rbuf = drctl_generate_resp(res, count, &size, 333*2309Srsmaeda DRCTL_STATUS_ALLOW); 334*2309Srsmaeda *rsize = size; 335*2309Srsmaeda } 336*2309Srsmaeda return (0); 337*2309Srsmaeda } 338*2309Srsmaeda 339*2309Srsmaeda bufp = pack_message(cmd, flags, count, (void *)res, &size); 340*2309Srsmaeda DR_DBG_CTL("%s: from pack_message, bufp = %p size %ld\n", 341*2309Srsmaeda me, (void *)bufp, size); 342*2309Srsmaeda if (bufp == NULL || size == 0) 343*2309Srsmaeda return (EIO); 344*2309Srsmaeda 345*2309Srsmaeda rv = send_message(bufp, size, (void **)rbuf, rsize); 346*2309Srsmaeda 347*2309Srsmaeda /* 348*2309Srsmaeda * For failure, as part of our contract with the caller, 349*2309Srsmaeda * generate a response message, but mark all proposed 350*2309Srsmaeda * changes as 'denied'. 351*2309Srsmaeda */ 352*2309Srsmaeda if (rv != 0) { 353*2309Srsmaeda *rbuf = drctl_generate_resp(res, count, &size, 354*2309Srsmaeda DRCTL_STATUS_DENY); 355*2309Srsmaeda *rsize = size; 356*2309Srsmaeda } 357*2309Srsmaeda 358*2309Srsmaeda return (rv); 359*2309Srsmaeda } 360*2309Srsmaeda 361*2309Srsmaeda /* 362*2309Srsmaeda * Since the response comes from userland, make sure it is 363*2309Srsmaeda * at least the minimum size and, if it contains error 364*2309Srsmaeda * strings, that the string area is null-terminated. 365*2309Srsmaeda */ 366*2309Srsmaeda static int 367*2309Srsmaeda verify_response(int count, drctl_rsrc_t *resp, size_t size) 368*2309Srsmaeda { 369*2309Srsmaeda int idx; 370*2309Srsmaeda int need_terminator = 0; 371*2309Srsmaeda static const char me[] = "verify_response"; 372*2309Srsmaeda 373*2309Srsmaeda if (resp == NULL || size < count * sizeof (*resp)) { 374*2309Srsmaeda DR_DBG_CTL("%s: BAD size - count %d size %ld\n", 375*2309Srsmaeda me, count, size); 376*2309Srsmaeda return (EIO); 377*2309Srsmaeda } 378*2309Srsmaeda 379*2309Srsmaeda for (idx = 0; idx < count; idx++) { 380*2309Srsmaeda 381*2309Srsmaeda if (resp[idx].offset != 0) 382*2309Srsmaeda need_terminator++; 383*2309Srsmaeda } 384*2309Srsmaeda 385*2309Srsmaeda if (need_terminator && *((caddr_t)(resp) + size - 1) != '\0') { 386*2309Srsmaeda DR_DBG_CTL("%s: unterm. strings: resp %p size %ld char %d\n", 387*2309Srsmaeda me, (void *)resp, size, *((caddr_t)(resp) + size - 1)); 388*2309Srsmaeda /* Don't fail the transaction, but don't advertise strings */ 389*2309Srsmaeda for (idx = 0; idx < count; idx++) 390*2309Srsmaeda resp[idx].offset = 0; 391*2309Srsmaeda } 392*2309Srsmaeda 393*2309Srsmaeda return (0); 394*2309Srsmaeda } 395*2309Srsmaeda 396*2309Srsmaeda 397*2309Srsmaeda /* 398*2309Srsmaeda * Prepare for a reconfig operation. 399*2309Srsmaeda */ 400*2309Srsmaeda int 401*2309Srsmaeda drctl_config_init(int cmd, int flags, drctl_rsrc_t *res, 402*2309Srsmaeda int count, drctl_rsrc_t **rbuf, size_t *rsize, drctl_cookie_t ck) 403*2309Srsmaeda { 404*2309Srsmaeda static char me[] = "drctl_config_init"; 405*2309Srsmaeda int idx; 406*2309Srsmaeda int rv; 407*2309Srsmaeda 408*2309Srsmaeda if (ck == 0) 409*2309Srsmaeda return (EINVAL); 410*2309Srsmaeda 411*2309Srsmaeda mutex_enter(&drctlp->drc_lock); 412*2309Srsmaeda 413*2309Srsmaeda if (drctlp->drc_busy != NULL) { 414*2309Srsmaeda mutex_exit(&drctlp->drc_lock); 415*2309Srsmaeda return (EBUSY); 416*2309Srsmaeda } 417*2309Srsmaeda 418*2309Srsmaeda DR_DBG_CTL("%s: cmd %d flags %d res %p count %d\n", 419*2309Srsmaeda me, cmd, flags, (void *)res, count); 420*2309Srsmaeda 421*2309Srsmaeda /* Mark the link busy. Below we will fill in the actual cookie. */ 422*2309Srsmaeda drctlp->drc_busy = (drctl_cookie_t)-1; 423*2309Srsmaeda mutex_exit(&drctlp->drc_lock); 424*2309Srsmaeda 425*2309Srsmaeda if ((rv = drctl_config_common(cmd, 426*2309Srsmaeda flags, res, count, rbuf, rsize)) == 0 && 427*2309Srsmaeda verify_response(count, *rbuf, *rsize) == 0) { 428*2309Srsmaeda drctlp->drc_busy = ck; 429*2309Srsmaeda drctlp->drc_cmd = cmd; 430*2309Srsmaeda drctlp->drc_flags = flags; 431*2309Srsmaeda 432*2309Srsmaeda /* 433*2309Srsmaeda * If there wasn't a valid response msg passed back, 434*2309Srsmaeda * create a response with each resource op denied. 435*2309Srsmaeda */ 436*2309Srsmaeda if (*rbuf == NULL || *rsize == 0) { 437*2309Srsmaeda drctl_rsrc_t *bp = *rbuf; 438*2309Srsmaeda 439*2309Srsmaeda *rsize = count * sizeof (*bp); 440*2309Srsmaeda bp = kmem_zalloc(*rsize, KM_SLEEP); 441*2309Srsmaeda bcopy(res, bp, *rsize); 442*2309Srsmaeda 443*2309Srsmaeda for (idx = 0; idx < count; idx++) { 444*2309Srsmaeda bp[idx].status = DRCTL_STATUS_DENY; 445*2309Srsmaeda bp[idx].offset = 0; 446*2309Srsmaeda } 447*2309Srsmaeda } 448*2309Srsmaeda } else { 449*2309Srsmaeda drctlp->drc_cmd = -1; 450*2309Srsmaeda drctlp->drc_flags = 0; 451*2309Srsmaeda drctlp->drc_busy = NULL; 452*2309Srsmaeda } 453*2309Srsmaeda 454*2309Srsmaeda return (rv); 455*2309Srsmaeda } 456*2309Srsmaeda 457*2309Srsmaeda /* 458*2309Srsmaeda * Complete a reconfig operation. 459*2309Srsmaeda */ 460*2309Srsmaeda int 461*2309Srsmaeda drctl_config_fini(drctl_cookie_t ck, drctl_rsrc_t *res, int count) 462*2309Srsmaeda { 463*2309Srsmaeda int rv; 464*2309Srsmaeda int notify_cmd; 465*2309Srsmaeda int flags; 466*2309Srsmaeda 467*2309Srsmaeda mutex_enter(&drctlp->drc_lock); 468*2309Srsmaeda 469*2309Srsmaeda if (drctlp->drc_busy != ck) { 470*2309Srsmaeda mutex_exit(&drctlp->drc_lock); 471*2309Srsmaeda return (EBUSY); 472*2309Srsmaeda } 473*2309Srsmaeda 474*2309Srsmaeda mutex_exit(&drctlp->drc_lock); 475*2309Srsmaeda 476*2309Srsmaeda flags = drctlp->drc_flags; 477*2309Srsmaeda /* 478*2309Srsmaeda * Flip the saved _REQUEST command to its corresponding 479*2309Srsmaeda * _NOTIFY command. 480*2309Srsmaeda */ 481*2309Srsmaeda switch (drctlp->drc_cmd) { 482*2309Srsmaeda case DRCTL_CPU_CONFIG_REQUEST: 483*2309Srsmaeda notify_cmd = DRCTL_CPU_CONFIG_NOTIFY; 484*2309Srsmaeda break; 485*2309Srsmaeda 486*2309Srsmaeda case DRCTL_CPU_UNCONFIG_REQUEST: 487*2309Srsmaeda notify_cmd = DRCTL_CPU_UNCONFIG_NOTIFY; 488*2309Srsmaeda break; 489*2309Srsmaeda 490*2309Srsmaeda case DRCTL_MEM_CONFIG_REQUEST: 491*2309Srsmaeda case DRCTL_MEM_CONFIG_NOTIFY: 492*2309Srsmaeda case DRCTL_MEM_UNCONFIG_REQUEST: 493*2309Srsmaeda case DRCTL_MEM_UNCONFIG_NOTIFY: 494*2309Srsmaeda case DRCTL_IO_CONFIG_REQUEST: 495*2309Srsmaeda case DRCTL_IO_CONFIG_NOTIFY: 496*2309Srsmaeda case DRCTL_IO_UNCONFIG_REQUEST: 497*2309Srsmaeda case DRCTL_IO_UNCONFIG_NOTIFY: 498*2309Srsmaeda default: 499*2309Srsmaeda /* none of the above should have been accepted in _init */ 500*2309Srsmaeda ASSERT(0); 501*2309Srsmaeda cmn_err(CE_CONT, 502*2309Srsmaeda "drctl_config_fini: bad cmd %d\n", drctlp->drc_cmd); 503*2309Srsmaeda rv = EINVAL; 504*2309Srsmaeda goto done; 505*2309Srsmaeda } 506*2309Srsmaeda 507*2309Srsmaeda rv = drctl_config_common(notify_cmd, flags, res, count, NULL, 0); 508*2309Srsmaeda 509*2309Srsmaeda done: 510*2309Srsmaeda drctlp->drc_cmd = -1; 511*2309Srsmaeda drctlp->drc_flags = 0; 512*2309Srsmaeda drctlp->drc_busy = NULL; 513*2309Srsmaeda 514*2309Srsmaeda return (rv); 515*2309Srsmaeda } 516*2309Srsmaeda 517*2309Srsmaeda static int 518*2309Srsmaeda drctl_ioctl(dev_t dev, 519*2309Srsmaeda int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p) 520*2309Srsmaeda { 521*2309Srsmaeda _NOTE(ARGUNUSED(dev, mode, cred_p, rval_p)) 522*2309Srsmaeda 523*2309Srsmaeda int rv; 524*2309Srsmaeda 525*2309Srsmaeda switch (cmd) { 526*2309Srsmaeda case DRCTL_IOCTL_CONNECT_SERVER: 527*2309Srsmaeda rv = i_drctl_ioctl(cmd, arg); 528*2309Srsmaeda break; 529*2309Srsmaeda default: 530*2309Srsmaeda rv = ENOTSUP; 531*2309Srsmaeda } 532*2309Srsmaeda 533*2309Srsmaeda *rval_p = (rv == 0) ? 0 : -1; 534*2309Srsmaeda 535*2309Srsmaeda return (rv); 536*2309Srsmaeda } 537*2309Srsmaeda 538*2309Srsmaeda /* 539*2309Srsmaeda * Accept a preformatted request from caller and send a message to 540*2309Srsmaeda * the daemon. A pointer to the daemon's response buffer is passed 541*2309Srsmaeda * back in obufp, its size in osize. 542*2309Srsmaeda */ 543*2309Srsmaeda static int 544*2309Srsmaeda send_message(void *msg, size_t size, void **obufp, size_t *osize) 545*2309Srsmaeda { 546*2309Srsmaeda int rv; 547*2309Srsmaeda 548*2309Srsmaeda rv = i_drctl_send(msg, size, obufp, osize); 549*2309Srsmaeda 550*2309Srsmaeda kmem_free(msg, size); 551*2309Srsmaeda 552*2309Srsmaeda return (rv); 553*2309Srsmaeda } 554*2309Srsmaeda 555*2309Srsmaeda static void * 556*2309Srsmaeda pack_message(int cmd, int flags, int count, void *data, size_t *osize) 557*2309Srsmaeda { 558*2309Srsmaeda drd_msg_t *msgp; 559*2309Srsmaeda size_t hdr_size = offsetof(drd_msg_t, data); 560*2309Srsmaeda 561*2309Srsmaeda switch (cmd) { 562*2309Srsmaeda case DRCTL_CPU_CONFIG_REQUEST: 563*2309Srsmaeda case DRCTL_CPU_CONFIG_NOTIFY: 564*2309Srsmaeda case DRCTL_CPU_UNCONFIG_REQUEST: 565*2309Srsmaeda case DRCTL_CPU_UNCONFIG_NOTIFY: 566*2309Srsmaeda 567*2309Srsmaeda *osize = hdr_size + count * sizeof (drctl_rsrc_t); 568*2309Srsmaeda 569*2309Srsmaeda msgp = kmem_alloc(*osize, KM_SLEEP); 570*2309Srsmaeda msgp->cmd = cmd; 571*2309Srsmaeda msgp->count = count; 572*2309Srsmaeda msgp->flags = flags; 573*2309Srsmaeda bcopy(data, msgp->data, count * sizeof (drctl_rsrc_t)); 574*2309Srsmaeda break; 575*2309Srsmaeda default: 576*2309Srsmaeda cmn_err(CE_WARN, 577*2309Srsmaeda "drctl: pack_message received invalid cmd %d", cmd); 578*2309Srsmaeda msgp = NULL; 579*2309Srsmaeda } 580*2309Srsmaeda 581*2309Srsmaeda return (msgp); 582*2309Srsmaeda } 583