1*1ae08745Sheppo /* 2*1ae08745Sheppo * CDDL HEADER START 3*1ae08745Sheppo * 4*1ae08745Sheppo * The contents of this file are subject to the terms of the 5*1ae08745Sheppo * Common Development and Distribution License (the "License"). 6*1ae08745Sheppo * You may not use this file except in compliance with the License. 7*1ae08745Sheppo * 8*1ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 10*1ae08745Sheppo * See the License for the specific language governing permissions 11*1ae08745Sheppo * and limitations under the License. 12*1ae08745Sheppo * 13*1ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 14*1ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 16*1ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 17*1ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 18*1ae08745Sheppo * 19*1ae08745Sheppo * CDDL HEADER END 20*1ae08745Sheppo */ 21*1ae08745Sheppo 22*1ae08745Sheppo /* 23*1ae08745Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*1ae08745Sheppo * Use is subject to license terms. 25*1ae08745Sheppo */ 26*1ae08745Sheppo 27*1ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 28*1ae08745Sheppo 29*1ae08745Sheppo /* 30*1ae08745Sheppo * LDoms virtual disk client (vdc) device driver 31*1ae08745Sheppo * 32*1ae08745Sheppo * This driver runs on a guest logical domain and communicates with the virtual 33*1ae08745Sheppo * disk server (vds) driver running on the service domain which is exporting 34*1ae08745Sheppo * virtualized "disks" to the guest logical domain. 35*1ae08745Sheppo * 36*1ae08745Sheppo * The driver can be divided into four sections: 37*1ae08745Sheppo * 38*1ae08745Sheppo * 1) generic device driver housekeeping 39*1ae08745Sheppo * _init, _fini, attach, detach, ops structures, etc. 40*1ae08745Sheppo * 41*1ae08745Sheppo * 2) communication channel setup 42*1ae08745Sheppo * Setup the communications link over the LDC channel that vdc uses to 43*1ae08745Sheppo * talk to the vDisk server. Initialise the descriptor ring which 44*1ae08745Sheppo * allows the LDC clients to transfer data via memory mappings. 45*1ae08745Sheppo * 46*1ae08745Sheppo * 3) Support exported to upper layers (filesystems, etc) 47*1ae08745Sheppo * The upper layers call into vdc via strategy(9E) and DKIO(7I) 48*1ae08745Sheppo * ioctl calls. vdc will copy the data to be written to the descriptor 49*1ae08745Sheppo * ring or maps the buffer to store the data read by the vDisk 50*1ae08745Sheppo * server into the descriptor ring. It then sends a message to the 51*1ae08745Sheppo * vDisk server requesting it to complete the operation. 52*1ae08745Sheppo * 53*1ae08745Sheppo * 4) Handling responses from vDisk server. 54*1ae08745Sheppo * The vDisk server will ACK some or all of the messages vdc sends to it 55*1ae08745Sheppo * (this is configured during the handshake). Upon receipt of an ACK 56*1ae08745Sheppo * vdc will check the descriptor ring and signal to the upper layer 57*1ae08745Sheppo * code waiting on the IO. 58*1ae08745Sheppo */ 59*1ae08745Sheppo 60*1ae08745Sheppo #include <sys/conf.h> 61*1ae08745Sheppo #include <sys/disp.h> 62*1ae08745Sheppo #include <sys/ddi.h> 63*1ae08745Sheppo #include <sys/dkio.h> 64*1ae08745Sheppo #include <sys/efi_partition.h> 65*1ae08745Sheppo #include <sys/fcntl.h> 66*1ae08745Sheppo #include <sys/file.h> 67*1ae08745Sheppo #include <sys/mach_descrip.h> 68*1ae08745Sheppo #include <sys/modctl.h> 69*1ae08745Sheppo #include <sys/mdeg.h> 70*1ae08745Sheppo #include <sys/note.h> 71*1ae08745Sheppo #include <sys/open.h> 72*1ae08745Sheppo #include <sys/stat.h> 73*1ae08745Sheppo #include <sys/sunddi.h> 74*1ae08745Sheppo #include <sys/types.h> 75*1ae08745Sheppo #include <sys/promif.h> 76*1ae08745Sheppo #include <sys/vtoc.h> 77*1ae08745Sheppo #include <sys/archsystm.h> 78*1ae08745Sheppo #include <sys/sysmacros.h> 79*1ae08745Sheppo 80*1ae08745Sheppo #include <sys/cdio.h> 81*1ae08745Sheppo #include <sys/dktp/cm.h> 82*1ae08745Sheppo #include <sys/dktp/fdisk.h> 83*1ae08745Sheppo #include <sys/scsi/generic/sense.h> 84*1ae08745Sheppo #include <sys/scsi/impl/uscsi.h> /* Needed for defn of USCSICMD ioctl */ 85*1ae08745Sheppo #include <sys/scsi/targets/sddef.h> 86*1ae08745Sheppo 87*1ae08745Sheppo #include <sys/ldoms.h> 88*1ae08745Sheppo #include <sys/ldc.h> 89*1ae08745Sheppo #include <sys/vio_common.h> 90*1ae08745Sheppo #include <sys/vio_mailbox.h> 91*1ae08745Sheppo #include <sys/vdsk_common.h> 92*1ae08745Sheppo #include <sys/vdsk_mailbox.h> 93*1ae08745Sheppo #include <sys/vdc.h> 94*1ae08745Sheppo 95*1ae08745Sheppo /* 96*1ae08745Sheppo * function prototypes 97*1ae08745Sheppo */ 98*1ae08745Sheppo 99*1ae08745Sheppo /* standard driver functions */ 100*1ae08745Sheppo static int vdc_open(dev_t *dev, int flag, int otyp, cred_t *cred); 101*1ae08745Sheppo static int vdc_close(dev_t dev, int flag, int otyp, cred_t *cred); 102*1ae08745Sheppo static int vdc_strategy(struct buf *buf); 103*1ae08745Sheppo static int vdc_print(dev_t dev, char *str); 104*1ae08745Sheppo static int vdc_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk); 105*1ae08745Sheppo static int vdc_read(dev_t dev, struct uio *uio, cred_t *cred); 106*1ae08745Sheppo static int vdc_write(dev_t dev, struct uio *uio, cred_t *cred); 107*1ae08745Sheppo static int vdc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 108*1ae08745Sheppo cred_t *credp, int *rvalp); 109*1ae08745Sheppo static int vdc_aread(dev_t dev, struct aio_req *aio, cred_t *cred); 110*1ae08745Sheppo static int vdc_awrite(dev_t dev, struct aio_req *aio, cred_t *cred); 111*1ae08745Sheppo 112*1ae08745Sheppo static int vdc_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 113*1ae08745Sheppo void *arg, void **resultp); 114*1ae08745Sheppo static int vdc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 115*1ae08745Sheppo static int vdc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 116*1ae08745Sheppo 117*1ae08745Sheppo /* setup */ 118*1ae08745Sheppo static int vdc_send(ldc_handle_t ldc_handle, caddr_t pkt, size_t *msglen); 119*1ae08745Sheppo static int vdc_do_ldc_init(vdc_t *vdc); 120*1ae08745Sheppo static int vdc_start_ldc_connection(vdc_t *vdc); 121*1ae08745Sheppo static int vdc_create_device_nodes(vdc_t *vdc); 122*1ae08745Sheppo static int vdc_create_device_nodes_props(vdc_t *vdc); 123*1ae08745Sheppo static int vdc_get_ldc_id(dev_info_t *dip, uint64_t *ldc_id); 124*1ae08745Sheppo static void vdc_terminate_ldc(vdc_t *vdc); 125*1ae08745Sheppo static int vdc_init_descriptor_ring(vdc_t *vdc); 126*1ae08745Sheppo static void vdc_destroy_descriptor_ring(vdc_t *vdc); 127*1ae08745Sheppo 128*1ae08745Sheppo /* handshake with vds */ 129*1ae08745Sheppo static void vdc_init_handshake_negotiation(void *arg); 130*1ae08745Sheppo static int vdc_init_ver_negotiation(vdc_t *vdc); 131*1ae08745Sheppo static int vdc_init_attr_negotiation(vdc_t *vdc); 132*1ae08745Sheppo static int vdc_init_dring_negotiate(vdc_t *vdc); 133*1ae08745Sheppo static int vdc_handle_ver_negotiate(); 134*1ae08745Sheppo static int vdc_handle_attr_negotiate(); 135*1ae08745Sheppo static void vdc_reset_connection(vdc_t *vdc, boolean_t resetldc); 136*1ae08745Sheppo static boolean_t vdc_is_able_to_tx_data(vdc_t *vdc, int flag); 137*1ae08745Sheppo 138*1ae08745Sheppo /* processing */ 139*1ae08745Sheppo static void vdc_process_msg_thread(vdc_t *vdc); 140*1ae08745Sheppo static uint_t vdc_handle_cb(uint64_t event, caddr_t arg); 141*1ae08745Sheppo static void vdc_process_msg(void *arg); 142*1ae08745Sheppo static int vdc_process_ctrl_msg(vdc_t *vdc, vio_msg_t msg); 143*1ae08745Sheppo static int vdc_process_data_msg(vdc_t *vdc, vio_msg_t msg); 144*1ae08745Sheppo static int vdc_process_err_msg(vdc_t *vdc, vio_msg_t msg); 145*1ae08745Sheppo static void vdc_do_process_msg(vdc_t *vdc); 146*1ae08745Sheppo static int vdc_get_next_dring_entry_id(vdc_t *vdc, uint_t needed); 147*1ae08745Sheppo static int vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, 148*1ae08745Sheppo size_t nbytes, int op, uint64_t arg, uint64_t slice); 149*1ae08745Sheppo static int vdc_wait_for_descriptor_update(vdc_t *vdc, uint_t idx, 150*1ae08745Sheppo vio_dring_msg_t dmsg); 151*1ae08745Sheppo static int vdc_depopulate_descriptor(vdc_t *vdc, uint_t idx); 152*1ae08745Sheppo static int vdc_get_response(vdc_t *vdc, int start, int end); 153*1ae08745Sheppo static int vdc_populate_mem_hdl(vdc_t *vdc, uint_t idx, 154*1ae08745Sheppo caddr_t addr, size_t nbytes, int operation); 155*1ae08745Sheppo static boolean_t vdc_verify_seq_num(vdc_t *vdc, vio_dring_msg_t *dring_msg, int 156*1ae08745Sheppo num_msgs); 157*1ae08745Sheppo 158*1ae08745Sheppo /* dkio */ 159*1ae08745Sheppo static int vd_process_ioctl(dev_t dev, int cmd, caddr_t arg, int mode); 160*1ae08745Sheppo static int vdc_create_fake_geometry(vdc_t *vdc); 161*1ae08745Sheppo 162*1ae08745Sheppo /* 163*1ae08745Sheppo * Module variables 164*1ae08745Sheppo */ 165*1ae08745Sheppo uint64_t vdc_hz_timeout; 166*1ae08745Sheppo uint64_t vdc_usec_timeout = VDC_USEC_TIMEOUT_MIN; 167*1ae08745Sheppo uint64_t vdc_dump_usec_timeout = VDC_USEC_TIMEOUT_MIN / 300; 168*1ae08745Sheppo static int vdc_retries = VDC_RETRIES; 169*1ae08745Sheppo static int vdc_dump_retries = VDC_RETRIES * 10; 170*1ae08745Sheppo 171*1ae08745Sheppo /* Soft state pointer */ 172*1ae08745Sheppo static void *vdc_state; 173*1ae08745Sheppo 174*1ae08745Sheppo /* variable level controlling the verbosity of the error/debug messages */ 175*1ae08745Sheppo int vdc_msglevel = 0; 176*1ae08745Sheppo 177*1ae08745Sheppo 178*1ae08745Sheppo static void 179*1ae08745Sheppo vdc_msg(const char *format, ...) 180*1ae08745Sheppo { 181*1ae08745Sheppo va_list args; 182*1ae08745Sheppo 183*1ae08745Sheppo va_start(args, format); 184*1ae08745Sheppo vcmn_err(CE_CONT, format, args); 185*1ae08745Sheppo va_end(args); 186*1ae08745Sheppo } 187*1ae08745Sheppo 188*1ae08745Sheppo static struct cb_ops vdc_cb_ops = { 189*1ae08745Sheppo vdc_open, /* cb_open */ 190*1ae08745Sheppo vdc_close, /* cb_close */ 191*1ae08745Sheppo vdc_strategy, /* cb_strategy */ 192*1ae08745Sheppo vdc_print, /* cb_print */ 193*1ae08745Sheppo vdc_dump, /* cb_dump */ 194*1ae08745Sheppo vdc_read, /* cb_read */ 195*1ae08745Sheppo vdc_write, /* cb_write */ 196*1ae08745Sheppo vdc_ioctl, /* cb_ioctl */ 197*1ae08745Sheppo nodev, /* cb_devmap */ 198*1ae08745Sheppo nodev, /* cb_mmap */ 199*1ae08745Sheppo nodev, /* cb_segmap */ 200*1ae08745Sheppo nochpoll, /* cb_chpoll */ 201*1ae08745Sheppo ddi_prop_op, /* cb_prop_op */ 202*1ae08745Sheppo NULL, /* cb_str */ 203*1ae08745Sheppo D_MP | D_64BIT, /* cb_flag */ 204*1ae08745Sheppo CB_REV, /* cb_rev */ 205*1ae08745Sheppo vdc_aread, /* cb_aread */ 206*1ae08745Sheppo vdc_awrite /* cb_awrite */ 207*1ae08745Sheppo }; 208*1ae08745Sheppo 209*1ae08745Sheppo static struct dev_ops vdc_ops = { 210*1ae08745Sheppo DEVO_REV, /* devo_rev */ 211*1ae08745Sheppo 0, /* devo_refcnt */ 212*1ae08745Sheppo vdc_getinfo, /* devo_getinfo */ 213*1ae08745Sheppo nulldev, /* devo_identify */ 214*1ae08745Sheppo nulldev, /* devo_probe */ 215*1ae08745Sheppo vdc_attach, /* devo_attach */ 216*1ae08745Sheppo vdc_detach, /* devo_detach */ 217*1ae08745Sheppo nodev, /* devo_reset */ 218*1ae08745Sheppo &vdc_cb_ops, /* devo_cb_ops */ 219*1ae08745Sheppo NULL, /* devo_bus_ops */ 220*1ae08745Sheppo nulldev /* devo_power */ 221*1ae08745Sheppo }; 222*1ae08745Sheppo 223*1ae08745Sheppo static struct modldrv modldrv = { 224*1ae08745Sheppo &mod_driverops, 225*1ae08745Sheppo "virtual disk client %I%", 226*1ae08745Sheppo &vdc_ops, 227*1ae08745Sheppo }; 228*1ae08745Sheppo 229*1ae08745Sheppo static struct modlinkage modlinkage = { 230*1ae08745Sheppo MODREV_1, 231*1ae08745Sheppo &modldrv, 232*1ae08745Sheppo NULL 233*1ae08745Sheppo }; 234*1ae08745Sheppo 235*1ae08745Sheppo /* -------------------------------------------------------------------------- */ 236*1ae08745Sheppo 237*1ae08745Sheppo /* 238*1ae08745Sheppo * Device Driver housekeeping and setup 239*1ae08745Sheppo */ 240*1ae08745Sheppo 241*1ae08745Sheppo int 242*1ae08745Sheppo _init(void) 243*1ae08745Sheppo { 244*1ae08745Sheppo int status; 245*1ae08745Sheppo 246*1ae08745Sheppo if ((status = ddi_soft_state_init(&vdc_state, sizeof (vdc_t), 1)) != 0) 247*1ae08745Sheppo return (status); 248*1ae08745Sheppo if ((status = mod_install(&modlinkage)) != 0) 249*1ae08745Sheppo ddi_soft_state_fini(&vdc_state); 250*1ae08745Sheppo return (status); 251*1ae08745Sheppo } 252*1ae08745Sheppo 253*1ae08745Sheppo int 254*1ae08745Sheppo _info(struct modinfo *modinfop) 255*1ae08745Sheppo { 256*1ae08745Sheppo return (mod_info(&modlinkage, modinfop)); 257*1ae08745Sheppo } 258*1ae08745Sheppo 259*1ae08745Sheppo int 260*1ae08745Sheppo _fini(void) 261*1ae08745Sheppo { 262*1ae08745Sheppo int status; 263*1ae08745Sheppo 264*1ae08745Sheppo if ((status = mod_remove(&modlinkage)) != 0) 265*1ae08745Sheppo return (status); 266*1ae08745Sheppo ddi_soft_state_fini(&vdc_state); 267*1ae08745Sheppo return (0); 268*1ae08745Sheppo } 269*1ae08745Sheppo 270*1ae08745Sheppo static int 271*1ae08745Sheppo vdc_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) 272*1ae08745Sheppo { 273*1ae08745Sheppo _NOTE(ARGUNUSED(dip)) 274*1ae08745Sheppo 275*1ae08745Sheppo int instance = SDUNIT(getminor((dev_t)arg)); 276*1ae08745Sheppo vdc_t *vdc = NULL; 277*1ae08745Sheppo 278*1ae08745Sheppo switch (cmd) { 279*1ae08745Sheppo case DDI_INFO_DEVT2DEVINFO: 280*1ae08745Sheppo if ((vdc = ddi_get_soft_state(vdc_state, instance)) == NULL) { 281*1ae08745Sheppo *resultp = NULL; 282*1ae08745Sheppo return (DDI_FAILURE); 283*1ae08745Sheppo } 284*1ae08745Sheppo *resultp = vdc->dip; 285*1ae08745Sheppo return (DDI_SUCCESS); 286*1ae08745Sheppo case DDI_INFO_DEVT2INSTANCE: 287*1ae08745Sheppo *resultp = (void *)(uintptr_t)instance; 288*1ae08745Sheppo return (DDI_SUCCESS); 289*1ae08745Sheppo default: 290*1ae08745Sheppo *resultp = NULL; 291*1ae08745Sheppo return (DDI_FAILURE); 292*1ae08745Sheppo } 293*1ae08745Sheppo } 294*1ae08745Sheppo 295*1ae08745Sheppo static int 296*1ae08745Sheppo vdc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 297*1ae08745Sheppo { 298*1ae08745Sheppo int instance; 299*1ae08745Sheppo int rv; 300*1ae08745Sheppo uint_t retries = 0; 301*1ae08745Sheppo vdc_t *vdc = NULL; 302*1ae08745Sheppo 303*1ae08745Sheppo switch (cmd) { 304*1ae08745Sheppo case DDI_DETACH: 305*1ae08745Sheppo /* the real work happens below */ 306*1ae08745Sheppo break; 307*1ae08745Sheppo case DDI_SUSPEND: 308*1ae08745Sheppo /* nothing to do for this non-device */ 309*1ae08745Sheppo return (DDI_SUCCESS); 310*1ae08745Sheppo default: 311*1ae08745Sheppo return (DDI_FAILURE); 312*1ae08745Sheppo } 313*1ae08745Sheppo 314*1ae08745Sheppo ASSERT(cmd == DDI_DETACH); 315*1ae08745Sheppo instance = ddi_get_instance(dip); 316*1ae08745Sheppo PR1("%s[%d] Entered\n", __func__, instance); 317*1ae08745Sheppo 318*1ae08745Sheppo if ((vdc = ddi_get_soft_state(vdc_state, instance)) == NULL) { 319*1ae08745Sheppo vdc_msg("%s[%d]: Could not get state structure.", 320*1ae08745Sheppo __func__, instance); 321*1ae08745Sheppo return (DDI_FAILURE); 322*1ae08745Sheppo } 323*1ae08745Sheppo 324*1ae08745Sheppo if (vdc->open) { 325*1ae08745Sheppo PR0("%s[%d]: Cannot detach: device is open", 326*1ae08745Sheppo __func__, instance); 327*1ae08745Sheppo return (DDI_FAILURE); 328*1ae08745Sheppo } 329*1ae08745Sheppo 330*1ae08745Sheppo PR0("%s[%d] proceeding...\n", __func__, instance); 331*1ae08745Sheppo 332*1ae08745Sheppo /* 333*1ae08745Sheppo * try and disable callbacks to prevent another handshake 334*1ae08745Sheppo */ 335*1ae08745Sheppo rv = ldc_set_cb_mode(vdc->ldc_handle, LDC_CB_DISABLE); 336*1ae08745Sheppo PR0("%s[%d] callback disabled (rv=%d)\n", __func__, instance, rv); 337*1ae08745Sheppo 338*1ae08745Sheppo /* 339*1ae08745Sheppo * Prevent any more attempts to start a handshake with the vdisk 340*1ae08745Sheppo * server and tear down the existing connection. 341*1ae08745Sheppo */ 342*1ae08745Sheppo mutex_enter(&vdc->lock); 343*1ae08745Sheppo vdc->initialized |= VDC_HANDSHAKE_STOP; 344*1ae08745Sheppo vdc_reset_connection(vdc, B_TRUE); 345*1ae08745Sheppo mutex_exit(&vdc->lock); 346*1ae08745Sheppo 347*1ae08745Sheppo if (vdc->initialized & VDC_THREAD) { 348*1ae08745Sheppo mutex_enter(&vdc->msg_proc_lock); 349*1ae08745Sheppo vdc->msg_proc_thr_state = VDC_THR_STOP; 350*1ae08745Sheppo vdc->msg_pending = B_TRUE; 351*1ae08745Sheppo cv_signal(&vdc->msg_proc_cv); 352*1ae08745Sheppo 353*1ae08745Sheppo while (vdc->msg_proc_thr_state != VDC_THR_DONE) { 354*1ae08745Sheppo PR0("%s[%d]: Waiting for thread to exit\n", 355*1ae08745Sheppo __func__, instance); 356*1ae08745Sheppo rv = cv_timedwait(&vdc->msg_proc_cv, 357*1ae08745Sheppo &vdc->msg_proc_lock, VD_GET_TIMEOUT_HZ(1)); 358*1ae08745Sheppo if ((rv == -1) && (retries++ > vdc_retries)) 359*1ae08745Sheppo break; 360*1ae08745Sheppo } 361*1ae08745Sheppo mutex_exit(&vdc->msg_proc_lock); 362*1ae08745Sheppo } 363*1ae08745Sheppo 364*1ae08745Sheppo mutex_enter(&vdc->lock); 365*1ae08745Sheppo 366*1ae08745Sheppo if (vdc->initialized & VDC_DRING) 367*1ae08745Sheppo vdc_destroy_descriptor_ring(vdc); 368*1ae08745Sheppo 369*1ae08745Sheppo if (vdc->initialized & VDC_LDC) 370*1ae08745Sheppo vdc_terminate_ldc(vdc); 371*1ae08745Sheppo 372*1ae08745Sheppo mutex_exit(&vdc->lock); 373*1ae08745Sheppo 374*1ae08745Sheppo if (vdc->initialized & VDC_MINOR) { 375*1ae08745Sheppo ddi_prop_remove_all(dip); 376*1ae08745Sheppo ddi_remove_minor_node(dip, NULL); 377*1ae08745Sheppo } 378*1ae08745Sheppo 379*1ae08745Sheppo if (vdc->initialized & VDC_LOCKS) { 380*1ae08745Sheppo mutex_destroy(&vdc->lock); 381*1ae08745Sheppo mutex_destroy(&vdc->attach_lock); 382*1ae08745Sheppo mutex_destroy(&vdc->msg_proc_lock); 383*1ae08745Sheppo mutex_destroy(&vdc->dring_lock); 384*1ae08745Sheppo cv_destroy(&vdc->cv); 385*1ae08745Sheppo cv_destroy(&vdc->attach_cv); 386*1ae08745Sheppo cv_destroy(&vdc->msg_proc_cv); 387*1ae08745Sheppo } 388*1ae08745Sheppo 389*1ae08745Sheppo if (vdc->minfo) 390*1ae08745Sheppo kmem_free(vdc->minfo, sizeof (struct dk_minfo)); 391*1ae08745Sheppo 392*1ae08745Sheppo if (vdc->cinfo) 393*1ae08745Sheppo kmem_free(vdc->cinfo, sizeof (struct dk_cinfo)); 394*1ae08745Sheppo 395*1ae08745Sheppo if (vdc->vtoc) 396*1ae08745Sheppo kmem_free(vdc->vtoc, sizeof (struct vtoc)); 397*1ae08745Sheppo 398*1ae08745Sheppo if (vdc->initialized & VDC_SOFT_STATE) 399*1ae08745Sheppo ddi_soft_state_free(vdc_state, instance); 400*1ae08745Sheppo 401*1ae08745Sheppo PR0("%s[%d] End %p\n", __func__, instance, vdc); 402*1ae08745Sheppo 403*1ae08745Sheppo return (DDI_SUCCESS); 404*1ae08745Sheppo } 405*1ae08745Sheppo 406*1ae08745Sheppo 407*1ae08745Sheppo static int 408*1ae08745Sheppo vdc_do_attach(dev_info_t *dip) 409*1ae08745Sheppo { 410*1ae08745Sheppo int instance; 411*1ae08745Sheppo vdc_t *vdc = NULL; 412*1ae08745Sheppo int status; 413*1ae08745Sheppo uint_t retries = 0; 414*1ae08745Sheppo 415*1ae08745Sheppo ASSERT(dip != NULL); 416*1ae08745Sheppo 417*1ae08745Sheppo instance = ddi_get_instance(dip); 418*1ae08745Sheppo if (ddi_soft_state_zalloc(vdc_state, instance) != DDI_SUCCESS) { 419*1ae08745Sheppo vdc_msg("%s:(%d): Couldn't alloc state structure", 420*1ae08745Sheppo __func__, instance); 421*1ae08745Sheppo return (DDI_FAILURE); 422*1ae08745Sheppo } 423*1ae08745Sheppo 424*1ae08745Sheppo if ((vdc = ddi_get_soft_state(vdc_state, instance)) == NULL) { 425*1ae08745Sheppo vdc_msg("%s:(%d): Could not get state structure.", 426*1ae08745Sheppo __func__, instance); 427*1ae08745Sheppo return (DDI_FAILURE); 428*1ae08745Sheppo } 429*1ae08745Sheppo 430*1ae08745Sheppo /* 431*1ae08745Sheppo * We assign the value to initialized in this case to zero out the 432*1ae08745Sheppo * variable and then set bits in it to indicate what has been done 433*1ae08745Sheppo */ 434*1ae08745Sheppo vdc->initialized = VDC_SOFT_STATE; 435*1ae08745Sheppo 436*1ae08745Sheppo vdc_hz_timeout = drv_usectohz(vdc_usec_timeout); 437*1ae08745Sheppo 438*1ae08745Sheppo vdc->dip = dip; 439*1ae08745Sheppo vdc->instance = instance; 440*1ae08745Sheppo vdc->open = 0; 441*1ae08745Sheppo vdc->vdisk_type = VD_DISK_TYPE_UNK; 442*1ae08745Sheppo vdc->state = VD_STATE_INIT; 443*1ae08745Sheppo vdc->ldc_state = 0; 444*1ae08745Sheppo vdc->session_id = 0; 445*1ae08745Sheppo vdc->block_size = DEV_BSIZE; 446*1ae08745Sheppo vdc->max_xfer_sz = VD_MAX_BLOCK_SIZE / DEV_BSIZE; 447*1ae08745Sheppo 448*1ae08745Sheppo vdc->vtoc = NULL; 449*1ae08745Sheppo vdc->cinfo = NULL; 450*1ae08745Sheppo vdc->minfo = NULL; 451*1ae08745Sheppo 452*1ae08745Sheppo mutex_init(&vdc->lock, NULL, MUTEX_DRIVER, NULL); 453*1ae08745Sheppo mutex_init(&vdc->attach_lock, NULL, MUTEX_DRIVER, NULL); 454*1ae08745Sheppo mutex_init(&vdc->msg_proc_lock, NULL, MUTEX_DRIVER, NULL); 455*1ae08745Sheppo mutex_init(&vdc->dring_lock, NULL, MUTEX_DRIVER, NULL); 456*1ae08745Sheppo cv_init(&vdc->cv, NULL, CV_DRIVER, NULL); 457*1ae08745Sheppo cv_init(&vdc->attach_cv, NULL, CV_DRIVER, NULL); 458*1ae08745Sheppo cv_init(&vdc->msg_proc_cv, NULL, CV_DRIVER, NULL); 459*1ae08745Sheppo vdc->initialized |= VDC_LOCKS; 460*1ae08745Sheppo 461*1ae08745Sheppo vdc->msg_pending = B_FALSE; 462*1ae08745Sheppo vdc->msg_proc_thr_id = thread_create(NULL, 0, vdc_process_msg_thread, 463*1ae08745Sheppo vdc, 0, &p0, TS_RUN, minclsyspri); 464*1ae08745Sheppo if (vdc->msg_proc_thr_id == NULL) { 465*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Failed to create msg processing thread", 466*1ae08745Sheppo instance); 467*1ae08745Sheppo return (DDI_FAILURE); 468*1ae08745Sheppo } 469*1ae08745Sheppo vdc->initialized |= VDC_THREAD; 470*1ae08745Sheppo 471*1ae08745Sheppo /* initialise LDC channel which will be used to communicate with vds */ 472*1ae08745Sheppo if (vdc_do_ldc_init(vdc) != 0) { 473*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Couldn't initialize LDC", instance); 474*1ae08745Sheppo return (DDI_FAILURE); 475*1ae08745Sheppo } 476*1ae08745Sheppo 477*1ae08745Sheppo /* Bring up connection with vds via LDC */ 478*1ae08745Sheppo status = vdc_start_ldc_connection(vdc); 479*1ae08745Sheppo if (status != 0) { 480*1ae08745Sheppo vdc_msg("%s[%d] Could not start LDC", __func__, instance); 481*1ae08745Sheppo return (DDI_FAILURE); 482*1ae08745Sheppo } 483*1ae08745Sheppo 484*1ae08745Sheppo /* 485*1ae08745Sheppo * We need to wait until the handshake has completed before leaving 486*1ae08745Sheppo * the attach(). This is to allow the device node(s) to be created 487*1ae08745Sheppo * and the first usage of the filesystem to succeed. 488*1ae08745Sheppo */ 489*1ae08745Sheppo mutex_enter(&vdc->attach_lock); 490*1ae08745Sheppo while ((vdc->ldc_state != LDC_UP) || 491*1ae08745Sheppo (vdc->state != VD_STATE_DATA)) { 492*1ae08745Sheppo 493*1ae08745Sheppo PR0("%s[%d] handshake in progress [VD %d (LDC %d)]\n", 494*1ae08745Sheppo __func__, instance, vdc->state, vdc->ldc_state); 495*1ae08745Sheppo 496*1ae08745Sheppo status = cv_timedwait(&vdc->attach_cv, &vdc->attach_lock, 497*1ae08745Sheppo VD_GET_TIMEOUT_HZ(1)); 498*1ae08745Sheppo if (status == -1) { 499*1ae08745Sheppo if (retries >= vdc_retries) { 500*1ae08745Sheppo PR0("%s[%d] Give up handshake wait.\n", 501*1ae08745Sheppo __func__, instance); 502*1ae08745Sheppo mutex_exit(&vdc->attach_lock); 503*1ae08745Sheppo return (DDI_FAILURE); 504*1ae08745Sheppo } else { 505*1ae08745Sheppo PR0("%s[%d] Retry #%d for handshake.\n", 506*1ae08745Sheppo __func__, instance, retries); 507*1ae08745Sheppo retries++; 508*1ae08745Sheppo } 509*1ae08745Sheppo } 510*1ae08745Sheppo } 511*1ae08745Sheppo mutex_exit(&vdc->attach_lock); 512*1ae08745Sheppo 513*1ae08745Sheppo if (vdc->vtoc == NULL) 514*1ae08745Sheppo vdc->vtoc = kmem_zalloc(sizeof (struct vtoc), KM_SLEEP); 515*1ae08745Sheppo 516*1ae08745Sheppo status = vdc_populate_descriptor(vdc, (caddr_t)vdc->vtoc, 517*1ae08745Sheppo P2ROUNDUP(sizeof (struct vtoc), sizeof (uint64_t)), 518*1ae08745Sheppo VD_OP_GET_VTOC, FKIOCTL, 0); 519*1ae08745Sheppo if (status) { 520*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Failed to get VTOC", instance); 521*1ae08745Sheppo return (status); 522*1ae08745Sheppo } 523*1ae08745Sheppo 524*1ae08745Sheppo /* 525*1ae08745Sheppo * Now that we have the device info we can create the 526*1ae08745Sheppo * device nodes and properties 527*1ae08745Sheppo */ 528*1ae08745Sheppo status = vdc_create_device_nodes(vdc); 529*1ae08745Sheppo if (status) { 530*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Failed to create device nodes", 531*1ae08745Sheppo instance); 532*1ae08745Sheppo return (status); 533*1ae08745Sheppo } 534*1ae08745Sheppo status = vdc_create_device_nodes_props(vdc); 535*1ae08745Sheppo if (status) { 536*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Failed to create device nodes" 537*1ae08745Sheppo " properties", instance); 538*1ae08745Sheppo return (status); 539*1ae08745Sheppo } 540*1ae08745Sheppo 541*1ae08745Sheppo ddi_report_dev(dip); 542*1ae08745Sheppo 543*1ae08745Sheppo PR0("%s[%d] Attach completed\n", __func__, instance); 544*1ae08745Sheppo return (status); 545*1ae08745Sheppo } 546*1ae08745Sheppo 547*1ae08745Sheppo static int 548*1ae08745Sheppo vdc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 549*1ae08745Sheppo { 550*1ae08745Sheppo int status; 551*1ae08745Sheppo 552*1ae08745Sheppo PR0("%s[%d] Entered. Built %s %s\n", __func__, ddi_get_instance(dip), 553*1ae08745Sheppo __DATE__, __TIME__); 554*1ae08745Sheppo 555*1ae08745Sheppo switch (cmd) { 556*1ae08745Sheppo case DDI_ATTACH: 557*1ae08745Sheppo if ((status = vdc_do_attach(dip)) != 0) 558*1ae08745Sheppo (void) vdc_detach(dip, DDI_DETACH); 559*1ae08745Sheppo return (status); 560*1ae08745Sheppo case DDI_RESUME: 561*1ae08745Sheppo /* nothing to do for this non-device */ 562*1ae08745Sheppo return (DDI_SUCCESS); 563*1ae08745Sheppo default: 564*1ae08745Sheppo return (DDI_FAILURE); 565*1ae08745Sheppo } 566*1ae08745Sheppo } 567*1ae08745Sheppo 568*1ae08745Sheppo static int 569*1ae08745Sheppo vdc_do_ldc_init(vdc_t *vdc) 570*1ae08745Sheppo { 571*1ae08745Sheppo int status = 0; 572*1ae08745Sheppo ldc_status_t ldc_state; 573*1ae08745Sheppo ldc_attr_t ldc_attr; 574*1ae08745Sheppo uint64_t ldc_id = 0; 575*1ae08745Sheppo dev_info_t *dip = NULL; 576*1ae08745Sheppo 577*1ae08745Sheppo ASSERT(vdc != NULL); 578*1ae08745Sheppo 579*1ae08745Sheppo dip = vdc->dip; 580*1ae08745Sheppo vdc->initialized |= VDC_LDC; 581*1ae08745Sheppo 582*1ae08745Sheppo if ((status = vdc_get_ldc_id(dip, &ldc_id)) != 0) { 583*1ae08745Sheppo vdc_msg("%s: Failed to get <ldc_id> property\n", __func__); 584*1ae08745Sheppo return (EIO); 585*1ae08745Sheppo } 586*1ae08745Sheppo vdc->ldc_id = ldc_id; 587*1ae08745Sheppo 588*1ae08745Sheppo ldc_attr.devclass = LDC_DEV_BLK; 589*1ae08745Sheppo ldc_attr.instance = vdc->instance; 590*1ae08745Sheppo ldc_attr.mode = LDC_MODE_UNRELIABLE; /* unreliable transport */ 591*1ae08745Sheppo ldc_attr.qlen = VD_LDC_QLEN; 592*1ae08745Sheppo 593*1ae08745Sheppo if ((vdc->initialized & VDC_LDC_INIT) == 0) { 594*1ae08745Sheppo status = ldc_init(ldc_id, &ldc_attr, &vdc->ldc_handle); 595*1ae08745Sheppo if (status != 0) { 596*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] ldc_init(chan %ld) returned %d", 597*1ae08745Sheppo vdc->instance, ldc_id, status); 598*1ae08745Sheppo return (status); 599*1ae08745Sheppo } 600*1ae08745Sheppo vdc->initialized |= VDC_LDC_INIT; 601*1ae08745Sheppo } 602*1ae08745Sheppo status = ldc_status(vdc->ldc_handle, &ldc_state); 603*1ae08745Sheppo if (status != 0) { 604*1ae08745Sheppo vdc_msg("Cannot discover LDC status [err=%d].", status); 605*1ae08745Sheppo return (status); 606*1ae08745Sheppo } 607*1ae08745Sheppo vdc->ldc_state = ldc_state; 608*1ae08745Sheppo 609*1ae08745Sheppo if ((vdc->initialized & VDC_LDC_CB) == 0) { 610*1ae08745Sheppo status = ldc_reg_callback(vdc->ldc_handle, vdc_handle_cb, 611*1ae08745Sheppo (caddr_t)vdc); 612*1ae08745Sheppo if (status != 0) { 613*1ae08745Sheppo vdc_msg("%s: ldc_reg_callback()=%d", __func__, status); 614*1ae08745Sheppo return (status); 615*1ae08745Sheppo } 616*1ae08745Sheppo vdc->initialized |= VDC_LDC_CB; 617*1ae08745Sheppo } 618*1ae08745Sheppo 619*1ae08745Sheppo vdc->initialized |= VDC_LDC; 620*1ae08745Sheppo 621*1ae08745Sheppo /* 622*1ae08745Sheppo * At this stage we have initialised LDC, we will now try and open 623*1ae08745Sheppo * the connection. 624*1ae08745Sheppo */ 625*1ae08745Sheppo if (vdc->ldc_state == LDC_INIT) { 626*1ae08745Sheppo status = ldc_open(vdc->ldc_handle); 627*1ae08745Sheppo if (status != 0) { 628*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] ldc_open(chan %ld) returned %d", 629*1ae08745Sheppo vdc->instance, vdc->ldc_id, status); 630*1ae08745Sheppo return (status); 631*1ae08745Sheppo } 632*1ae08745Sheppo vdc->initialized |= VDC_LDC_OPEN; 633*1ae08745Sheppo } 634*1ae08745Sheppo 635*1ae08745Sheppo return (status); 636*1ae08745Sheppo } 637*1ae08745Sheppo 638*1ae08745Sheppo static int 639*1ae08745Sheppo vdc_start_ldc_connection(vdc_t *vdc) 640*1ae08745Sheppo { 641*1ae08745Sheppo int status = 0; 642*1ae08745Sheppo 643*1ae08745Sheppo ASSERT(vdc != NULL); 644*1ae08745Sheppo 645*1ae08745Sheppo mutex_enter(&vdc->lock); 646*1ae08745Sheppo 647*1ae08745Sheppo if (vdc->ldc_state == LDC_UP) { 648*1ae08745Sheppo PR0("%s: LDC is already UP ..\n", __func__); 649*1ae08745Sheppo mutex_exit(&vdc->lock); 650*1ae08745Sheppo return (0); 651*1ae08745Sheppo } 652*1ae08745Sheppo 653*1ae08745Sheppo if ((status = ldc_up(vdc->ldc_handle)) != 0) { 654*1ae08745Sheppo switch (status) { 655*1ae08745Sheppo case ECONNREFUSED: /* listener not ready at other end */ 656*1ae08745Sheppo PR0("%s: ldc_up(%d,...) return %d\n", 657*1ae08745Sheppo __func__, vdc->ldc_id, status); 658*1ae08745Sheppo status = 0; 659*1ae08745Sheppo break; 660*1ae08745Sheppo default: 661*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Failed to bring up LDC: " 662*1ae08745Sheppo "channel=%ld, err=%d", 663*1ae08745Sheppo vdc->instance, vdc->ldc_id, status); 664*1ae08745Sheppo } 665*1ae08745Sheppo } 666*1ae08745Sheppo 667*1ae08745Sheppo PR0("%s[%d] Finished bringing up LDC\n", __func__, vdc->instance); 668*1ae08745Sheppo 669*1ae08745Sheppo mutex_exit(&vdc->lock); 670*1ae08745Sheppo 671*1ae08745Sheppo return (status); 672*1ae08745Sheppo } 673*1ae08745Sheppo 674*1ae08745Sheppo 675*1ae08745Sheppo /* 676*1ae08745Sheppo * Function: 677*1ae08745Sheppo * vdc_create_device_nodes 678*1ae08745Sheppo * 679*1ae08745Sheppo * Description: 680*1ae08745Sheppo * This function creates the block and character device nodes under 681*1ae08745Sheppo * /devices along with the node properties. It is called as part of 682*1ae08745Sheppo * the attach(9E) of the instance during the handshake with vds after 683*1ae08745Sheppo * vds has sent the attributes to vdc. 684*1ae08745Sheppo * 685*1ae08745Sheppo * If the device is of type VD_DISK_TYPE_SLICE then the minor node 686*1ae08745Sheppo * of 2 is used in keeping with the Solaris convention that slice 2 687*1ae08745Sheppo * refers to a whole disk. Slices start at 'a' 688*1ae08745Sheppo * 689*1ae08745Sheppo * Parameters: 690*1ae08745Sheppo * vdc - soft state pointer 691*1ae08745Sheppo * 692*1ae08745Sheppo * Return Values 693*1ae08745Sheppo * 0 - Success 694*1ae08745Sheppo * EIO - Failed to create node 695*1ae08745Sheppo * EINVAL - Unknown type of disk exported 696*1ae08745Sheppo */ 697*1ae08745Sheppo static int 698*1ae08745Sheppo vdc_create_device_nodes(vdc_t *vdc) 699*1ae08745Sheppo { 700*1ae08745Sheppo /* uses NNNN which is OK as long as # of disks <= 10000 */ 701*1ae08745Sheppo char name[sizeof ("disk@NNNN:s,raw")]; 702*1ae08745Sheppo dev_info_t *dip = NULL; 703*1ae08745Sheppo int instance; 704*1ae08745Sheppo int num_slices = 1; 705*1ae08745Sheppo int i; 706*1ae08745Sheppo 707*1ae08745Sheppo ASSERT(vdc != NULL); 708*1ae08745Sheppo 709*1ae08745Sheppo instance = vdc->instance; 710*1ae08745Sheppo dip = vdc->dip; 711*1ae08745Sheppo 712*1ae08745Sheppo switch (vdc->vdisk_type) { 713*1ae08745Sheppo case VD_DISK_TYPE_DISK: 714*1ae08745Sheppo num_slices = V_NUMPAR; 715*1ae08745Sheppo break; 716*1ae08745Sheppo case VD_DISK_TYPE_SLICE: 717*1ae08745Sheppo num_slices = 1; 718*1ae08745Sheppo break; 719*1ae08745Sheppo case VD_DISK_TYPE_UNK: 720*1ae08745Sheppo default: 721*1ae08745Sheppo return (EINVAL); 722*1ae08745Sheppo } 723*1ae08745Sheppo 724*1ae08745Sheppo for (i = 0; i < num_slices; i++) { 725*1ae08745Sheppo (void) snprintf(name, sizeof (name), "%c", 'a' + i); 726*1ae08745Sheppo if (ddi_create_minor_node(dip, name, S_IFBLK, 727*1ae08745Sheppo VD_MAKE_DEV(instance, i), DDI_NT_BLOCK, 0) != DDI_SUCCESS) { 728*1ae08745Sheppo vdc_msg("%s[%d]: Couldn't add block node %s.", 729*1ae08745Sheppo __func__, instance, name); 730*1ae08745Sheppo return (EIO); 731*1ae08745Sheppo } 732*1ae08745Sheppo 733*1ae08745Sheppo /* if any device node is created we set this flag */ 734*1ae08745Sheppo vdc->initialized |= VDC_MINOR; 735*1ae08745Sheppo 736*1ae08745Sheppo (void) snprintf(name, sizeof (name), "%c%s", 737*1ae08745Sheppo 'a' + i, ",raw"); 738*1ae08745Sheppo if (ddi_create_minor_node(dip, name, S_IFCHR, 739*1ae08745Sheppo VD_MAKE_DEV(instance, i), DDI_NT_BLOCK, 0) != DDI_SUCCESS) { 740*1ae08745Sheppo vdc_msg("%s[%d]: Could not add raw node %s.", 741*1ae08745Sheppo __func__, instance, name); 742*1ae08745Sheppo return (EIO); 743*1ae08745Sheppo } 744*1ae08745Sheppo } 745*1ae08745Sheppo 746*1ae08745Sheppo return (0); 747*1ae08745Sheppo } 748*1ae08745Sheppo 749*1ae08745Sheppo /* 750*1ae08745Sheppo * Function: 751*1ae08745Sheppo * vdc_create_device_nodes_props 752*1ae08745Sheppo * 753*1ae08745Sheppo * Description: 754*1ae08745Sheppo * This function creates the block and character device nodes under 755*1ae08745Sheppo * /devices along with the node properties. It is called as part of 756*1ae08745Sheppo * the attach(9E) of the instance during the handshake with vds after 757*1ae08745Sheppo * vds has sent the attributes to vdc. 758*1ae08745Sheppo * 759*1ae08745Sheppo * Parameters: 760*1ae08745Sheppo * vdc - soft state pointer 761*1ae08745Sheppo * 762*1ae08745Sheppo * Return Values 763*1ae08745Sheppo * 0 - Success 764*1ae08745Sheppo * EIO - Failed to create device node property 765*1ae08745Sheppo * EINVAL - Unknown type of disk exported 766*1ae08745Sheppo */ 767*1ae08745Sheppo static int 768*1ae08745Sheppo vdc_create_device_nodes_props(vdc_t *vdc) 769*1ae08745Sheppo { 770*1ae08745Sheppo dev_info_t *dip = NULL; 771*1ae08745Sheppo int instance; 772*1ae08745Sheppo int num_slices = 1; 773*1ae08745Sheppo int64_t size = 0; 774*1ae08745Sheppo dev_t dev; 775*1ae08745Sheppo int rv; 776*1ae08745Sheppo int i; 777*1ae08745Sheppo 778*1ae08745Sheppo ASSERT(vdc != NULL); 779*1ae08745Sheppo 780*1ae08745Sheppo instance = vdc->instance; 781*1ae08745Sheppo dip = vdc->dip; 782*1ae08745Sheppo 783*1ae08745Sheppo if ((vdc->vtoc == NULL) || (vdc->vtoc->v_sanity != VTOC_SANE)) { 784*1ae08745Sheppo cmn_err(CE_NOTE, "![%d] Could not create device node property." 785*1ae08745Sheppo " No VTOC available", instance); 786*1ae08745Sheppo return (ENXIO); 787*1ae08745Sheppo } 788*1ae08745Sheppo 789*1ae08745Sheppo switch (vdc->vdisk_type) { 790*1ae08745Sheppo case VD_DISK_TYPE_DISK: 791*1ae08745Sheppo num_slices = V_NUMPAR; 792*1ae08745Sheppo break; 793*1ae08745Sheppo case VD_DISK_TYPE_SLICE: 794*1ae08745Sheppo num_slices = 1; 795*1ae08745Sheppo break; 796*1ae08745Sheppo case VD_DISK_TYPE_UNK: 797*1ae08745Sheppo default: 798*1ae08745Sheppo return (EINVAL); 799*1ae08745Sheppo } 800*1ae08745Sheppo 801*1ae08745Sheppo for (i = 0; i < num_slices; i++) { 802*1ae08745Sheppo dev = makedevice(ddi_driver_major(dip), 803*1ae08745Sheppo VD_MAKE_DEV(instance, i)); 804*1ae08745Sheppo 805*1ae08745Sheppo size = vdc->vtoc->v_part[i].p_size * vdc->vtoc->v_sectorsz; 806*1ae08745Sheppo PR0("%s[%d] sz %ld (%ld Mb) p_size %lx\n", 807*1ae08745Sheppo __func__, instance, size, size / (1024 * 1024), 808*1ae08745Sheppo vdc->vtoc->v_part[i].p_size); 809*1ae08745Sheppo 810*1ae08745Sheppo rv = ddi_prop_update_int64(dev, dip, VDC_SIZE_PROP_NAME, size); 811*1ae08745Sheppo if (rv != DDI_PROP_SUCCESS) { 812*1ae08745Sheppo vdc_msg("%s:(%d): Couldn't add \"%s\" [%d]\n", 813*1ae08745Sheppo __func__, instance, VDC_SIZE_PROP_NAME, size); 814*1ae08745Sheppo return (EIO); 815*1ae08745Sheppo } 816*1ae08745Sheppo 817*1ae08745Sheppo rv = ddi_prop_update_int64(dev, dip, VDC_NBLOCKS_PROP_NAME, 818*1ae08745Sheppo lbtodb(size)); 819*1ae08745Sheppo if (rv != DDI_PROP_SUCCESS) { 820*1ae08745Sheppo vdc_msg("%s:(%d): Couldn't add \"%s\" [%d]\n", __func__, 821*1ae08745Sheppo instance, VDC_NBLOCKS_PROP_NAME, lbtodb(size)); 822*1ae08745Sheppo return (EIO); 823*1ae08745Sheppo } 824*1ae08745Sheppo } 825*1ae08745Sheppo 826*1ae08745Sheppo return (0); 827*1ae08745Sheppo } 828*1ae08745Sheppo 829*1ae08745Sheppo static int 830*1ae08745Sheppo vdc_open(dev_t *dev, int flag, int otyp, cred_t *cred) 831*1ae08745Sheppo { 832*1ae08745Sheppo _NOTE(ARGUNUSED(cred)) 833*1ae08745Sheppo 834*1ae08745Sheppo int instance; 835*1ae08745Sheppo int status = 0; 836*1ae08745Sheppo vdc_t *vdc; 837*1ae08745Sheppo 838*1ae08745Sheppo ASSERT(dev != NULL); 839*1ae08745Sheppo instance = SDUNIT(getminor(*dev)); 840*1ae08745Sheppo 841*1ae08745Sheppo PR0("%s[%d] minor = %d flag = %x, otyp = %x\n", __func__, instance, 842*1ae08745Sheppo getminor(*dev), flag, otyp); 843*1ae08745Sheppo 844*1ae08745Sheppo if ((otyp != OTYP_CHR) && (otyp != OTYP_BLK)) 845*1ae08745Sheppo return (EINVAL); 846*1ae08745Sheppo 847*1ae08745Sheppo if ((vdc = ddi_get_soft_state(vdc_state, instance)) == NULL) { 848*1ae08745Sheppo vdc_msg("%s[%d] Could not get state.", __func__, instance); 849*1ae08745Sheppo return (ENXIO); 850*1ae08745Sheppo } 851*1ae08745Sheppo 852*1ae08745Sheppo /* 853*1ae08745Sheppo * Check to see if we can communicate with vds 854*1ae08745Sheppo */ 855*1ae08745Sheppo status = vdc_is_able_to_tx_data(vdc, flag); 856*1ae08745Sheppo if (status == B_FALSE) { 857*1ae08745Sheppo PR0("%s[%d] Not ready to transmit data\n", __func__, instance); 858*1ae08745Sheppo return (ENOLINK); 859*1ae08745Sheppo } 860*1ae08745Sheppo 861*1ae08745Sheppo mutex_enter(&vdc->lock); 862*1ae08745Sheppo vdc->open++; 863*1ae08745Sheppo mutex_exit(&vdc->lock); 864*1ae08745Sheppo 865*1ae08745Sheppo return (0); 866*1ae08745Sheppo } 867*1ae08745Sheppo 868*1ae08745Sheppo static int 869*1ae08745Sheppo vdc_close(dev_t dev, int flag, int otyp, cred_t *cred) 870*1ae08745Sheppo { 871*1ae08745Sheppo _NOTE(ARGUNUSED(cred)) 872*1ae08745Sheppo 873*1ae08745Sheppo int instance; 874*1ae08745Sheppo vdc_t *vdc; 875*1ae08745Sheppo 876*1ae08745Sheppo instance = SDUNIT(getminor(dev)); 877*1ae08745Sheppo 878*1ae08745Sheppo PR0("%s[%d] flag = %x, otyp = %x\n", __func__, instance, flag, otyp); 879*1ae08745Sheppo 880*1ae08745Sheppo if ((otyp != OTYP_CHR) && (otyp != OTYP_BLK)) 881*1ae08745Sheppo return (EINVAL); 882*1ae08745Sheppo 883*1ae08745Sheppo if ((vdc = ddi_get_soft_state(vdc_state, instance)) == NULL) { 884*1ae08745Sheppo vdc_msg("%s[%d] Could not get state.", __func__, instance); 885*1ae08745Sheppo return (ENXIO); 886*1ae08745Sheppo } 887*1ae08745Sheppo 888*1ae08745Sheppo /* 889*1ae08745Sheppo * Check to see if we can communicate with vds 890*1ae08745Sheppo */ 891*1ae08745Sheppo if (vdc_is_able_to_tx_data(vdc, 0) == B_FALSE) { 892*1ae08745Sheppo PR0("%s[%d] Not ready to transmit data\n", __func__, instance); 893*1ae08745Sheppo return (ETIMEDOUT); 894*1ae08745Sheppo } 895*1ae08745Sheppo 896*1ae08745Sheppo if (vdc->dkio_flush_pending) { 897*1ae08745Sheppo PR0("%s[%d]: Cannot detach: %d outstanding DKIO flushes", 898*1ae08745Sheppo __func__, instance, vdc->dkio_flush_pending); 899*1ae08745Sheppo return (EBUSY); 900*1ae08745Sheppo } 901*1ae08745Sheppo 902*1ae08745Sheppo /* 903*1ae08745Sheppo * Should not need the mutex here, since the framework should protect 904*1ae08745Sheppo * against more opens on this device, but just in case. 905*1ae08745Sheppo */ 906*1ae08745Sheppo mutex_enter(&vdc->lock); 907*1ae08745Sheppo vdc->open--; 908*1ae08745Sheppo mutex_exit(&vdc->lock); 909*1ae08745Sheppo 910*1ae08745Sheppo return (0); 911*1ae08745Sheppo } 912*1ae08745Sheppo 913*1ae08745Sheppo static int 914*1ae08745Sheppo vdc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) 915*1ae08745Sheppo { 916*1ae08745Sheppo _NOTE(ARGUNUSED(credp)) 917*1ae08745Sheppo _NOTE(ARGUNUSED(rvalp)) 918*1ae08745Sheppo 919*1ae08745Sheppo return (vd_process_ioctl(dev, cmd, (caddr_t)arg, mode)); 920*1ae08745Sheppo } 921*1ae08745Sheppo 922*1ae08745Sheppo static int 923*1ae08745Sheppo vdc_print(dev_t dev, char *str) 924*1ae08745Sheppo { 925*1ae08745Sheppo cmn_err(CE_NOTE, "vdc%d: %s", SDUNIT(getminor(dev)), str); 926*1ae08745Sheppo return (0); 927*1ae08745Sheppo } 928*1ae08745Sheppo 929*1ae08745Sheppo static int 930*1ae08745Sheppo vdc_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) 931*1ae08745Sheppo { 932*1ae08745Sheppo int rv = 0; 933*1ae08745Sheppo size_t nbytes = (nblk * DEV_BSIZE); 934*1ae08745Sheppo int instance = SDUNIT(getminor(dev)); 935*1ae08745Sheppo vdc_t *vdc; 936*1ae08745Sheppo 937*1ae08745Sheppo if ((vdc = ddi_get_soft_state(vdc_state, instance)) == NULL) { 938*1ae08745Sheppo vdc_msg("%s (%d): Could not get state.", __func__, instance); 939*1ae08745Sheppo return (ENXIO); 940*1ae08745Sheppo } 941*1ae08745Sheppo 942*1ae08745Sheppo rv = vdc_populate_descriptor(vdc, addr, nbytes, VD_OP_BWRITE, 943*1ae08745Sheppo blkno, SDPART(getminor(dev))); 944*1ae08745Sheppo 945*1ae08745Sheppo PR1("%s: status=%d\n", __func__, rv); 946*1ae08745Sheppo 947*1ae08745Sheppo return (rv); 948*1ae08745Sheppo } 949*1ae08745Sheppo 950*1ae08745Sheppo /* -------------------------------------------------------------------------- */ 951*1ae08745Sheppo 952*1ae08745Sheppo /* 953*1ae08745Sheppo * Disk access routines 954*1ae08745Sheppo * 955*1ae08745Sheppo */ 956*1ae08745Sheppo 957*1ae08745Sheppo /* 958*1ae08745Sheppo * vdc_strategy() 959*1ae08745Sheppo * 960*1ae08745Sheppo * Return Value: 961*1ae08745Sheppo * 0: As per strategy(9E), the strategy() function must return 0 962*1ae08745Sheppo * [ bioerror(9f) sets b_flags to the proper error code ] 963*1ae08745Sheppo */ 964*1ae08745Sheppo static int 965*1ae08745Sheppo vdc_strategy(struct buf *buf) 966*1ae08745Sheppo { 967*1ae08745Sheppo int rv = -1; 968*1ae08745Sheppo vdc_t *vdc = NULL; 969*1ae08745Sheppo int instance = SDUNIT(getminor(buf->b_edev)); 970*1ae08745Sheppo int op = (buf->b_flags & B_READ) ? VD_OP_BREAD : VD_OP_BWRITE; 971*1ae08745Sheppo 972*1ae08745Sheppo PR1("%s: %s %ld bytes at block %ld : b_addr=0x%p", 973*1ae08745Sheppo __func__, (buf->b_flags & B_READ) ? "Read" : "Write", 974*1ae08745Sheppo buf->b_bcount, buf->b_lblkno, buf->b_un.b_addr); 975*1ae08745Sheppo 976*1ae08745Sheppo if ((vdc = ddi_get_soft_state(vdc_state, instance)) == NULL) { 977*1ae08745Sheppo vdc_msg("%s[%d]: Could not get state.", __func__, instance); 978*1ae08745Sheppo bioerror(buf, ENXIO); 979*1ae08745Sheppo biodone(buf); 980*1ae08745Sheppo return (0); 981*1ae08745Sheppo } 982*1ae08745Sheppo 983*1ae08745Sheppo ASSERT(buf->b_bcount <= (vdc->max_xfer_sz * vdc->block_size)); 984*1ae08745Sheppo 985*1ae08745Sheppo if (vdc_is_able_to_tx_data(vdc, O_NONBLOCK) == B_FALSE) { 986*1ae08745Sheppo vdc_msg("%s: Not ready to transmit data", __func__); 987*1ae08745Sheppo bioerror(buf, ENXIO); 988*1ae08745Sheppo biodone(buf); 989*1ae08745Sheppo return (0); 990*1ae08745Sheppo } 991*1ae08745Sheppo bp_mapin(buf); 992*1ae08745Sheppo 993*1ae08745Sheppo rv = vdc_populate_descriptor(vdc, buf->b_un.b_addr, buf->b_bcount, op, 994*1ae08745Sheppo buf->b_lblkno, SDPART(getminor(buf->b_edev))); 995*1ae08745Sheppo 996*1ae08745Sheppo PR1("%s: status=%d", __func__, rv); 997*1ae08745Sheppo bioerror(buf, rv); 998*1ae08745Sheppo biodone(buf); 999*1ae08745Sheppo return (0); 1000*1ae08745Sheppo } 1001*1ae08745Sheppo 1002*1ae08745Sheppo 1003*1ae08745Sheppo static int 1004*1ae08745Sheppo vdc_read(dev_t dev, struct uio *uio, cred_t *cred) 1005*1ae08745Sheppo { 1006*1ae08745Sheppo _NOTE(ARGUNUSED(cred)) 1007*1ae08745Sheppo 1008*1ae08745Sheppo PR1("vdc_read(): Entered"); 1009*1ae08745Sheppo return (physio(vdc_strategy, NULL, dev, B_READ, minphys, uio)); 1010*1ae08745Sheppo } 1011*1ae08745Sheppo 1012*1ae08745Sheppo static int 1013*1ae08745Sheppo vdc_write(dev_t dev, struct uio *uio, cred_t *cred) 1014*1ae08745Sheppo { 1015*1ae08745Sheppo _NOTE(ARGUNUSED(cred)) 1016*1ae08745Sheppo 1017*1ae08745Sheppo PR1("vdc_write(): Entered"); 1018*1ae08745Sheppo return (physio(vdc_strategy, NULL, dev, B_WRITE, minphys, uio)); 1019*1ae08745Sheppo } 1020*1ae08745Sheppo 1021*1ae08745Sheppo static int 1022*1ae08745Sheppo vdc_aread(dev_t dev, struct aio_req *aio, cred_t *cred) 1023*1ae08745Sheppo { 1024*1ae08745Sheppo _NOTE(ARGUNUSED(cred)) 1025*1ae08745Sheppo 1026*1ae08745Sheppo PR1("vdc_aread(): Entered"); 1027*1ae08745Sheppo return (aphysio(vdc_strategy, anocancel, dev, B_READ, minphys, aio)); 1028*1ae08745Sheppo } 1029*1ae08745Sheppo 1030*1ae08745Sheppo static int 1031*1ae08745Sheppo vdc_awrite(dev_t dev, struct aio_req *aio, cred_t *cred) 1032*1ae08745Sheppo { 1033*1ae08745Sheppo _NOTE(ARGUNUSED(cred)) 1034*1ae08745Sheppo 1035*1ae08745Sheppo PR1("vdc_awrite(): Entered"); 1036*1ae08745Sheppo return (aphysio(vdc_strategy, anocancel, dev, B_WRITE, minphys, aio)); 1037*1ae08745Sheppo } 1038*1ae08745Sheppo 1039*1ae08745Sheppo 1040*1ae08745Sheppo /* -------------------------------------------------------------------------- */ 1041*1ae08745Sheppo 1042*1ae08745Sheppo /* 1043*1ae08745Sheppo * Handshake support 1044*1ae08745Sheppo */ 1045*1ae08745Sheppo 1046*1ae08745Sheppo /* 1047*1ae08745Sheppo * vdc_init_handshake_negotiation 1048*1ae08745Sheppo * 1049*1ae08745Sheppo * Description: 1050*1ae08745Sheppo * This function is called to trigger the handshake negotiations between 1051*1ae08745Sheppo * the client (vdc) and the server (vds). It may be called multiple times. 1052*1ae08745Sheppo * 1053*1ae08745Sheppo * Parameters: 1054*1ae08745Sheppo * vdc - soft state pointer 1055*1ae08745Sheppo */ 1056*1ae08745Sheppo static void 1057*1ae08745Sheppo vdc_init_handshake_negotiation(void *arg) 1058*1ae08745Sheppo { 1059*1ae08745Sheppo vdc_t *vdc = (vdc_t *)(void *)arg; 1060*1ae08745Sheppo vd_state_t state; 1061*1ae08745Sheppo 1062*1ae08745Sheppo ASSERT(vdc != NULL); 1063*1ae08745Sheppo ASSERT(vdc->ldc_state == LDC_UP); 1064*1ae08745Sheppo 1065*1ae08745Sheppo mutex_enter(&vdc->lock); 1066*1ae08745Sheppo 1067*1ae08745Sheppo /* 1068*1ae08745Sheppo * Do not continue if another thread has triggered a handshake which 1069*1ae08745Sheppo * is in progress or detach() has stopped further handshakes. 1070*1ae08745Sheppo */ 1071*1ae08745Sheppo if (vdc->initialized & (VDC_HANDSHAKE | VDC_HANDSHAKE_STOP)) { 1072*1ae08745Sheppo PR0("%s[%d] Negotiation not triggered. [init=%x]\n", 1073*1ae08745Sheppo __func__, vdc->instance, vdc->initialized); 1074*1ae08745Sheppo mutex_exit(&vdc->lock); 1075*1ae08745Sheppo return; 1076*1ae08745Sheppo } 1077*1ae08745Sheppo 1078*1ae08745Sheppo PR0("Initializing vdc<->vds handshake\n"); 1079*1ae08745Sheppo 1080*1ae08745Sheppo vdc->initialized |= VDC_HANDSHAKE; 1081*1ae08745Sheppo 1082*1ae08745Sheppo state = vdc->state; 1083*1ae08745Sheppo 1084*1ae08745Sheppo if (state == VD_STATE_INIT) { 1085*1ae08745Sheppo (void) vdc_init_ver_negotiation(vdc); 1086*1ae08745Sheppo } else if (state == VD_STATE_VER) { 1087*1ae08745Sheppo (void) vdc_init_attr_negotiation(vdc); 1088*1ae08745Sheppo } else if (state == VD_STATE_ATTR) { 1089*1ae08745Sheppo (void) vdc_init_dring_negotiate(vdc); 1090*1ae08745Sheppo } else if (state == VD_STATE_DATA) { 1091*1ae08745Sheppo /* 1092*1ae08745Sheppo * nothing to do - we have already completed the negotiation 1093*1ae08745Sheppo * and we can transmit data when ready. 1094*1ae08745Sheppo */ 1095*1ae08745Sheppo PR0("%s[%d] Negotiation triggered after handshake completed", 1096*1ae08745Sheppo __func__, vdc->instance); 1097*1ae08745Sheppo } 1098*1ae08745Sheppo 1099*1ae08745Sheppo mutex_exit(&vdc->lock); 1100*1ae08745Sheppo } 1101*1ae08745Sheppo 1102*1ae08745Sheppo static int 1103*1ae08745Sheppo vdc_init_ver_negotiation(vdc_t *vdc) 1104*1ae08745Sheppo { 1105*1ae08745Sheppo vio_ver_msg_t pkt; 1106*1ae08745Sheppo size_t msglen = sizeof (pkt); 1107*1ae08745Sheppo int status = -1; 1108*1ae08745Sheppo 1109*1ae08745Sheppo PR0("%s: Entered.\n", __func__); 1110*1ae08745Sheppo 1111*1ae08745Sheppo ASSERT(vdc != NULL); 1112*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 1113*1ae08745Sheppo 1114*1ae08745Sheppo /* 1115*1ae08745Sheppo * set the Session ID to a unique value 1116*1ae08745Sheppo * (the lower 32 bits of the clock tick) 1117*1ae08745Sheppo */ 1118*1ae08745Sheppo vdc->session_id = ((uint32_t)gettick() & 0xffffffff); 1119*1ae08745Sheppo 1120*1ae08745Sheppo pkt.tag.vio_msgtype = VIO_TYPE_CTRL; 1121*1ae08745Sheppo pkt.tag.vio_subtype = VIO_SUBTYPE_INFO; 1122*1ae08745Sheppo pkt.tag.vio_subtype_env = VIO_VER_INFO; 1123*1ae08745Sheppo pkt.tag.vio_sid = vdc->session_id; 1124*1ae08745Sheppo pkt.dev_class = VDEV_DISK; 1125*1ae08745Sheppo pkt.ver_major = VD_VER_MAJOR; 1126*1ae08745Sheppo pkt.ver_minor = VD_VER_MINOR; 1127*1ae08745Sheppo 1128*1ae08745Sheppo status = vdc_send(vdc->ldc_handle, (caddr_t)&pkt, &msglen); 1129*1ae08745Sheppo PR0("%s: vdc_send(status = %d)\n", __func__, status); 1130*1ae08745Sheppo 1131*1ae08745Sheppo if ((status != 0) || (msglen != sizeof (vio_ver_msg_t))) { 1132*1ae08745Sheppo PR0("%s[%d] vdc_send failed: id(%lx) rv(%d) size(%d)\n", 1133*1ae08745Sheppo __func__, vdc->instance, vdc->ldc_handle, 1134*1ae08745Sheppo status, msglen); 1135*1ae08745Sheppo if (msglen != sizeof (vio_ver_msg_t)) 1136*1ae08745Sheppo status = ENOMSG; 1137*1ae08745Sheppo } 1138*1ae08745Sheppo 1139*1ae08745Sheppo return (status); 1140*1ae08745Sheppo } 1141*1ae08745Sheppo 1142*1ae08745Sheppo static int 1143*1ae08745Sheppo vdc_init_attr_negotiation(vdc_t *vdc) 1144*1ae08745Sheppo { 1145*1ae08745Sheppo vd_attr_msg_t pkt; 1146*1ae08745Sheppo size_t msglen = sizeof (pkt); 1147*1ae08745Sheppo int status; 1148*1ae08745Sheppo 1149*1ae08745Sheppo ASSERT(vdc != NULL); 1150*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 1151*1ae08745Sheppo 1152*1ae08745Sheppo PR0("%s[%d] entered\n", __func__, vdc->instance); 1153*1ae08745Sheppo 1154*1ae08745Sheppo /* fill in tag */ 1155*1ae08745Sheppo pkt.tag.vio_msgtype = VIO_TYPE_CTRL; 1156*1ae08745Sheppo pkt.tag.vio_subtype = VIO_SUBTYPE_INFO; 1157*1ae08745Sheppo pkt.tag.vio_subtype_env = VIO_ATTR_INFO; 1158*1ae08745Sheppo pkt.tag.vio_sid = vdc->session_id; 1159*1ae08745Sheppo /* fill in payload */ 1160*1ae08745Sheppo pkt.max_xfer_sz = vdc->max_xfer_sz; 1161*1ae08745Sheppo pkt.vdisk_block_size = vdc->block_size; 1162*1ae08745Sheppo pkt.xfer_mode = VIO_DRING_MODE; 1163*1ae08745Sheppo pkt.operations = 0; /* server will set bits of valid operations */ 1164*1ae08745Sheppo pkt.vdisk_type = 0; /* server will set to valid device type */ 1165*1ae08745Sheppo pkt.vdisk_size = 0; /* server will set to valid size */ 1166*1ae08745Sheppo 1167*1ae08745Sheppo status = vdc_send(vdc->ldc_handle, (caddr_t)&pkt, &msglen); 1168*1ae08745Sheppo PR0("%s: vdc_send(status = %d)\n", __func__, status); 1169*1ae08745Sheppo 1170*1ae08745Sheppo if ((status != 0) || (msglen != sizeof (vio_ver_msg_t))) { 1171*1ae08745Sheppo PR0("%s[%d] ldc_write failed: id(%lx) rv(%d) size (%d)\n", 1172*1ae08745Sheppo __func__, vdc->instance, vdc->ldc_handle, 1173*1ae08745Sheppo status, msglen); 1174*1ae08745Sheppo if (msglen != sizeof (vio_ver_msg_t)) 1175*1ae08745Sheppo status = ENOMSG; 1176*1ae08745Sheppo } 1177*1ae08745Sheppo 1178*1ae08745Sheppo return (status); 1179*1ae08745Sheppo } 1180*1ae08745Sheppo 1181*1ae08745Sheppo static int 1182*1ae08745Sheppo vdc_init_dring_negotiate(vdc_t *vdc) 1183*1ae08745Sheppo { 1184*1ae08745Sheppo vio_dring_reg_msg_t pkt; 1185*1ae08745Sheppo size_t msglen = sizeof (pkt); 1186*1ae08745Sheppo int status = -1; 1187*1ae08745Sheppo 1188*1ae08745Sheppo ASSERT(vdc != NULL); 1189*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 1190*1ae08745Sheppo 1191*1ae08745Sheppo status = vdc_init_descriptor_ring(vdc); 1192*1ae08745Sheppo PR0("%s[%d] Init of descriptor ring completed (status = %d)\n", 1193*1ae08745Sheppo __func__, vdc->instance, status); 1194*1ae08745Sheppo if (status != 0) { 1195*1ae08745Sheppo cmn_err(CE_CONT, "[%d] Failed to init DRing (status = %d)\n", 1196*1ae08745Sheppo vdc->instance, status); 1197*1ae08745Sheppo vdc_reset_connection(vdc, B_FALSE); 1198*1ae08745Sheppo return (status); 1199*1ae08745Sheppo } 1200*1ae08745Sheppo 1201*1ae08745Sheppo /* fill in tag */ 1202*1ae08745Sheppo pkt.tag.vio_msgtype = VIO_TYPE_CTRL; 1203*1ae08745Sheppo pkt.tag.vio_subtype = VIO_SUBTYPE_INFO; 1204*1ae08745Sheppo pkt.tag.vio_subtype_env = VIO_DRING_REG; 1205*1ae08745Sheppo pkt.tag.vio_sid = vdc->session_id; 1206*1ae08745Sheppo /* fill in payload */ 1207*1ae08745Sheppo pkt.dring_ident = 0; 1208*1ae08745Sheppo pkt.num_descriptors = VD_DRING_LEN; 1209*1ae08745Sheppo pkt.descriptor_size = VD_DRING_ENTRY_SZ; 1210*1ae08745Sheppo pkt.options = (VIO_TX_DRING | VIO_RX_DRING); 1211*1ae08745Sheppo pkt.ncookies = vdc->dring_cookie_count; 1212*1ae08745Sheppo pkt.cookie[0] = vdc->dring_cookie[0]; /* for now just one cookie */ 1213*1ae08745Sheppo 1214*1ae08745Sheppo status = vdc_send(vdc->ldc_handle, (caddr_t)&pkt, &msglen); 1215*1ae08745Sheppo if (status != 0) { 1216*1ae08745Sheppo PR0("%s[%d] Failed to register DRing (status = %d)\n", 1217*1ae08745Sheppo __func__, vdc->instance, status); 1218*1ae08745Sheppo vdc_reset_connection(vdc, B_FALSE); 1219*1ae08745Sheppo } 1220*1ae08745Sheppo 1221*1ae08745Sheppo return (status); 1222*1ae08745Sheppo } 1223*1ae08745Sheppo 1224*1ae08745Sheppo 1225*1ae08745Sheppo /* -------------------------------------------------------------------------- */ 1226*1ae08745Sheppo 1227*1ae08745Sheppo /* 1228*1ae08745Sheppo * LDC helper routines 1229*1ae08745Sheppo */ 1230*1ae08745Sheppo 1231*1ae08745Sheppo /* 1232*1ae08745Sheppo * Function: 1233*1ae08745Sheppo * vdc_send() 1234*1ae08745Sheppo * 1235*1ae08745Sheppo * Description: 1236*1ae08745Sheppo * The function encapsulates the call to write a message using LDC. 1237*1ae08745Sheppo * If LDC indicates that the call failed due to the queue being full, 1238*1ae08745Sheppo * we retry the ldc_write() [ up to 'vdc_retries' time ], otherwise 1239*1ae08745Sheppo * we return the error returned by LDC. 1240*1ae08745Sheppo * 1241*1ae08745Sheppo * Arguments: 1242*1ae08745Sheppo * ldc_handle - LDC handle for the channel this instance of vdc uses 1243*1ae08745Sheppo * pkt - address of LDC message to be sent 1244*1ae08745Sheppo * msglen - the size of the message being sent. When the function 1245*1ae08745Sheppo * returns, this contains the number of bytes written. 1246*1ae08745Sheppo * 1247*1ae08745Sheppo * Return Code: 1248*1ae08745Sheppo * 0 - Success. 1249*1ae08745Sheppo * EINVAL - pkt or msglen were NULL 1250*1ae08745Sheppo * ECONNRESET - The connection was not up. 1251*1ae08745Sheppo * EWOULDBLOCK - LDC queue is full 1252*1ae08745Sheppo * xxx - other error codes returned by ldc_write 1253*1ae08745Sheppo */ 1254*1ae08745Sheppo static int 1255*1ae08745Sheppo vdc_send(ldc_handle_t ldc_handle, caddr_t pkt, size_t *msglen) 1256*1ae08745Sheppo { 1257*1ae08745Sheppo size_t size = 0; 1258*1ae08745Sheppo int retries = 0; 1259*1ae08745Sheppo int status = 0; 1260*1ae08745Sheppo 1261*1ae08745Sheppo ASSERT(msglen != NULL); 1262*1ae08745Sheppo ASSERT(*msglen != 0); 1263*1ae08745Sheppo 1264*1ae08745Sheppo do { 1265*1ae08745Sheppo size = *msglen; 1266*1ae08745Sheppo status = ldc_write(ldc_handle, pkt, &size); 1267*1ae08745Sheppo } while (status == EWOULDBLOCK && retries++ < vdc_retries); 1268*1ae08745Sheppo 1269*1ae08745Sheppo /* return the last size written */ 1270*1ae08745Sheppo *msglen = size; 1271*1ae08745Sheppo 1272*1ae08745Sheppo return (status); 1273*1ae08745Sheppo } 1274*1ae08745Sheppo 1275*1ae08745Sheppo /* 1276*1ae08745Sheppo * Function: 1277*1ae08745Sheppo * vdc_get_ldc_id() 1278*1ae08745Sheppo * 1279*1ae08745Sheppo * Description: 1280*1ae08745Sheppo * This function gets the 'ldc-id' for this particular instance of vdc. 1281*1ae08745Sheppo * The id returned is the guest domain channel endpoint LDC uses for 1282*1ae08745Sheppo * communication with vds. 1283*1ae08745Sheppo * 1284*1ae08745Sheppo * Arguments: 1285*1ae08745Sheppo * dip - dev info pointer for this instance of the device driver. 1286*1ae08745Sheppo * ldc_id - pointer to variable used to return the 'ldc-id' found. 1287*1ae08745Sheppo * 1288*1ae08745Sheppo * Return Code: 1289*1ae08745Sheppo * 0 - Success. 1290*1ae08745Sheppo * ENOENT - Expected node or property did not exist. 1291*1ae08745Sheppo * ENXIO - Unexpected error communicating with MD framework 1292*1ae08745Sheppo */ 1293*1ae08745Sheppo static int 1294*1ae08745Sheppo vdc_get_ldc_id(dev_info_t *dip, uint64_t *ldc_id) 1295*1ae08745Sheppo { 1296*1ae08745Sheppo int status = ENOENT; 1297*1ae08745Sheppo char *node_name = NULL; 1298*1ae08745Sheppo md_t *mdp = NULL; 1299*1ae08745Sheppo int num_nodes; 1300*1ae08745Sheppo int num_vdevs; 1301*1ae08745Sheppo int num_chans; 1302*1ae08745Sheppo mde_cookie_t rootnode; 1303*1ae08745Sheppo mde_cookie_t *listp = NULL; 1304*1ae08745Sheppo mde_cookie_t *chanp = NULL; 1305*1ae08745Sheppo boolean_t found_inst = B_FALSE; 1306*1ae08745Sheppo int listsz; 1307*1ae08745Sheppo int idx; 1308*1ae08745Sheppo uint64_t md_inst; 1309*1ae08745Sheppo int obp_inst; 1310*1ae08745Sheppo int instance = ddi_get_instance(dip); 1311*1ae08745Sheppo 1312*1ae08745Sheppo ASSERT(ldc_id != NULL); 1313*1ae08745Sheppo *ldc_id = 0; 1314*1ae08745Sheppo 1315*1ae08745Sheppo /* 1316*1ae08745Sheppo * Get the OBP instance number for comparison with the MD instance 1317*1ae08745Sheppo * 1318*1ae08745Sheppo * The "cfg-handle" property of a vdc node in an MD contains the MD's 1319*1ae08745Sheppo * notion of "instance", or unique identifier, for that node; OBP 1320*1ae08745Sheppo * stores the value of the "cfg-handle" MD property as the value of 1321*1ae08745Sheppo * the "reg" property on the node in the device tree it builds from 1322*1ae08745Sheppo * the MD and passes to Solaris. Thus, we look up the devinfo node's 1323*1ae08745Sheppo * "reg" property value to uniquely identify this device instance. 1324*1ae08745Sheppo * If the "reg" property cannot be found, the device tree state is 1325*1ae08745Sheppo * presumably so broken that there is no point in continuing. 1326*1ae08745Sheppo */ 1327*1ae08745Sheppo if (!ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, OBP_REG)) { 1328*1ae08745Sheppo cmn_err(CE_WARN, "'%s' property does not exist", OBP_REG); 1329*1ae08745Sheppo return (ENOENT); 1330*1ae08745Sheppo } 1331*1ae08745Sheppo obp_inst = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1332*1ae08745Sheppo OBP_REG, -1); 1333*1ae08745Sheppo PR1("%s[%d]: OBP inst=%d\n", __func__, instance, obp_inst); 1334*1ae08745Sheppo 1335*1ae08745Sheppo /* 1336*1ae08745Sheppo * We now walk the MD nodes and if an instance of a vdc node matches 1337*1ae08745Sheppo * the instance got from OBP we get the ldc-id property. 1338*1ae08745Sheppo */ 1339*1ae08745Sheppo if ((mdp = md_get_handle()) == NULL) { 1340*1ae08745Sheppo cmn_err(CE_WARN, "unable to init machine description"); 1341*1ae08745Sheppo return (ENXIO); 1342*1ae08745Sheppo } 1343*1ae08745Sheppo 1344*1ae08745Sheppo num_nodes = md_node_count(mdp); 1345*1ae08745Sheppo ASSERT(num_nodes > 0); 1346*1ae08745Sheppo 1347*1ae08745Sheppo listsz = num_nodes * sizeof (mde_cookie_t); 1348*1ae08745Sheppo 1349*1ae08745Sheppo /* allocate memory for nodes */ 1350*1ae08745Sheppo listp = kmem_zalloc(listsz, KM_SLEEP); 1351*1ae08745Sheppo chanp = kmem_zalloc(listsz, KM_SLEEP); 1352*1ae08745Sheppo 1353*1ae08745Sheppo rootnode = md_root_node(mdp); 1354*1ae08745Sheppo ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE); 1355*1ae08745Sheppo 1356*1ae08745Sheppo /* 1357*1ae08745Sheppo * Search for all the virtual devices, we will then check to see which 1358*1ae08745Sheppo * ones are disk nodes. 1359*1ae08745Sheppo */ 1360*1ae08745Sheppo num_vdevs = md_scan_dag(mdp, rootnode, 1361*1ae08745Sheppo md_find_name(mdp, VDC_MD_VDEV_NAME), 1362*1ae08745Sheppo md_find_name(mdp, "fwd"), listp); 1363*1ae08745Sheppo 1364*1ae08745Sheppo if (num_vdevs <= 0) { 1365*1ae08745Sheppo cmn_err(CE_NOTE, "No '%s' node found", VDC_MD_VDEV_NAME); 1366*1ae08745Sheppo status = ENOENT; 1367*1ae08745Sheppo goto done; 1368*1ae08745Sheppo } 1369*1ae08745Sheppo 1370*1ae08745Sheppo PR1("%s[%d] num_vdevs=%d\n", __func__, instance, num_vdevs); 1371*1ae08745Sheppo for (idx = 0; idx < num_vdevs; idx++) { 1372*1ae08745Sheppo status = md_get_prop_str(mdp, listp[idx], "name", &node_name); 1373*1ae08745Sheppo if ((status != 0) || (node_name == NULL)) { 1374*1ae08745Sheppo cmn_err(CE_NOTE, "Unable to get name of node type '%s'" 1375*1ae08745Sheppo ": err %d", VDC_MD_VDEV_NAME, status); 1376*1ae08745Sheppo continue; 1377*1ae08745Sheppo } 1378*1ae08745Sheppo 1379*1ae08745Sheppo PR1("%s[%d] Found node %s\n", __func__, instance, node_name); 1380*1ae08745Sheppo if (strcmp(VDC_MD_DISK_NAME, node_name) == 0) { 1381*1ae08745Sheppo status = md_get_prop_val(mdp, listp[idx], 1382*1ae08745Sheppo VDC_MD_CFG_HDL, &md_inst); 1383*1ae08745Sheppo PR1("%s[%d] vdc inst# in MD=%d\n", 1384*1ae08745Sheppo __func__, instance, md_inst); 1385*1ae08745Sheppo if ((status == 0) && (md_inst == obp_inst)) { 1386*1ae08745Sheppo found_inst = B_TRUE; 1387*1ae08745Sheppo break; 1388*1ae08745Sheppo } 1389*1ae08745Sheppo } 1390*1ae08745Sheppo } 1391*1ae08745Sheppo 1392*1ae08745Sheppo if (found_inst == B_FALSE) { 1393*1ae08745Sheppo cmn_err(CE_NOTE, "Unable to find correct '%s' node", 1394*1ae08745Sheppo VDC_MD_DISK_NAME); 1395*1ae08745Sheppo status = ENOENT; 1396*1ae08745Sheppo goto done; 1397*1ae08745Sheppo } 1398*1ae08745Sheppo PR0("%s[%d] MD inst=%d\n", __func__, instance, md_inst); 1399*1ae08745Sheppo 1400*1ae08745Sheppo /* get the channels for this node */ 1401*1ae08745Sheppo num_chans = md_scan_dag(mdp, listp[idx], 1402*1ae08745Sheppo md_find_name(mdp, VDC_MD_CHAN_NAME), 1403*1ae08745Sheppo md_find_name(mdp, "fwd"), chanp); 1404*1ae08745Sheppo 1405*1ae08745Sheppo /* expecting at least one channel */ 1406*1ae08745Sheppo if (num_chans <= 0) { 1407*1ae08745Sheppo cmn_err(CE_NOTE, "No '%s' node for '%s' port", 1408*1ae08745Sheppo VDC_MD_CHAN_NAME, VDC_MD_VDEV_NAME); 1409*1ae08745Sheppo status = ENOENT; 1410*1ae08745Sheppo goto done; 1411*1ae08745Sheppo 1412*1ae08745Sheppo } else if (num_chans != 1) { 1413*1ae08745Sheppo PR0("%s[%d] Expected 1 '%s' node for '%s' port, found %d\n", 1414*1ae08745Sheppo __func__, instance, VDC_MD_CHAN_NAME, VDC_MD_VDEV_NAME, 1415*1ae08745Sheppo num_chans); 1416*1ae08745Sheppo } 1417*1ae08745Sheppo 1418*1ae08745Sheppo /* 1419*1ae08745Sheppo * We use the first channel found (index 0), irrespective of how 1420*1ae08745Sheppo * many are there in total. 1421*1ae08745Sheppo */ 1422*1ae08745Sheppo if (md_get_prop_val(mdp, chanp[0], VDC_ID_PROP, ldc_id) != 0) { 1423*1ae08745Sheppo cmn_err(CE_NOTE, "Channel '%s' property not found", 1424*1ae08745Sheppo VDC_ID_PROP); 1425*1ae08745Sheppo status = ENOENT; 1426*1ae08745Sheppo } 1427*1ae08745Sheppo 1428*1ae08745Sheppo PR0("%s[%d] LDC id is 0x%lx\n", __func__, instance, *ldc_id); 1429*1ae08745Sheppo 1430*1ae08745Sheppo done: 1431*1ae08745Sheppo if (chanp) 1432*1ae08745Sheppo kmem_free(chanp, listsz); 1433*1ae08745Sheppo if (listp) 1434*1ae08745Sheppo kmem_free(listp, listsz); 1435*1ae08745Sheppo 1436*1ae08745Sheppo (void) md_fini_handle(mdp); 1437*1ae08745Sheppo 1438*1ae08745Sheppo return (status); 1439*1ae08745Sheppo } 1440*1ae08745Sheppo 1441*1ae08745Sheppo 1442*1ae08745Sheppo /* 1443*1ae08745Sheppo * vdc_is_able_to_tx_data() 1444*1ae08745Sheppo * 1445*1ae08745Sheppo * Description: 1446*1ae08745Sheppo * This function checks if we are able to send data to the 1447*1ae08745Sheppo * vDisk server (vds). The LDC connection needs to be up and 1448*1ae08745Sheppo * vdc & vds need to have completed the handshake negotiation. 1449*1ae08745Sheppo * 1450*1ae08745Sheppo * Parameters: 1451*1ae08745Sheppo * vdc - soft state pointer 1452*1ae08745Sheppo * flag - flag to indicate if we can block or not 1453*1ae08745Sheppo * [ If O_NONBLOCK or O_NDELAY (which are defined in 1454*1ae08745Sheppo * open(2)) are set then do not block) 1455*1ae08745Sheppo * 1456*1ae08745Sheppo * Return Values 1457*1ae08745Sheppo * B_TRUE - can talk to vds 1458*1ae08745Sheppo * B_FALSE - unable to talk to vds 1459*1ae08745Sheppo */ 1460*1ae08745Sheppo static boolean_t 1461*1ae08745Sheppo vdc_is_able_to_tx_data(vdc_t *vdc, int flag) 1462*1ae08745Sheppo { 1463*1ae08745Sheppo vd_state_t state; 1464*1ae08745Sheppo uint32_t ldc_state; 1465*1ae08745Sheppo uint_t retries = 0; 1466*1ae08745Sheppo int rv = -1; 1467*1ae08745Sheppo 1468*1ae08745Sheppo ASSERT(vdc != NULL); 1469*1ae08745Sheppo 1470*1ae08745Sheppo mutex_enter(&vdc->lock); 1471*1ae08745Sheppo state = vdc->state; 1472*1ae08745Sheppo ldc_state = vdc->ldc_state; 1473*1ae08745Sheppo mutex_exit(&vdc->lock); 1474*1ae08745Sheppo 1475*1ae08745Sheppo if ((state == VD_STATE_DATA) && (ldc_state == LDC_UP)) 1476*1ae08745Sheppo return (B_TRUE); 1477*1ae08745Sheppo 1478*1ae08745Sheppo if ((flag & O_NONBLOCK) || (flag & O_NDELAY)) { 1479*1ae08745Sheppo PR0("%s[%d] Not ready to tx - state %d LDC state %d\n", 1480*1ae08745Sheppo __func__, vdc->instance, state, ldc_state); 1481*1ae08745Sheppo return (B_FALSE); 1482*1ae08745Sheppo } 1483*1ae08745Sheppo 1484*1ae08745Sheppo /* 1485*1ae08745Sheppo * We want to check and see if any negotiations triggered earlier 1486*1ae08745Sheppo * have succeeded. We are prepared to wait a little while in case 1487*1ae08745Sheppo * they are still in progress. 1488*1ae08745Sheppo */ 1489*1ae08745Sheppo mutex_enter(&vdc->lock); 1490*1ae08745Sheppo while ((vdc->ldc_state != LDC_UP) || (vdc->state != VD_STATE_DATA)) { 1491*1ae08745Sheppo PR0("%s: Waiting for connection at state %d (LDC state %d)\n", 1492*1ae08745Sheppo __func__, vdc->state, vdc->ldc_state); 1493*1ae08745Sheppo 1494*1ae08745Sheppo rv = cv_timedwait(&vdc->cv, &vdc->lock, 1495*1ae08745Sheppo VD_GET_TIMEOUT_HZ(retries)); 1496*1ae08745Sheppo 1497*1ae08745Sheppo /* 1498*1ae08745Sheppo * An rv of -1 indicates that we timed out without the LDC 1499*1ae08745Sheppo * state changing so it looks like the other side (vdc) is 1500*1ae08745Sheppo * not yet ready/responding. 1501*1ae08745Sheppo * 1502*1ae08745Sheppo * Any other value of rv indicates that the LDC triggered an 1503*1ae08745Sheppo * interrupt so we just loop again, check the handshake state 1504*1ae08745Sheppo * and keep waiting if necessary. 1505*1ae08745Sheppo */ 1506*1ae08745Sheppo if (rv == -1) { 1507*1ae08745Sheppo if (retries >= vdc_retries) { 1508*1ae08745Sheppo PR0("%s[%d] handshake wait timed out.\n", 1509*1ae08745Sheppo __func__, vdc->instance); 1510*1ae08745Sheppo mutex_exit(&vdc->lock); 1511*1ae08745Sheppo return (B_FALSE); 1512*1ae08745Sheppo } else { 1513*1ae08745Sheppo PR1("%s[%d] Retry #%d for handshake timedout\n", 1514*1ae08745Sheppo __func__, vdc->instance, retries); 1515*1ae08745Sheppo retries++; 1516*1ae08745Sheppo } 1517*1ae08745Sheppo } 1518*1ae08745Sheppo } 1519*1ae08745Sheppo 1520*1ae08745Sheppo ASSERT(vdc->ldc_state == LDC_UP); 1521*1ae08745Sheppo ASSERT(vdc->state == VD_STATE_DATA); 1522*1ae08745Sheppo 1523*1ae08745Sheppo mutex_exit(&vdc->lock); 1524*1ae08745Sheppo 1525*1ae08745Sheppo return (B_TRUE); 1526*1ae08745Sheppo } 1527*1ae08745Sheppo 1528*1ae08745Sheppo 1529*1ae08745Sheppo static void 1530*1ae08745Sheppo vdc_terminate_ldc(vdc_t *vdc) 1531*1ae08745Sheppo { 1532*1ae08745Sheppo int instance = ddi_get_instance(vdc->dip); 1533*1ae08745Sheppo 1534*1ae08745Sheppo ASSERT(vdc != NULL); 1535*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 1536*1ae08745Sheppo 1537*1ae08745Sheppo PR0("%s[%d] initialized=%x\n", __func__, instance, vdc->initialized); 1538*1ae08745Sheppo 1539*1ae08745Sheppo if (vdc->initialized & VDC_LDC_OPEN) { 1540*1ae08745Sheppo PR0("%s[%d]: ldc_close()\n", __func__, instance); 1541*1ae08745Sheppo (void) ldc_close(vdc->ldc_handle); 1542*1ae08745Sheppo } 1543*1ae08745Sheppo if (vdc->initialized & VDC_LDC_CB) { 1544*1ae08745Sheppo PR0("%s[%d]: ldc_unreg_callback()\n", __func__, instance); 1545*1ae08745Sheppo (void) ldc_unreg_callback(vdc->ldc_handle); 1546*1ae08745Sheppo } 1547*1ae08745Sheppo if (vdc->initialized & VDC_LDC) { 1548*1ae08745Sheppo PR0("%s[%d]: ldc_fini()\n", __func__, instance); 1549*1ae08745Sheppo (void) ldc_fini(vdc->ldc_handle); 1550*1ae08745Sheppo vdc->ldc_handle = NULL; 1551*1ae08745Sheppo } 1552*1ae08745Sheppo 1553*1ae08745Sheppo vdc->initialized &= ~(VDC_LDC | VDC_LDC_CB | VDC_LDC_OPEN); 1554*1ae08745Sheppo } 1555*1ae08745Sheppo 1556*1ae08745Sheppo static void 1557*1ae08745Sheppo vdc_reset_connection(vdc_t *vdc, boolean_t reset_ldc) 1558*1ae08745Sheppo { 1559*1ae08745Sheppo int status; 1560*1ae08745Sheppo 1561*1ae08745Sheppo ASSERT(vdc != NULL); 1562*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 1563*1ae08745Sheppo 1564*1ae08745Sheppo PR0("%s[%d] Entered\n", __func__, vdc->instance); 1565*1ae08745Sheppo 1566*1ae08745Sheppo vdc->state = VD_STATE_INIT; 1567*1ae08745Sheppo 1568*1ae08745Sheppo if (reset_ldc == B_TRUE) { 1569*1ae08745Sheppo status = ldc_reset(vdc->ldc_handle); 1570*1ae08745Sheppo PR0("%s[%d] ldc_reset() = %d\n", 1571*1ae08745Sheppo __func__, vdc->instance, status); 1572*1ae08745Sheppo } 1573*1ae08745Sheppo 1574*1ae08745Sheppo vdc->initialized &= ~VDC_HANDSHAKE; 1575*1ae08745Sheppo PR0("%s[%d] init=%x\n", __func__, vdc->instance, vdc->initialized); 1576*1ae08745Sheppo } 1577*1ae08745Sheppo 1578*1ae08745Sheppo /* -------------------------------------------------------------------------- */ 1579*1ae08745Sheppo 1580*1ae08745Sheppo /* 1581*1ae08745Sheppo * Descriptor Ring helper routines 1582*1ae08745Sheppo */ 1583*1ae08745Sheppo 1584*1ae08745Sheppo static int 1585*1ae08745Sheppo vdc_init_descriptor_ring(vdc_t *vdc) 1586*1ae08745Sheppo { 1587*1ae08745Sheppo vd_dring_entry_t *dep = NULL; /* DRing Entry pointer */ 1588*1ae08745Sheppo int status = -1; 1589*1ae08745Sheppo int i; 1590*1ae08745Sheppo 1591*1ae08745Sheppo PR0("%s\n", __func__); 1592*1ae08745Sheppo 1593*1ae08745Sheppo ASSERT(vdc != NULL); 1594*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 1595*1ae08745Sheppo ASSERT(vdc->ldc_handle != NULL); 1596*1ae08745Sheppo 1597*1ae08745Sheppo status = ldc_mem_dring_create(VD_DRING_LEN, VD_DRING_ENTRY_SZ, 1598*1ae08745Sheppo &vdc->ldc_dring_hdl); 1599*1ae08745Sheppo if ((vdc->ldc_dring_hdl == NULL) || (status != 0)) { 1600*1ae08745Sheppo PR0("%s: Failed to create a descriptor ring", __func__); 1601*1ae08745Sheppo return (status); 1602*1ae08745Sheppo } 1603*1ae08745Sheppo vdc->initialized |= VDC_DRING; 1604*1ae08745Sheppo vdc->dring_entry_size = VD_DRING_ENTRY_SZ; 1605*1ae08745Sheppo vdc->dring_len = VD_DRING_LEN; 1606*1ae08745Sheppo 1607*1ae08745Sheppo vdc->dring_cookie = kmem_zalloc(sizeof (ldc_mem_cookie_t), KM_SLEEP); 1608*1ae08745Sheppo 1609*1ae08745Sheppo status = ldc_mem_dring_bind(vdc->ldc_handle, vdc->ldc_dring_hdl, 1610*1ae08745Sheppo LDC_SHADOW_MAP, LDC_MEM_RW, &vdc->dring_cookie[0], 1611*1ae08745Sheppo &vdc->dring_cookie_count); 1612*1ae08745Sheppo if (status != 0) { 1613*1ae08745Sheppo PR0("%s: Failed to bind descriptor ring (%p) to channel (%p)\n", 1614*1ae08745Sheppo __func__, vdc->ldc_dring_hdl, vdc->ldc_handle); 1615*1ae08745Sheppo return (status); 1616*1ae08745Sheppo } 1617*1ae08745Sheppo ASSERT(vdc->dring_cookie_count == 1); 1618*1ae08745Sheppo vdc->initialized |= VDC_DRING_BOUND; 1619*1ae08745Sheppo 1620*1ae08745Sheppo status = ldc_mem_dring_info(vdc->ldc_dring_hdl, &vdc->dring_mem_info); 1621*1ae08745Sheppo if (status != 0) { 1622*1ae08745Sheppo PR0("%s: Failed to get info for descriptor ring (%p)\n", 1623*1ae08745Sheppo __func__, vdc->ldc_dring_hdl); 1624*1ae08745Sheppo return (status); 1625*1ae08745Sheppo } 1626*1ae08745Sheppo 1627*1ae08745Sheppo /* Allocate the local copy of this dring */ 1628*1ae08745Sheppo vdc->local_dring = kmem_zalloc(VD_DRING_LEN * sizeof (vdc_local_desc_t), 1629*1ae08745Sheppo KM_SLEEP); 1630*1ae08745Sheppo vdc->initialized |= VDC_DRING_LOCAL; 1631*1ae08745Sheppo 1632*1ae08745Sheppo /* 1633*1ae08745Sheppo * Mark all DRing entries as free and init priv desc memory handles 1634*1ae08745Sheppo * If any entry is initialized, we need to free it later so we set 1635*1ae08745Sheppo * the bit in 'initialized' at the start. 1636*1ae08745Sheppo */ 1637*1ae08745Sheppo vdc->initialized |= VDC_DRING_ENTRY; 1638*1ae08745Sheppo for (i = 0; i < VD_DRING_LEN; i++) { 1639*1ae08745Sheppo dep = VDC_GET_DRING_ENTRY_PTR(vdc, i); 1640*1ae08745Sheppo dep->hdr.dstate = VIO_DESC_FREE; 1641*1ae08745Sheppo 1642*1ae08745Sheppo status = ldc_mem_alloc_handle(vdc->ldc_handle, 1643*1ae08745Sheppo &vdc->local_dring[i].desc_mhdl); 1644*1ae08745Sheppo if (status != 0) { 1645*1ae08745Sheppo cmn_err(CE_NOTE, "![%d] Failed to alloc mem handle for" 1646*1ae08745Sheppo " descriptor %d", vdc->instance, i); 1647*1ae08745Sheppo return (status); 1648*1ae08745Sheppo } 1649*1ae08745Sheppo vdc->local_dring[i].flags = VIO_DESC_FREE; 1650*1ae08745Sheppo vdc->local_dring[i].flags |= VDC_ALLOC_HANDLE; 1651*1ae08745Sheppo vdc->local_dring[i].dep = dep; 1652*1ae08745Sheppo 1653*1ae08745Sheppo mutex_init(&vdc->local_dring[i].lock, NULL, MUTEX_DRIVER, NULL); 1654*1ae08745Sheppo cv_init(&vdc->local_dring[i].cv, NULL, CV_DRIVER, NULL); 1655*1ae08745Sheppo } 1656*1ae08745Sheppo 1657*1ae08745Sheppo /* 1658*1ae08745Sheppo * We init the index of the last DRing entry used. Since the code to 1659*1ae08745Sheppo * get the next available entry increments it before selecting one, 1660*1ae08745Sheppo * we set it to the last DRing entry so that it wraps around to zero 1661*1ae08745Sheppo * for the 1st entry to be used. 1662*1ae08745Sheppo */ 1663*1ae08745Sheppo vdc->dring_curr_idx = VD_DRING_LEN - 1; 1664*1ae08745Sheppo 1665*1ae08745Sheppo return (status); 1666*1ae08745Sheppo } 1667*1ae08745Sheppo 1668*1ae08745Sheppo static void 1669*1ae08745Sheppo vdc_destroy_descriptor_ring(vdc_t *vdc) 1670*1ae08745Sheppo { 1671*1ae08745Sheppo ldc_mem_handle_t mhdl = NULL; 1672*1ae08745Sheppo int status = -1; 1673*1ae08745Sheppo int i; /* loop */ 1674*1ae08745Sheppo 1675*1ae08745Sheppo ASSERT(vdc != NULL); 1676*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 1677*1ae08745Sheppo ASSERT(vdc->state == VD_STATE_INIT); 1678*1ae08745Sheppo 1679*1ae08745Sheppo PR0("%s: Entered\n", __func__); 1680*1ae08745Sheppo 1681*1ae08745Sheppo if (vdc->initialized & VDC_DRING_ENTRY) { 1682*1ae08745Sheppo for (i = 0; i < VD_DRING_LEN; i++) { 1683*1ae08745Sheppo mhdl = vdc->local_dring[i].desc_mhdl; 1684*1ae08745Sheppo 1685*1ae08745Sheppo if (vdc->local_dring[i].flags | VDC_ALLOC_HANDLE) 1686*1ae08745Sheppo (void) ldc_mem_free_handle(mhdl); 1687*1ae08745Sheppo 1688*1ae08745Sheppo mutex_destroy(&vdc->local_dring[i].lock); 1689*1ae08745Sheppo cv_destroy(&vdc->local_dring[i].cv); 1690*1ae08745Sheppo 1691*1ae08745Sheppo bzero(&vdc->local_dring[i].desc_mhdl, 1692*1ae08745Sheppo sizeof (ldc_mem_handle_t)); 1693*1ae08745Sheppo } 1694*1ae08745Sheppo vdc->initialized &= ~VDC_DRING_ENTRY; 1695*1ae08745Sheppo } 1696*1ae08745Sheppo 1697*1ae08745Sheppo if (vdc->initialized & VDC_DRING_LOCAL) { 1698*1ae08745Sheppo kmem_free(vdc->local_dring, 1699*1ae08745Sheppo VD_DRING_LEN * sizeof (vdc_local_desc_t)); 1700*1ae08745Sheppo vdc->initialized &= ~VDC_DRING_LOCAL; 1701*1ae08745Sheppo } 1702*1ae08745Sheppo 1703*1ae08745Sheppo if (vdc->initialized & VDC_DRING_BOUND) { 1704*1ae08745Sheppo status = ldc_mem_dring_unbind(vdc->ldc_dring_hdl); 1705*1ae08745Sheppo if (status == 0) { 1706*1ae08745Sheppo vdc->initialized &= ~VDC_DRING_BOUND; 1707*1ae08745Sheppo } else { 1708*1ae08745Sheppo vdc_msg("%s: Failed to unbind Descriptor Ring (%lx)\n", 1709*1ae08745Sheppo vdc->ldc_dring_hdl); 1710*1ae08745Sheppo } 1711*1ae08745Sheppo } 1712*1ae08745Sheppo 1713*1ae08745Sheppo if (vdc->initialized & VDC_DRING_INIT) { 1714*1ae08745Sheppo status = ldc_mem_dring_destroy(vdc->ldc_dring_hdl); 1715*1ae08745Sheppo if (status == 0) { 1716*1ae08745Sheppo vdc->ldc_dring_hdl = NULL; 1717*1ae08745Sheppo bzero(&vdc->dring_mem_info, sizeof (ldc_mem_info_t)); 1718*1ae08745Sheppo vdc->initialized &= ~VDC_DRING_INIT; 1719*1ae08745Sheppo } else { 1720*1ae08745Sheppo vdc_msg("%s: Failed to destroy Descriptor Ring (%lx)\n", 1721*1ae08745Sheppo vdc->ldc_dring_hdl); 1722*1ae08745Sheppo } 1723*1ae08745Sheppo } 1724*1ae08745Sheppo } 1725*1ae08745Sheppo 1726*1ae08745Sheppo /* 1727*1ae08745Sheppo * vdc_get_next_dring_entry_idx() 1728*1ae08745Sheppo * 1729*1ae08745Sheppo * Description: 1730*1ae08745Sheppo * This function gets the index of the next Descriptor Ring entry available 1731*1ae08745Sheppo * 1732*1ae08745Sheppo * Return Value: 1733*1ae08745Sheppo * 0 <= rv < VD_DRING_LEN Next available slot 1734*1ae08745Sheppo * -1 DRing is full 1735*1ae08745Sheppo */ 1736*1ae08745Sheppo static int 1737*1ae08745Sheppo vdc_get_next_dring_entry_idx(vdc_t *vdc, uint_t num_slots_needed) 1738*1ae08745Sheppo { 1739*1ae08745Sheppo _NOTE(ARGUNUSED(num_slots_needed)) 1740*1ae08745Sheppo 1741*1ae08745Sheppo vd_dring_entry_t *dep = NULL; /* Dring Entry Pointer */ 1742*1ae08745Sheppo int idx = -1; 1743*1ae08745Sheppo int start_idx = 0; 1744*1ae08745Sheppo 1745*1ae08745Sheppo ASSERT(vdc != NULL); 1746*1ae08745Sheppo ASSERT(vdc->dring_len == VD_DRING_LEN); 1747*1ae08745Sheppo ASSERT(vdc->dring_curr_idx >= 0); 1748*1ae08745Sheppo ASSERT(vdc->dring_curr_idx < VD_DRING_LEN); 1749*1ae08745Sheppo ASSERT(mutex_owned(&vdc->dring_lock)); 1750*1ae08745Sheppo 1751*1ae08745Sheppo /* Start at the last entry used */ 1752*1ae08745Sheppo idx = start_idx = vdc->dring_curr_idx; 1753*1ae08745Sheppo 1754*1ae08745Sheppo /* 1755*1ae08745Sheppo * Loop through Descriptor Ring checking for a free entry until we reach 1756*1ae08745Sheppo * the entry we started at. We should never come close to filling the 1757*1ae08745Sheppo * Ring at any stage, instead this is just to prevent an entry which 1758*1ae08745Sheppo * gets into an inconsistent state (e.g. due to a request timing out) 1759*1ae08745Sheppo * from blocking progress. 1760*1ae08745Sheppo */ 1761*1ae08745Sheppo do { 1762*1ae08745Sheppo /* Get the next entry after the last known index tried */ 1763*1ae08745Sheppo idx = (idx + 1) % VD_DRING_LEN; 1764*1ae08745Sheppo 1765*1ae08745Sheppo dep = VDC_GET_DRING_ENTRY_PTR(vdc, idx); 1766*1ae08745Sheppo ASSERT(dep != NULL); 1767*1ae08745Sheppo 1768*1ae08745Sheppo if (dep->hdr.dstate == VIO_DESC_FREE) { 1769*1ae08745Sheppo ASSERT(idx >= 0); 1770*1ae08745Sheppo ASSERT(idx < VD_DRING_LEN); 1771*1ae08745Sheppo vdc->dring_curr_idx = idx; 1772*1ae08745Sheppo return (idx); 1773*1ae08745Sheppo 1774*1ae08745Sheppo } else if (dep->hdr.dstate == VIO_DESC_READY) { 1775*1ae08745Sheppo PR0("%s: Entry %d waiting to be accepted\n", 1776*1ae08745Sheppo __func__, idx); 1777*1ae08745Sheppo continue; 1778*1ae08745Sheppo 1779*1ae08745Sheppo } else if (dep->hdr.dstate == VIO_DESC_ACCEPTED) { 1780*1ae08745Sheppo PR0("%s: Entry %d waiting to be processed\n", 1781*1ae08745Sheppo __func__, idx); 1782*1ae08745Sheppo continue; 1783*1ae08745Sheppo 1784*1ae08745Sheppo } else if (dep->hdr.dstate == VIO_DESC_DONE) { 1785*1ae08745Sheppo PR0("%s: Entry %d done but not marked free\n", 1786*1ae08745Sheppo __func__, idx); 1787*1ae08745Sheppo 1788*1ae08745Sheppo /* 1789*1ae08745Sheppo * If we are currently panicking, interrupts are 1790*1ae08745Sheppo * disabled and we will not be getting ACKs from the 1791*1ae08745Sheppo * vDisk server so we mark the descriptor ring entries 1792*1ae08745Sheppo * as FREE here instead of in the ACK handler. 1793*1ae08745Sheppo */ 1794*1ae08745Sheppo if (panicstr) { 1795*1ae08745Sheppo (void) vdc_depopulate_descriptor(vdc, idx); 1796*1ae08745Sheppo dep->hdr.dstate = VIO_DESC_FREE; 1797*1ae08745Sheppo vdc->local_dring[idx].flags = VIO_DESC_FREE; 1798*1ae08745Sheppo } 1799*1ae08745Sheppo continue; 1800*1ae08745Sheppo 1801*1ae08745Sheppo } else { 1802*1ae08745Sheppo vdc_msg("Public Descriptor Ring entry corrupted"); 1803*1ae08745Sheppo mutex_enter(&vdc->lock); 1804*1ae08745Sheppo vdc_reset_connection(vdc, B_TRUE); 1805*1ae08745Sheppo mutex_exit(&vdc->lock); 1806*1ae08745Sheppo return (-1); 1807*1ae08745Sheppo } 1808*1ae08745Sheppo 1809*1ae08745Sheppo } while (idx != start_idx); 1810*1ae08745Sheppo 1811*1ae08745Sheppo return (-1); 1812*1ae08745Sheppo } 1813*1ae08745Sheppo 1814*1ae08745Sheppo /* 1815*1ae08745Sheppo * Function: 1816*1ae08745Sheppo * vdc_populate_descriptor 1817*1ae08745Sheppo * 1818*1ae08745Sheppo * Description: 1819*1ae08745Sheppo * This routine writes the data to be transmitted to vds into the 1820*1ae08745Sheppo * descriptor, notifies vds that the ring has been updated and 1821*1ae08745Sheppo * then waits for the request to be processed. 1822*1ae08745Sheppo * 1823*1ae08745Sheppo * Arguments: 1824*1ae08745Sheppo * vdc - the soft state pointer 1825*1ae08745Sheppo * addr - start address of memory region. 1826*1ae08745Sheppo * nbytes - number of bytes to read/write 1827*1ae08745Sheppo * operation - operation we want vds to perform (VD_OP_XXX) 1828*1ae08745Sheppo * arg - parameter to be sent to server (depends on VD_OP_XXX type) 1829*1ae08745Sheppo * . mode for ioctl(9e) 1830*1ae08745Sheppo * . LP64 diskaddr_t (block I/O) 1831*1ae08745Sheppo * slice - the disk slice this request is for 1832*1ae08745Sheppo * 1833*1ae08745Sheppo * Return Codes: 1834*1ae08745Sheppo * 0 1835*1ae08745Sheppo * EAGAIN 1836*1ae08745Sheppo * EFAULT 1837*1ae08745Sheppo * ENXIO 1838*1ae08745Sheppo * EIO 1839*1ae08745Sheppo */ 1840*1ae08745Sheppo static int 1841*1ae08745Sheppo vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, size_t nbytes, int operation, 1842*1ae08745Sheppo uint64_t arg, uint64_t slice) 1843*1ae08745Sheppo { 1844*1ae08745Sheppo vdc_local_desc_t *local_dep = NULL; /* Local Dring Entry Pointer */ 1845*1ae08745Sheppo vd_dring_entry_t *dep = NULL; /* Dring Entry Pointer */ 1846*1ae08745Sheppo int idx = 0; /* Index of DRing entry used */ 1847*1ae08745Sheppo vio_dring_msg_t dmsg; 1848*1ae08745Sheppo size_t msglen = sizeof (dmsg); 1849*1ae08745Sheppo int status = 0; 1850*1ae08745Sheppo int rv; 1851*1ae08745Sheppo int retries = 0; 1852*1ae08745Sheppo 1853*1ae08745Sheppo ASSERT(vdc != NULL); 1854*1ae08745Sheppo ASSERT(slice < V_NUMPAR); 1855*1ae08745Sheppo 1856*1ae08745Sheppo /* 1857*1ae08745Sheppo * Get next available DRing entry. 1858*1ae08745Sheppo */ 1859*1ae08745Sheppo mutex_enter(&vdc->dring_lock); 1860*1ae08745Sheppo idx = vdc_get_next_dring_entry_idx(vdc, 1); 1861*1ae08745Sheppo if (idx == -1) { 1862*1ae08745Sheppo mutex_exit(&vdc->dring_lock); 1863*1ae08745Sheppo vdc_msg("%s[%d]: no descriptor ring entry avail, seq=%d\n", 1864*1ae08745Sheppo __func__, vdc->instance, vdc->seq_num); 1865*1ae08745Sheppo 1866*1ae08745Sheppo /* 1867*1ae08745Sheppo * Since strategy should not block we don't wait for the DRing 1868*1ae08745Sheppo * to empty and instead return 1869*1ae08745Sheppo */ 1870*1ae08745Sheppo return (EAGAIN); 1871*1ae08745Sheppo } 1872*1ae08745Sheppo 1873*1ae08745Sheppo ASSERT(idx < VD_DRING_LEN); 1874*1ae08745Sheppo local_dep = &vdc->local_dring[idx]; 1875*1ae08745Sheppo dep = local_dep->dep; 1876*1ae08745Sheppo ASSERT(dep != NULL); 1877*1ae08745Sheppo 1878*1ae08745Sheppo /* 1879*1ae08745Sheppo * Wait for anybody still using the DRing entry to finish. 1880*1ae08745Sheppo * (e.g. still waiting for vds to respond to a request) 1881*1ae08745Sheppo */ 1882*1ae08745Sheppo mutex_enter(&local_dep->lock); 1883*1ae08745Sheppo 1884*1ae08745Sheppo switch (operation) { 1885*1ae08745Sheppo case VD_OP_BREAD: 1886*1ae08745Sheppo case VD_OP_BWRITE: 1887*1ae08745Sheppo PR1("buf=%p, block=%lx, nbytes=%lx\n", addr, arg, nbytes); 1888*1ae08745Sheppo dep->payload.addr = (diskaddr_t)arg; 1889*1ae08745Sheppo rv = vdc_populate_mem_hdl(vdc, idx, addr, nbytes, operation); 1890*1ae08745Sheppo break; 1891*1ae08745Sheppo 1892*1ae08745Sheppo case VD_OP_FLUSH: 1893*1ae08745Sheppo case VD_OP_GET_VTOC: 1894*1ae08745Sheppo case VD_OP_SET_VTOC: 1895*1ae08745Sheppo case VD_OP_GET_DISKGEOM: 1896*1ae08745Sheppo case VD_OP_SET_DISKGEOM: 1897*1ae08745Sheppo case VD_OP_SCSICMD: 1898*1ae08745Sheppo if (nbytes > 0) { 1899*1ae08745Sheppo rv = vdc_populate_mem_hdl(vdc, idx, addr, nbytes, 1900*1ae08745Sheppo operation); 1901*1ae08745Sheppo } 1902*1ae08745Sheppo break; 1903*1ae08745Sheppo default: 1904*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Unsupported vDisk operation [%d]\n", 1905*1ae08745Sheppo vdc->instance, operation); 1906*1ae08745Sheppo rv = EINVAL; 1907*1ae08745Sheppo } 1908*1ae08745Sheppo 1909*1ae08745Sheppo if (rv != 0) { 1910*1ae08745Sheppo mutex_exit(&local_dep->lock); 1911*1ae08745Sheppo mutex_exit(&vdc->dring_lock); 1912*1ae08745Sheppo return (rv); 1913*1ae08745Sheppo } 1914*1ae08745Sheppo 1915*1ae08745Sheppo /* 1916*1ae08745Sheppo * fill in the data details into the DRing 1917*1ae08745Sheppo */ 1918*1ae08745Sheppo dep->payload.req_id = VDC_GET_NEXT_REQ_ID(vdc); 1919*1ae08745Sheppo dep->payload.operation = operation; 1920*1ae08745Sheppo dep->payload.nbytes = nbytes; 1921*1ae08745Sheppo dep->payload.status = EINPROGRESS; /* vds will set valid value */ 1922*1ae08745Sheppo dep->payload.slice = slice; 1923*1ae08745Sheppo dep->hdr.dstate = VIO_DESC_READY; 1924*1ae08745Sheppo dep->hdr.ack = 1; /* request an ACK for every message */ 1925*1ae08745Sheppo 1926*1ae08745Sheppo local_dep->flags = VIO_DESC_READY; 1927*1ae08745Sheppo local_dep->addr = addr; 1928*1ae08745Sheppo 1929*1ae08745Sheppo /* 1930*1ae08745Sheppo * Send a msg with the DRing details to vds 1931*1ae08745Sheppo */ 1932*1ae08745Sheppo VIO_INIT_DRING_DATA_TAG(dmsg); 1933*1ae08745Sheppo VDC_INIT_DRING_DATA_MSG_IDS(dmsg, vdc); 1934*1ae08745Sheppo dmsg.dring_ident = vdc->dring_ident; 1935*1ae08745Sheppo dmsg.start_idx = idx; 1936*1ae08745Sheppo dmsg.end_idx = idx; 1937*1ae08745Sheppo 1938*1ae08745Sheppo PR1("ident=0x%llx, st=%d, end=%d, seq=%d req=%d dep=%p\n", 1939*1ae08745Sheppo vdc->dring_ident, dmsg.start_idx, dmsg.end_idx, 1940*1ae08745Sheppo dmsg.seq_num, dep->payload.req_id, dep); 1941*1ae08745Sheppo 1942*1ae08745Sheppo status = vdc_send(vdc->ldc_handle, (caddr_t)&dmsg, &msglen); 1943*1ae08745Sheppo PR1("%s[%d]: ldc_write() status=%d\n", __func__, vdc->instance, status); 1944*1ae08745Sheppo if (status != 0) { 1945*1ae08745Sheppo mutex_exit(&local_dep->lock); 1946*1ae08745Sheppo mutex_exit(&vdc->dring_lock); 1947*1ae08745Sheppo vdc_msg("%s: ldc_write(%d)\n", __func__, status); 1948*1ae08745Sheppo return (EAGAIN); 1949*1ae08745Sheppo } 1950*1ae08745Sheppo 1951*1ae08745Sheppo /* 1952*1ae08745Sheppo * XXX - potential performance enhancement (Investigate at a later date) 1953*1ae08745Sheppo * 1954*1ae08745Sheppo * for calls from strategy(9E), instead of waiting for a response from 1955*1ae08745Sheppo * vds, we could return at this stage and let the ACK handling code 1956*1ae08745Sheppo * trigger the biodone(9F) 1957*1ae08745Sheppo */ 1958*1ae08745Sheppo 1959*1ae08745Sheppo /* 1960*1ae08745Sheppo * When a guest is panicking, the completion of requests needs to be 1961*1ae08745Sheppo * handled differently because interrupts are disabled and vdc 1962*1ae08745Sheppo * will not get messages. We have to poll for the messages instead. 1963*1ae08745Sheppo */ 1964*1ae08745Sheppo if (ddi_in_panic()) { 1965*1ae08745Sheppo int start = 0; 1966*1ae08745Sheppo retries = 0; 1967*1ae08745Sheppo for (;;) { 1968*1ae08745Sheppo msglen = sizeof (dmsg); 1969*1ae08745Sheppo status = ldc_read(vdc->ldc_handle, (caddr_t)&dmsg, 1970*1ae08745Sheppo &msglen); 1971*1ae08745Sheppo if (status) { 1972*1ae08745Sheppo status = EINVAL; 1973*1ae08745Sheppo break; 1974*1ae08745Sheppo } 1975*1ae08745Sheppo 1976*1ae08745Sheppo /* 1977*1ae08745Sheppo * if there are no packets wait and check again 1978*1ae08745Sheppo */ 1979*1ae08745Sheppo if ((status == 0) && (msglen == 0)) { 1980*1ae08745Sheppo if (retries++ > vdc_dump_retries) { 1981*1ae08745Sheppo PR0("[%d] Giving up waiting, idx %d\n", 1982*1ae08745Sheppo vdc->instance, idx); 1983*1ae08745Sheppo status = EAGAIN; 1984*1ae08745Sheppo break; 1985*1ae08745Sheppo } 1986*1ae08745Sheppo 1987*1ae08745Sheppo PR1("Waiting for next packet @ %d\n", idx); 1988*1ae08745Sheppo delay(drv_usectohz(vdc_dump_usec_timeout)); 1989*1ae08745Sheppo continue; 1990*1ae08745Sheppo } 1991*1ae08745Sheppo 1992*1ae08745Sheppo /* 1993*1ae08745Sheppo * Ignore all messages that are not ACKs/NACKs to 1994*1ae08745Sheppo * DRing requests. 1995*1ae08745Sheppo */ 1996*1ae08745Sheppo if ((dmsg.tag.vio_msgtype != VIO_TYPE_DATA) || 1997*1ae08745Sheppo (dmsg.tag.vio_subtype_env != VIO_DRING_DATA)) { 1998*1ae08745Sheppo PR0("discarding pkt: type=%d sub=%d env=%d\n", 1999*1ae08745Sheppo dmsg.tag.vio_msgtype, 2000*1ae08745Sheppo dmsg.tag.vio_subtype, 2001*1ae08745Sheppo dmsg.tag.vio_subtype_env); 2002*1ae08745Sheppo continue; 2003*1ae08745Sheppo } 2004*1ae08745Sheppo 2005*1ae08745Sheppo /* 2006*1ae08745Sheppo * set the appropriate return value for the 2007*1ae08745Sheppo * current request. 2008*1ae08745Sheppo */ 2009*1ae08745Sheppo switch (dmsg.tag.vio_subtype) { 2010*1ae08745Sheppo case VIO_SUBTYPE_ACK: 2011*1ae08745Sheppo status = 0; 2012*1ae08745Sheppo break; 2013*1ae08745Sheppo case VIO_SUBTYPE_NACK: 2014*1ae08745Sheppo status = EAGAIN; 2015*1ae08745Sheppo break; 2016*1ae08745Sheppo default: 2017*1ae08745Sheppo continue; 2018*1ae08745Sheppo } 2019*1ae08745Sheppo 2020*1ae08745Sheppo start = dmsg.start_idx; 2021*1ae08745Sheppo if (start >= VD_DRING_LEN) { 2022*1ae08745Sheppo PR0("[%d] Bogus ack data : start %d\n", 2023*1ae08745Sheppo vdc->instance, start); 2024*1ae08745Sheppo continue; 2025*1ae08745Sheppo } 2026*1ae08745Sheppo 2027*1ae08745Sheppo dep = VDC_GET_DRING_ENTRY_PTR(vdc, start); 2028*1ae08745Sheppo 2029*1ae08745Sheppo PR1("[%d] Dumping start=%d idx=%d state=%d\n", 2030*1ae08745Sheppo vdc->instance, start, idx, dep->hdr.dstate); 2031*1ae08745Sheppo 2032*1ae08745Sheppo if (dep->hdr.dstate != VIO_DESC_DONE) { 2033*1ae08745Sheppo PR0("[%d] Entry @ %d - state !DONE %d\n", 2034*1ae08745Sheppo vdc->instance, start, dep->hdr.dstate); 2035*1ae08745Sheppo continue; 2036*1ae08745Sheppo } 2037*1ae08745Sheppo 2038*1ae08745Sheppo (void) vdc_depopulate_descriptor(vdc, start); 2039*1ae08745Sheppo 2040*1ae08745Sheppo /* 2041*1ae08745Sheppo * We want to process all Dring entries up to 2042*1ae08745Sheppo * the current one so that we can return an 2043*1ae08745Sheppo * error with the correct request. 2044*1ae08745Sheppo */ 2045*1ae08745Sheppo if (idx > start) { 2046*1ae08745Sheppo PR0("[%d] Looping: start %d, idx %d\n", 2047*1ae08745Sheppo vdc->instance, idx, start); 2048*1ae08745Sheppo continue; 2049*1ae08745Sheppo } 2050*1ae08745Sheppo 2051*1ae08745Sheppo /* exit - all outstanding requests are completed */ 2052*1ae08745Sheppo break; 2053*1ae08745Sheppo } 2054*1ae08745Sheppo 2055*1ae08745Sheppo mutex_exit(&local_dep->lock); 2056*1ae08745Sheppo mutex_exit(&vdc->dring_lock); 2057*1ae08745Sheppo 2058*1ae08745Sheppo return (status); 2059*1ae08745Sheppo } 2060*1ae08745Sheppo 2061*1ae08745Sheppo /* 2062*1ae08745Sheppo * Now watch the DRing entries we modified to get the response 2063*1ae08745Sheppo * from vds. 2064*1ae08745Sheppo */ 2065*1ae08745Sheppo status = vdc_wait_for_descriptor_update(vdc, idx, dmsg); 2066*1ae08745Sheppo if (status == ETIMEDOUT) { 2067*1ae08745Sheppo /* debug info when dumping state on vds side */ 2068*1ae08745Sheppo dep->payload.status = ECANCELED; 2069*1ae08745Sheppo } 2070*1ae08745Sheppo 2071*1ae08745Sheppo status = vdc_depopulate_descriptor(vdc, idx); 2072*1ae08745Sheppo PR1("%s[%d] Status=%d\n", __func__, vdc->instance, status); 2073*1ae08745Sheppo 2074*1ae08745Sheppo mutex_exit(&local_dep->lock); 2075*1ae08745Sheppo mutex_exit(&vdc->dring_lock); 2076*1ae08745Sheppo 2077*1ae08745Sheppo return (status); 2078*1ae08745Sheppo } 2079*1ae08745Sheppo 2080*1ae08745Sheppo static int 2081*1ae08745Sheppo vdc_wait_for_descriptor_update(vdc_t *vdc, uint_t idx, vio_dring_msg_t dmsg) 2082*1ae08745Sheppo { 2083*1ae08745Sheppo vd_dring_entry_t *dep = NULL; /* Dring Entry Pointer */ 2084*1ae08745Sheppo vdc_local_desc_t *local_dep = NULL; /* Local Dring Entry Pointer */ 2085*1ae08745Sheppo size_t msglen = sizeof (dmsg); 2086*1ae08745Sheppo int retries = 0; 2087*1ae08745Sheppo int status = ENXIO; 2088*1ae08745Sheppo int rv = 0; 2089*1ae08745Sheppo 2090*1ae08745Sheppo ASSERT(vdc != NULL); 2091*1ae08745Sheppo ASSERT(idx < VD_DRING_LEN); 2092*1ae08745Sheppo local_dep = &vdc->local_dring[idx]; 2093*1ae08745Sheppo ASSERT(local_dep != NULL); 2094*1ae08745Sheppo dep = local_dep->dep; 2095*1ae08745Sheppo ASSERT(dep != NULL); 2096*1ae08745Sheppo 2097*1ae08745Sheppo while (dep->hdr.dstate != VIO_DESC_DONE) { 2098*1ae08745Sheppo rv = cv_timedwait(&local_dep->cv, &local_dep->lock, 2099*1ae08745Sheppo VD_GET_TIMEOUT_HZ(retries)); 2100*1ae08745Sheppo if (rv == -1) { 2101*1ae08745Sheppo /* 2102*1ae08745Sheppo * If they persist in ignoring us we'll storm off in a 2103*1ae08745Sheppo * huff and return ETIMEDOUT to the upper layers. 2104*1ae08745Sheppo */ 2105*1ae08745Sheppo if (retries >= vdc_retries) { 2106*1ae08745Sheppo PR0("%s: Finished waiting on entry %d\n", 2107*1ae08745Sheppo __func__, idx); 2108*1ae08745Sheppo status = ETIMEDOUT; 2109*1ae08745Sheppo break; 2110*1ae08745Sheppo } else { 2111*1ae08745Sheppo retries++; 2112*1ae08745Sheppo PR0("%s[%d]: Timeout #%d on entry %d " 2113*1ae08745Sheppo "[seq %d][req %d]\n", __func__, 2114*1ae08745Sheppo vdc->instance, 2115*1ae08745Sheppo retries, idx, dmsg.seq_num, 2116*1ae08745Sheppo dep->payload.req_id); 2117*1ae08745Sheppo } 2118*1ae08745Sheppo 2119*1ae08745Sheppo if (dep->hdr.dstate & VIO_DESC_ACCEPTED) { 2120*1ae08745Sheppo PR0("%s[%d]: vds has accessed entry %d [seq %d]" 2121*1ae08745Sheppo "[req %d] but not ack'ed it yet\n", 2122*1ae08745Sheppo __func__, vdc->instance, idx, dmsg.seq_num, 2123*1ae08745Sheppo dep->payload.req_id); 2124*1ae08745Sheppo continue; 2125*1ae08745Sheppo } 2126*1ae08745Sheppo 2127*1ae08745Sheppo /* 2128*1ae08745Sheppo * we resend the message as it may have been dropped 2129*1ae08745Sheppo * and have never made it to the other side (vds). 2130*1ae08745Sheppo * (We reuse the original message but update seq ID) 2131*1ae08745Sheppo */ 2132*1ae08745Sheppo VDC_INIT_DRING_DATA_MSG_IDS(dmsg, vdc); 2133*1ae08745Sheppo retries = 0; 2134*1ae08745Sheppo status = vdc_send(vdc->ldc_handle, (caddr_t)&dmsg, 2135*1ae08745Sheppo &msglen); 2136*1ae08745Sheppo if (status != 0) { 2137*1ae08745Sheppo vdc_msg("%s: Error (%d) while resending after " 2138*1ae08745Sheppo "timeout\n", __func__, status); 2139*1ae08745Sheppo status = ETIMEDOUT; 2140*1ae08745Sheppo break; 2141*1ae08745Sheppo } 2142*1ae08745Sheppo } 2143*1ae08745Sheppo } 2144*1ae08745Sheppo 2145*1ae08745Sheppo return (status); 2146*1ae08745Sheppo } 2147*1ae08745Sheppo 2148*1ae08745Sheppo static int 2149*1ae08745Sheppo vdc_get_response(vdc_t *vdc, int start, int end) 2150*1ae08745Sheppo { 2151*1ae08745Sheppo vdc_local_desc_t *ldep = NULL; /* Local Dring Entry Pointer */ 2152*1ae08745Sheppo vd_dring_entry_t *dep = NULL; /* Dring Entry Pointer */ 2153*1ae08745Sheppo int status = ENXIO; 2154*1ae08745Sheppo int idx = -1; 2155*1ae08745Sheppo 2156*1ae08745Sheppo ASSERT(vdc != NULL); 2157*1ae08745Sheppo ASSERT(start >= 0); 2158*1ae08745Sheppo ASSERT(start <= VD_DRING_LEN); 2159*1ae08745Sheppo ASSERT(start >= -1); 2160*1ae08745Sheppo ASSERT(start <= VD_DRING_LEN); 2161*1ae08745Sheppo 2162*1ae08745Sheppo idx = start; 2163*1ae08745Sheppo ldep = &vdc->local_dring[idx]; 2164*1ae08745Sheppo ASSERT(ldep != NULL); 2165*1ae08745Sheppo dep = ldep->dep; 2166*1ae08745Sheppo ASSERT(dep != NULL); 2167*1ae08745Sheppo 2168*1ae08745Sheppo PR0("%s[%d] DRING entry=%d status=%d\n", __func__, vdc->instance, 2169*1ae08745Sheppo idx, VIO_GET_DESC_STATE(dep->hdr.dstate)); 2170*1ae08745Sheppo while (VIO_GET_DESC_STATE(dep->hdr.dstate) == VIO_DESC_DONE) { 2171*1ae08745Sheppo if ((end != -1) && (idx > end)) 2172*1ae08745Sheppo return (0); 2173*1ae08745Sheppo 2174*1ae08745Sheppo switch (ldep->operation) { 2175*1ae08745Sheppo case VD_OP_BREAD: 2176*1ae08745Sheppo case VD_OP_BWRITE: 2177*1ae08745Sheppo /* call bioxxx */ 2178*1ae08745Sheppo break; 2179*1ae08745Sheppo default: 2180*1ae08745Sheppo /* signal waiter */ 2181*1ae08745Sheppo break; 2182*1ae08745Sheppo } 2183*1ae08745Sheppo 2184*1ae08745Sheppo /* Clear the DRing entry */ 2185*1ae08745Sheppo status = vdc_depopulate_descriptor(vdc, idx); 2186*1ae08745Sheppo PR0("%s[%d] Status=%d\n", __func__, vdc->instance, status); 2187*1ae08745Sheppo 2188*1ae08745Sheppo /* loop accounting to get next DRing entry */ 2189*1ae08745Sheppo idx++; 2190*1ae08745Sheppo ldep = &vdc->local_dring[idx]; 2191*1ae08745Sheppo dep = ldep->dep; 2192*1ae08745Sheppo } 2193*1ae08745Sheppo 2194*1ae08745Sheppo return (status); 2195*1ae08745Sheppo } 2196*1ae08745Sheppo 2197*1ae08745Sheppo static int 2198*1ae08745Sheppo vdc_depopulate_descriptor(vdc_t *vdc, uint_t idx) 2199*1ae08745Sheppo { 2200*1ae08745Sheppo vd_dring_entry_t *dep = NULL; /* Dring Entry Pointer */ 2201*1ae08745Sheppo vdc_local_desc_t *ldep = NULL; /* Local Dring Entry Pointer */ 2202*1ae08745Sheppo int status = ENXIO; 2203*1ae08745Sheppo 2204*1ae08745Sheppo ASSERT(vdc != NULL); 2205*1ae08745Sheppo ASSERT(idx < VD_DRING_LEN); 2206*1ae08745Sheppo ldep = &vdc->local_dring[idx]; 2207*1ae08745Sheppo ASSERT(ldep != NULL); 2208*1ae08745Sheppo dep = ldep->dep; 2209*1ae08745Sheppo ASSERT(dep != NULL); 2210*1ae08745Sheppo 2211*1ae08745Sheppo status = dep->payload.status; 2212*1ae08745Sheppo VDC_MARK_DRING_ENTRY_FREE(vdc, idx); 2213*1ae08745Sheppo ldep = &vdc->local_dring[idx]; 2214*1ae08745Sheppo VIO_SET_DESC_STATE(ldep->flags, VIO_DESC_FREE); 2215*1ae08745Sheppo 2216*1ae08745Sheppo /* 2217*1ae08745Sheppo * If the upper layer passed in a misaligned address we copied the 2218*1ae08745Sheppo * data into an aligned buffer before sending it to LDC - we now 2219*1ae08745Sheppo * copy it back to the original buffer. 2220*1ae08745Sheppo */ 2221*1ae08745Sheppo if (ldep->align_addr) { 2222*1ae08745Sheppo ASSERT(ldep->addr != NULL); 2223*1ae08745Sheppo ASSERT(dep->payload.nbytes > 0); 2224*1ae08745Sheppo 2225*1ae08745Sheppo bcopy(ldep->align_addr, ldep->addr, dep->payload.nbytes); 2226*1ae08745Sheppo kmem_free(ldep->align_addr, 2227*1ae08745Sheppo sizeof (caddr_t) * dep->payload.nbytes); 2228*1ae08745Sheppo ldep->align_addr = NULL; 2229*1ae08745Sheppo } 2230*1ae08745Sheppo 2231*1ae08745Sheppo status = ldc_mem_unbind_handle(ldep->desc_mhdl); 2232*1ae08745Sheppo if (status != 0) { 2233*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] unbind mem hdl 0x%lx @ idx %d failed:%d", 2234*1ae08745Sheppo vdc->instance, ldep->desc_mhdl, idx, status); 2235*1ae08745Sheppo } 2236*1ae08745Sheppo 2237*1ae08745Sheppo return (status); 2238*1ae08745Sheppo } 2239*1ae08745Sheppo 2240*1ae08745Sheppo static int 2241*1ae08745Sheppo vdc_populate_mem_hdl(vdc_t *vdc, uint_t idx, caddr_t addr, size_t nbytes, 2242*1ae08745Sheppo int operation) 2243*1ae08745Sheppo { 2244*1ae08745Sheppo vd_dring_entry_t *dep = NULL; 2245*1ae08745Sheppo vdc_local_desc_t *ldep = NULL; 2246*1ae08745Sheppo ldc_mem_handle_t mhdl; 2247*1ae08745Sheppo caddr_t vaddr; 2248*1ae08745Sheppo int perm = LDC_MEM_RW; 2249*1ae08745Sheppo int rv = 0; 2250*1ae08745Sheppo int i; 2251*1ae08745Sheppo 2252*1ae08745Sheppo ASSERT(vdc != NULL); 2253*1ae08745Sheppo ASSERT(idx < VD_DRING_LEN); 2254*1ae08745Sheppo 2255*1ae08745Sheppo dep = VDC_GET_DRING_ENTRY_PTR(vdc, idx); 2256*1ae08745Sheppo ldep = &vdc->local_dring[idx]; 2257*1ae08745Sheppo mhdl = ldep->desc_mhdl; 2258*1ae08745Sheppo 2259*1ae08745Sheppo switch (operation) { 2260*1ae08745Sheppo case VD_OP_BREAD: 2261*1ae08745Sheppo perm = LDC_MEM_W; 2262*1ae08745Sheppo break; 2263*1ae08745Sheppo 2264*1ae08745Sheppo case VD_OP_BWRITE: 2265*1ae08745Sheppo perm = LDC_MEM_R; 2266*1ae08745Sheppo break; 2267*1ae08745Sheppo 2268*1ae08745Sheppo case VD_OP_FLUSH: 2269*1ae08745Sheppo case VD_OP_GET_VTOC: 2270*1ae08745Sheppo case VD_OP_SET_VTOC: 2271*1ae08745Sheppo case VD_OP_GET_DISKGEOM: 2272*1ae08745Sheppo case VD_OP_SET_DISKGEOM: 2273*1ae08745Sheppo case VD_OP_SCSICMD: 2274*1ae08745Sheppo perm = LDC_MEM_RW; 2275*1ae08745Sheppo break; 2276*1ae08745Sheppo 2277*1ae08745Sheppo default: 2278*1ae08745Sheppo ASSERT(0); /* catch bad programming in vdc */ 2279*1ae08745Sheppo } 2280*1ae08745Sheppo 2281*1ae08745Sheppo /* 2282*1ae08745Sheppo * LDC expects any addresses passed in to be 8-byte aligned. We need 2283*1ae08745Sheppo * to copy the contents of any misaligned buffers to a newly allocated 2284*1ae08745Sheppo * buffer and bind it instead (and copy the the contents back to the 2285*1ae08745Sheppo * original buffer passed in when depopulating the descriptor) 2286*1ae08745Sheppo */ 2287*1ae08745Sheppo vaddr = addr; 2288*1ae08745Sheppo if (((uint64_t)addr & 0x7) != 0) { 2289*1ae08745Sheppo ldep->align_addr = 2290*1ae08745Sheppo kmem_zalloc(sizeof (caddr_t) * nbytes, KM_SLEEP); 2291*1ae08745Sheppo PR0("%s[%d] Misaligned address %lx reallocating " 2292*1ae08745Sheppo "(buf=%lx entry=%d)\n", 2293*1ae08745Sheppo __func__, vdc->instance, addr, ldep->align_addr, idx); 2294*1ae08745Sheppo bcopy(addr, ldep->align_addr, nbytes); 2295*1ae08745Sheppo vaddr = ldep->align_addr; 2296*1ae08745Sheppo } 2297*1ae08745Sheppo 2298*1ae08745Sheppo rv = ldc_mem_bind_handle(mhdl, vaddr, P2ROUNDUP(nbytes, 8), 2299*1ae08745Sheppo vdc->dring_mem_info.mtype, perm, &dep->payload.cookie[0], 2300*1ae08745Sheppo &dep->payload.ncookies); 2301*1ae08745Sheppo PR1("%s[%d] bound mem handle; ncookies=%d\n", 2302*1ae08745Sheppo __func__, vdc->instance, dep->payload.ncookies); 2303*1ae08745Sheppo if (rv != 0) { 2304*1ae08745Sheppo vdc_msg("%s[%d] failed to ldc_mem_bind_handle " 2305*1ae08745Sheppo "(mhdl=%lx, buf=%lx entry=%d err=%d)\n", 2306*1ae08745Sheppo __func__, vdc->instance, mhdl, addr, idx, rv); 2307*1ae08745Sheppo if (ldep->align_addr) { 2308*1ae08745Sheppo kmem_free(ldep->align_addr, 2309*1ae08745Sheppo sizeof (caddr_t) * dep->payload.nbytes); 2310*1ae08745Sheppo ldep->align_addr = NULL; 2311*1ae08745Sheppo } 2312*1ae08745Sheppo return (EAGAIN); 2313*1ae08745Sheppo } 2314*1ae08745Sheppo 2315*1ae08745Sheppo /* 2316*1ae08745Sheppo * Get the other cookies (if any). 2317*1ae08745Sheppo */ 2318*1ae08745Sheppo for (i = 1; i < dep->payload.ncookies; i++) { 2319*1ae08745Sheppo rv = ldc_mem_nextcookie(mhdl, &dep->payload.cookie[i]); 2320*1ae08745Sheppo if (rv != 0) { 2321*1ae08745Sheppo (void) ldc_mem_unbind_handle(mhdl); 2322*1ae08745Sheppo vdc_msg("%s: failed to get next cookie(mhdl=%lx " 2323*1ae08745Sheppo "cnum=%d), err=%d", __func__, mhdl, i, rv); 2324*1ae08745Sheppo if (ldep->align_addr) { 2325*1ae08745Sheppo kmem_free(ldep->align_addr, 2326*1ae08745Sheppo sizeof (caddr_t) * dep->payload.nbytes); 2327*1ae08745Sheppo ldep->align_addr = NULL; 2328*1ae08745Sheppo } 2329*1ae08745Sheppo return (EAGAIN); 2330*1ae08745Sheppo } 2331*1ae08745Sheppo } 2332*1ae08745Sheppo 2333*1ae08745Sheppo return (rv); 2334*1ae08745Sheppo } 2335*1ae08745Sheppo 2336*1ae08745Sheppo /* 2337*1ae08745Sheppo * Interrupt handlers for messages from LDC 2338*1ae08745Sheppo */ 2339*1ae08745Sheppo 2340*1ae08745Sheppo static uint_t 2341*1ae08745Sheppo vdc_handle_cb(uint64_t event, caddr_t arg) 2342*1ae08745Sheppo { 2343*1ae08745Sheppo ldc_status_t ldc_state; 2344*1ae08745Sheppo int rv = 0; 2345*1ae08745Sheppo 2346*1ae08745Sheppo vdc_t *vdc = (vdc_t *)(void *)arg; 2347*1ae08745Sheppo 2348*1ae08745Sheppo ASSERT(vdc != NULL); 2349*1ae08745Sheppo 2350*1ae08745Sheppo PR1("%s[%d] event=%x seqID=%d\n", 2351*1ae08745Sheppo __func__, vdc->instance, event, vdc->seq_num); 2352*1ae08745Sheppo 2353*1ae08745Sheppo /* 2354*1ae08745Sheppo * Depending on the type of event that triggered this callback, 2355*1ae08745Sheppo * we modify the handhske state or read the data. 2356*1ae08745Sheppo * 2357*1ae08745Sheppo * NOTE: not done as a switch() as event could be triggered by 2358*1ae08745Sheppo * a state change and a read request. Also the ordering of the 2359*1ae08745Sheppo * check for the event types is deliberate. 2360*1ae08745Sheppo */ 2361*1ae08745Sheppo if (event & LDC_EVT_UP) { 2362*1ae08745Sheppo PR0("%s[%d] Received LDC_EVT_UP\n", __func__, vdc->instance); 2363*1ae08745Sheppo 2364*1ae08745Sheppo /* get LDC state */ 2365*1ae08745Sheppo rv = ldc_status(vdc->ldc_handle, &ldc_state); 2366*1ae08745Sheppo if (rv != 0) { 2367*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Couldn't get LDC status %d", 2368*1ae08745Sheppo vdc->instance, rv); 2369*1ae08745Sheppo vdc_reset_connection(vdc, B_TRUE); 2370*1ae08745Sheppo return (LDC_SUCCESS); 2371*1ae08745Sheppo } 2372*1ae08745Sheppo 2373*1ae08745Sheppo /* 2374*1ae08745Sheppo * Reset the transaction sequence numbers when LDC comes up. 2375*1ae08745Sheppo * We then kick off the handshake negotiation with the vDisk 2376*1ae08745Sheppo * server. 2377*1ae08745Sheppo */ 2378*1ae08745Sheppo mutex_enter(&vdc->lock); 2379*1ae08745Sheppo vdc->seq_num = 0; 2380*1ae08745Sheppo vdc->seq_num_reply = 0; 2381*1ae08745Sheppo vdc->ldc_state = ldc_state; 2382*1ae08745Sheppo ASSERT(ldc_state == LDC_UP); 2383*1ae08745Sheppo mutex_exit(&vdc->lock); 2384*1ae08745Sheppo 2385*1ae08745Sheppo vdc_init_handshake_negotiation(vdc); 2386*1ae08745Sheppo 2387*1ae08745Sheppo ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0); 2388*1ae08745Sheppo } 2389*1ae08745Sheppo 2390*1ae08745Sheppo if (event & LDC_EVT_READ) { 2391*1ae08745Sheppo /* 2392*1ae08745Sheppo * Wake up the worker thread to process the message 2393*1ae08745Sheppo */ 2394*1ae08745Sheppo mutex_enter(&vdc->msg_proc_lock); 2395*1ae08745Sheppo vdc->msg_pending = B_TRUE; 2396*1ae08745Sheppo cv_signal(&vdc->msg_proc_cv); 2397*1ae08745Sheppo mutex_exit(&vdc->msg_proc_lock); 2398*1ae08745Sheppo 2399*1ae08745Sheppo ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0); 2400*1ae08745Sheppo 2401*1ae08745Sheppo /* that's all we have to do - no need to handle DOWN/RESET */ 2402*1ae08745Sheppo return (LDC_SUCCESS); 2403*1ae08745Sheppo } 2404*1ae08745Sheppo 2405*1ae08745Sheppo if (event & LDC_EVT_RESET) { 2406*1ae08745Sheppo PR0("%s[%d] Recvd LDC RESET event\n", __func__, vdc->instance); 2407*1ae08745Sheppo } 2408*1ae08745Sheppo 2409*1ae08745Sheppo if (event & LDC_EVT_DOWN) { 2410*1ae08745Sheppo PR0("%s[%d] Recvd LDC DOWN event\n", __func__, vdc->instance); 2411*1ae08745Sheppo 2412*1ae08745Sheppo /* get LDC state */ 2413*1ae08745Sheppo rv = ldc_status(vdc->ldc_handle, &ldc_state); 2414*1ae08745Sheppo if (rv != 0) { 2415*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Couldn't get LDC status %d", 2416*1ae08745Sheppo vdc->instance, rv); 2417*1ae08745Sheppo ldc_state = LDC_OPEN; 2418*1ae08745Sheppo } 2419*1ae08745Sheppo mutex_enter(&vdc->lock); 2420*1ae08745Sheppo vdc->ldc_state = ldc_state; 2421*1ae08745Sheppo mutex_exit(&vdc->lock); 2422*1ae08745Sheppo 2423*1ae08745Sheppo vdc_reset_connection(vdc, B_TRUE); 2424*1ae08745Sheppo } 2425*1ae08745Sheppo 2426*1ae08745Sheppo if (event & ~(LDC_EVT_UP | LDC_EVT_RESET | LDC_EVT_DOWN | LDC_EVT_READ)) 2427*1ae08745Sheppo cmn_err(CE_NOTE, "![%d] Unexpected LDC event (%lx) received", 2428*1ae08745Sheppo vdc->instance, event); 2429*1ae08745Sheppo 2430*1ae08745Sheppo return (LDC_SUCCESS); 2431*1ae08745Sheppo } 2432*1ae08745Sheppo 2433*1ae08745Sheppo /* -------------------------------------------------------------------------- */ 2434*1ae08745Sheppo 2435*1ae08745Sheppo /* 2436*1ae08745Sheppo * The following functions process the incoming messages from vds 2437*1ae08745Sheppo */ 2438*1ae08745Sheppo 2439*1ae08745Sheppo 2440*1ae08745Sheppo static void 2441*1ae08745Sheppo vdc_process_msg_thread(vdc_t *vdc) 2442*1ae08745Sheppo { 2443*1ae08745Sheppo int status = 0; 2444*1ae08745Sheppo boolean_t q_is_empty = B_TRUE; 2445*1ae08745Sheppo 2446*1ae08745Sheppo ASSERT(vdc != NULL); 2447*1ae08745Sheppo 2448*1ae08745Sheppo mutex_enter(&vdc->msg_proc_lock); 2449*1ae08745Sheppo PR0("%s[%d]: Starting\n", __func__, vdc->instance); 2450*1ae08745Sheppo 2451*1ae08745Sheppo vdc->msg_proc_thr_state = VDC_THR_RUNNING; 2452*1ae08745Sheppo 2453*1ae08745Sheppo while (vdc->msg_proc_thr_state == VDC_THR_RUNNING) { 2454*1ae08745Sheppo 2455*1ae08745Sheppo PR1("%s[%d] Waiting\n", __func__, vdc->instance); 2456*1ae08745Sheppo while (vdc->msg_pending == B_FALSE) 2457*1ae08745Sheppo cv_wait(&vdc->msg_proc_cv, &vdc->msg_proc_lock); 2458*1ae08745Sheppo 2459*1ae08745Sheppo PR1("%s[%d] Message Received\n", __func__, vdc->instance); 2460*1ae08745Sheppo 2461*1ae08745Sheppo /* check if there is data */ 2462*1ae08745Sheppo status = ldc_chkq(vdc->ldc_handle, &q_is_empty); 2463*1ae08745Sheppo if ((status != 0) && 2464*1ae08745Sheppo (vdc->msg_proc_thr_state == VDC_THR_RUNNING)) { 2465*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Unable to communicate with vDisk" 2466*1ae08745Sheppo " server. Cannot check LDC queue: %d", 2467*1ae08745Sheppo vdc->instance, status); 2468*1ae08745Sheppo mutex_enter(&vdc->lock); 2469*1ae08745Sheppo vdc_reset_connection(vdc, B_TRUE); 2470*1ae08745Sheppo mutex_exit(&vdc->lock); 2471*1ae08745Sheppo vdc->msg_proc_thr_state = VDC_THR_STOP; 2472*1ae08745Sheppo continue; 2473*1ae08745Sheppo } 2474*1ae08745Sheppo 2475*1ae08745Sheppo if (q_is_empty == B_FALSE) { 2476*1ae08745Sheppo PR1("%s: new pkt(s) available\n", __func__); 2477*1ae08745Sheppo vdc_process_msg(vdc); 2478*1ae08745Sheppo } 2479*1ae08745Sheppo 2480*1ae08745Sheppo vdc->msg_pending = B_FALSE; 2481*1ae08745Sheppo } 2482*1ae08745Sheppo 2483*1ae08745Sheppo PR0("Message processing thread stopped\n"); 2484*1ae08745Sheppo vdc->msg_pending = B_FALSE; 2485*1ae08745Sheppo vdc->msg_proc_thr_state = VDC_THR_DONE; 2486*1ae08745Sheppo cv_signal(&vdc->msg_proc_cv); 2487*1ae08745Sheppo mutex_exit(&vdc->msg_proc_lock); 2488*1ae08745Sheppo thread_exit(); 2489*1ae08745Sheppo } 2490*1ae08745Sheppo 2491*1ae08745Sheppo 2492*1ae08745Sheppo /* 2493*1ae08745Sheppo * Function: 2494*1ae08745Sheppo * vdc_process_msg() 2495*1ae08745Sheppo * 2496*1ae08745Sheppo * Description: 2497*1ae08745Sheppo * This function is called by the message processing thread each time it 2498*1ae08745Sheppo * is triggered when LDC sends an interrupt to indicate that there are 2499*1ae08745Sheppo * more packets on the queue. When it is called it will continue to loop 2500*1ae08745Sheppo * and read the messages until there are no more left of the queue. If it 2501*1ae08745Sheppo * encounters an invalid sized message it will drop it and check the next 2502*1ae08745Sheppo * message. 2503*1ae08745Sheppo * 2504*1ae08745Sheppo * Arguments: 2505*1ae08745Sheppo * arg - soft state pointer for this instance of the device driver. 2506*1ae08745Sheppo * 2507*1ae08745Sheppo * Return Code: 2508*1ae08745Sheppo * None. 2509*1ae08745Sheppo */ 2510*1ae08745Sheppo static void 2511*1ae08745Sheppo vdc_process_msg(void *arg) 2512*1ae08745Sheppo { 2513*1ae08745Sheppo vdc_t *vdc = (vdc_t *)(void *)arg; 2514*1ae08745Sheppo vio_msg_t vio_msg; 2515*1ae08745Sheppo size_t nbytes = sizeof (vio_msg); 2516*1ae08745Sheppo int status; 2517*1ae08745Sheppo 2518*1ae08745Sheppo ASSERT(vdc != NULL); 2519*1ae08745Sheppo 2520*1ae08745Sheppo mutex_enter(&vdc->lock); 2521*1ae08745Sheppo 2522*1ae08745Sheppo PR1("%s\n", __func__); 2523*1ae08745Sheppo 2524*1ae08745Sheppo for (;;) { 2525*1ae08745Sheppo 2526*1ae08745Sheppo /* read all messages - until no more left */ 2527*1ae08745Sheppo status = ldc_read(vdc->ldc_handle, (caddr_t)&vio_msg, &nbytes); 2528*1ae08745Sheppo 2529*1ae08745Sheppo if (status) { 2530*1ae08745Sheppo vdc_msg("%s: ldc_read() failed = %d", __func__, status); 2531*1ae08745Sheppo 2532*1ae08745Sheppo /* if status is ECONNRESET --- reset vdc state */ 2533*1ae08745Sheppo if (status == EIO || status == ECONNRESET) { 2534*1ae08745Sheppo vdc_reset_connection(vdc, B_FALSE); 2535*1ae08745Sheppo } 2536*1ae08745Sheppo 2537*1ae08745Sheppo mutex_exit(&vdc->lock); 2538*1ae08745Sheppo return; 2539*1ae08745Sheppo } 2540*1ae08745Sheppo 2541*1ae08745Sheppo if ((nbytes > 0) && (nbytes < sizeof (vio_msg_tag_t))) { 2542*1ae08745Sheppo cmn_err(CE_CONT, "![%d] Expect %lu bytes; recv'd %lu\n", 2543*1ae08745Sheppo vdc->instance, sizeof (vio_msg_tag_t), nbytes); 2544*1ae08745Sheppo mutex_exit(&vdc->lock); 2545*1ae08745Sheppo return; 2546*1ae08745Sheppo } 2547*1ae08745Sheppo 2548*1ae08745Sheppo if (nbytes == 0) { 2549*1ae08745Sheppo PR2("%s[%d]: ldc_read() done..\n", 2550*1ae08745Sheppo __func__, vdc->instance); 2551*1ae08745Sheppo mutex_exit(&vdc->lock); 2552*1ae08745Sheppo return; 2553*1ae08745Sheppo } 2554*1ae08745Sheppo 2555*1ae08745Sheppo PR1("%s[%d] (%x/%x/%x)\n", __func__, vdc->instance, 2556*1ae08745Sheppo vio_msg.tag.vio_msgtype, 2557*1ae08745Sheppo vio_msg.tag.vio_subtype, 2558*1ae08745Sheppo vio_msg.tag.vio_subtype_env); 2559*1ae08745Sheppo 2560*1ae08745Sheppo /* 2561*1ae08745Sheppo * Verify the Session ID of the message 2562*1ae08745Sheppo * 2563*1ae08745Sheppo * Every message after the Version has been negotiated should 2564*1ae08745Sheppo * have the correct session ID set. 2565*1ae08745Sheppo */ 2566*1ae08745Sheppo if ((vio_msg.tag.vio_sid != vdc->session_id) && 2567*1ae08745Sheppo (vio_msg.tag.vio_subtype_env != VIO_VER_INFO)) { 2568*1ae08745Sheppo PR0("%s: Incorrect SID 0x%x msg 0x%lx, expected 0x%x\n", 2569*1ae08745Sheppo __func__, vio_msg.tag.vio_sid, &vio_msg, 2570*1ae08745Sheppo vdc->session_id); 2571*1ae08745Sheppo vdc_reset_connection(vdc, B_FALSE); 2572*1ae08745Sheppo mutex_exit(&vdc->lock); 2573*1ae08745Sheppo return; 2574*1ae08745Sheppo } 2575*1ae08745Sheppo 2576*1ae08745Sheppo switch (vio_msg.tag.vio_msgtype) { 2577*1ae08745Sheppo case VIO_TYPE_CTRL: 2578*1ae08745Sheppo status = vdc_process_ctrl_msg(vdc, vio_msg); 2579*1ae08745Sheppo break; 2580*1ae08745Sheppo case VIO_TYPE_DATA: 2581*1ae08745Sheppo status = vdc_process_data_msg(vdc, vio_msg); 2582*1ae08745Sheppo break; 2583*1ae08745Sheppo case VIO_TYPE_ERR: 2584*1ae08745Sheppo status = vdc_process_err_msg(vdc, vio_msg); 2585*1ae08745Sheppo break; 2586*1ae08745Sheppo default: 2587*1ae08745Sheppo PR1("%s", __func__); 2588*1ae08745Sheppo status = EINVAL; 2589*1ae08745Sheppo break; 2590*1ae08745Sheppo } 2591*1ae08745Sheppo 2592*1ae08745Sheppo if (status != 0) { 2593*1ae08745Sheppo PR0("%s[%d] Error (%d) occcurred processing msg\n", 2594*1ae08745Sheppo __func__, vdc->instance, status); 2595*1ae08745Sheppo vdc_reset_connection(vdc, B_FALSE); 2596*1ae08745Sheppo } 2597*1ae08745Sheppo } 2598*1ae08745Sheppo _NOTE(NOTREACHED) 2599*1ae08745Sheppo } 2600*1ae08745Sheppo 2601*1ae08745Sheppo /* 2602*1ae08745Sheppo * Function: 2603*1ae08745Sheppo * vdc_process_ctrl_msg() 2604*1ae08745Sheppo * 2605*1ae08745Sheppo * Description: 2606*1ae08745Sheppo * This function is called by the message processing thread each time 2607*1ae08745Sheppo * an LDC message with a msgtype of VIO_TYPE_CTRL is received. 2608*1ae08745Sheppo * 2609*1ae08745Sheppo * Arguments: 2610*1ae08745Sheppo * vdc - soft state pointer for this instance of the device driver. 2611*1ae08745Sheppo * msg - the LDC message sent by vds 2612*1ae08745Sheppo * 2613*1ae08745Sheppo * Return Codes: 2614*1ae08745Sheppo * 0 - Success. 2615*1ae08745Sheppo * EPROTO - A message was received which shouldn't have happened according 2616*1ae08745Sheppo * to the protocol 2617*1ae08745Sheppo * ENOTSUP - An action which is allowed according to the protocol but which 2618*1ae08745Sheppo * isn't (or doesn't need to be) implemented yet. 2619*1ae08745Sheppo * EINVAL - An invalid value was returned as part of a message. 2620*1ae08745Sheppo */ 2621*1ae08745Sheppo static int 2622*1ae08745Sheppo vdc_process_ctrl_msg(vdc_t *vdc, vio_msg_t msg) 2623*1ae08745Sheppo { 2624*1ae08745Sheppo size_t msglen = sizeof (msg); 2625*1ae08745Sheppo vd_attr_msg_t *attr_msg = NULL; 2626*1ae08745Sheppo vio_dring_reg_msg_t *dring_msg = NULL; 2627*1ae08745Sheppo int status = -1; 2628*1ae08745Sheppo 2629*1ae08745Sheppo ASSERT(msg.tag.vio_msgtype == VIO_TYPE_CTRL); 2630*1ae08745Sheppo ASSERT(vdc != NULL); 2631*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 2632*1ae08745Sheppo 2633*1ae08745Sheppo /* Depending on which state we are in; process the message */ 2634*1ae08745Sheppo switch (vdc->state) { 2635*1ae08745Sheppo case VD_STATE_INIT: 2636*1ae08745Sheppo if (msg.tag.vio_subtype_env != VIO_VER_INFO) { 2637*1ae08745Sheppo status = EPROTO; 2638*1ae08745Sheppo break; 2639*1ae08745Sheppo } 2640*1ae08745Sheppo 2641*1ae08745Sheppo switch (msg.tag.vio_subtype) { 2642*1ae08745Sheppo case VIO_SUBTYPE_ACK: 2643*1ae08745Sheppo vdc->state = VD_STATE_VER; 2644*1ae08745Sheppo status = vdc_init_attr_negotiation(vdc); 2645*1ae08745Sheppo break; 2646*1ae08745Sheppo case VIO_SUBTYPE_NACK: 2647*1ae08745Sheppo /* 2648*1ae08745Sheppo * For now there is only one version number so we 2649*1ae08745Sheppo * cannot step back to an earlier version but in the 2650*1ae08745Sheppo * future we may need to add further logic here 2651*1ae08745Sheppo * to try negotiating an earlier version as the VIO 2652*1ae08745Sheppo * design allow for it. 2653*1ae08745Sheppo */ 2654*1ae08745Sheppo 2655*1ae08745Sheppo /* 2656*1ae08745Sheppo * vds could not handle the version we sent so we just 2657*1ae08745Sheppo * stop negotiating. 2658*1ae08745Sheppo */ 2659*1ae08745Sheppo status = EPROTO; 2660*1ae08745Sheppo break; 2661*1ae08745Sheppo 2662*1ae08745Sheppo case VIO_SUBTYPE_INFO: 2663*1ae08745Sheppo /* 2664*1ae08745Sheppo * Handle the case where vds starts handshake 2665*1ae08745Sheppo * (for now only vdc is the instigatior) 2666*1ae08745Sheppo */ 2667*1ae08745Sheppo status = ENOTSUP; 2668*1ae08745Sheppo break; 2669*1ae08745Sheppo 2670*1ae08745Sheppo default: 2671*1ae08745Sheppo status = ENOTSUP; 2672*1ae08745Sheppo break; 2673*1ae08745Sheppo } 2674*1ae08745Sheppo break; 2675*1ae08745Sheppo 2676*1ae08745Sheppo case VD_STATE_VER: 2677*1ae08745Sheppo if (msg.tag.vio_subtype_env != VIO_ATTR_INFO) { 2678*1ae08745Sheppo status = EPROTO; 2679*1ae08745Sheppo break; 2680*1ae08745Sheppo } 2681*1ae08745Sheppo 2682*1ae08745Sheppo switch (msg.tag.vio_subtype) { 2683*1ae08745Sheppo case VIO_SUBTYPE_ACK: 2684*1ae08745Sheppo /* 2685*1ae08745Sheppo * We now verify the attributes sent by vds. 2686*1ae08745Sheppo */ 2687*1ae08745Sheppo attr_msg = (vd_attr_msg_t *)&msg; 2688*1ae08745Sheppo vdc->vdisk_size = attr_msg->vdisk_size; 2689*1ae08745Sheppo vdc->vdisk_type = attr_msg->vdisk_type; 2690*1ae08745Sheppo 2691*1ae08745Sheppo if ((attr_msg->max_xfer_sz != vdc->max_xfer_sz) || 2692*1ae08745Sheppo (attr_msg->vdisk_block_size != vdc->block_size)) { 2693*1ae08745Sheppo /* 2694*1ae08745Sheppo * Future support: step down to the block size 2695*1ae08745Sheppo * and max transfer size suggested by the 2696*1ae08745Sheppo * server. (If this value is less than 128K 2697*1ae08745Sheppo * then multiple Dring entries per request 2698*1ae08745Sheppo * would need to be implemented) 2699*1ae08745Sheppo */ 2700*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Couldn't process block " 2701*1ae08745Sheppo "attrs from vds", vdc->instance); 2702*1ae08745Sheppo status = EINVAL; 2703*1ae08745Sheppo break; 2704*1ae08745Sheppo } 2705*1ae08745Sheppo 2706*1ae08745Sheppo if ((attr_msg->xfer_mode != VIO_DRING_MODE) || 2707*1ae08745Sheppo (attr_msg->vdisk_size > INT64_MAX) || 2708*1ae08745Sheppo (attr_msg->vdisk_type > VD_DISK_TYPE_DISK)) { 2709*1ae08745Sheppo vdc_msg("%s[%d] Couldn't process attrs " 2710*1ae08745Sheppo "from vds", __func__, vdc->instance); 2711*1ae08745Sheppo status = EINVAL; 2712*1ae08745Sheppo break; 2713*1ae08745Sheppo } 2714*1ae08745Sheppo 2715*1ae08745Sheppo vdc->state = VD_STATE_ATTR; 2716*1ae08745Sheppo status = vdc_init_dring_negotiate(vdc); 2717*1ae08745Sheppo break; 2718*1ae08745Sheppo 2719*1ae08745Sheppo case VIO_SUBTYPE_NACK: 2720*1ae08745Sheppo /* 2721*1ae08745Sheppo * vds could not handle the attributes we sent so we 2722*1ae08745Sheppo * stop negotiating. 2723*1ae08745Sheppo */ 2724*1ae08745Sheppo status = EPROTO; 2725*1ae08745Sheppo break; 2726*1ae08745Sheppo 2727*1ae08745Sheppo case VIO_SUBTYPE_INFO: 2728*1ae08745Sheppo /* 2729*1ae08745Sheppo * Handle the case where vds starts the handshake 2730*1ae08745Sheppo * (for now; vdc is the only supported instigatior) 2731*1ae08745Sheppo */ 2732*1ae08745Sheppo status = ENOTSUP; 2733*1ae08745Sheppo break; 2734*1ae08745Sheppo 2735*1ae08745Sheppo default: 2736*1ae08745Sheppo status = ENOTSUP; 2737*1ae08745Sheppo break; 2738*1ae08745Sheppo } 2739*1ae08745Sheppo break; 2740*1ae08745Sheppo 2741*1ae08745Sheppo 2742*1ae08745Sheppo case VD_STATE_ATTR: 2743*1ae08745Sheppo if (msg.tag.vio_subtype_env != VIO_DRING_REG) { 2744*1ae08745Sheppo status = EPROTO; 2745*1ae08745Sheppo break; 2746*1ae08745Sheppo } 2747*1ae08745Sheppo 2748*1ae08745Sheppo switch (msg.tag.vio_subtype) { 2749*1ae08745Sheppo case VIO_SUBTYPE_ACK: 2750*1ae08745Sheppo /* Verify that we have sent all the descr. ring info */ 2751*1ae08745Sheppo /* nop for now as we have just 1 dring */ 2752*1ae08745Sheppo dring_msg = (vio_dring_reg_msg_t *)&msg; 2753*1ae08745Sheppo 2754*1ae08745Sheppo /* save the received dring_ident */ 2755*1ae08745Sheppo vdc->dring_ident = dring_msg->dring_ident; 2756*1ae08745Sheppo PR0("%s[%d] Received dring ident=0x%lx\n", 2757*1ae08745Sheppo __func__, vdc->instance, vdc->dring_ident); 2758*1ae08745Sheppo 2759*1ae08745Sheppo /* 2760*1ae08745Sheppo * Send an RDX message to vds to indicate we are ready 2761*1ae08745Sheppo * to send data 2762*1ae08745Sheppo */ 2763*1ae08745Sheppo msg.tag.vio_msgtype = VIO_TYPE_CTRL; 2764*1ae08745Sheppo msg.tag.vio_subtype = VIO_SUBTYPE_INFO; 2765*1ae08745Sheppo msg.tag.vio_subtype_env = VIO_RDX; 2766*1ae08745Sheppo msg.tag.vio_sid = vdc->session_id; 2767*1ae08745Sheppo status = vdc_send(vdc->ldc_handle, (caddr_t)&msg, 2768*1ae08745Sheppo &msglen); 2769*1ae08745Sheppo if (status != 0) { 2770*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Failed to send RDX" 2771*1ae08745Sheppo " message (%d)", vdc->instance, status); 2772*1ae08745Sheppo break; 2773*1ae08745Sheppo } 2774*1ae08745Sheppo 2775*1ae08745Sheppo status = vdc_create_fake_geometry(vdc); 2776*1ae08745Sheppo if (status != 0) { 2777*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Failed to create disk " 2778*1ae08745Sheppo "geometery(%d)", vdc->instance, status); 2779*1ae08745Sheppo break; 2780*1ae08745Sheppo } 2781*1ae08745Sheppo 2782*1ae08745Sheppo vdc->state = VD_STATE_RDX; 2783*1ae08745Sheppo break; 2784*1ae08745Sheppo 2785*1ae08745Sheppo case VIO_SUBTYPE_NACK: 2786*1ae08745Sheppo /* 2787*1ae08745Sheppo * vds could not handle the DRing info we sent so we 2788*1ae08745Sheppo * stop negotiating. 2789*1ae08745Sheppo */ 2790*1ae08745Sheppo cmn_err(CE_CONT, "server could not register DRing\n"); 2791*1ae08745Sheppo vdc_reset_connection(vdc, B_FALSE); 2792*1ae08745Sheppo vdc_destroy_descriptor_ring(vdc); 2793*1ae08745Sheppo status = EPROTO; 2794*1ae08745Sheppo break; 2795*1ae08745Sheppo 2796*1ae08745Sheppo case VIO_SUBTYPE_INFO: 2797*1ae08745Sheppo /* 2798*1ae08745Sheppo * Handle the case where vds starts handshake 2799*1ae08745Sheppo * (for now only vdc is the instigatior) 2800*1ae08745Sheppo */ 2801*1ae08745Sheppo status = ENOTSUP; 2802*1ae08745Sheppo break; 2803*1ae08745Sheppo default: 2804*1ae08745Sheppo status = ENOTSUP; 2805*1ae08745Sheppo } 2806*1ae08745Sheppo break; 2807*1ae08745Sheppo 2808*1ae08745Sheppo case VD_STATE_RDX: 2809*1ae08745Sheppo if (msg.tag.vio_subtype_env != VIO_RDX) { 2810*1ae08745Sheppo status = EPROTO; 2811*1ae08745Sheppo break; 2812*1ae08745Sheppo } 2813*1ae08745Sheppo 2814*1ae08745Sheppo PR0("%s: Received RDX - handshake successful\n", __func__); 2815*1ae08745Sheppo 2816*1ae08745Sheppo status = 0; 2817*1ae08745Sheppo vdc->state = VD_STATE_DATA; 2818*1ae08745Sheppo 2819*1ae08745Sheppo cv_broadcast(&vdc->attach_cv); 2820*1ae08745Sheppo break; 2821*1ae08745Sheppo 2822*1ae08745Sheppo default: 2823*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] unknown handshake negotiation state %d", 2824*1ae08745Sheppo vdc->instance, vdc->state); 2825*1ae08745Sheppo break; 2826*1ae08745Sheppo } 2827*1ae08745Sheppo 2828*1ae08745Sheppo return (status); 2829*1ae08745Sheppo } 2830*1ae08745Sheppo 2831*1ae08745Sheppo 2832*1ae08745Sheppo /* 2833*1ae08745Sheppo * Function: 2834*1ae08745Sheppo * vdc_process_data_msg() 2835*1ae08745Sheppo * 2836*1ae08745Sheppo * Description: 2837*1ae08745Sheppo * This function is called by the message processing thread each time it 2838*1ae08745Sheppo * a message with a msgtype of VIO_TYPE_DATA is received. It will either 2839*1ae08745Sheppo * be an ACK or NACK from vds[1] which vdc handles as follows. 2840*1ae08745Sheppo * ACK - wake up the waiting thread 2841*1ae08745Sheppo * NACK - resend any messages necessary 2842*1ae08745Sheppo * 2843*1ae08745Sheppo * [1] Although the message format allows it, vds should not send a 2844*1ae08745Sheppo * VIO_SUBTYPE_INFO message to vdc asking it to read data; if for 2845*1ae08745Sheppo * some bizarre reason it does, vdc will reset the connection. 2846*1ae08745Sheppo * 2847*1ae08745Sheppo * Arguments: 2848*1ae08745Sheppo * vdc - soft state pointer for this instance of the device driver. 2849*1ae08745Sheppo * msg - the LDC message sent by vds 2850*1ae08745Sheppo * 2851*1ae08745Sheppo * Return Code: 2852*1ae08745Sheppo * 0 - Success. 2853*1ae08745Sheppo * > 0 - error value returned by LDC 2854*1ae08745Sheppo */ 2855*1ae08745Sheppo static int 2856*1ae08745Sheppo vdc_process_data_msg(vdc_t *vdc, vio_msg_t msg) 2857*1ae08745Sheppo { 2858*1ae08745Sheppo int status = 0; 2859*1ae08745Sheppo vdc_local_desc_t *local_dep = NULL; 2860*1ae08745Sheppo vio_dring_msg_t *dring_msg = NULL; 2861*1ae08745Sheppo size_t msglen = sizeof (*dring_msg); 2862*1ae08745Sheppo uint_t num_msgs; 2863*1ae08745Sheppo uint_t start; 2864*1ae08745Sheppo uint_t end; 2865*1ae08745Sheppo uint_t i; 2866*1ae08745Sheppo 2867*1ae08745Sheppo ASSERT(msg.tag.vio_msgtype == VIO_TYPE_DATA); 2868*1ae08745Sheppo ASSERT(vdc != NULL); 2869*1ae08745Sheppo ASSERT(mutex_owned(&vdc->lock)); 2870*1ae08745Sheppo 2871*1ae08745Sheppo dring_msg = (vio_dring_msg_t *)&msg; 2872*1ae08745Sheppo 2873*1ae08745Sheppo /* 2874*1ae08745Sheppo * Check to see if the message has bogus data 2875*1ae08745Sheppo */ 2876*1ae08745Sheppo start = dring_msg->start_idx; 2877*1ae08745Sheppo end = dring_msg->end_idx; 2878*1ae08745Sheppo if ((start >= VD_DRING_LEN) || (end >= VD_DRING_LEN)) { 2879*1ae08745Sheppo vdc_msg("%s: Bogus ACK data : start %d, end %d\n", 2880*1ae08745Sheppo __func__, start, end); 2881*1ae08745Sheppo return (EPROTO); 2882*1ae08745Sheppo } 2883*1ae08745Sheppo 2884*1ae08745Sheppo /* 2885*1ae08745Sheppo * calculate the number of messages that vds ACK'ed 2886*1ae08745Sheppo * 2887*1ae08745Sheppo * Assumes, (like the rest of vdc) that there is a 1:1 mapping 2888*1ae08745Sheppo * between requests and Dring entries. 2889*1ae08745Sheppo */ 2890*1ae08745Sheppo num_msgs = (end >= start) ? 2891*1ae08745Sheppo (end - start + 1) : 2892*1ae08745Sheppo (VD_DRING_LEN - start + end + 1); 2893*1ae08745Sheppo 2894*1ae08745Sheppo /* 2895*1ae08745Sheppo * Verify that the sequence number is what vdc expects. 2896*1ae08745Sheppo */ 2897*1ae08745Sheppo if (vdc_verify_seq_num(vdc, dring_msg, num_msgs) == B_FALSE) { 2898*1ae08745Sheppo return (ENXIO); 2899*1ae08745Sheppo } 2900*1ae08745Sheppo 2901*1ae08745Sheppo switch (msg.tag.vio_subtype) { 2902*1ae08745Sheppo case VIO_SUBTYPE_ACK: 2903*1ae08745Sheppo PR2("%s: DATA ACK\n", __func__); 2904*1ae08745Sheppo 2905*1ae08745Sheppo /* 2906*1ae08745Sheppo * Wake the thread waiting for each DRing entry ACK'ed 2907*1ae08745Sheppo */ 2908*1ae08745Sheppo for (i = 0; i < num_msgs; i++) { 2909*1ae08745Sheppo int idx = (start + i) % VD_DRING_LEN; 2910*1ae08745Sheppo 2911*1ae08745Sheppo local_dep = &vdc->local_dring[idx]; 2912*1ae08745Sheppo mutex_enter(&local_dep->lock); 2913*1ae08745Sheppo cv_signal(&local_dep->cv); 2914*1ae08745Sheppo mutex_exit(&local_dep->lock); 2915*1ae08745Sheppo } 2916*1ae08745Sheppo break; 2917*1ae08745Sheppo 2918*1ae08745Sheppo case VIO_SUBTYPE_NACK: 2919*1ae08745Sheppo PR0("%s: DATA NACK\n", __func__); 2920*1ae08745Sheppo dring_msg = (vio_dring_msg_t *)&msg; 2921*1ae08745Sheppo VDC_DUMP_DRING_MSG(dring_msg); 2922*1ae08745Sheppo 2923*1ae08745Sheppo /* Resend necessary messages */ 2924*1ae08745Sheppo for (i = 0; i < num_msgs; i++) { 2925*1ae08745Sheppo int idx = (start + i) % VD_DRING_LEN; 2926*1ae08745Sheppo 2927*1ae08745Sheppo local_dep = &vdc->local_dring[idx]; 2928*1ae08745Sheppo ASSERT(local_dep != NULL); 2929*1ae08745Sheppo mutex_enter(&local_dep->lock); 2930*1ae08745Sheppo 2931*1ae08745Sheppo if (local_dep->dep->hdr.dstate != VIO_DESC_READY) { 2932*1ae08745Sheppo PR0("%s[%d]: Won't resend entry %d [flag=%d]\n", 2933*1ae08745Sheppo __func__, vdc->instance, idx, 2934*1ae08745Sheppo local_dep->dep->hdr.dstate); 2935*1ae08745Sheppo mutex_exit(&local_dep->lock); 2936*1ae08745Sheppo break; 2937*1ae08745Sheppo } 2938*1ae08745Sheppo 2939*1ae08745Sheppo /* we'll reuse the message passed in */ 2940*1ae08745Sheppo VIO_INIT_DRING_DATA_TAG(msg); 2941*1ae08745Sheppo dring_msg->tag.vio_sid = vdc->session_id; 2942*1ae08745Sheppo dring_msg->seq_num = ++(vdc->seq_num); 2943*1ae08745Sheppo VDC_DUMP_DRING_MSG(dring_msg); 2944*1ae08745Sheppo 2945*1ae08745Sheppo status = vdc_send(vdc->ldc_handle, (caddr_t)&dring_msg, 2946*1ae08745Sheppo &msglen); 2947*1ae08745Sheppo PR1("%s: ldc_write() status=%d\n", __func__, status); 2948*1ae08745Sheppo if (status != 0) { 2949*1ae08745Sheppo vdc_msg("%s ldc_write(%d)\n", __func__, status); 2950*1ae08745Sheppo mutex_exit(&local_dep->lock); 2951*1ae08745Sheppo break; 2952*1ae08745Sheppo } 2953*1ae08745Sheppo 2954*1ae08745Sheppo mutex_exit(&local_dep->lock); 2955*1ae08745Sheppo } 2956*1ae08745Sheppo break; 2957*1ae08745Sheppo 2958*1ae08745Sheppo case VIO_SUBTYPE_INFO: 2959*1ae08745Sheppo default: 2960*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Got an unexpected DATA msg [subtype %d]", 2961*1ae08745Sheppo vdc->instance, msg.tag.vio_subtype); 2962*1ae08745Sheppo break; 2963*1ae08745Sheppo } 2964*1ae08745Sheppo 2965*1ae08745Sheppo return (status); 2966*1ae08745Sheppo } 2967*1ae08745Sheppo 2968*1ae08745Sheppo /* 2969*1ae08745Sheppo * Function: 2970*1ae08745Sheppo * vdc_process_err_msg() 2971*1ae08745Sheppo * 2972*1ae08745Sheppo * NOTE: No error messages are used as part of the vDisk protocol 2973*1ae08745Sheppo */ 2974*1ae08745Sheppo static int 2975*1ae08745Sheppo vdc_process_err_msg(vdc_t *vdc, vio_msg_t msg) 2976*1ae08745Sheppo { 2977*1ae08745Sheppo _NOTE(ARGUNUSED(vdc)) 2978*1ae08745Sheppo _NOTE(ARGUNUSED(msg)) 2979*1ae08745Sheppo 2980*1ae08745Sheppo int status = ENOTSUP; 2981*1ae08745Sheppo 2982*1ae08745Sheppo ASSERT(msg.tag.vio_msgtype == VIO_TYPE_ERR); 2983*1ae08745Sheppo cmn_err(CE_NOTE, "[%d] Got an ERR msg", vdc->instance); 2984*1ae08745Sheppo 2985*1ae08745Sheppo return (status); 2986*1ae08745Sheppo } 2987*1ae08745Sheppo 2988*1ae08745Sheppo /* 2989*1ae08745Sheppo * Function: 2990*1ae08745Sheppo * vdc_verify_seq_num() 2991*1ae08745Sheppo * 2992*1ae08745Sheppo * Description: 2993*1ae08745Sheppo * This functions verifies that the sequence number sent back by vds with 2994*1ae08745Sheppo * the latest message correctly follows the last request processed. 2995*1ae08745Sheppo * 2996*1ae08745Sheppo * Arguments: 2997*1ae08745Sheppo * vdc - soft state pointer for this instance of the driver. 2998*1ae08745Sheppo * dring_msg - pointer to the LDC message sent by vds 2999*1ae08745Sheppo * num_msgs - the number of requests being acknowledged 3000*1ae08745Sheppo * 3001*1ae08745Sheppo * Return Code: 3002*1ae08745Sheppo * B_TRUE - Success. 3003*1ae08745Sheppo * B_FALSE - The seq numbers are so out of sync, vdc cannot deal with them 3004*1ae08745Sheppo */ 3005*1ae08745Sheppo static boolean_t 3006*1ae08745Sheppo vdc_verify_seq_num(vdc_t *vdc, vio_dring_msg_t *dring_msg, int num_msgs) 3007*1ae08745Sheppo { 3008*1ae08745Sheppo ASSERT(vdc != NULL); 3009*1ae08745Sheppo ASSERT(dring_msg != NULL); 3010*1ae08745Sheppo 3011*1ae08745Sheppo /* 3012*1ae08745Sheppo * Check to see if the messages were responded to in the correct 3013*1ae08745Sheppo * order by vds. There are 3 possible scenarios: 3014*1ae08745Sheppo * - the seq_num we expected is returned (everything is OK) 3015*1ae08745Sheppo * - a seq_num earlier than the last one acknowledged is returned, 3016*1ae08745Sheppo * if so something is seriously wrong so we reset the connection 3017*1ae08745Sheppo * - a seq_num greater than what we expected is returned. 3018*1ae08745Sheppo */ 3019*1ae08745Sheppo if (dring_msg->seq_num != (vdc->seq_num_reply + num_msgs)) { 3020*1ae08745Sheppo vdc_msg("%s[%d]: Bogus seq_num %d, expected %d\n", 3021*1ae08745Sheppo __func__, vdc->instance, dring_msg->seq_num, 3022*1ae08745Sheppo vdc->seq_num_reply + num_msgs); 3023*1ae08745Sheppo if (dring_msg->seq_num < (vdc->seq_num_reply + num_msgs)) { 3024*1ae08745Sheppo return (B_FALSE); 3025*1ae08745Sheppo } else { 3026*1ae08745Sheppo /* 3027*1ae08745Sheppo * vds has responded with a seq_num greater than what we 3028*1ae08745Sheppo * expected 3029*1ae08745Sheppo */ 3030*1ae08745Sheppo return (B_FALSE); 3031*1ae08745Sheppo } 3032*1ae08745Sheppo } 3033*1ae08745Sheppo vdc->seq_num_reply += num_msgs; 3034*1ae08745Sheppo 3035*1ae08745Sheppo return (B_TRUE); 3036*1ae08745Sheppo } 3037*1ae08745Sheppo 3038*1ae08745Sheppo /* -------------------------------------------------------------------------- */ 3039*1ae08745Sheppo 3040*1ae08745Sheppo /* 3041*1ae08745Sheppo * DKIO(7) support 3042*1ae08745Sheppo * 3043*1ae08745Sheppo * XXX FIXME - needs to be converted to use the structures defined in the 3044*1ae08745Sheppo * latest VIO spec to communicate with the vDisk server. 3045*1ae08745Sheppo */ 3046*1ae08745Sheppo 3047*1ae08745Sheppo typedef struct vdc_dk_arg { 3048*1ae08745Sheppo struct dk_callback dkc; 3049*1ae08745Sheppo int mode; 3050*1ae08745Sheppo dev_t dev; 3051*1ae08745Sheppo vdc_t *vdc; 3052*1ae08745Sheppo } vdc_dk_arg_t; 3053*1ae08745Sheppo 3054*1ae08745Sheppo /* 3055*1ae08745Sheppo * Function: 3056*1ae08745Sheppo * vdc_dkio_flush_cb() 3057*1ae08745Sheppo * 3058*1ae08745Sheppo * Description: 3059*1ae08745Sheppo * This routine is a callback for DKIOCFLUSHWRITECACHE which can be called 3060*1ae08745Sheppo * by kernel code. 3061*1ae08745Sheppo * 3062*1ae08745Sheppo * Arguments: 3063*1ae08745Sheppo * arg - a pointer to a vdc_dk_arg_t structure. 3064*1ae08745Sheppo */ 3065*1ae08745Sheppo void 3066*1ae08745Sheppo vdc_dkio_flush_cb(void *arg) 3067*1ae08745Sheppo { 3068*1ae08745Sheppo struct vdc_dk_arg *dk_arg = (struct vdc_dk_arg *)arg; 3069*1ae08745Sheppo struct dk_callback *dkc = NULL; 3070*1ae08745Sheppo vdc_t *vdc = NULL; 3071*1ae08745Sheppo int rv; 3072*1ae08745Sheppo 3073*1ae08745Sheppo if (dk_arg == NULL) { 3074*1ae08745Sheppo vdc_msg("%s[?] DKIOCFLUSHWRITECACHE arg is NULL\n", __func__); 3075*1ae08745Sheppo return; 3076*1ae08745Sheppo } 3077*1ae08745Sheppo dkc = &dk_arg->dkc; 3078*1ae08745Sheppo vdc = dk_arg->vdc; 3079*1ae08745Sheppo ASSERT(vdc != NULL); 3080*1ae08745Sheppo 3081*1ae08745Sheppo rv = vdc_populate_descriptor(vdc, NULL, 0, VD_OP_FLUSH, 3082*1ae08745Sheppo dk_arg->mode, SDPART(getminor(dk_arg->dev))); 3083*1ae08745Sheppo if (rv != 0) { 3084*1ae08745Sheppo PR0("%s[%d] DKIOCFLUSHWRITECACHE failed : model %x\n", 3085*1ae08745Sheppo __func__, vdc->instance, 3086*1ae08745Sheppo ddi_model_convert_from(dk_arg->mode & FMODELS)); 3087*1ae08745Sheppo return; 3088*1ae08745Sheppo } 3089*1ae08745Sheppo 3090*1ae08745Sheppo /* 3091*1ae08745Sheppo * Trigger the call back to notify the caller the the ioctl call has 3092*1ae08745Sheppo * been completed. 3093*1ae08745Sheppo */ 3094*1ae08745Sheppo if ((dk_arg->mode & FKIOCTL) && 3095*1ae08745Sheppo (dkc != NULL) && 3096*1ae08745Sheppo (dkc->dkc_callback != NULL)) { 3097*1ae08745Sheppo ASSERT(dkc->dkc_cookie != NULL); 3098*1ae08745Sheppo (*dkc->dkc_callback)(dkc->dkc_cookie, ENOTSUP); 3099*1ae08745Sheppo } 3100*1ae08745Sheppo 3101*1ae08745Sheppo /* Indicate that one less DKIO write flush is outstanding */ 3102*1ae08745Sheppo mutex_enter(&vdc->lock); 3103*1ae08745Sheppo vdc->dkio_flush_pending--; 3104*1ae08745Sheppo ASSERT(vdc->dkio_flush_pending >= 0); 3105*1ae08745Sheppo mutex_exit(&vdc->lock); 3106*1ae08745Sheppo } 3107*1ae08745Sheppo 3108*1ae08745Sheppo 3109*1ae08745Sheppo /* 3110*1ae08745Sheppo * This structure is used in the DKIO(7I) array below. 3111*1ae08745Sheppo */ 3112*1ae08745Sheppo typedef struct vdc_dk_ioctl { 3113*1ae08745Sheppo uint8_t op; /* VD_OP_XXX value */ 3114*1ae08745Sheppo int cmd; /* Solaris ioctl operation number */ 3115*1ae08745Sheppo uint8_t copy; /* copyin and/or copyout needed ? */ 3116*1ae08745Sheppo size_t nbytes; /* size of structure to be copied */ 3117*1ae08745Sheppo size_t nbytes32; /* size of 32bit struct if different */ 3118*1ae08745Sheppo /* to 64bit struct (zero otherwise) */ 3119*1ae08745Sheppo } vdc_dk_ioctl_t; 3120*1ae08745Sheppo 3121*1ae08745Sheppo /* 3122*1ae08745Sheppo * Subset of DKIO(7I) operations currently supported 3123*1ae08745Sheppo */ 3124*1ae08745Sheppo static vdc_dk_ioctl_t dk_ioctl[] = { 3125*1ae08745Sheppo {VD_OP_FLUSH, DKIOCFLUSHWRITECACHE, 0, 3126*1ae08745Sheppo 0, 0}, 3127*1ae08745Sheppo {VD_OP_GET_WCE, DKIOCGETWCE, 0, 3128*1ae08745Sheppo 0, 0}, 3129*1ae08745Sheppo {VD_OP_SET_WCE, DKIOCSETWCE, 0, 3130*1ae08745Sheppo 0, 0}, 3131*1ae08745Sheppo {VD_OP_GET_VTOC, DKIOCGVTOC, VD_COPYOUT, 3132*1ae08745Sheppo sizeof (struct vtoc), sizeof (struct vtoc32)}, 3133*1ae08745Sheppo {VD_OP_SET_VTOC, DKIOCSVTOC, VD_COPYIN, 3134*1ae08745Sheppo sizeof (struct vtoc), sizeof (struct vtoc32)}, 3135*1ae08745Sheppo {VD_OP_SET_DISKGEOM, DKIOCSGEOM, VD_COPYIN, 3136*1ae08745Sheppo sizeof (struct dk_geom), 0}, 3137*1ae08745Sheppo {VD_OP_GET_DISKGEOM, DKIOCGGEOM, VD_COPYOUT, 3138*1ae08745Sheppo sizeof (struct dk_geom), 0}, 3139*1ae08745Sheppo {VD_OP_GET_DISKGEOM, DKIOCG_PHYGEOM, VD_COPYOUT, 3140*1ae08745Sheppo sizeof (struct dk_geom), 0}, 3141*1ae08745Sheppo {VD_OP_GET_DISKGEOM, DKIOCG_VIRTGEOM, VD_COPYOUT, 3142*1ae08745Sheppo sizeof (struct dk_geom), 0}, 3143*1ae08745Sheppo {VD_OP_SET_DISKGEOM, DKIOCSGEOM, VD_COPYOUT, 3144*1ae08745Sheppo sizeof (struct dk_geom), 0}, 3145*1ae08745Sheppo {VD_OP_SCSICMD, USCSICMD, VD_COPYIN|VD_COPYOUT, 3146*1ae08745Sheppo sizeof (struct uscsi_cmd), sizeof (struct uscsi_cmd32)}, 3147*1ae08745Sheppo {0, DKIOCINFO, VD_COPYOUT, 3148*1ae08745Sheppo sizeof (struct dk_cinfo), 0}, 3149*1ae08745Sheppo {0, DKIOCGMEDIAINFO, VD_COPYOUT, 3150*1ae08745Sheppo sizeof (struct dk_minfo), 0}, 3151*1ae08745Sheppo {0, DKIOCREMOVABLE, 0, 3152*1ae08745Sheppo 0, 0}, 3153*1ae08745Sheppo {0, CDROMREADOFFSET, 0, 3154*1ae08745Sheppo 0, 0} 3155*1ae08745Sheppo }; 3156*1ae08745Sheppo 3157*1ae08745Sheppo /* 3158*1ae08745Sheppo * Function: 3159*1ae08745Sheppo * vd_process_ioctl() 3160*1ae08745Sheppo * 3161*1ae08745Sheppo * Description: 3162*1ae08745Sheppo * This routine is the driver entry point for handling user 3163*1ae08745Sheppo * requests to get the device geometry. 3164*1ae08745Sheppo * 3165*1ae08745Sheppo * Arguments: 3166*1ae08745Sheppo * dev - the device number 3167*1ae08745Sheppo * cmd - the operation [dkio(7I)] to be processed 3168*1ae08745Sheppo * arg - pointer to user provided structure 3169*1ae08745Sheppo * (contains data to be set or reference parameter for get) 3170*1ae08745Sheppo * mode - bit flag, indicating open settings, 32/64 bit type, etc 3171*1ae08745Sheppo * rvalp - calling process return value, used in some ioctl calls 3172*1ae08745Sheppo * (passed throught to vds who fills in the value) 3173*1ae08745Sheppo * 3174*1ae08745Sheppo * Assumptions: 3175*1ae08745Sheppo * vds will make the ioctl calls in the 64 bit address space so vdc 3176*1ae08745Sheppo * will convert the data to/from 32 bit as necessary before doing 3177*1ae08745Sheppo * the copyin or copyout. 3178*1ae08745Sheppo * 3179*1ae08745Sheppo * Return Code: 3180*1ae08745Sheppo * 0 3181*1ae08745Sheppo * EFAULT 3182*1ae08745Sheppo * ENXIO 3183*1ae08745Sheppo * EIO 3184*1ae08745Sheppo * ENOTSUP 3185*1ae08745Sheppo */ 3186*1ae08745Sheppo static int 3187*1ae08745Sheppo vd_process_ioctl(dev_t dev, int cmd, caddr_t arg, int mode) 3188*1ae08745Sheppo { 3189*1ae08745Sheppo int instance = SDUNIT(getminor(dev)); 3190*1ae08745Sheppo vdc_t *vdc = NULL; 3191*1ae08745Sheppo int op = -1; /* VD_OP_XXX value */ 3192*1ae08745Sheppo int rv = -1; 3193*1ae08745Sheppo int idx = 0; /* index into dk_ioctl[] */ 3194*1ae08745Sheppo size_t len = 0; /* #bytes to send to vds */ 3195*1ae08745Sheppo size_t alloc_len = 0; /* #bytes to allocate mem for */ 3196*1ae08745Sheppo size_t copy_len = 0; /* #bytes to copy in/out */ 3197*1ae08745Sheppo caddr_t mem_p = NULL; 3198*1ae08745Sheppo boolean_t do_convert_32to64 = B_FALSE; 3199*1ae08745Sheppo size_t nioctls = (sizeof (dk_ioctl)) / (sizeof (dk_ioctl[0])); 3200*1ae08745Sheppo 3201*1ae08745Sheppo PR0("%s: Processing ioctl(%x) for dev %x : model %x\n", 3202*1ae08745Sheppo __func__, cmd, dev, ddi_model_convert_from(mode & FMODELS)); 3203*1ae08745Sheppo 3204*1ae08745Sheppo vdc = ddi_get_soft_state(vdc_state, instance); 3205*1ae08745Sheppo if (vdc == NULL) { 3206*1ae08745Sheppo cmn_err(CE_NOTE, "![%d] Could not get soft state structure", 3207*1ae08745Sheppo instance); 3208*1ae08745Sheppo return (ENXIO); 3209*1ae08745Sheppo } 3210*1ae08745Sheppo 3211*1ae08745Sheppo /* 3212*1ae08745Sheppo * Check to see if we can communicate with the vDisk server 3213*1ae08745Sheppo */ 3214*1ae08745Sheppo rv = vdc_is_able_to_tx_data(vdc, O_NONBLOCK); 3215*1ae08745Sheppo if (rv == B_FALSE) { 3216*1ae08745Sheppo PR0("%s[%d] Not ready to transmit data\n", __func__, instance); 3217*1ae08745Sheppo return (ENOLINK); 3218*1ae08745Sheppo } 3219*1ae08745Sheppo 3220*1ae08745Sheppo /* 3221*1ae08745Sheppo * Validate the ioctl operation to be performed. 3222*1ae08745Sheppo * 3223*1ae08745Sheppo * If we have looped through the array without finding a match then we 3224*1ae08745Sheppo * don't support this ioctl. 3225*1ae08745Sheppo */ 3226*1ae08745Sheppo for (idx = 0; idx < nioctls; idx++) { 3227*1ae08745Sheppo if (cmd == dk_ioctl[idx].cmd) 3228*1ae08745Sheppo break; 3229*1ae08745Sheppo } 3230*1ae08745Sheppo 3231*1ae08745Sheppo if (idx >= nioctls) { 3232*1ae08745Sheppo PR0("%s[%d] Unsupported ioctl(%x)\n", 3233*1ae08745Sheppo __func__, vdc->instance, cmd); 3234*1ae08745Sheppo return (ENOTSUP); 3235*1ae08745Sheppo } 3236*1ae08745Sheppo 3237*1ae08745Sheppo copy_len = len = dk_ioctl[idx].nbytes; 3238*1ae08745Sheppo op = dk_ioctl[idx].op; 3239*1ae08745Sheppo 3240*1ae08745Sheppo /* 3241*1ae08745Sheppo * Some ioctl operations have different sized structures for 32 bit 3242*1ae08745Sheppo * and 64 bit. If the userland caller is 32 bit, we need to check 3243*1ae08745Sheppo * to see if the operation is one of those special cases and 3244*1ae08745Sheppo * flag that we need to convert to and/or from 32 bit since vds 3245*1ae08745Sheppo * will make the call as 64 bit. 3246*1ae08745Sheppo */ 3247*1ae08745Sheppo if ((ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) && 3248*1ae08745Sheppo (dk_ioctl[idx].nbytes != 0) && 3249*1ae08745Sheppo (dk_ioctl[idx].nbytes32 != 0)) { 3250*1ae08745Sheppo do_convert_32to64 = B_TRUE; 3251*1ae08745Sheppo copy_len = dk_ioctl[idx].nbytes32; 3252*1ae08745Sheppo } 3253*1ae08745Sheppo 3254*1ae08745Sheppo /* 3255*1ae08745Sheppo * Deal with the ioctls which the server does not provide. 3256*1ae08745Sheppo */ 3257*1ae08745Sheppo switch (cmd) { 3258*1ae08745Sheppo case CDROMREADOFFSET: 3259*1ae08745Sheppo case DKIOCREMOVABLE: 3260*1ae08745Sheppo return (ENOTTY); 3261*1ae08745Sheppo 3262*1ae08745Sheppo case DKIOCINFO: 3263*1ae08745Sheppo { 3264*1ae08745Sheppo struct dk_cinfo cinfo; 3265*1ae08745Sheppo if (vdc->cinfo == NULL) 3266*1ae08745Sheppo return (ENXIO); 3267*1ae08745Sheppo 3268*1ae08745Sheppo bcopy(vdc->cinfo, &cinfo, sizeof (struct dk_cinfo)); 3269*1ae08745Sheppo cinfo.dki_partition = SDPART(getminor(dev)); 3270*1ae08745Sheppo 3271*1ae08745Sheppo rv = ddi_copyout(&cinfo, (void *)arg, 3272*1ae08745Sheppo sizeof (struct dk_cinfo), mode); 3273*1ae08745Sheppo if (rv != 0) 3274*1ae08745Sheppo return (EFAULT); 3275*1ae08745Sheppo 3276*1ae08745Sheppo return (0); 3277*1ae08745Sheppo } 3278*1ae08745Sheppo 3279*1ae08745Sheppo case DKIOCGMEDIAINFO: 3280*1ae08745Sheppo if (vdc->minfo == NULL) 3281*1ae08745Sheppo return (ENXIO); 3282*1ae08745Sheppo 3283*1ae08745Sheppo rv = ddi_copyout(vdc->minfo, (void *)arg, 3284*1ae08745Sheppo sizeof (struct dk_minfo), mode); 3285*1ae08745Sheppo if (rv != 0) 3286*1ae08745Sheppo return (EFAULT); 3287*1ae08745Sheppo 3288*1ae08745Sheppo return (0); 3289*1ae08745Sheppo } 3290*1ae08745Sheppo 3291*1ae08745Sheppo /* catch programming error in vdc - should be a VD_OP_XXX ioctl */ 3292*1ae08745Sheppo ASSERT(op != 0); 3293*1ae08745Sheppo 3294*1ae08745Sheppo /* LDC requires that the memory being mapped is 8-byte aligned */ 3295*1ae08745Sheppo alloc_len = P2ROUNDUP(len, sizeof (uint64_t)); 3296*1ae08745Sheppo PR1("%s[%d]: struct size %d alloc %d\n", 3297*1ae08745Sheppo __func__, instance, len, alloc_len); 3298*1ae08745Sheppo 3299*1ae08745Sheppo if (alloc_len != 0) 3300*1ae08745Sheppo mem_p = kmem_zalloc(alloc_len, KM_SLEEP); 3301*1ae08745Sheppo 3302*1ae08745Sheppo if (dk_ioctl[idx].copy & VD_COPYIN) { 3303*1ae08745Sheppo if (arg == NULL) { 3304*1ae08745Sheppo if (mem_p != NULL) 3305*1ae08745Sheppo kmem_free(mem_p, alloc_len); 3306*1ae08745Sheppo return (EINVAL); 3307*1ae08745Sheppo } 3308*1ae08745Sheppo 3309*1ae08745Sheppo ASSERT(copy_len != 0); 3310*1ae08745Sheppo 3311*1ae08745Sheppo rv = ddi_copyin((void *)arg, mem_p, copy_len, mode); 3312*1ae08745Sheppo if (rv != 0) { 3313*1ae08745Sheppo if (mem_p != NULL) 3314*1ae08745Sheppo kmem_free(mem_p, alloc_len); 3315*1ae08745Sheppo return (EFAULT); 3316*1ae08745Sheppo } 3317*1ae08745Sheppo 3318*1ae08745Sheppo /* 3319*1ae08745Sheppo * some operations need the data to be converted from 32 bit 3320*1ae08745Sheppo * to 64 bit structures so that vds can process them on the 3321*1ae08745Sheppo * other side. 3322*1ae08745Sheppo */ 3323*1ae08745Sheppo if (do_convert_32to64) { 3324*1ae08745Sheppo switch (cmd) { 3325*1ae08745Sheppo case DKIOCSVTOC: 3326*1ae08745Sheppo { 3327*1ae08745Sheppo struct vtoc vt; 3328*1ae08745Sheppo struct vtoc32 vt32; 3329*1ae08745Sheppo 3330*1ae08745Sheppo ASSERT(mem_p != NULL); 3331*1ae08745Sheppo vt32 = *((struct vtoc32 *)(mem_p)); 3332*1ae08745Sheppo 3333*1ae08745Sheppo vtoc32tovtoc(vt32, vt); 3334*1ae08745Sheppo bcopy(&vt, mem_p, len); 3335*1ae08745Sheppo break; 3336*1ae08745Sheppo } 3337*1ae08745Sheppo 3338*1ae08745Sheppo case USCSICMD: 3339*1ae08745Sheppo { 3340*1ae08745Sheppo struct uscsi_cmd scmd; 3341*1ae08745Sheppo struct uscsi_cmd *uscmd = &scmd; 3342*1ae08745Sheppo struct uscsi_cmd32 *uscmd32; 3343*1ae08745Sheppo 3344*1ae08745Sheppo ASSERT(mem_p != NULL); 3345*1ae08745Sheppo uscmd32 = (struct uscsi_cmd32 *)mem_p; 3346*1ae08745Sheppo 3347*1ae08745Sheppo /* 3348*1ae08745Sheppo * Convert the ILP32 uscsi data from the 3349*1ae08745Sheppo * application to LP64 for internal use. 3350*1ae08745Sheppo */ 3351*1ae08745Sheppo uscsi_cmd32touscsi_cmd(uscmd32, uscmd); 3352*1ae08745Sheppo bcopy(uscmd, mem_p, len); 3353*1ae08745Sheppo break; 3354*1ae08745Sheppo } 3355*1ae08745Sheppo default: 3356*1ae08745Sheppo break; 3357*1ae08745Sheppo } 3358*1ae08745Sheppo } 3359*1ae08745Sheppo } 3360*1ae08745Sheppo 3361*1ae08745Sheppo /* 3362*1ae08745Sheppo * handle the special case of DKIOCFLUSHWRITECACHE 3363*1ae08745Sheppo */ 3364*1ae08745Sheppo if (cmd == DKIOCFLUSHWRITECACHE) { 3365*1ae08745Sheppo struct dk_callback *dkc = (struct dk_callback *)arg; 3366*1ae08745Sheppo 3367*1ae08745Sheppo PR0("%s[%d]: DKIOCFLUSHWRITECACHE\n", __func__, instance); 3368*1ae08745Sheppo 3369*1ae08745Sheppo /* no mem should have been allocated hence no need to free it */ 3370*1ae08745Sheppo ASSERT(mem_p == NULL); 3371*1ae08745Sheppo 3372*1ae08745Sheppo /* 3373*1ae08745Sheppo * If arg is NULL, we break here and the call operates 3374*1ae08745Sheppo * synchronously; waiting for vds to return. 3375*1ae08745Sheppo * 3376*1ae08745Sheppo * i.e. after the request to vds returns successfully, 3377*1ae08745Sheppo * all writes completed prior to the ioctl will have been 3378*1ae08745Sheppo * flushed from the disk write cache to persistent media. 3379*1ae08745Sheppo */ 3380*1ae08745Sheppo if (dkc != NULL) { 3381*1ae08745Sheppo vdc_dk_arg_t arg; 3382*1ae08745Sheppo arg.mode = mode; 3383*1ae08745Sheppo arg.dev = dev; 3384*1ae08745Sheppo bcopy(dkc, &arg.dkc, sizeof (*dkc)); 3385*1ae08745Sheppo 3386*1ae08745Sheppo mutex_enter(&vdc->lock); 3387*1ae08745Sheppo vdc->dkio_flush_pending++; 3388*1ae08745Sheppo arg.vdc = vdc; 3389*1ae08745Sheppo mutex_exit(&vdc->lock); 3390*1ae08745Sheppo 3391*1ae08745Sheppo /* put the request on a task queue */ 3392*1ae08745Sheppo rv = taskq_dispatch(system_taskq, vdc_dkio_flush_cb, 3393*1ae08745Sheppo (void *)&arg, DDI_SLEEP); 3394*1ae08745Sheppo 3395*1ae08745Sheppo return (rv == NULL ? ENOMEM : 0); 3396*1ae08745Sheppo } 3397*1ae08745Sheppo } 3398*1ae08745Sheppo 3399*1ae08745Sheppo /* 3400*1ae08745Sheppo * send request to vds to service the ioctl. 3401*1ae08745Sheppo */ 3402*1ae08745Sheppo rv = vdc_populate_descriptor(vdc, mem_p, alloc_len, op, mode, 3403*1ae08745Sheppo SDPART((getminor(dev)))); 3404*1ae08745Sheppo if (rv != 0) { 3405*1ae08745Sheppo /* 3406*1ae08745Sheppo * This is not necessarily an error. The ioctl could 3407*1ae08745Sheppo * be returning a value such as ENOTTY to indicate 3408*1ae08745Sheppo * that the ioctl is not applicable. 3409*1ae08745Sheppo */ 3410*1ae08745Sheppo PR0("%s[%d]: vds returned %d for ioctl 0x%x\n", 3411*1ae08745Sheppo __func__, instance, rv, cmd); 3412*1ae08745Sheppo if (mem_p != NULL) 3413*1ae08745Sheppo kmem_free(mem_p, alloc_len); 3414*1ae08745Sheppo return (rv); 3415*1ae08745Sheppo } 3416*1ae08745Sheppo 3417*1ae08745Sheppo /* 3418*1ae08745Sheppo * If the VTOC has been changed, then vdc needs to update the copy 3419*1ae08745Sheppo * it saved in the soft state structure and try and update the device 3420*1ae08745Sheppo * node properties. Failing to set the properties should not cause 3421*1ae08745Sheppo * an error to be return the caller though. 3422*1ae08745Sheppo */ 3423*1ae08745Sheppo if (cmd == DKIOCSVTOC) { 3424*1ae08745Sheppo bcopy(mem_p, vdc->vtoc, sizeof (struct vtoc)); 3425*1ae08745Sheppo if (vdc_create_device_nodes_props(vdc)) { 3426*1ae08745Sheppo cmn_err(CE_NOTE, "![%d] Failed to update device nodes" 3427*1ae08745Sheppo " properties", instance); 3428*1ae08745Sheppo } 3429*1ae08745Sheppo } 3430*1ae08745Sheppo 3431*1ae08745Sheppo /* 3432*1ae08745Sheppo * if we don't have to do a copyout, we have nothing left to do 3433*1ae08745Sheppo * so we just return. 3434*1ae08745Sheppo */ 3435*1ae08745Sheppo if ((dk_ioctl[idx].copy & VD_COPYOUT) == 0) { 3436*1ae08745Sheppo if (mem_p != NULL) 3437*1ae08745Sheppo kmem_free(mem_p, alloc_len); 3438*1ae08745Sheppo return (0); 3439*1ae08745Sheppo } 3440*1ae08745Sheppo 3441*1ae08745Sheppo /* sanity check */ 3442*1ae08745Sheppo if (mem_p == NULL) 3443*1ae08745Sheppo return (EFAULT); 3444*1ae08745Sheppo 3445*1ae08745Sheppo 3446*1ae08745Sheppo /* 3447*1ae08745Sheppo * some operations need the data to be converted from 64 bit 3448*1ae08745Sheppo * back to 32 bit structures after vds has processed them. 3449*1ae08745Sheppo */ 3450*1ae08745Sheppo if (do_convert_32to64) { 3451*1ae08745Sheppo switch (cmd) { 3452*1ae08745Sheppo case DKIOCGVTOC: 3453*1ae08745Sheppo { 3454*1ae08745Sheppo struct vtoc vt; 3455*1ae08745Sheppo struct vtoc32 vt32; 3456*1ae08745Sheppo 3457*1ae08745Sheppo ASSERT(mem_p != NULL); 3458*1ae08745Sheppo vt = *((struct vtoc *)(mem_p)); 3459*1ae08745Sheppo 3460*1ae08745Sheppo vtoctovtoc32(vt, vt32); 3461*1ae08745Sheppo bcopy(&vt32, mem_p, copy_len); 3462*1ae08745Sheppo break; 3463*1ae08745Sheppo } 3464*1ae08745Sheppo 3465*1ae08745Sheppo case USCSICMD: 3466*1ae08745Sheppo { 3467*1ae08745Sheppo struct uscsi_cmd32 *uc32; 3468*1ae08745Sheppo struct uscsi_cmd *uc; 3469*1ae08745Sheppo 3470*1ae08745Sheppo len = sizeof (struct uscsi_cmd32); 3471*1ae08745Sheppo 3472*1ae08745Sheppo ASSERT(mem_p != NULL); 3473*1ae08745Sheppo uc = (struct uscsi_cmd *)mem_p; 3474*1ae08745Sheppo uc32 = kmem_zalloc(len, KM_SLEEP); 3475*1ae08745Sheppo 3476*1ae08745Sheppo uscsi_cmdtouscsi_cmd32(uc, uc32); 3477*1ae08745Sheppo bcopy(uc32, mem_p, copy_len); 3478*1ae08745Sheppo PR0("%s[%d]: uscsi_cmd32:%x\n", __func__, instance, 3479*1ae08745Sheppo ((struct uscsi_cmd32 *)mem_p)->uscsi_cdblen); 3480*1ae08745Sheppo kmem_free(uc32, len); 3481*1ae08745Sheppo break; 3482*1ae08745Sheppo } 3483*1ae08745Sheppo default: 3484*1ae08745Sheppo PR1("%s[%d]: This mode (%x) should just work for(%x)\n", 3485*1ae08745Sheppo __func__, instance, mode, cmd); 3486*1ae08745Sheppo break; 3487*1ae08745Sheppo } 3488*1ae08745Sheppo } 3489*1ae08745Sheppo 3490*1ae08745Sheppo ASSERT(len != 0); 3491*1ae08745Sheppo ASSERT(mem_p != NULL); 3492*1ae08745Sheppo 3493*1ae08745Sheppo rv = ddi_copyout(mem_p, (void *)arg, copy_len, mode); 3494*1ae08745Sheppo if (rv != 0) { 3495*1ae08745Sheppo vdc_msg("%s[%d]: Could not do copy out for ioctl (%x)\n", 3496*1ae08745Sheppo __func__, instance, cmd); 3497*1ae08745Sheppo rv = EFAULT; 3498*1ae08745Sheppo } 3499*1ae08745Sheppo 3500*1ae08745Sheppo if (mem_p != NULL) 3501*1ae08745Sheppo kmem_free(mem_p, alloc_len); 3502*1ae08745Sheppo 3503*1ae08745Sheppo return (rv); 3504*1ae08745Sheppo } 3505*1ae08745Sheppo 3506*1ae08745Sheppo /* 3507*1ae08745Sheppo * Function: 3508*1ae08745Sheppo * vdc_create_fake_geometry() 3509*1ae08745Sheppo * 3510*1ae08745Sheppo * Description: 3511*1ae08745Sheppo * This routine fakes up the disk info needed for some DKIO ioctls. 3512*1ae08745Sheppo * - DKIOCINFO 3513*1ae08745Sheppo * - DKIOCGMEDIAINFO 3514*1ae08745Sheppo * 3515*1ae08745Sheppo * [ just like lofi(7D) and ramdisk(7D) ] 3516*1ae08745Sheppo * 3517*1ae08745Sheppo * Arguments: 3518*1ae08745Sheppo * vdc - soft state pointer for this instance of the device driver. 3519*1ae08745Sheppo * 3520*1ae08745Sheppo * Return Code: 3521*1ae08745Sheppo * 0 - Success 3522*1ae08745Sheppo */ 3523*1ae08745Sheppo static int 3524*1ae08745Sheppo vdc_create_fake_geometry(vdc_t *vdc) 3525*1ae08745Sheppo { 3526*1ae08745Sheppo ASSERT(vdc != NULL); 3527*1ae08745Sheppo 3528*1ae08745Sheppo /* 3529*1ae08745Sheppo * DKIOCINFO support 3530*1ae08745Sheppo */ 3531*1ae08745Sheppo vdc->cinfo = kmem_zalloc(sizeof (struct dk_cinfo), KM_SLEEP); 3532*1ae08745Sheppo 3533*1ae08745Sheppo (void) strcpy(vdc->cinfo->dki_cname, VDC_DRIVER_NAME); 3534*1ae08745Sheppo (void) strcpy(vdc->cinfo->dki_dname, VDC_DRIVER_NAME); 3535*1ae08745Sheppo vdc->cinfo->dki_maxtransfer = vdc->max_xfer_sz / vdc->block_size; 3536*1ae08745Sheppo vdc->cinfo->dki_ctype = DKC_SCSI_CCS; 3537*1ae08745Sheppo vdc->cinfo->dki_flags = DKI_FMTVOL; 3538*1ae08745Sheppo vdc->cinfo->dki_cnum = 0; 3539*1ae08745Sheppo vdc->cinfo->dki_addr = 0; 3540*1ae08745Sheppo vdc->cinfo->dki_space = 0; 3541*1ae08745Sheppo vdc->cinfo->dki_prio = 0; 3542*1ae08745Sheppo vdc->cinfo->dki_vec = 0; 3543*1ae08745Sheppo vdc->cinfo->dki_unit = vdc->instance; 3544*1ae08745Sheppo vdc->cinfo->dki_slave = 0; 3545*1ae08745Sheppo /* 3546*1ae08745Sheppo * The partition number will be created on the fly depending on the 3547*1ae08745Sheppo * actual slice (i.e. minor node) that is used to request the data. 3548*1ae08745Sheppo */ 3549*1ae08745Sheppo vdc->cinfo->dki_partition = 0; 3550*1ae08745Sheppo 3551*1ae08745Sheppo /* 3552*1ae08745Sheppo * DKIOCGMEDIAINFO support 3553*1ae08745Sheppo */ 3554*1ae08745Sheppo vdc->minfo = kmem_zalloc(sizeof (struct dk_minfo), KM_SLEEP); 3555*1ae08745Sheppo vdc->minfo->dki_media_type = DK_FIXED_DISK; 3556*1ae08745Sheppo vdc->minfo->dki_capacity = 1; 3557*1ae08745Sheppo vdc->minfo->dki_lbsize = DEV_BSIZE; 3558*1ae08745Sheppo 3559*1ae08745Sheppo return (0); 3560*1ae08745Sheppo } 3561