1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte /* 2240b706cfSMilan Jurik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23fcf3ce44SJohn Forte * Use is subject to license terms. 24fcf3ce44SJohn Forte */ 25fcf3ce44SJohn Forte 26fcf3ce44SJohn Forte /* 27fcf3ce44SJohn Forte * fcsm - ULP Module for Fibre Channel SAN Management 28fcf3ce44SJohn Forte */ 29fcf3ce44SJohn Forte 30fcf3ce44SJohn Forte #include <sys/types.h> 31fcf3ce44SJohn Forte #include <sys/file.h> 32fcf3ce44SJohn Forte #include <sys/kmem.h> 33fcf3ce44SJohn Forte #include <sys/scsi/scsi.h> 34fcf3ce44SJohn Forte #include <sys/var.h> 35fcf3ce44SJohn Forte #include <sys/byteorder.h> 36fcf3ce44SJohn Forte #include <sys/fibre-channel/fc.h> 37fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_ulpif.h> 38fcf3ce44SJohn Forte #include <sys/fibre-channel/ulp/fcsm.h> 39fcf3ce44SJohn Forte 40fcf3ce44SJohn Forte /* Definitions */ 41*7ff83669SZhong Wang #define FCSM_VERSION "20090729-1.28" 42fcf3ce44SJohn Forte #define FCSM_NAME_VERSION "SunFC FCSM v" FCSM_VERSION 43fcf3ce44SJohn Forte 44fcf3ce44SJohn Forte /* Global Variables */ 45fcf3ce44SJohn Forte static char fcsm_name[] = "FCSM"; 46fcf3ce44SJohn Forte static void *fcsm_state = NULL; 47fcf3ce44SJohn Forte static kmutex_t fcsm_global_mutex; 48fcf3ce44SJohn Forte static uint32_t fcsm_flag = FCSM_IDLE; 49fcf3ce44SJohn Forte static dev_info_t *fcsm_dip = NULL; 50fcf3ce44SJohn Forte static fcsm_t *fcsm_port_head = NULL; 51fcf3ce44SJohn Forte static kmem_cache_t *fcsm_job_cache = NULL; 52fcf3ce44SJohn Forte static int fcsm_num_attaching = 0; 53fcf3ce44SJohn Forte static int fcsm_num_detaching = 0; 54fcf3ce44SJohn Forte static int fcsm_detached = 0; 55fcf3ce44SJohn Forte 56fcf3ce44SJohn Forte static int fcsm_max_cmd_retries = FCSM_MAX_CMD_RETRIES; 57fcf3ce44SJohn Forte static int fcsm_retry_interval = FCSM_RETRY_INTERVAL; 58fcf3ce44SJohn Forte static int fcsm_retry_ticker = FCSM_RETRY_TICKER; 59fcf3ce44SJohn Forte static int fcsm_offline_ticker = FCSM_OFFLINE_TICKER; 60fcf3ce44SJohn Forte static int fcsm_max_job_retries = FCSM_MAX_JOB_RETRIES; 61fcf3ce44SJohn Forte static clock_t fcsm_retry_ticks; 62fcf3ce44SJohn Forte static clock_t fcsm_offline_ticks; 63fcf3ce44SJohn Forte 64fcf3ce44SJohn Forte 65fcf3ce44SJohn Forte 66fcf3ce44SJohn Forte #ifdef DEBUG 67fcf3ce44SJohn Forte uint32_t fcsm_debug = (SMDL_TRACE | SMDL_IO | 68fcf3ce44SJohn Forte SMDL_ERR | SMDL_INFO); 69fcf3ce44SJohn Forte #endif 70fcf3ce44SJohn Forte 71fcf3ce44SJohn Forte 72fcf3ce44SJohn Forte /* Character/Block entry points */ 73fcf3ce44SJohn Forte struct cb_ops fcsm_cb_ops = { 74fcf3ce44SJohn Forte fcsm_open, /* open */ 75fcf3ce44SJohn Forte fcsm_close, /* close */ 76fcf3ce44SJohn Forte nodev, /* strategy */ 77fcf3ce44SJohn Forte nodev, /* print */ 78fcf3ce44SJohn Forte nodev, /* dump */ 79fcf3ce44SJohn Forte nodev, /* read */ 80fcf3ce44SJohn Forte nodev, /* write */ 81fcf3ce44SJohn Forte fcsm_ioctl, /* ioctl */ 82fcf3ce44SJohn Forte nodev, /* devmap */ 83fcf3ce44SJohn Forte nodev, /* mmap */ 84fcf3ce44SJohn Forte nodev, /* segmap */ 85fcf3ce44SJohn Forte nochpoll, /* poll */ 86fcf3ce44SJohn Forte ddi_prop_op, 87fcf3ce44SJohn Forte NULL, /* streams info */ 88fcf3ce44SJohn Forte D_NEW | D_MP, 89fcf3ce44SJohn Forte CB_REV, 90fcf3ce44SJohn Forte nodev, /* aread */ 91fcf3ce44SJohn Forte nodev /* awrite */ 92fcf3ce44SJohn Forte }; 93fcf3ce44SJohn Forte 94fcf3ce44SJohn Forte struct dev_ops fcsm_ops = { 95fcf3ce44SJohn Forte DEVO_REV, 96fcf3ce44SJohn Forte 0, /* refcnt */ 97fcf3ce44SJohn Forte fcsm_getinfo, /* get info */ 98fcf3ce44SJohn Forte nulldev, /* identify (obsolete) */ 99fcf3ce44SJohn Forte nulldev, /* probe (not required for self-identifying devices) */ 100fcf3ce44SJohn Forte fcsm_attach, /* attach */ 101fcf3ce44SJohn Forte fcsm_detach, /* detach */ 102fcf3ce44SJohn Forte nodev, /* reset */ 103fcf3ce44SJohn Forte &fcsm_cb_ops, /* char/block entry points structure for leaf drivers */ 104fcf3ce44SJohn Forte NULL, /* bus operations for nexus driver */ 105fcf3ce44SJohn Forte NULL /* power management */ 106fcf3ce44SJohn Forte }; 107fcf3ce44SJohn Forte 108fcf3ce44SJohn Forte 109fcf3ce44SJohn Forte struct modldrv modldrv = { 110fcf3ce44SJohn Forte &mod_driverops, 111fcf3ce44SJohn Forte FCSM_NAME_VERSION, 112fcf3ce44SJohn Forte &fcsm_ops 113fcf3ce44SJohn Forte }; 114fcf3ce44SJohn Forte 115fcf3ce44SJohn Forte struct modlinkage modlinkage = { 116fcf3ce44SJohn Forte MODREV_1, 117fcf3ce44SJohn Forte &modldrv, 118fcf3ce44SJohn Forte NULL 119fcf3ce44SJohn Forte }; 120fcf3ce44SJohn Forte 121fcf3ce44SJohn Forte static fc_ulp_modinfo_t fcsm_modinfo = { 122fcf3ce44SJohn Forte &fcsm_modinfo, /* ulp_handle */ 123fcf3ce44SJohn Forte FCTL_ULP_MODREV_4, /* ulp_rev */ 124fcf3ce44SJohn Forte FC_TYPE_FC_SERVICES, /* ulp_type */ 125fcf3ce44SJohn Forte fcsm_name, /* ulp_name */ 126fcf3ce44SJohn Forte 0, /* ulp_statec_mask: get all statec callbacks */ 127fcf3ce44SJohn Forte fcsm_port_attach, /* ulp_port_attach */ 128fcf3ce44SJohn Forte fcsm_port_detach, /* ulp_port_detach */ 129fcf3ce44SJohn Forte fcsm_port_ioctl, /* ulp_port_ioctl */ 130fcf3ce44SJohn Forte fcsm_els_cb, /* ulp_els_callback */ 131fcf3ce44SJohn Forte fcsm_data_cb, /* ulp_data_callback */ 132fcf3ce44SJohn Forte fcsm_statec_cb /* ulp_statec_callback */ 133fcf3ce44SJohn Forte }; 134fcf3ce44SJohn Forte 135fcf3ce44SJohn Forte struct fcsm_xlat_pkt_state { 136fcf3ce44SJohn Forte uchar_t xlat_state; 137fcf3ce44SJohn Forte int xlat_rval; 138fcf3ce44SJohn Forte } fcsm_xlat_pkt_state [] = { 139fcf3ce44SJohn Forte { FC_PKT_SUCCESS, FC_SUCCESS }, 140fcf3ce44SJohn Forte { FC_PKT_REMOTE_STOP, FC_FAILURE }, 141fcf3ce44SJohn Forte { FC_PKT_LOCAL_RJT, FC_TRANSPORT_ERROR }, 142fcf3ce44SJohn Forte { FC_PKT_NPORT_RJT, FC_PREJECT }, 143fcf3ce44SJohn Forte { FC_PKT_FABRIC_RJT, FC_FREJECT }, 144fcf3ce44SJohn Forte { FC_PKT_LOCAL_BSY, FC_TRAN_BUSY }, 145fcf3ce44SJohn Forte { FC_PKT_TRAN_BSY, FC_TRAN_BUSY }, 146fcf3ce44SJohn Forte { FC_PKT_NPORT_BSY, FC_PBUSY }, 147fcf3ce44SJohn Forte { FC_PKT_FABRIC_BSY, FC_FBUSY }, 148fcf3ce44SJohn Forte { FC_PKT_LS_RJT, FC_PREJECT }, 149fcf3ce44SJohn Forte { FC_PKT_BA_RJT, FC_PREJECT }, 150fcf3ce44SJohn Forte { FC_PKT_TIMEOUT, FC_FAILURE }, 151fcf3ce44SJohn Forte { FC_PKT_FS_RJT, FC_FAILURE }, 152fcf3ce44SJohn Forte { FC_PKT_TRAN_ERROR, FC_TRANSPORT_ERROR }, 153fcf3ce44SJohn Forte { FC_PKT_FAILURE, FC_FAILURE }, 154fcf3ce44SJohn Forte { FC_PKT_PORT_OFFLINE, FC_OFFLINE }, 155fcf3ce44SJohn Forte { FC_PKT_ELS_IN_PROGRESS, FC_FAILURE } 156fcf3ce44SJohn Forte }; 157fcf3ce44SJohn Forte 158fcf3ce44SJohn Forte struct fcsm_xlat_port_state { 159fcf3ce44SJohn Forte uint32_t xlat_pstate; 160fcf3ce44SJohn Forte caddr_t xlat_state_str; 161fcf3ce44SJohn Forte } fcsm_xlat_port_state [] = { 162fcf3ce44SJohn Forte { FC_STATE_OFFLINE, "OFFLINE" }, 163fcf3ce44SJohn Forte { FC_STATE_ONLINE, "ONLINE" }, 164fcf3ce44SJohn Forte { FC_STATE_LOOP, "LOOP" }, 165fcf3ce44SJohn Forte { FC_STATE_NAMESERVICE, "NAMESERVICE" }, 166fcf3ce44SJohn Forte { FC_STATE_RESET, "RESET" }, 167fcf3ce44SJohn Forte { FC_STATE_RESET_REQUESTED, "RESET_REQUESTED" }, 168fcf3ce44SJohn Forte { FC_STATE_LIP, "LIP" }, 169fcf3ce44SJohn Forte { FC_STATE_LIP_LBIT_SET, "LIP_LBIT_SET" }, 170fcf3ce44SJohn Forte { FC_STATE_DEVICE_CHANGE, "DEVICE_CHANGE" }, 171fcf3ce44SJohn Forte { FC_STATE_TARGET_PORT_RESET, "TARGET_PORT_RESET" } 172fcf3ce44SJohn Forte }; 173fcf3ce44SJohn Forte 174fcf3ce44SJohn Forte struct fcsm_xlat_topology { 175fcf3ce44SJohn Forte uint32_t xlat_top; 176fcf3ce44SJohn Forte caddr_t xlat_top_str; 177fcf3ce44SJohn Forte } fcsm_xlat_topology [] = { 178fcf3ce44SJohn Forte { FC_TOP_UNKNOWN, "UNKNOWN" }, 179fcf3ce44SJohn Forte { FC_TOP_PRIVATE_LOOP, "Private Loop" }, 180fcf3ce44SJohn Forte { FC_TOP_PUBLIC_LOOP, "Public Loop" }, 181fcf3ce44SJohn Forte { FC_TOP_FABRIC, "Fabric" }, 182fcf3ce44SJohn Forte { FC_TOP_PT_PT, "Point-to-Point" }, 183fcf3ce44SJohn Forte { FC_TOP_NO_NS, "NO_NS" } 184fcf3ce44SJohn Forte }; 185fcf3ce44SJohn Forte 186fcf3ce44SJohn Forte struct fcsm_xlat_dev_type { 187fcf3ce44SJohn Forte uint32_t xlat_type; 188fcf3ce44SJohn Forte caddr_t xlat_str; 189fcf3ce44SJohn Forte } fcsm_xlat_dev_type [] = { 190fcf3ce44SJohn Forte { PORT_DEVICE_NOCHANGE, "No Change" }, 191fcf3ce44SJohn Forte { PORT_DEVICE_NEW, "New" }, 192fcf3ce44SJohn Forte { PORT_DEVICE_OLD, "Old" }, 193fcf3ce44SJohn Forte { PORT_DEVICE_CHANGED, "Changed" }, 194fcf3ce44SJohn Forte { PORT_DEVICE_DELETE, "Delete" }, 195fcf3ce44SJohn Forte { PORT_DEVICE_USER_LOGIN, "User Login" }, 196fcf3ce44SJohn Forte { PORT_DEVICE_USER_LOGOUT, "User Logout" }, 197fcf3ce44SJohn Forte { PORT_DEVICE_USER_CREATE, "User Create" }, 198fcf3ce44SJohn Forte { PORT_DEVICE_USER_DELETE, "User Delete" } 199fcf3ce44SJohn Forte }; 200fcf3ce44SJohn Forte 201fcf3ce44SJohn Forte int 202fcf3ce44SJohn Forte _init(void) 203fcf3ce44SJohn Forte { 204fcf3ce44SJohn Forte int rval; 205fcf3ce44SJohn Forte 206fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, "_init")); 207fcf3ce44SJohn Forte 208fcf3ce44SJohn Forte fcsm_retry_ticks = drv_usectohz(fcsm_retry_ticker * 1000 * 1000); 209fcf3ce44SJohn Forte fcsm_offline_ticks = drv_usectohz(fcsm_offline_ticker * 1000 * 1000); 210fcf3ce44SJohn Forte 211fcf3ce44SJohn Forte if (rval = ddi_soft_state_init(&fcsm_state, sizeof (fcsm_t), 212fcf3ce44SJohn Forte FCSM_INIT_INSTANCES)) { 213fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, NULL, 214fcf3ce44SJohn Forte "_init: ddi_soft_state_init failed"); 215fcf3ce44SJohn Forte return (ENOMEM); 216fcf3ce44SJohn Forte } 217fcf3ce44SJohn Forte 218fcf3ce44SJohn Forte mutex_init(&fcsm_global_mutex, NULL, MUTEX_DRIVER, NULL); 219fcf3ce44SJohn Forte 220fcf3ce44SJohn Forte fcsm_job_cache = kmem_cache_create("fcsm_job_cache", 221fcf3ce44SJohn Forte sizeof (fcsm_job_t), 8, fcsm_job_cache_constructor, 222fcf3ce44SJohn Forte fcsm_job_cache_destructor, NULL, NULL, NULL, 0); 223fcf3ce44SJohn Forte 224fcf3ce44SJohn Forte if (fcsm_job_cache == NULL) { 225fcf3ce44SJohn Forte mutex_destroy(&fcsm_global_mutex); 226fcf3ce44SJohn Forte ddi_soft_state_fini(&fcsm_state); 227fcf3ce44SJohn Forte return (ENOMEM); 228fcf3ce44SJohn Forte } 229fcf3ce44SJohn Forte 230fcf3ce44SJohn Forte /* 231fcf3ce44SJohn Forte * Now call fc_ulp_add to add this ULP in the transport layer 232fcf3ce44SJohn Forte * database. This will cause 'ulp_port_attach' callback function 233fcf3ce44SJohn Forte * to be called. 234fcf3ce44SJohn Forte */ 235fcf3ce44SJohn Forte rval = fc_ulp_add(&fcsm_modinfo); 236fcf3ce44SJohn Forte if (rval != 0) { 237fcf3ce44SJohn Forte switch (rval) { 238fcf3ce44SJohn Forte case FC_ULP_SAMEMODULE: 239fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, NULL, 240fcf3ce44SJohn Forte "_init: FC SAN Management module is already " 241fcf3ce44SJohn Forte "registered with transport layer"); 242fcf3ce44SJohn Forte rval = EEXIST; 243fcf3ce44SJohn Forte break; 244fcf3ce44SJohn Forte 245fcf3ce44SJohn Forte case FC_ULP_SAMETYPE: 246fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, NULL, 247fcf3ce44SJohn Forte "_init: Another module with same type 0x%x is " 248fcf3ce44SJohn Forte "already registered with transport layer", 249fcf3ce44SJohn Forte fcsm_modinfo.ulp_type); 250fcf3ce44SJohn Forte rval = EEXIST; 251fcf3ce44SJohn Forte break; 252fcf3ce44SJohn Forte 253fcf3ce44SJohn Forte case FC_BADULP: 254fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, NULL, 255fcf3ce44SJohn Forte "_init: Please upgrade this module. Current " 256fcf3ce44SJohn Forte "version 0x%x is not the most recent version", 257fcf3ce44SJohn Forte fcsm_modinfo.ulp_rev); 258fcf3ce44SJohn Forte rval = EIO; 259fcf3ce44SJohn Forte break; 260fcf3ce44SJohn Forte default: 261fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, NULL, 262fcf3ce44SJohn Forte "_init: fc_ulp_add failed with status 0x%x", rval); 263fcf3ce44SJohn Forte rval = EIO; 264fcf3ce44SJohn Forte break; 265fcf3ce44SJohn Forte } 266fcf3ce44SJohn Forte kmem_cache_destroy(fcsm_job_cache); 267fcf3ce44SJohn Forte mutex_destroy(&fcsm_global_mutex); 268fcf3ce44SJohn Forte ddi_soft_state_fini(&fcsm_state); 269fcf3ce44SJohn Forte return (rval); 270fcf3ce44SJohn Forte } 271fcf3ce44SJohn Forte 272fcf3ce44SJohn Forte if ((rval = mod_install(&modlinkage)) != 0) { 273fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_WARN, SM_LOG, NULL, NULL, 274fcf3ce44SJohn Forte "_init: mod_install failed with status 0x%x", rval)); 275fcf3ce44SJohn Forte (void) fc_ulp_remove(&fcsm_modinfo); 276fcf3ce44SJohn Forte kmem_cache_destroy(fcsm_job_cache); 277fcf3ce44SJohn Forte mutex_destroy(&fcsm_global_mutex); 278fcf3ce44SJohn Forte ddi_soft_state_fini(&fcsm_state); 279fcf3ce44SJohn Forte return (rval); 280fcf3ce44SJohn Forte } 281fcf3ce44SJohn Forte 282fcf3ce44SJohn Forte return (rval); 283fcf3ce44SJohn Forte } 284fcf3ce44SJohn Forte 285fcf3ce44SJohn Forte int 286fcf3ce44SJohn Forte _fini(void) 287fcf3ce44SJohn Forte { 288fcf3ce44SJohn Forte int rval; 289fcf3ce44SJohn Forte #ifdef DEBUG 290fcf3ce44SJohn Forte int status; 291fcf3ce44SJohn Forte #endif /* DEBUG */ 292fcf3ce44SJohn Forte 293fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, "_fini")); 294fcf3ce44SJohn Forte 295fcf3ce44SJohn Forte /* 296fcf3ce44SJohn Forte * don't start cleaning up until we know that the module remove 297fcf3ce44SJohn Forte * has worked -- if this works, then we know that each instance 298fcf3ce44SJohn Forte * has successfully been DDI_DETACHed 299fcf3ce44SJohn Forte */ 300fcf3ce44SJohn Forte if ((rval = mod_remove(&modlinkage)) != 0) { 301fcf3ce44SJohn Forte return (rval); 302fcf3ce44SJohn Forte } 303fcf3ce44SJohn Forte 304fcf3ce44SJohn Forte #ifdef DEBUG 305fcf3ce44SJohn Forte status = fc_ulp_remove(&fcsm_modinfo); 306fcf3ce44SJohn Forte if (status != 0) { 307fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_WARN, SM_LOG, NULL, NULL, 308fcf3ce44SJohn Forte "_fini: fc_ulp_remove failed with status 0x%x", status)); 309fcf3ce44SJohn Forte } 310fcf3ce44SJohn Forte #else 311fcf3ce44SJohn Forte (void) fc_ulp_remove(&fcsm_modinfo); 312fcf3ce44SJohn Forte #endif /* DEBUG */ 313fcf3ce44SJohn Forte 314fcf3ce44SJohn Forte fcsm_detached = 0; 315fcf3ce44SJohn Forte 316fcf3ce44SJohn Forte /* 317fcf3ce44SJohn Forte * It is possible to modunload fcsm manually, which will cause 318fcf3ce44SJohn Forte * a bypass of all the port_detach functionality. We may need 319fcf3ce44SJohn Forte * to force that code path to be executed to properly clean up 320fcf3ce44SJohn Forte * in that case. 321fcf3ce44SJohn Forte */ 322fcf3ce44SJohn Forte fcsm_force_port_detach_all(); 323fcf3ce44SJohn Forte 324fcf3ce44SJohn Forte kmem_cache_destroy(fcsm_job_cache); 325fcf3ce44SJohn Forte mutex_destroy(&fcsm_global_mutex); 326fcf3ce44SJohn Forte ddi_soft_state_fini(&fcsm_state); 327fcf3ce44SJohn Forte 328fcf3ce44SJohn Forte return (rval); 329fcf3ce44SJohn Forte } 330fcf3ce44SJohn Forte 331fcf3ce44SJohn Forte 332fcf3ce44SJohn Forte int 333fcf3ce44SJohn Forte _info(struct modinfo *modinfop) 334fcf3ce44SJohn Forte { 335fcf3ce44SJohn Forte return (mod_info(&modlinkage, modinfop)); 336fcf3ce44SJohn Forte } 337fcf3ce44SJohn Forte 338fcf3ce44SJohn Forte /* ARGSUSED */ 339fcf3ce44SJohn Forte static int 340fcf3ce44SJohn Forte fcsm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 341fcf3ce44SJohn Forte { 342fcf3ce44SJohn Forte int rval = DDI_FAILURE; 343fcf3ce44SJohn Forte 344fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 345fcf3ce44SJohn Forte "attach: cmd 0x%x", cmd)); 346fcf3ce44SJohn Forte 347fcf3ce44SJohn Forte switch (cmd) { 348fcf3ce44SJohn Forte case DDI_ATTACH: 349fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 350fcf3ce44SJohn Forte if (fcsm_dip != NULL) { 351fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 352fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 353fcf3ce44SJohn Forte "attach: duplicate attach of fcsm!!")); 354fcf3ce44SJohn Forte break; 355fcf3ce44SJohn Forte } 356fcf3ce44SJohn Forte 357fcf3ce44SJohn Forte fcsm_dip = dip; 358fcf3ce44SJohn Forte 359fcf3ce44SJohn Forte /* 360fcf3ce44SJohn Forte * The detach routine cleans up all the port instances 361fcf3ce44SJohn Forte * i.e. it detaches all ports. 362fcf3ce44SJohn Forte * If _fini never got called after detach, then 363fcf3ce44SJohn Forte * perform an fc_ulp_remove() followed by fc_ulp_add() 364fcf3ce44SJohn Forte * to ensure that port_attach callbacks are called 365fcf3ce44SJohn Forte * again. 366fcf3ce44SJohn Forte */ 367fcf3ce44SJohn Forte if (fcsm_detached) { 368fcf3ce44SJohn Forte int status; 369fcf3ce44SJohn Forte 370fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 371fcf3ce44SJohn Forte "attach: rebinding to transport driver")); 372fcf3ce44SJohn Forte 373fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 374fcf3ce44SJohn Forte 375fcf3ce44SJohn Forte (void) fc_ulp_remove(&fcsm_modinfo); 376fcf3ce44SJohn Forte 377fcf3ce44SJohn Forte /* 378fcf3ce44SJohn Forte * Reset the detached flag, so that ports can attach 379fcf3ce44SJohn Forte */ 380fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 381fcf3ce44SJohn Forte fcsm_detached = 0; 382fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 383fcf3ce44SJohn Forte 384fcf3ce44SJohn Forte status = fc_ulp_add(&fcsm_modinfo); 385fcf3ce44SJohn Forte 386fcf3ce44SJohn Forte if (status != 0) { 387fcf3ce44SJohn Forte /* 388fcf3ce44SJohn Forte * ULP add failed. So set the 389fcf3ce44SJohn Forte * detached flag again 390fcf3ce44SJohn Forte */ 391fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 392fcf3ce44SJohn Forte fcsm_detached = 1; 393fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 394fcf3ce44SJohn Forte 395fcf3ce44SJohn Forte switch (status) { 396fcf3ce44SJohn Forte case FC_ULP_SAMEMODULE: 397fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, 398fcf3ce44SJohn Forte NULL, "attach: FC SAN Management " 399fcf3ce44SJohn Forte "module is already " 400fcf3ce44SJohn Forte "registered with transport layer"); 401fcf3ce44SJohn Forte break; 402fcf3ce44SJohn Forte 403fcf3ce44SJohn Forte case FC_ULP_SAMETYPE: 404fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, 405fcf3ce44SJohn Forte NULL, "attach: Another module with " 406fcf3ce44SJohn Forte "same type 0x%x is already " 407fcf3ce44SJohn Forte "registered with transport layer", 408fcf3ce44SJohn Forte fcsm_modinfo.ulp_type); 409fcf3ce44SJohn Forte break; 410fcf3ce44SJohn Forte 411fcf3ce44SJohn Forte case FC_BADULP: 412fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, 413fcf3ce44SJohn Forte NULL, "attach: Please upgrade this " 414fcf3ce44SJohn Forte "module. Current version 0x%x is " 415fcf3ce44SJohn Forte "not the most recent version", 416fcf3ce44SJohn Forte fcsm_modinfo.ulp_rev); 417fcf3ce44SJohn Forte break; 418fcf3ce44SJohn Forte default: 419fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, 420fcf3ce44SJohn Forte NULL, "attach: fc_ulp_add failed " 421fcf3ce44SJohn Forte "with status 0x%x", status); 422fcf3ce44SJohn Forte break; 423fcf3ce44SJohn Forte } 424fcf3ce44SJohn Forte 425fcf3ce44SJohn Forte /* Return failure */ 426fcf3ce44SJohn Forte break; 427fcf3ce44SJohn Forte } 428fcf3ce44SJohn Forte 429fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 430fcf3ce44SJohn Forte } 431fcf3ce44SJohn Forte 432fcf3ce44SJohn Forte /* Create a minor node */ 433fcf3ce44SJohn Forte if (ddi_create_minor_node(fcsm_dip, "fcsm", S_IFCHR, 434fcf3ce44SJohn Forte NULL, DDI_PSEUDO, 0) == DDI_SUCCESS) { 435fcf3ce44SJohn Forte /* Announce presence of the device */ 436fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 437fcf3ce44SJohn Forte ddi_report_dev(dip); 438fcf3ce44SJohn Forte rval = DDI_SUCCESS; 439fcf3ce44SJohn Forte } else { 440fcf3ce44SJohn Forte fcsm_dip = NULL; 441fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 442fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG_AND_CONSOLE, 443fcf3ce44SJohn Forte NULL, NULL, "attach: create minor node failed"); 444fcf3ce44SJohn Forte } 445fcf3ce44SJohn Forte break; 446fcf3ce44SJohn Forte 447fcf3ce44SJohn Forte case DDI_RESUME: 448fcf3ce44SJohn Forte rval = DDI_SUCCESS; 449fcf3ce44SJohn Forte break; 450fcf3ce44SJohn Forte 451fcf3ce44SJohn Forte default: 452fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_NOTE, SM_LOG, NULL, NULL, 453fcf3ce44SJohn Forte "attach: unknown cmd 0x%x dip 0x%p", cmd, dip)); 454fcf3ce44SJohn Forte break; 455fcf3ce44SJohn Forte } 456fcf3ce44SJohn Forte 457fcf3ce44SJohn Forte return (rval); 458fcf3ce44SJohn Forte } 459fcf3ce44SJohn Forte 460fcf3ce44SJohn Forte /* ARGSUSED */ 461fcf3ce44SJohn Forte static int 462fcf3ce44SJohn Forte fcsm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 463fcf3ce44SJohn Forte { 464fcf3ce44SJohn Forte int instance; 465fcf3ce44SJohn Forte int rval = DDI_SUCCESS; 466fcf3ce44SJohn Forte 467fcf3ce44SJohn Forte instance = getminor((dev_t)arg); 468fcf3ce44SJohn Forte 469fcf3ce44SJohn Forte switch (cmd) { 470fcf3ce44SJohn Forte case DDI_INFO_DEVT2INSTANCE: 471fcf3ce44SJohn Forte *result = (void *)(long)instance; /* minor number is instance */ 472fcf3ce44SJohn Forte break; 473fcf3ce44SJohn Forte 474fcf3ce44SJohn Forte case DDI_INFO_DEVT2DEVINFO: 475fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 476fcf3ce44SJohn Forte *result = (void *)fcsm_dip; 477fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 478fcf3ce44SJohn Forte break; 479fcf3ce44SJohn Forte 480fcf3ce44SJohn Forte default: 481fcf3ce44SJohn Forte rval = DDI_FAILURE; 482fcf3ce44SJohn Forte break; 483fcf3ce44SJohn Forte } 484fcf3ce44SJohn Forte 485fcf3ce44SJohn Forte return (rval); 486fcf3ce44SJohn Forte } 487fcf3ce44SJohn Forte 488fcf3ce44SJohn Forte 489fcf3ce44SJohn Forte /* ARGSUSED */ 490fcf3ce44SJohn Forte static int 491fcf3ce44SJohn Forte fcsm_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 492fcf3ce44SJohn Forte fc_attach_cmd_t cmd, uint32_t s_id) 493fcf3ce44SJohn Forte { 494fcf3ce44SJohn Forte int instance; 495fcf3ce44SJohn Forte int rval = FC_FAILURE; 496fcf3ce44SJohn Forte 497fcf3ce44SJohn Forte instance = ddi_get_instance(pinfo->port_dip); 498fcf3ce44SJohn Forte 499fcf3ce44SJohn Forte /* 500fcf3ce44SJohn Forte * Set the attaching flag, so that fcsm_detach will fail, if 501fcf3ce44SJohn Forte * port attach is in progress. 502fcf3ce44SJohn Forte */ 503fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 504fcf3ce44SJohn Forte if (fcsm_detached) { 505fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 506fcf3ce44SJohn Forte 507fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 508fcf3ce44SJohn Forte "port_attach: end. detach in progress. failing attach " 509fcf3ce44SJohn Forte "instance 0x%x", instance)); 510fcf3ce44SJohn Forte return (((cmd == FC_CMD_POWER_UP) || (cmd == FC_CMD_RESUME)) ? 511fcf3ce44SJohn Forte FC_FAILURE_SILENT : FC_FAILURE); 512fcf3ce44SJohn Forte } 513fcf3ce44SJohn Forte 514fcf3ce44SJohn Forte fcsm_num_attaching++; 515fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 516fcf3ce44SJohn Forte 517fcf3ce44SJohn Forte switch (cmd) { 518fcf3ce44SJohn Forte case FC_CMD_ATTACH: 519fcf3ce44SJohn Forte if (fcsm_handle_port_attach(pinfo, s_id, instance) 520fcf3ce44SJohn Forte != DDI_SUCCESS) { 521fcf3ce44SJohn Forte ASSERT(ddi_get_soft_state(fcsm_state, 522fcf3ce44SJohn Forte instance) == NULL); 523fcf3ce44SJohn Forte break; 524fcf3ce44SJohn Forte } 525fcf3ce44SJohn Forte rval = FC_SUCCESS; 526fcf3ce44SJohn Forte break; 527fcf3ce44SJohn Forte 528fcf3ce44SJohn Forte case FC_CMD_RESUME: 529fcf3ce44SJohn Forte case FC_CMD_POWER_UP: { 530fcf3ce44SJohn Forte fcsm_t *fcsm; 531fcf3ce44SJohn Forte char fcsm_pathname[MAXPATHLEN]; 532fcf3ce44SJohn Forte 533fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 534fcf3ce44SJohn Forte "port_attach: cmd 0x%x instance 0x%x", cmd, instance)); 535fcf3ce44SJohn Forte 536fcf3ce44SJohn Forte /* Get the soft state structure */ 537fcf3ce44SJohn Forte if ((fcsm = ddi_get_soft_state(fcsm_state, instance)) == NULL) { 538fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, NULL, NULL, 539fcf3ce44SJohn Forte "port_attach: instance 0x%x, cmd 0x%x " 540fcf3ce44SJohn Forte "get softstate failed", instance, cmd)); 541fcf3ce44SJohn Forte break; 542fcf3ce44SJohn Forte } 543fcf3ce44SJohn Forte 544fcf3ce44SJohn Forte ASSERT(fcsm->sm_instance == instance); 545fcf3ce44SJohn Forte 546fcf3ce44SJohn Forte /* If this instance is not attached, then return failure */ 547fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 548fcf3ce44SJohn Forte if ((fcsm->sm_flags & FCSM_ATTACHED) == 0) { 549fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 550fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, fcsm, NULL, 551fcf3ce44SJohn Forte "port_detach: port is not attached"); 552fcf3ce44SJohn Forte break; 553fcf3ce44SJohn Forte } 554fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 555fcf3ce44SJohn Forte 556fcf3ce44SJohn Forte if (fcsm_handle_port_resume(ulph, pinfo, cmd, s_id, fcsm) != 557fcf3ce44SJohn Forte DDI_SUCCESS) { 558fcf3ce44SJohn Forte break; 559fcf3ce44SJohn Forte } 560fcf3ce44SJohn Forte 561fcf3ce44SJohn Forte (void) ddi_pathname(fcsm->sm_port_info.port_dip, fcsm_pathname); 562fcf3ce44SJohn Forte fcsm_display(CE_NOTE, SM_LOG, fcsm, NULL, 563fcf3ce44SJohn Forte "attached to path %s", fcsm_pathname); 564fcf3ce44SJohn Forte rval = FC_SUCCESS; 565fcf3ce44SJohn Forte break; 566fcf3ce44SJohn Forte } 567fcf3ce44SJohn Forte 568fcf3ce44SJohn Forte default: 569fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_NOTE, SM_LOG, NULL, NULL, 570fcf3ce44SJohn Forte "port_attach: unknown cmd 0x%x for port 0x%x", 571fcf3ce44SJohn Forte cmd, instance)); 572fcf3ce44SJohn Forte break; 573fcf3ce44SJohn Forte } 574fcf3ce44SJohn Forte 575fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 576fcf3ce44SJohn Forte fcsm_num_attaching--; 577fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 578fcf3ce44SJohn Forte return (rval); 579fcf3ce44SJohn Forte } 580fcf3ce44SJohn Forte 581fcf3ce44SJohn Forte 582fcf3ce44SJohn Forte static int 583fcf3ce44SJohn Forte fcsm_handle_port_attach(fc_ulp_port_info_t *pinfo, uint32_t s_id, int instance) 584fcf3ce44SJohn Forte { 585fcf3ce44SJohn Forte fcsm_t *fcsm; 586fcf3ce44SJohn Forte kthread_t *thread; 587fcf3ce44SJohn Forte char name[32]; 588fcf3ce44SJohn Forte char fcsm_pathname[MAXPATHLEN]; 589fcf3ce44SJohn Forte 590fcf3ce44SJohn Forte /* Allocate a soft state structure for the port */ 591fcf3ce44SJohn Forte if (ddi_soft_state_zalloc(fcsm_state, instance) != DDI_SUCCESS) { 592fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, NULL, 593fcf3ce44SJohn Forte "port_attach: instance 0x%x, soft state alloc failed", 594fcf3ce44SJohn Forte instance); 595fcf3ce44SJohn Forte return (DDI_FAILURE); 596fcf3ce44SJohn Forte } 597fcf3ce44SJohn Forte 598fcf3ce44SJohn Forte if ((fcsm = ddi_get_soft_state(fcsm_state, instance)) == NULL) { 599fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, NULL, NULL, 600fcf3ce44SJohn Forte "port_attach: instance 0x%x, get soft state failed", 601fcf3ce44SJohn Forte instance); 602fcf3ce44SJohn Forte ddi_soft_state_free(fcsm_state, instance); 603fcf3ce44SJohn Forte return (DDI_FAILURE); 604fcf3ce44SJohn Forte } 605fcf3ce44SJohn Forte 606fcf3ce44SJohn Forte 607fcf3ce44SJohn Forte /* Initialize the mutex */ 608fcf3ce44SJohn Forte mutex_init(&fcsm->sm_mutex, NULL, MUTEX_DRIVER, NULL); 609fcf3ce44SJohn Forte cv_init(&fcsm->sm_job_cv, NULL, CV_DRIVER, NULL); 610fcf3ce44SJohn Forte 611fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 612fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_ATTACHING; 613fcf3ce44SJohn Forte fcsm->sm_sid = s_id; 614fcf3ce44SJohn Forte fcsm->sm_instance = instance; 615fcf3ce44SJohn Forte fcsm->sm_port_state = pinfo->port_state; 616fcf3ce44SJohn Forte 617fcf3ce44SJohn Forte /* 618fcf3ce44SJohn Forte * Make a copy of the port_information structure, since fctl 619fcf3ce44SJohn Forte * uses a temporary structure. 620fcf3ce44SJohn Forte */ 621fcf3ce44SJohn Forte fcsm->sm_port_info = *pinfo; /* Structure copy !!! */ 622fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 623fcf3ce44SJohn Forte 624fcf3ce44SJohn Forte 625fcf3ce44SJohn Forte (void) sprintf(name, "fcsm%d_cmd_cache", fcsm->sm_instance); 626fcf3ce44SJohn Forte fcsm->sm_cmd_cache = kmem_cache_create(name, 627fcf3ce44SJohn Forte sizeof (fcsm_cmd_t) + pinfo->port_fca_pkt_size, 8, 628fcf3ce44SJohn Forte fcsm_cmd_cache_constructor, fcsm_cmd_cache_destructor, 629fcf3ce44SJohn Forte NULL, (void *)fcsm, NULL, 0); 630fcf3ce44SJohn Forte if (fcsm->sm_cmd_cache == NULL) { 631fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, fcsm, NULL, 632fcf3ce44SJohn Forte "port_attach: pkt cache create failed"); 633fcf3ce44SJohn Forte cv_destroy(&fcsm->sm_job_cv); 634fcf3ce44SJohn Forte mutex_destroy(&fcsm->sm_mutex); 635fcf3ce44SJohn Forte ddi_soft_state_free(fcsm_state, instance); 636fcf3ce44SJohn Forte return (DDI_FAILURE); 637fcf3ce44SJohn Forte } 638fcf3ce44SJohn Forte 639fcf3ce44SJohn Forte thread = thread_create((caddr_t)NULL, 0, fcsm_job_thread, 640fcf3ce44SJohn Forte (caddr_t)fcsm, 0, &p0, TS_RUN, v.v_maxsyspri-2); 641fcf3ce44SJohn Forte if (thread == NULL) { 642fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, fcsm, NULL, 643fcf3ce44SJohn Forte "port_attach: job thread create failed"); 644fcf3ce44SJohn Forte kmem_cache_destroy(fcsm->sm_cmd_cache); 645fcf3ce44SJohn Forte cv_destroy(&fcsm->sm_job_cv); 646fcf3ce44SJohn Forte mutex_destroy(&fcsm->sm_mutex); 647fcf3ce44SJohn Forte ddi_soft_state_free(fcsm_state, instance); 648fcf3ce44SJohn Forte return (DDI_FAILURE); 649fcf3ce44SJohn Forte } 650fcf3ce44SJohn Forte 651fcf3ce44SJohn Forte fcsm->sm_thread = thread; 652fcf3ce44SJohn Forte 653fcf3ce44SJohn Forte /* Add this structure to fcsm global linked list */ 654fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 655fcf3ce44SJohn Forte if (fcsm_port_head == NULL) { 656fcf3ce44SJohn Forte fcsm_port_head = fcsm; 657fcf3ce44SJohn Forte } else { 658fcf3ce44SJohn Forte fcsm->sm_next = fcsm_port_head; 659fcf3ce44SJohn Forte fcsm_port_head = fcsm; 660fcf3ce44SJohn Forte } 661fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 662fcf3ce44SJohn Forte 663fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 664fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_ATTACHING; 665fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_ATTACHED; 666fcf3ce44SJohn Forte fcsm->sm_port_top = pinfo->port_flags; 667fcf3ce44SJohn Forte fcsm->sm_port_state = pinfo->port_state; 668*7ff83669SZhong Wang if (pinfo->port_acc_attr == NULL) { 669*7ff83669SZhong Wang /* 670*7ff83669SZhong Wang * The corresponding FCA doesn't support DMA at all 671*7ff83669SZhong Wang */ 672*7ff83669SZhong Wang fcsm->sm_flags |= FCSM_USING_NODMA_FCA; 673*7ff83669SZhong Wang } 674fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 675fcf3ce44SJohn Forte 676fcf3ce44SJohn Forte (void) ddi_pathname(fcsm->sm_port_info.port_dip, fcsm_pathname); 677fcf3ce44SJohn Forte fcsm_display(CE_NOTE, SM_LOG, fcsm, NULL, 678fcf3ce44SJohn Forte "attached to path %s", fcsm_pathname); 679fcf3ce44SJohn Forte 680fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 681fcf3ce44SJohn Forte "port_attach: state <%s>(0x%x) topology <%s>(0x%x)", 682fcf3ce44SJohn Forte fcsm_port_state_to_str(FC_PORT_STATE_MASK(pinfo->port_state)), 683fcf3ce44SJohn Forte pinfo->port_state, 684fcf3ce44SJohn Forte fcsm_topology_to_str(pinfo->port_flags), pinfo->port_flags)); 685fcf3ce44SJohn Forte 686fcf3ce44SJohn Forte return (DDI_SUCCESS); 687fcf3ce44SJohn Forte } 688fcf3ce44SJohn Forte 689fcf3ce44SJohn Forte static int 690fcf3ce44SJohn Forte fcsm_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 691fcf3ce44SJohn Forte fc_attach_cmd_t cmd, uint32_t s_id, fcsm_t *fcsm) 692fcf3ce44SJohn Forte { 693fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 694fcf3ce44SJohn Forte "port_resume: cmd 0x%x", cmd)); 695fcf3ce44SJohn Forte 696fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 697fcf3ce44SJohn Forte 698fcf3ce44SJohn Forte switch (cmd) { 699fcf3ce44SJohn Forte case FC_CMD_RESUME: 700fcf3ce44SJohn Forte ASSERT(!(fcsm->sm_flags & FCSM_POWER_DOWN)); 701fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_SUSPENDED; 702fcf3ce44SJohn Forte break; 703fcf3ce44SJohn Forte 704fcf3ce44SJohn Forte case FC_CMD_POWER_UP: 705fcf3ce44SJohn Forte /* If port is suspended, then no need to resume */ 706fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_POWER_DOWN; 707fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_SUSPENDED) { 708fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 709fcf3ce44SJohn Forte return (DDI_SUCCESS); 710fcf3ce44SJohn Forte } 711fcf3ce44SJohn Forte break; 712fcf3ce44SJohn Forte default: 713fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 714fcf3ce44SJohn Forte return (DDI_FAILURE); 715fcf3ce44SJohn Forte } 716fcf3ce44SJohn Forte 717fcf3ce44SJohn Forte fcsm->sm_sid = s_id; 718fcf3ce44SJohn Forte 719fcf3ce44SJohn Forte /* 720fcf3ce44SJohn Forte * Make a copy of the new port_information structure 721fcf3ce44SJohn Forte */ 722fcf3ce44SJohn Forte fcsm->sm_port_info = *pinfo; /* Structure copy !!! */ 723fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 724fcf3ce44SJohn Forte 725fcf3ce44SJohn Forte fcsm_resume_port(fcsm); 726fcf3ce44SJohn Forte 727fcf3ce44SJohn Forte /* 728fcf3ce44SJohn Forte * Invoke state change processing. 729fcf3ce44SJohn Forte * This will ensure that 730fcf3ce44SJohn Forte * - offline timer is started if new port state changed to offline. 731fcf3ce44SJohn Forte * - MGMT_SERVER_LOGIN flag is reset. 732fcf3ce44SJohn Forte * - Port topology is updated. 733fcf3ce44SJohn Forte */ 734fcf3ce44SJohn Forte fcsm_statec_cb(ulph, (opaque_t)pinfo->port_handle, pinfo->port_state, 735fcf3ce44SJohn Forte pinfo->port_flags, NULL, 0, s_id); 736fcf3ce44SJohn Forte 737fcf3ce44SJohn Forte return (DDI_SUCCESS); 738fcf3ce44SJohn Forte } 739fcf3ce44SJohn Forte 740fcf3ce44SJohn Forte 741fcf3ce44SJohn Forte /* ARGSUSED */ 742fcf3ce44SJohn Forte static int 743fcf3ce44SJohn Forte fcsm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 744fcf3ce44SJohn Forte { 745fcf3ce44SJohn Forte int rval = DDI_SUCCESS; 746fcf3ce44SJohn Forte 747fcf3ce44SJohn Forte switch (cmd) { 748fcf3ce44SJohn Forte case DDI_DETACH: { 749fcf3ce44SJohn Forte fcsm_t *fcsm; 750fcf3ce44SJohn Forte 751fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 752fcf3ce44SJohn Forte "detach: start. cmd <DETACH>", cmd)); 753fcf3ce44SJohn Forte 754fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 755fcf3ce44SJohn Forte 756fcf3ce44SJohn Forte /* 757fcf3ce44SJohn Forte * If port attach/detach in progress, then wait for 5 seconds 758fcf3ce44SJohn Forte * for them to complete. 759fcf3ce44SJohn Forte */ 760fcf3ce44SJohn Forte if (fcsm_num_attaching || fcsm_num_detaching) { 761fcf3ce44SJohn Forte int count; 762fcf3ce44SJohn Forte 763fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, NULL, NULL, 764fcf3ce44SJohn Forte "detach: wait for port attach/detach to complete")); 765fcf3ce44SJohn Forte 766fcf3ce44SJohn Forte count = 0; 767fcf3ce44SJohn Forte while ((count++ <= 30) && 768fcf3ce44SJohn Forte (fcsm_num_attaching || fcsm_num_detaching)) { 769fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 770fcf3ce44SJohn Forte delay(drv_usectohz(1000000)); 771fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 772fcf3ce44SJohn Forte } 773fcf3ce44SJohn Forte 774fcf3ce44SJohn Forte /* Port attach/detach still in prog, so fail detach */ 775fcf3ce44SJohn Forte if (fcsm_num_attaching || fcsm_num_detaching) { 776fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 777fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_WARN, SM_LOG, NULL, 778fcf3ce44SJohn Forte NULL, "detach: Failing detach. port " 779fcf3ce44SJohn Forte "attach/detach in progress")); 780fcf3ce44SJohn Forte rval = DDI_FAILURE; 781fcf3ce44SJohn Forte break; 782fcf3ce44SJohn Forte } 783fcf3ce44SJohn Forte } 784fcf3ce44SJohn Forte 785fcf3ce44SJohn Forte if (fcsm_port_head == NULL) { 786fcf3ce44SJohn Forte /* Not much do, Succeed to detach. */ 787fcf3ce44SJohn Forte ddi_remove_minor_node(fcsm_dip, NULL); 788fcf3ce44SJohn Forte fcsm_dip = NULL; 789fcf3ce44SJohn Forte fcsm_detached = 0; 790fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 791fcf3ce44SJohn Forte break; 792fcf3ce44SJohn Forte } 793fcf3ce44SJohn Forte 794fcf3ce44SJohn Forte /* 795fcf3ce44SJohn Forte * Check to see, if any ports are active. 796fcf3ce44SJohn Forte * If not, then set the DETACHING flag to indicate 797fcf3ce44SJohn Forte * that they are being detached. 798fcf3ce44SJohn Forte */ 799fcf3ce44SJohn Forte fcsm = fcsm_port_head; 800fcf3ce44SJohn Forte while (fcsm != NULL) { 801fcf3ce44SJohn Forte 802fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 803fcf3ce44SJohn Forte if (!(fcsm->sm_flags & FCSM_ATTACHED) || 804fcf3ce44SJohn Forte fcsm->sm_ncmds || fcsm->sm_cb_count) { 805fcf3ce44SJohn Forte /* port is busy. We can't detach */ 806fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 807fcf3ce44SJohn Forte break; 808fcf3ce44SJohn Forte } 809fcf3ce44SJohn Forte 810fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_DETACHING; 811fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 812fcf3ce44SJohn Forte 813fcf3ce44SJohn Forte fcsm = fcsm->sm_next; 814fcf3ce44SJohn Forte } 815fcf3ce44SJohn Forte 816fcf3ce44SJohn Forte /* 817fcf3ce44SJohn Forte * If all ports could not be marked for detaching, 818fcf3ce44SJohn Forte * then clear the flags and fail the detach. 819fcf3ce44SJohn Forte * Also if a port attach is currently in progress 820fcf3ce44SJohn Forte * then fail the detach. 821fcf3ce44SJohn Forte */ 822fcf3ce44SJohn Forte if (fcsm != NULL || fcsm_num_attaching || fcsm_num_detaching) { 823fcf3ce44SJohn Forte /* 824fcf3ce44SJohn Forte * Some ports were busy, so can't detach. 825fcf3ce44SJohn Forte * Clear the DETACHING flag and return failure 826fcf3ce44SJohn Forte */ 827fcf3ce44SJohn Forte fcsm = fcsm_port_head; 828fcf3ce44SJohn Forte while (fcsm != NULL) { 829fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 830fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_DETACHING) { 831fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_DETACHING; 832fcf3ce44SJohn Forte } 833fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 834fcf3ce44SJohn Forte 835fcf3ce44SJohn Forte fcsm = fcsm->sm_next; 836fcf3ce44SJohn Forte } 837fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 838fcf3ce44SJohn Forte return (DDI_FAILURE); 839fcf3ce44SJohn Forte } else { 840fcf3ce44SJohn Forte fcsm_detached = 1; 841fcf3ce44SJohn Forte /* 842fcf3ce44SJohn Forte * Mark all the detaching ports as detached, as we 843fcf3ce44SJohn Forte * will be detaching them 844fcf3ce44SJohn Forte */ 845fcf3ce44SJohn Forte fcsm = fcsm_port_head; 846fcf3ce44SJohn Forte while (fcsm != NULL) { 847fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 848fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_DETACHING; 849fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_DETACHED; 850fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 851fcf3ce44SJohn Forte 852fcf3ce44SJohn Forte fcsm = fcsm->sm_next; 853fcf3ce44SJohn Forte } 854fcf3ce44SJohn Forte } 855fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 856fcf3ce44SJohn Forte 857fcf3ce44SJohn Forte 858fcf3ce44SJohn Forte /* 859fcf3ce44SJohn Forte * Go ahead and detach the ports 860fcf3ce44SJohn Forte */ 861fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 862fcf3ce44SJohn Forte while (fcsm_port_head != NULL) { 863fcf3ce44SJohn Forte fcsm = fcsm_port_head; 864fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 865fcf3ce44SJohn Forte 866fcf3ce44SJohn Forte /* 867fcf3ce44SJohn Forte * Call fcsm_cleanup_port(). This cleansup and 868fcf3ce44SJohn Forte * removes the fcsm structure from global linked list 869fcf3ce44SJohn Forte */ 870fcf3ce44SJohn Forte fcsm_cleanup_port(fcsm); 871fcf3ce44SJohn Forte 872fcf3ce44SJohn Forte /* 873fcf3ce44SJohn Forte * Soft state cleanup done. 874fcf3ce44SJohn Forte * Remember that fcsm struct doesn't exist anymore. 875fcf3ce44SJohn Forte */ 876fcf3ce44SJohn Forte 877fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 878fcf3ce44SJohn Forte } 879fcf3ce44SJohn Forte 880fcf3ce44SJohn Forte ddi_remove_minor_node(fcsm_dip, NULL); 881fcf3ce44SJohn Forte fcsm_dip = NULL; 882fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 883fcf3ce44SJohn Forte break; 884fcf3ce44SJohn Forte } 885fcf3ce44SJohn Forte 886fcf3ce44SJohn Forte case DDI_SUSPEND: 887fcf3ce44SJohn Forte rval = DDI_SUCCESS; 888fcf3ce44SJohn Forte break; 889fcf3ce44SJohn Forte 890fcf3ce44SJohn Forte default: 891fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_NOTE, SM_LOG, NULL, NULL, 892fcf3ce44SJohn Forte "detach: unknown cmd 0x%x", cmd)); 893fcf3ce44SJohn Forte rval = DDI_FAILURE; 894fcf3ce44SJohn Forte break; 895fcf3ce44SJohn Forte } 896fcf3ce44SJohn Forte 897fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 898fcf3ce44SJohn Forte "detach: end. cmd 0x%x, rval 0x%x", cmd, rval)); 899fcf3ce44SJohn Forte 900fcf3ce44SJohn Forte return (rval); 901fcf3ce44SJohn Forte } 902fcf3ce44SJohn Forte 903fcf3ce44SJohn Forte 904fcf3ce44SJohn Forte /* ARGSUSED */ 905fcf3ce44SJohn Forte static void 906fcf3ce44SJohn Forte fcsm_force_port_detach_all(void) 907fcf3ce44SJohn Forte { 908fcf3ce44SJohn Forte fcsm_t *fcsm; 909fcf3ce44SJohn Forte 910fcf3ce44SJohn Forte fcsm = fcsm_port_head; 911fcf3ce44SJohn Forte 912fcf3ce44SJohn Forte while (fcsm) { 913fcf3ce44SJohn Forte fcsm_cleanup_port(fcsm); 914fcf3ce44SJohn Forte /* 915fcf3ce44SJohn Forte * fcsm_cleanup_port will remove the current fcsm structure 916fcf3ce44SJohn Forte * from the list, which will cause fcsm_port_head to point 917fcf3ce44SJohn Forte * to what would have been the next structure on the list. 918fcf3ce44SJohn Forte */ 919fcf3ce44SJohn Forte fcsm = fcsm_port_head; 920fcf3ce44SJohn Forte } 921fcf3ce44SJohn Forte } 922fcf3ce44SJohn Forte 923fcf3ce44SJohn Forte 924fcf3ce44SJohn Forte /* ARGSUSED */ 925fcf3ce44SJohn Forte static int 926fcf3ce44SJohn Forte fcsm_port_detach(opaque_t ulph, fc_ulp_port_info_t *pinfo, fc_detach_cmd_t cmd) 927fcf3ce44SJohn Forte { 928fcf3ce44SJohn Forte int instance; 929fcf3ce44SJohn Forte int rval = FC_FAILURE; 930fcf3ce44SJohn Forte fcsm_t *fcsm; 931fcf3ce44SJohn Forte 932fcf3ce44SJohn Forte instance = ddi_get_instance(pinfo->port_dip); 933fcf3ce44SJohn Forte 934fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 935fcf3ce44SJohn Forte if (fcsm_detached) { 936fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 937fcf3ce44SJohn Forte 938fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, NULL, NULL, 939fcf3ce44SJohn Forte "port_detach: end. instance 0x%x, fcsm is detached", 940fcf3ce44SJohn Forte instance)); 941fcf3ce44SJohn Forte return (FC_SUCCESS); 942fcf3ce44SJohn Forte } 943fcf3ce44SJohn Forte fcsm_num_detaching++; /* Set the flag */ 944fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 945fcf3ce44SJohn Forte 946fcf3ce44SJohn Forte /* Get the soft state structure */ 947fcf3ce44SJohn Forte if ((fcsm = ddi_get_soft_state(fcsm_state, instance)) == NULL) { 948fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, NULL, NULL, 949fcf3ce44SJohn Forte "port_detach: instance 0x%x, cmd 0x%x get softstate failed", 950fcf3ce44SJohn Forte instance, cmd)); 951fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 952fcf3ce44SJohn Forte fcsm_num_detaching--; 953fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 954fcf3ce44SJohn Forte return (rval); 955fcf3ce44SJohn Forte } 956fcf3ce44SJohn Forte 957fcf3ce44SJohn Forte ASSERT(fcsm->sm_instance == instance); 958fcf3ce44SJohn Forte 959fcf3ce44SJohn Forte /* If this instance is not attached, then fail the detach */ 960fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 961fcf3ce44SJohn Forte if ((fcsm->sm_flags & FCSM_ATTACHED) == 0) { 962fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 963fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, fcsm, NULL, 964fcf3ce44SJohn Forte "port_detach: port is not attached"); 965fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 966fcf3ce44SJohn Forte fcsm_num_detaching--; 967fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 968fcf3ce44SJohn Forte return (rval); 969fcf3ce44SJohn Forte } 970fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 971fcf3ce44SJohn Forte 972fcf3ce44SJohn Forte /* 973fcf3ce44SJohn Forte * If fcsm has been detached, then all instance has already been 974fcf3ce44SJohn Forte * detached or are being detached. So succeed this detach. 975fcf3ce44SJohn Forte */ 976fcf3ce44SJohn Forte 977fcf3ce44SJohn Forte switch (cmd) { 978fcf3ce44SJohn Forte case FC_CMD_DETACH: 979fcf3ce44SJohn Forte case FC_CMD_SUSPEND: 980fcf3ce44SJohn Forte case FC_CMD_POWER_DOWN: 981fcf3ce44SJohn Forte break; 982fcf3ce44SJohn Forte 983fcf3ce44SJohn Forte default: 984fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 985fcf3ce44SJohn Forte "port_detach: port unknown cmd 0x%x", cmd)); 986fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 987fcf3ce44SJohn Forte fcsm_num_detaching--; 988fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 989fcf3ce44SJohn Forte return (rval); 990fcf3ce44SJohn Forte }; 991fcf3ce44SJohn Forte 992fcf3ce44SJohn Forte if (fcsm_handle_port_detach(pinfo, fcsm, cmd) == DDI_SUCCESS) { 993fcf3ce44SJohn Forte rval = FC_SUCCESS; 994fcf3ce44SJohn Forte } 995fcf3ce44SJohn Forte 996fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 997fcf3ce44SJohn Forte fcsm_num_detaching--; 998fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 999fcf3ce44SJohn Forte 1000fcf3ce44SJohn Forte /* If it was a detach, then fcsm state structure no longer exists */ 1001fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 1002fcf3ce44SJohn Forte "port_detach: end. cmd 0x%x rval 0x%x", cmd, rval)); 1003fcf3ce44SJohn Forte return (rval); 1004fcf3ce44SJohn Forte } 1005fcf3ce44SJohn Forte 1006fcf3ce44SJohn Forte 1007fcf3ce44SJohn Forte static int 1008fcf3ce44SJohn Forte fcsm_handle_port_detach(fc_ulp_port_info_t *pinfo, fcsm_t *fcsm, 1009fcf3ce44SJohn Forte fc_detach_cmd_t cmd) 1010fcf3ce44SJohn Forte { 1011fcf3ce44SJohn Forte uint32_t flag; 1012fcf3ce44SJohn Forte int count; 1013fcf3ce44SJohn Forte #ifdef DEBUG 1014fcf3ce44SJohn Forte char pathname[MAXPATHLEN]; 1015fcf3ce44SJohn Forte #endif /* DEBUG */ 1016fcf3ce44SJohn Forte 1017fcf3ce44SJohn Forte /* 1018fcf3ce44SJohn Forte * If port is already powered down OR suspended and there is nothing 1019fcf3ce44SJohn Forte * else to do then just return. 1020fcf3ce44SJohn Forte * Otherwise, set the flag, so that no more new activity will be 1021fcf3ce44SJohn Forte * initiated on this port. 1022fcf3ce44SJohn Forte */ 1023fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1024fcf3ce44SJohn Forte 1025fcf3ce44SJohn Forte switch (cmd) { 1026fcf3ce44SJohn Forte case FC_CMD_DETACH: 1027fcf3ce44SJohn Forte flag = FCSM_DETACHING; 1028fcf3ce44SJohn Forte break; 1029fcf3ce44SJohn Forte 1030fcf3ce44SJohn Forte case FC_CMD_SUSPEND: 1031fcf3ce44SJohn Forte case FC_CMD_POWER_DOWN: 1032*7ff83669SZhong Wang ((cmd == FC_CMD_SUSPEND) ? (flag = FCSM_SUSPENDED) : 1033*7ff83669SZhong Wang (flag = FCSM_POWER_DOWN)); 1034fcf3ce44SJohn Forte if (fcsm->sm_flags & 1035fcf3ce44SJohn Forte (FCSM_POWER_DOWN | FCSM_SUSPENDED)) { 1036fcf3ce44SJohn Forte fcsm->sm_flags |= flag; 1037fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1038fcf3ce44SJohn Forte return (DDI_SUCCESS); 1039fcf3ce44SJohn Forte } 1040fcf3ce44SJohn Forte break; 1041fcf3ce44SJohn Forte 1042fcf3ce44SJohn Forte default: 1043fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1044fcf3ce44SJohn Forte return (DDI_FAILURE); 1045fcf3ce44SJohn Forte }; 1046fcf3ce44SJohn Forte 1047fcf3ce44SJohn Forte fcsm->sm_flags |= flag; 1048fcf3ce44SJohn Forte 1049fcf3ce44SJohn Forte /* 1050fcf3ce44SJohn Forte * If some commands are pending OR callback in progress, then 1051fcf3ce44SJohn Forte * wait for some finite amount of time for their completion. 1052fcf3ce44SJohn Forte * TODO: add more checks here to check for cmd timeout, offline 1053fcf3ce44SJohn Forte * timeout and other (??) threads. 1054fcf3ce44SJohn Forte */ 1055fcf3ce44SJohn Forte count = 0; 1056fcf3ce44SJohn Forte while ((count++ <= 30) && (fcsm->sm_ncmds || fcsm->sm_cb_count)) { 1057fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1058fcf3ce44SJohn Forte delay(drv_usectohz(1000000)); 1059fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1060fcf3ce44SJohn Forte } 1061fcf3ce44SJohn Forte if (fcsm->sm_ncmds || fcsm->sm_cb_count) { 1062fcf3ce44SJohn Forte fcsm->sm_flags &= ~flag; 1063fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1064fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, fcsm, NULL, 1065fcf3ce44SJohn Forte "port_detach: Failing suspend, port is busy"); 1066fcf3ce44SJohn Forte return (DDI_FAILURE); 1067fcf3ce44SJohn Forte } 1068fcf3ce44SJohn Forte if (flag == FCSM_DETACHING) { 1069fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_DETACHING; 1070fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_DETACHED; 1071fcf3ce44SJohn Forte } 1072fcf3ce44SJohn Forte 1073fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1074fcf3ce44SJohn Forte 1075fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_INFO, (CE_CONT, SM_LOG, fcsm, NULL, 1076fcf3ce44SJohn Forte "port_detach: cmd 0x%x pathname <%s>", 1077fcf3ce44SJohn Forte cmd, ddi_pathname(pinfo->port_dip, pathname))); 1078fcf3ce44SJohn Forte 1079fcf3ce44SJohn Forte if (cmd == FC_CMD_DETACH) { 1080fcf3ce44SJohn Forte fcsm_cleanup_port(fcsm); 1081fcf3ce44SJohn Forte /* 1082fcf3ce44SJohn Forte * Soft state cleanup done. 1083fcf3ce44SJohn Forte * Always remember that fcsm struct doesn't exist anymore. 1084fcf3ce44SJohn Forte */ 1085fcf3ce44SJohn Forte } else { 1086fcf3ce44SJohn Forte fcsm_suspend_port(fcsm); 1087fcf3ce44SJohn Forte } 1088fcf3ce44SJohn Forte 1089fcf3ce44SJohn Forte return (DDI_SUCCESS); 1090fcf3ce44SJohn Forte } 1091fcf3ce44SJohn Forte 1092fcf3ce44SJohn Forte static void 1093fcf3ce44SJohn Forte fcsm_suspend_port(fcsm_t *fcsm) 1094fcf3ce44SJohn Forte { 1095fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1096fcf3ce44SJohn Forte 1097fcf3ce44SJohn Forte if (fcsm->sm_offline_tid != NULL) { 1098fcf3ce44SJohn Forte timeout_id_t tid; 1099fcf3ce44SJohn Forte 1100fcf3ce44SJohn Forte tid = fcsm->sm_offline_tid; 1101fcf3ce44SJohn Forte fcsm->sm_offline_tid = (timeout_id_t)NULL; 1102fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1103fcf3ce44SJohn Forte (void) untimeout(tid); 1104fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1105fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_RESTORE_OFFLINE_TIMEOUT; 1106fcf3ce44SJohn Forte } 1107fcf3ce44SJohn Forte 1108fcf3ce44SJohn Forte if (fcsm->sm_retry_tid != NULL) { 1109fcf3ce44SJohn Forte timeout_id_t tid; 1110fcf3ce44SJohn Forte 1111fcf3ce44SJohn Forte tid = fcsm->sm_retry_tid; 1112fcf3ce44SJohn Forte fcsm->sm_retry_tid = (timeout_id_t)NULL; 1113fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1114fcf3ce44SJohn Forte (void) untimeout(tid); 1115fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1116fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_RESTORE_RETRY_TIMEOUT; 1117fcf3ce44SJohn Forte } 1118fcf3ce44SJohn Forte 1119fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1120fcf3ce44SJohn Forte } 1121fcf3ce44SJohn Forte 1122fcf3ce44SJohn Forte static void 1123fcf3ce44SJohn Forte fcsm_resume_port(fcsm_t *fcsm) 1124fcf3ce44SJohn Forte { 1125fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1126fcf3ce44SJohn Forte 1127fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_RESTORE_OFFLINE_TIMEOUT) { 1128fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_RESTORE_OFFLINE_TIMEOUT; 1129fcf3ce44SJohn Forte 1130fcf3ce44SJohn Forte /* 1131fcf3ce44SJohn Forte * If port if offline, link is not marked down and offline 1132fcf3ce44SJohn Forte * timer is not already running, then restart offline timer. 1133fcf3ce44SJohn Forte */ 1134fcf3ce44SJohn Forte if (!(fcsm->sm_flags & FCSM_LINK_DOWN) && 1135fcf3ce44SJohn Forte fcsm->sm_offline_tid == NULL && 1136fcf3ce44SJohn Forte (fcsm->sm_flags & FCSM_PORT_OFFLINE)) { 1137fcf3ce44SJohn Forte fcsm->sm_offline_tid = timeout(fcsm_offline_timeout, 1138fcf3ce44SJohn Forte (caddr_t)fcsm, fcsm_offline_ticks); 1139fcf3ce44SJohn Forte } 1140fcf3ce44SJohn Forte } 1141fcf3ce44SJohn Forte 1142fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_RESTORE_RETRY_TIMEOUT) { 1143fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_RESTORE_RETRY_TIMEOUT; 1144fcf3ce44SJohn Forte 1145fcf3ce44SJohn Forte /* 1146fcf3ce44SJohn Forte * If retry queue is not suspended and some cmds are waiting 1147fcf3ce44SJohn Forte * to be retried, then restart the retry timer 1148fcf3ce44SJohn Forte */ 1149fcf3ce44SJohn Forte if (fcsm->sm_retry_head && fcsm->sm_retry_tid == NULL) { 1150fcf3ce44SJohn Forte fcsm->sm_retry_tid = timeout(fcsm_retry_timeout, 1151fcf3ce44SJohn Forte (caddr_t)fcsm, fcsm_retry_ticks); 1152fcf3ce44SJohn Forte } 1153fcf3ce44SJohn Forte } 1154fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1155fcf3ce44SJohn Forte } 1156fcf3ce44SJohn Forte 1157fcf3ce44SJohn Forte static void 1158fcf3ce44SJohn Forte fcsm_cleanup_port(fcsm_t *fcsm) 1159fcf3ce44SJohn Forte { 1160fcf3ce44SJohn Forte fcsm_t *curr, *prev; 1161fcf3ce44SJohn Forte int status; 1162fcf3ce44SJohn Forte fcsm_job_t *job; 1163fcf3ce44SJohn Forte 1164fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 1165fcf3ce44SJohn Forte "fcsm_cleanup_port: entered")); 1166fcf3ce44SJohn Forte 1167fcf3ce44SJohn Forte /* 1168fcf3ce44SJohn Forte * Kill the job thread 1169fcf3ce44SJohn Forte */ 1170fcf3ce44SJohn Forte job = fcsm_alloc_job(KM_SLEEP); 1171fcf3ce44SJohn Forte ASSERT(job != NULL); 1172fcf3ce44SJohn Forte fcsm_init_job(job, fcsm->sm_instance, FCSM_JOB_THREAD_SHUTDOWN, 1173fcf3ce44SJohn Forte FCSM_JOBFLAG_SYNC, NULL, NULL, NULL, NULL); 1174fcf3ce44SJohn Forte 1175fcf3ce44SJohn Forte status = fcsm_process_job(job, 0); 1176fcf3ce44SJohn Forte ASSERT(status == FC_SUCCESS); 1177fcf3ce44SJohn Forte 1178fcf3ce44SJohn Forte ASSERT(job->job_result == FC_SUCCESS); 1179fcf3ce44SJohn Forte fcsm_dealloc_job(job); 1180fcf3ce44SJohn Forte 1181fcf3ce44SJohn Forte /* 1182fcf3ce44SJohn Forte * We got here after ensuring the no commands are pending or active. 1183fcf3ce44SJohn Forte * Therefore retry timeout thread should NOT be running. 1184fcf3ce44SJohn Forte * Kill the offline timeout thread if currently running. 1185fcf3ce44SJohn Forte */ 1186fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1187fcf3ce44SJohn Forte 1188fcf3ce44SJohn Forte ASSERT(fcsm->sm_retry_tid == NULL); 1189fcf3ce44SJohn Forte 1190fcf3ce44SJohn Forte if (fcsm->sm_offline_tid != NULL) { 1191fcf3ce44SJohn Forte timeout_id_t tid; 1192fcf3ce44SJohn Forte 1193fcf3ce44SJohn Forte tid = fcsm->sm_offline_tid; 1194fcf3ce44SJohn Forte fcsm->sm_offline_tid = (timeout_id_t)NULL; 1195fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1196fcf3ce44SJohn Forte (void) untimeout(tid); 1197fcf3ce44SJohn Forte } else { 1198fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1199fcf3ce44SJohn Forte } 1200fcf3ce44SJohn Forte 1201fcf3ce44SJohn Forte /* Remove from the fcsm state structure from global linked list */ 1202fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 1203fcf3ce44SJohn Forte curr = fcsm_port_head; 1204fcf3ce44SJohn Forte prev = NULL; 1205fcf3ce44SJohn Forte while (curr != fcsm && curr != NULL) { 1206fcf3ce44SJohn Forte prev = curr; 1207fcf3ce44SJohn Forte curr = curr->sm_next; 1208fcf3ce44SJohn Forte } 1209fcf3ce44SJohn Forte ASSERT(curr != NULL); 1210fcf3ce44SJohn Forte 1211fcf3ce44SJohn Forte if (prev == NULL) { 1212fcf3ce44SJohn Forte fcsm_port_head = curr->sm_next; 1213fcf3ce44SJohn Forte } else { 1214fcf3ce44SJohn Forte prev->sm_next = curr->sm_next; 1215fcf3ce44SJohn Forte } 1216fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1217fcf3ce44SJohn Forte 1218fcf3ce44SJohn Forte if (fcsm->sm_cmd_cache != NULL) { 1219fcf3ce44SJohn Forte kmem_cache_destroy(fcsm->sm_cmd_cache); 1220fcf3ce44SJohn Forte } 1221fcf3ce44SJohn Forte cv_destroy(&fcsm->sm_job_cv); 1222fcf3ce44SJohn Forte mutex_destroy(&fcsm->sm_mutex); 1223fcf3ce44SJohn Forte 1224fcf3ce44SJohn Forte /* Free the fcsm state structure */ 1225fcf3ce44SJohn Forte ddi_soft_state_free(fcsm_state, fcsm->sm_instance); 1226fcf3ce44SJohn Forte } 1227fcf3ce44SJohn Forte 1228fcf3ce44SJohn Forte 1229fcf3ce44SJohn Forte /* ARGSUSED */ 1230fcf3ce44SJohn Forte static void 1231fcf3ce44SJohn Forte fcsm_statec_cb(opaque_t ulph, opaque_t port_handle, uint32_t port_state, 1232fcf3ce44SJohn Forte uint32_t port_top, fc_portmap_t *devlist, uint32_t dev_cnt, 1233fcf3ce44SJohn Forte uint32_t port_sid) 1234fcf3ce44SJohn Forte { 1235fcf3ce44SJohn Forte fcsm_t *fcsm; 1236fcf3ce44SJohn Forte timeout_id_t offline_tid, retry_tid; 1237fcf3ce44SJohn Forte 1238fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 1239fcf3ce44SJohn Forte if (fcsm_detached) { 1240fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1241fcf3ce44SJohn Forte return; 1242fcf3ce44SJohn Forte } 1243fcf3ce44SJohn Forte 1244fcf3ce44SJohn Forte fcsm = ddi_get_soft_state(fcsm_state, 1245fcf3ce44SJohn Forte fc_ulp_get_port_instance(port_handle)); 1246fcf3ce44SJohn Forte if (fcsm == NULL) { 1247fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1248fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_NOTE, SM_LOG, NULL, NULL, 1249fcf3ce44SJohn Forte "statec_cb: instance 0x%x not found", 1250fcf3ce44SJohn Forte fc_ulp_get_port_instance(port_handle))); 1251fcf3ce44SJohn Forte return; 1252fcf3ce44SJohn Forte } 1253fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1254fcf3ce44SJohn Forte ASSERT(fcsm->sm_instance == fc_ulp_get_port_instance(port_handle)); 1255fcf3ce44SJohn Forte if ((fcsm->sm_flags & FCSM_ATTACHED) == 0) { 1256fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1257fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1258fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_NOTE, SM_LOG, fcsm, NULL, 1259fcf3ce44SJohn Forte "statec_cb: port not attached")); 1260fcf3ce44SJohn Forte return; 1261fcf3ce44SJohn Forte } 1262fcf3ce44SJohn Forte 1263fcf3ce44SJohn Forte ASSERT(fcsm->sm_cb_count >= 0); 1264fcf3ce44SJohn Forte 1265fcf3ce44SJohn Forte fcsm->sm_cb_count++; 1266fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1267fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1268fcf3ce44SJohn Forte 1269fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 1270fcf3ce44SJohn Forte "statec_cb: state <%s>(0x%x) topology <%s>(0x%x) dev_cnt %d", 1271fcf3ce44SJohn Forte fcsm_port_state_to_str(FC_PORT_STATE_MASK(port_state)), port_state, 1272fcf3ce44SJohn Forte fcsm_topology_to_str(port_top), port_top, dev_cnt)); 1273fcf3ce44SJohn Forte 1274fcf3ce44SJohn Forte fcsm_disp_devlist(fcsm, devlist, dev_cnt); 1275fcf3ce44SJohn Forte 1276fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1277fcf3ce44SJohn Forte 1278fcf3ce44SJohn Forte /* 1279fcf3ce44SJohn Forte * Reset the Mgmt server Login flag, so that login is performed again. 1280fcf3ce44SJohn Forte */ 1281fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_MGMT_SERVER_LOGGED_IN; 1282fcf3ce44SJohn Forte 1283fcf3ce44SJohn Forte fcsm->sm_sid = port_sid; 1284fcf3ce44SJohn Forte fcsm->sm_port_top = port_top; 1285fcf3ce44SJohn Forte fcsm->sm_port_state = port_state; 1286fcf3ce44SJohn Forte 1287fcf3ce44SJohn Forte switch (port_state) { 1288fcf3ce44SJohn Forte case FC_STATE_OFFLINE: 1289fcf3ce44SJohn Forte case FC_STATE_RESET: 1290fcf3ce44SJohn Forte case FC_STATE_RESET_REQUESTED: 1291fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_PORT_OFFLINE; 1292fcf3ce44SJohn Forte break; 1293fcf3ce44SJohn Forte 1294fcf3ce44SJohn Forte case FC_STATE_ONLINE: 1295fcf3ce44SJohn Forte case FC_STATE_LOOP: 1296fcf3ce44SJohn Forte case FC_STATE_LIP: 1297fcf3ce44SJohn Forte case FC_STATE_LIP_LBIT_SET: 1298fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_PORT_OFFLINE; 1299fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_LINK_DOWN; 1300fcf3ce44SJohn Forte break; 1301fcf3ce44SJohn Forte 1302fcf3ce44SJohn Forte case FC_STATE_NAMESERVICE: 1303fcf3ce44SJohn Forte case FC_STATE_DEVICE_CHANGE: 1304fcf3ce44SJohn Forte case FC_STATE_TARGET_PORT_RESET: 1305fcf3ce44SJohn Forte default: 1306fcf3ce44SJohn Forte /* Do nothing */ 1307fcf3ce44SJohn Forte break; 1308fcf3ce44SJohn Forte } 1309fcf3ce44SJohn Forte 1310fcf3ce44SJohn Forte offline_tid = retry_tid = NULL; 1311fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_PORT_OFFLINE) { 1312fcf3ce44SJohn Forte /* 1313fcf3ce44SJohn Forte * Port is offline. 1314fcf3ce44SJohn Forte * Suspend cmd processing and start offline timeout thread. 1315fcf3ce44SJohn Forte */ 1316fcf3ce44SJohn Forte if (fcsm->sm_offline_tid == NULL) { 1317fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 1318fcf3ce44SJohn Forte "statec_cb: schedule offline timeout thread")); 1319fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_CMD_RETRY_Q_SUSPENDED; 1320fcf3ce44SJohn Forte /* Stop the cmd retry thread */ 1321fcf3ce44SJohn Forte retry_tid = fcsm->sm_retry_tid; 1322fcf3ce44SJohn Forte fcsm->sm_retry_tid = (timeout_id_t)NULL; 1323fcf3ce44SJohn Forte 1324fcf3ce44SJohn Forte fcsm->sm_offline_tid = timeout(fcsm_offline_timeout, 1325fcf3ce44SJohn Forte (caddr_t)fcsm, fcsm_offline_ticks); 1326fcf3ce44SJohn Forte } 1327fcf3ce44SJohn Forte 1328fcf3ce44SJohn Forte } else { 1329fcf3ce44SJohn Forte /* 1330fcf3ce44SJohn Forte * Port is online. 1331fcf3ce44SJohn Forte * Cancel offline timeout thread and resume command processing. 1332fcf3ce44SJohn Forte */ 1333fcf3ce44SJohn Forte if (fcsm->sm_offline_tid) { 1334fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 1335fcf3ce44SJohn Forte "statec_cb: cancel offline timeout thread")); 1336fcf3ce44SJohn Forte offline_tid = fcsm->sm_offline_tid; 1337fcf3ce44SJohn Forte fcsm->sm_offline_tid = (timeout_id_t)NULL; 1338fcf3ce44SJohn Forte } 1339fcf3ce44SJohn Forte 1340fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_CMD_RETRY_Q_SUSPENDED; 1341fcf3ce44SJohn Forte /* Start retry thread if needed */ 1342fcf3ce44SJohn Forte if (fcsm->sm_retry_head && fcsm->sm_retry_tid == NULL) { 1343fcf3ce44SJohn Forte fcsm->sm_retry_tid = timeout(fcsm_retry_timeout, 1344fcf3ce44SJohn Forte (caddr_t)fcsm, fcsm_retry_ticks); 1345fcf3ce44SJohn Forte } 1346fcf3ce44SJohn Forte } 1347fcf3ce44SJohn Forte 1348fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1349fcf3ce44SJohn Forte 1350fcf3ce44SJohn Forte if (offline_tid != NULL) { 1351fcf3ce44SJohn Forte (void) untimeout(offline_tid); 1352fcf3ce44SJohn Forte } 1353fcf3ce44SJohn Forte 1354fcf3ce44SJohn Forte if (retry_tid != NULL) { 1355fcf3ce44SJohn Forte (void) untimeout(retry_tid); 1356fcf3ce44SJohn Forte } 1357fcf3ce44SJohn Forte 1358fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1359fcf3ce44SJohn Forte fcsm->sm_cb_count--; 1360fcf3ce44SJohn Forte ASSERT(fcsm->sm_cb_count >= 0); 1361fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1362fcf3ce44SJohn Forte } 1363fcf3ce44SJohn Forte 1364fcf3ce44SJohn Forte 1365fcf3ce44SJohn Forte static void 1366fcf3ce44SJohn Forte fcsm_offline_timeout(void *handle) 1367fcf3ce44SJohn Forte { 1368fcf3ce44SJohn Forte fcsm_t *fcsm = (fcsm_t *)handle; 1369fcf3ce44SJohn Forte 1370fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 1371fcf3ce44SJohn Forte "offline_timeout")); 1372fcf3ce44SJohn Forte 1373fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1374fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_PORT_OFFLINE) { 1375fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_LINK_DOWN; 1376fcf3ce44SJohn Forte } 1377fcf3ce44SJohn Forte fcsm->sm_offline_tid = (timeout_id_t)NULL; 1378fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_CMD_RETRY_Q_SUSPENDED; 1379fcf3ce44SJohn Forte 1380fcf3ce44SJohn Forte /* Start the retry thread if needed */ 1381fcf3ce44SJohn Forte if (fcsm->sm_retry_head && fcsm->sm_retry_tid == NULL) { 1382fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 1383fcf3ce44SJohn Forte "offline_timeout: reschedule cmd retry thread")); 1384fcf3ce44SJohn Forte ASSERT(fcsm->sm_retry_tid == NULL); 1385fcf3ce44SJohn Forte fcsm->sm_retry_tid = timeout(fcsm_retry_timeout, 1386fcf3ce44SJohn Forte (caddr_t)fcsm, fcsm_retry_ticks); 1387fcf3ce44SJohn Forte } 1388fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1389fcf3ce44SJohn Forte } 1390fcf3ce44SJohn Forte 1391fcf3ce44SJohn Forte /* ARGSUSED */ 1392fcf3ce44SJohn Forte static int 1393fcf3ce44SJohn Forte fcsm_els_cb(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 1394fcf3ce44SJohn Forte uint32_t claimed) 1395fcf3ce44SJohn Forte { 1396fcf3ce44SJohn Forte return (FC_UNCLAIMED); 1397fcf3ce44SJohn Forte } 1398fcf3ce44SJohn Forte 1399fcf3ce44SJohn Forte 1400fcf3ce44SJohn Forte /* ARGSUSED */ 1401fcf3ce44SJohn Forte static int 1402fcf3ce44SJohn Forte fcsm_data_cb(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 1403fcf3ce44SJohn Forte uint32_t claimed) 1404fcf3ce44SJohn Forte { 1405fcf3ce44SJohn Forte return (FC_UNCLAIMED); 1406fcf3ce44SJohn Forte } 1407fcf3ce44SJohn Forte 1408fcf3ce44SJohn Forte 1409fcf3ce44SJohn Forte /* ARGSUSED */ 1410fcf3ce44SJohn Forte static int 1411fcf3ce44SJohn Forte fcsm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 1412fcf3ce44SJohn Forte int *rval_p) 1413fcf3ce44SJohn Forte { 1414fcf3ce44SJohn Forte int retval = 0; 1415fcf3ce44SJohn Forte 1416fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, "ioctl: start")); 1417fcf3ce44SJohn Forte 1418fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 1419fcf3ce44SJohn Forte if (!(fcsm_flag & FCSM_OPEN)) { 1420fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1421fcf3ce44SJohn Forte return (ENXIO); 1422fcf3ce44SJohn Forte } 1423fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1424fcf3ce44SJohn Forte 1425fcf3ce44SJohn Forte /* Allow only root to talk */ 1426fcf3ce44SJohn Forte if (drv_priv(credp)) { 1427fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 1428fcf3ce44SJohn Forte "ioctl: end (disallowing underprivileged user)")); 1429fcf3ce44SJohn Forte return (EPERM); 1430fcf3ce44SJohn Forte } 1431fcf3ce44SJohn Forte 1432fcf3ce44SJohn Forte switch (cmd) { 1433fcf3ce44SJohn Forte 1434fcf3ce44SJohn Forte case FCSMIO_CMD: { 1435fcf3ce44SJohn Forte fcio_t fcio; 1436fcf3ce44SJohn Forte int status; 1437fcf3ce44SJohn Forte #ifdef _MULTI_DATAMODEL 1438fcf3ce44SJohn Forte switch (ddi_model_convert_from(mode & FMODELS)) { 1439fcf3ce44SJohn Forte case DDI_MODEL_ILP32: { 1440fcf3ce44SJohn Forte struct fcio32 fcio32; 1441fcf3ce44SJohn Forte 1442fcf3ce44SJohn Forte if (status = ddi_copyin((void *)arg, (void *)&fcio32, 1443fcf3ce44SJohn Forte sizeof (struct fcio32), mode)) { 1444fcf3ce44SJohn Forte retval = EFAULT; 1445fcf3ce44SJohn Forte break; 1446fcf3ce44SJohn Forte } 1447fcf3ce44SJohn Forte fcio.fcio_xfer = fcio32.fcio_xfer; 1448fcf3ce44SJohn Forte fcio.fcio_cmd = fcio32.fcio_cmd; 1449fcf3ce44SJohn Forte fcio.fcio_flags = fcio32.fcio_flags; 1450fcf3ce44SJohn Forte fcio.fcio_cmd_flags = fcio32.fcio_cmd_flags; 1451fcf3ce44SJohn Forte fcio.fcio_ilen = (size_t)fcio32.fcio_ilen; 1452fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)(long)fcio32.fcio_ibuf; 1453fcf3ce44SJohn Forte fcio.fcio_olen = (size_t)fcio32.fcio_olen; 1454fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)(long)fcio32.fcio_obuf; 1455fcf3ce44SJohn Forte fcio.fcio_alen = (size_t)fcio32.fcio_alen; 1456fcf3ce44SJohn Forte fcio.fcio_abuf = (caddr_t)(long)fcio32.fcio_abuf; 1457fcf3ce44SJohn Forte fcio.fcio_errno = fcio32.fcio_errno; 1458fcf3ce44SJohn Forte break; 1459fcf3ce44SJohn Forte } 1460fcf3ce44SJohn Forte 1461fcf3ce44SJohn Forte case DDI_MODEL_NONE: 1462fcf3ce44SJohn Forte if (status = ddi_copyin((void *)arg, (void *)&fcio, 1463fcf3ce44SJohn Forte sizeof (fcio_t), mode)) { 1464fcf3ce44SJohn Forte retval = EFAULT; 1465fcf3ce44SJohn Forte } 1466fcf3ce44SJohn Forte break; 1467fcf3ce44SJohn Forte } 1468fcf3ce44SJohn Forte #else /* _MULTI_DATAMODEL */ 1469fcf3ce44SJohn Forte if (status = ddi_copyin((void *)arg, (void *)&fcio, 1470fcf3ce44SJohn Forte sizeof (fcio_t), mode)) { 1471fcf3ce44SJohn Forte retval = EFAULT; 1472fcf3ce44SJohn Forte break; 1473fcf3ce44SJohn Forte } 1474fcf3ce44SJohn Forte #endif /* _MULTI_DATAMODEL */ 1475fcf3ce44SJohn Forte if (!status) { 1476fcf3ce44SJohn Forte retval = fcsm_fciocmd(arg, mode, credp, &fcio); 1477fcf3ce44SJohn Forte } 1478fcf3ce44SJohn Forte break; 1479fcf3ce44SJohn Forte } 1480fcf3ce44SJohn Forte 1481fcf3ce44SJohn Forte default: 1482fcf3ce44SJohn Forte retval = ENOTTY; 1483fcf3ce44SJohn Forte break; 1484fcf3ce44SJohn Forte } 1485fcf3ce44SJohn Forte 1486fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, "ioctl: end")); 1487fcf3ce44SJohn Forte return (retval); 1488fcf3ce44SJohn Forte } 1489fcf3ce44SJohn Forte 1490fcf3ce44SJohn Forte /* ARGSUSED */ 1491fcf3ce44SJohn Forte static int 1492fcf3ce44SJohn Forte fcsm_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 1493fcf3ce44SJohn Forte intptr_t arg, int mode, cred_t *credp, int *rval, uint32_t claimed) 1494fcf3ce44SJohn Forte { 1495fcf3ce44SJohn Forte return (FC_UNCLAIMED); 1496fcf3ce44SJohn Forte } 1497fcf3ce44SJohn Forte 1498fcf3ce44SJohn Forte 1499fcf3ce44SJohn Forte /* ARGSUSED */ 1500fcf3ce44SJohn Forte static int 1501fcf3ce44SJohn Forte fcsm_fciocmd(intptr_t arg, int mode, cred_t *credp, fcio_t *fcio) 1502fcf3ce44SJohn Forte { 1503fcf3ce44SJohn Forte int retval = 0; 1504fcf3ce44SJohn Forte 1505fcf3ce44SJohn Forte switch (fcio->fcio_cmd) { 1506fcf3ce44SJohn Forte case FCSMIO_CT_CMD: { 1507fcf3ce44SJohn Forte fcsm_t *fcsm; 1508fcf3ce44SJohn Forte caddr_t user_ibuf, user_obuf; 1509fcf3ce44SJohn Forte caddr_t req_iu, rsp_iu, abuf; 1510fcf3ce44SJohn Forte int status, instance, count; 1511fcf3ce44SJohn Forte 1512fcf3ce44SJohn Forte if ((fcio->fcio_xfer != FCIO_XFER_RW) || 1513fcf3ce44SJohn Forte (fcio->fcio_ilen == 0) || (fcio->fcio_ibuf == 0) || 1514fcf3ce44SJohn Forte (fcio->fcio_olen == 0) || (fcio->fcio_obuf == 0) || 1515fcf3ce44SJohn Forte (fcio->fcio_alen == 0) || (fcio->fcio_abuf == 0) || 1516fcf3ce44SJohn Forte (fcio->fcio_flags != 0) || (fcio->fcio_cmd_flags != 0) || 1517fcf3ce44SJohn Forte (fcio->fcio_ilen > FCSM_MAX_CT_SIZE) || 1518fcf3ce44SJohn Forte (fcio->fcio_olen > FCSM_MAX_CT_SIZE) || 1519fcf3ce44SJohn Forte (fcio->fcio_alen > MAXPATHLEN)) { 1520fcf3ce44SJohn Forte retval = EINVAL; 1521fcf3ce44SJohn Forte break; 1522fcf3ce44SJohn Forte } 1523fcf3ce44SJohn Forte 1524fcf3ce44SJohn Forte /* 1525fcf3ce44SJohn Forte * Get the destination port for which this ioctl 1526fcf3ce44SJohn Forte * is targeted. The abuf will have the fp_minor 1527fcf3ce44SJohn Forte * number. 1528fcf3ce44SJohn Forte */ 1529fcf3ce44SJohn Forte abuf = kmem_zalloc(fcio->fcio_alen, KM_SLEEP); 1530fcf3ce44SJohn Forte ASSERT(abuf != NULL); 1531fcf3ce44SJohn Forte if (ddi_copyin(fcio->fcio_abuf, abuf, fcio->fcio_alen, mode)) { 1532fcf3ce44SJohn Forte retval = EFAULT; 1533fcf3ce44SJohn Forte kmem_free(abuf, fcio->fcio_alen); 1534fcf3ce44SJohn Forte break; 1535fcf3ce44SJohn Forte } 1536fcf3ce44SJohn Forte 1537fcf3ce44SJohn Forte instance = *((int *)abuf); 1538fcf3ce44SJohn Forte kmem_free(abuf, fcio->fcio_alen); 1539fcf3ce44SJohn Forte 1540fcf3ce44SJohn Forte if (instance < 0) { 1541fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, NULL, NULL, 1542fcf3ce44SJohn Forte "fciocmd: instance 0x%x, invalid instance", 1543fcf3ce44SJohn Forte instance)); 1544fcf3ce44SJohn Forte retval = ENXIO; 1545fcf3ce44SJohn Forte break; 1546fcf3ce44SJohn Forte } 1547fcf3ce44SJohn Forte 1548fcf3ce44SJohn Forte /* 1549fcf3ce44SJohn Forte * We confirmed that path corresponds to our port driver 1550fcf3ce44SJohn Forte * and a valid instance. 1551fcf3ce44SJohn Forte * If this port instance is not yet attached, then wait 1552fcf3ce44SJohn Forte * for a finite time for attach to complete 1553fcf3ce44SJohn Forte */ 1554fcf3ce44SJohn Forte fcsm = ddi_get_soft_state(fcsm_state, instance); 1555fcf3ce44SJohn Forte count = 0; 1556fcf3ce44SJohn Forte while (count++ <= 30) { 1557fcf3ce44SJohn Forte if (fcsm != NULL) { 1558fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 1559fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_ATTACHED) { 1560fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1561fcf3ce44SJohn Forte break; 1562fcf3ce44SJohn Forte } 1563fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 1564fcf3ce44SJohn Forte } 1565fcf3ce44SJohn Forte if (count == 1) { 1566fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, 1567fcf3ce44SJohn Forte (CE_WARN, SM_LOG, NULL, NULL, 1568fcf3ce44SJohn Forte "fciocmd: instance 0x%x, " 1569fcf3ce44SJohn Forte "wait for port attach", instance)); 1570fcf3ce44SJohn Forte } 1571fcf3ce44SJohn Forte delay(drv_usectohz(1000000)); 1572fcf3ce44SJohn Forte fcsm = ddi_get_soft_state(fcsm_state, instance); 1573fcf3ce44SJohn Forte } 1574fcf3ce44SJohn Forte if (count > 30) { 1575fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, NULL, NULL, 1576fcf3ce44SJohn Forte "fciocmd: instance 0x%x, port not attached", 1577fcf3ce44SJohn Forte instance)); 1578fcf3ce44SJohn Forte retval = ENXIO; 1579fcf3ce44SJohn Forte break; 1580fcf3ce44SJohn Forte } 1581fcf3ce44SJohn Forte 1582fcf3ce44SJohn Forte req_iu = kmem_zalloc(fcio->fcio_ilen, KM_SLEEP); 1583fcf3ce44SJohn Forte rsp_iu = kmem_zalloc(fcio->fcio_olen, KM_SLEEP); 1584fcf3ce44SJohn Forte ASSERT((req_iu != NULL) && (rsp_iu != NULL)); 1585fcf3ce44SJohn Forte 1586fcf3ce44SJohn Forte if (ddi_copyin(fcio->fcio_ibuf, req_iu, 1587fcf3ce44SJohn Forte fcio->fcio_ilen, mode)) { 1588fcf3ce44SJohn Forte retval = EFAULT; 1589fcf3ce44SJohn Forte kmem_free(req_iu, fcio->fcio_ilen); 1590fcf3ce44SJohn Forte kmem_free(rsp_iu, fcio->fcio_olen); 1591fcf3ce44SJohn Forte break; 1592fcf3ce44SJohn Forte } 1593fcf3ce44SJohn Forte 1594fcf3ce44SJohn Forte user_ibuf = fcio->fcio_ibuf; 1595fcf3ce44SJohn Forte user_obuf = fcio->fcio_obuf; 1596fcf3ce44SJohn Forte fcio->fcio_ibuf = req_iu; 1597fcf3ce44SJohn Forte fcio->fcio_obuf = rsp_iu; 1598fcf3ce44SJohn Forte 1599fcf3ce44SJohn Forte status = fcsm_ct_passthru(fcsm->sm_instance, fcio, KM_SLEEP, 1600fcf3ce44SJohn Forte FCSM_JOBFLAG_SYNC, NULL); 1601fcf3ce44SJohn Forte if (status != FC_SUCCESS) { 1602fcf3ce44SJohn Forte retval = EIO; 1603fcf3ce44SJohn Forte } 1604fcf3ce44SJohn Forte 1605fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 1606fcf3ce44SJohn Forte "fciocmd: cmd 0x%x completion status 0x%x", 1607fcf3ce44SJohn Forte fcio->fcio_cmd, status)); 1608fcf3ce44SJohn Forte fcio->fcio_errno = status; 1609fcf3ce44SJohn Forte fcio->fcio_ibuf = user_ibuf; 1610fcf3ce44SJohn Forte fcio->fcio_obuf = user_obuf; 1611fcf3ce44SJohn Forte 1612fcf3ce44SJohn Forte if (ddi_copyout(rsp_iu, fcio->fcio_obuf, 1613fcf3ce44SJohn Forte fcio->fcio_olen, mode)) { 1614fcf3ce44SJohn Forte retval = EFAULT; 1615fcf3ce44SJohn Forte kmem_free(req_iu, fcio->fcio_ilen); 1616fcf3ce44SJohn Forte kmem_free(rsp_iu, fcio->fcio_olen); 1617fcf3ce44SJohn Forte break; 1618fcf3ce44SJohn Forte } 1619fcf3ce44SJohn Forte 1620fcf3ce44SJohn Forte kmem_free(req_iu, fcio->fcio_ilen); 1621fcf3ce44SJohn Forte kmem_free(rsp_iu, fcio->fcio_olen); 1622fcf3ce44SJohn Forte 1623fcf3ce44SJohn Forte if (fcsm_fcio_copyout(fcio, arg, mode)) { 1624fcf3ce44SJohn Forte retval = EFAULT; 1625fcf3ce44SJohn Forte } 1626fcf3ce44SJohn Forte break; 1627fcf3ce44SJohn Forte } 1628fcf3ce44SJohn Forte 1629fcf3ce44SJohn Forte case FCSMIO_ADAPTER_LIST: { 1630fcf3ce44SJohn Forte fc_hba_list_t *list; 1631fcf3ce44SJohn Forte int count; 1632fcf3ce44SJohn Forte 1633fcf3ce44SJohn Forte if ((fcio->fcio_xfer != FCIO_XFER_RW) || 1634fcf3ce44SJohn Forte (fcio->fcio_olen == 0) || (fcio->fcio_obuf == 0)) { 1635fcf3ce44SJohn Forte retval = EINVAL; 1636fcf3ce44SJohn Forte break; 1637fcf3ce44SJohn Forte } 1638fcf3ce44SJohn Forte 1639fcf3ce44SJohn Forte list = kmem_zalloc(fcio->fcio_olen, KM_SLEEP); 1640fcf3ce44SJohn Forte 1641fcf3ce44SJohn Forte if (ddi_copyin(fcio->fcio_obuf, list, fcio->fcio_olen, mode)) { 1642fcf3ce44SJohn Forte retval = EFAULT; 1643fcf3ce44SJohn Forte break; 1644fcf3ce44SJohn Forte } 1645fcf3ce44SJohn Forte list->version = FC_HBA_LIST_VERSION; 1646fcf3ce44SJohn Forte 1647fcf3ce44SJohn Forte if (fcio->fcio_olen < MAXPATHLEN * list->numAdapters) { 1648fcf3ce44SJohn Forte retval = EFAULT; 1649fcf3ce44SJohn Forte break; 1650fcf3ce44SJohn Forte } 1651fcf3ce44SJohn Forte 1652fcf3ce44SJohn Forte count = fc_ulp_get_adapter_paths((char *)list->hbaPaths, 1653fcf3ce44SJohn Forte list->numAdapters); 1654*7ff83669SZhong Wang if (count < 0) { 1655*7ff83669SZhong Wang /* Did something go wrong? */ 1656fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 1657fcf3ce44SJohn Forte "Error fetching adapter list.")); 1658fcf3ce44SJohn Forte retval = ENXIO; 1659fcf3ce44SJohn Forte kmem_free(list, fcio->fcio_olen); 1660fcf3ce44SJohn Forte break; 1661fcf3ce44SJohn Forte } 1662fcf3ce44SJohn Forte /* Sucess (or short buffer) */ 1663fcf3ce44SJohn Forte list->numAdapters = count; 1664fcf3ce44SJohn Forte if (ddi_copyout(list, fcio->fcio_obuf, 1665fcf3ce44SJohn Forte fcio->fcio_olen, mode)) { 1666fcf3ce44SJohn Forte retval = EFAULT; 1667fcf3ce44SJohn Forte } 1668fcf3ce44SJohn Forte kmem_free(list, fcio->fcio_olen); 1669fcf3ce44SJohn Forte break; 1670fcf3ce44SJohn Forte } 1671fcf3ce44SJohn Forte 1672fcf3ce44SJohn Forte default: 1673fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_NOTE, SM_LOG, NULL, NULL, 1674fcf3ce44SJohn Forte "fciocmd: unknown cmd <0x%x>", fcio->fcio_cmd)); 1675fcf3ce44SJohn Forte retval = ENOTTY; 1676fcf3ce44SJohn Forte break; 1677fcf3ce44SJohn Forte } 1678fcf3ce44SJohn Forte 1679fcf3ce44SJohn Forte return (retval); 1680fcf3ce44SJohn Forte } 1681fcf3ce44SJohn Forte 1682fcf3ce44SJohn Forte static int 1683fcf3ce44SJohn Forte fcsm_fcio_copyout(fcio_t *fcio, intptr_t arg, int mode) 1684fcf3ce44SJohn Forte { 1685fcf3ce44SJohn Forte int status; 1686fcf3ce44SJohn Forte 1687fcf3ce44SJohn Forte #ifdef _MULTI_DATAMODEL 1688fcf3ce44SJohn Forte switch (ddi_model_convert_from(mode & FMODELS)) { 1689fcf3ce44SJohn Forte case DDI_MODEL_ILP32: { 1690fcf3ce44SJohn Forte struct fcio32 fcio32; 1691fcf3ce44SJohn Forte 1692fcf3ce44SJohn Forte fcio32.fcio_xfer = fcio->fcio_xfer; 1693fcf3ce44SJohn Forte fcio32.fcio_cmd = fcio->fcio_cmd; 1694fcf3ce44SJohn Forte fcio32.fcio_flags = fcio->fcio_flags; 1695fcf3ce44SJohn Forte fcio32.fcio_cmd_flags = fcio->fcio_cmd_flags; 1696fcf3ce44SJohn Forte fcio32.fcio_ilen = fcio->fcio_ilen; 1697fcf3ce44SJohn Forte fcio32.fcio_ibuf = (caddr32_t)(long)fcio->fcio_ibuf; 1698fcf3ce44SJohn Forte fcio32.fcio_olen = fcio->fcio_olen; 1699fcf3ce44SJohn Forte fcio32.fcio_obuf = (caddr32_t)(long)fcio->fcio_obuf; 1700fcf3ce44SJohn Forte fcio32.fcio_alen = fcio->fcio_alen; 1701fcf3ce44SJohn Forte fcio32.fcio_abuf = (caddr32_t)(long)fcio->fcio_abuf; 1702fcf3ce44SJohn Forte fcio32.fcio_errno = fcio->fcio_errno; 1703fcf3ce44SJohn Forte 1704fcf3ce44SJohn Forte status = ddi_copyout((void *)&fcio32, (void *)arg, 1705fcf3ce44SJohn Forte sizeof (struct fcio32), mode); 1706fcf3ce44SJohn Forte break; 1707fcf3ce44SJohn Forte } 1708fcf3ce44SJohn Forte case DDI_MODEL_NONE: 1709fcf3ce44SJohn Forte status = ddi_copyout((void *)fcio, (void *)arg, 1710fcf3ce44SJohn Forte sizeof (fcio_t), mode); 1711fcf3ce44SJohn Forte break; 1712fcf3ce44SJohn Forte } 1713fcf3ce44SJohn Forte #else /* _MULTI_DATAMODEL */ 1714fcf3ce44SJohn Forte status = ddi_copyout((void *)fcio, (void *)arg, sizeof (fcio_t), mode); 1715fcf3ce44SJohn Forte #endif /* _MULTI_DATAMODEL */ 1716fcf3ce44SJohn Forte 1717fcf3ce44SJohn Forte return (status); 1718fcf3ce44SJohn Forte } 1719fcf3ce44SJohn Forte 1720fcf3ce44SJohn Forte 1721fcf3ce44SJohn Forte /* ARGSUSED */ 1722fcf3ce44SJohn Forte static int 1723fcf3ce44SJohn Forte fcsm_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1724fcf3ce44SJohn Forte { 1725fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, "open")); 1726fcf3ce44SJohn Forte 1727fcf3ce44SJohn Forte if (otyp != OTYP_CHR) { 1728fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 1729fcf3ce44SJohn Forte "fcsm_open: failed. open type 0x%x for minor 0x%x is not " 1730fcf3ce44SJohn Forte "OTYP_CHR", otyp, getminor(*devp))); 1731fcf3ce44SJohn Forte return (EINVAL); 1732fcf3ce44SJohn Forte } 1733fcf3ce44SJohn Forte 1734fcf3ce44SJohn Forte /* 1735fcf3ce44SJohn Forte * Allow anybody to open (both root and non-root users). 1736fcf3ce44SJohn Forte * Previlege level checks are made on the per ioctl basis. 1737fcf3ce44SJohn Forte */ 1738fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 1739fcf3ce44SJohn Forte if (flags & FEXCL) { 1740fcf3ce44SJohn Forte if (fcsm_flag & FCSM_OPEN) { 1741fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1742fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 1743fcf3ce44SJohn Forte "fcsm_open: exclusive open of 0x%x failed", 1744fcf3ce44SJohn Forte getminor(*devp))); 1745fcf3ce44SJohn Forte return (EBUSY); 1746fcf3ce44SJohn Forte } else { 1747fcf3ce44SJohn Forte ASSERT(fcsm_flag == FCSM_IDLE); 1748fcf3ce44SJohn Forte fcsm_flag |= FCSM_EXCL; 1749fcf3ce44SJohn Forte } 1750fcf3ce44SJohn Forte } else { 1751fcf3ce44SJohn Forte if (fcsm_flag & FCSM_EXCL) { 1752fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1753fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 1754fcf3ce44SJohn Forte "fcsm_open: failed. Device minor 0x%x is in " 1755fcf3ce44SJohn Forte "exclusive open mode", getminor(*devp))); 1756fcf3ce44SJohn Forte return (EBUSY); 1757fcf3ce44SJohn Forte } 1758fcf3ce44SJohn Forte 1759fcf3ce44SJohn Forte } 1760fcf3ce44SJohn Forte fcsm_flag |= FCSM_OPEN; 1761fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1762fcf3ce44SJohn Forte return (0); 1763fcf3ce44SJohn Forte } 1764fcf3ce44SJohn Forte 1765fcf3ce44SJohn Forte 1766fcf3ce44SJohn Forte /* ARGSUSED */ 1767fcf3ce44SJohn Forte static int 1768fcf3ce44SJohn Forte fcsm_close(dev_t dev, int flag, int otyp, cred_t *credp) 1769fcf3ce44SJohn Forte { 1770fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, "close")); 1771fcf3ce44SJohn Forte 1772fcf3ce44SJohn Forte if (otyp != OTYP_CHR) { 1773fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 1774fcf3ce44SJohn Forte "fcsm_close: failed. close type 0x%x for minor 0x%x is not " 1775fcf3ce44SJohn Forte "OTYP_CHR", otyp, getminor(dev))); 1776fcf3ce44SJohn Forte return (EINVAL); 1777fcf3ce44SJohn Forte } 1778fcf3ce44SJohn Forte 1779fcf3ce44SJohn Forte mutex_enter(&fcsm_global_mutex); 1780fcf3ce44SJohn Forte if ((fcsm_flag & FCSM_OPEN) == 0) { 1781fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1782fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 1783fcf3ce44SJohn Forte "fcsm_close: failed. minor 0x%x is already closed", 1784fcf3ce44SJohn Forte getminor(dev))); 1785fcf3ce44SJohn Forte return (ENODEV); 1786fcf3ce44SJohn Forte } 1787fcf3ce44SJohn Forte fcsm_flag = FCSM_IDLE; 1788fcf3ce44SJohn Forte mutex_exit(&fcsm_global_mutex); 1789fcf3ce44SJohn Forte return (0); 1790fcf3ce44SJohn Forte } 1791fcf3ce44SJohn Forte 1792fcf3ce44SJohn Forte 1793fcf3ce44SJohn Forte /* ARGSUSED */ 1794fcf3ce44SJohn Forte static void 1795fcf3ce44SJohn Forte fcsm_disp_devlist(fcsm_t *fcsm, fc_portmap_t *devlist, uint32_t dev_cnt) 1796fcf3ce44SJohn Forte { 1797fcf3ce44SJohn Forte fc_portmap_t *map; 1798fcf3ce44SJohn Forte uint32_t i; 1799fcf3ce44SJohn Forte 1800fcf3ce44SJohn Forte if (dev_cnt == 0) { 1801fcf3ce44SJohn Forte return; 1802fcf3ce44SJohn Forte } 1803fcf3ce44SJohn Forte 1804fcf3ce44SJohn Forte ASSERT(devlist != NULL); 1805fcf3ce44SJohn Forte for (i = 0; i < dev_cnt; i++) { 1806fcf3ce44SJohn Forte map = &devlist[i]; 1807fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 1808fcf3ce44SJohn Forte "list[%d]: ID 0x%x WWN %x:%x:%x:%x:%x:%x:%x:%x " 1809fcf3ce44SJohn Forte "state (0x%x) " 1810fcf3ce44SJohn Forte "type <%s>(0x%x) " 1811fcf3ce44SJohn Forte "flags (0x%x)", 1812fcf3ce44SJohn Forte i, map->map_did.port_id, 1813fcf3ce44SJohn Forte map->map_pwwn.raw_wwn[0], map->map_pwwn.raw_wwn[1], 1814fcf3ce44SJohn Forte map->map_pwwn.raw_wwn[2], map->map_pwwn.raw_wwn[3], 1815fcf3ce44SJohn Forte map->map_pwwn.raw_wwn[4], map->map_pwwn.raw_wwn[5], 1816fcf3ce44SJohn Forte map->map_pwwn.raw_wwn[6], map->map_pwwn.raw_wwn[7], 1817fcf3ce44SJohn Forte map->map_state, 1818fcf3ce44SJohn Forte fcsm_dev_type_to_str(map->map_type), map->map_type, 1819fcf3ce44SJohn Forte map->map_flags)); 1820fcf3ce44SJohn Forte } 1821fcf3ce44SJohn Forte } 1822fcf3ce44SJohn Forte 1823fcf3ce44SJohn Forte /* ARGSUSED */ 1824fcf3ce44SJohn Forte static void 1825fcf3ce44SJohn Forte fcsm_display(int level, int flags, fcsm_t *fcsm, fc_packet_t *pkt, 1826fcf3ce44SJohn Forte const char *fmt, ...) 1827fcf3ce44SJohn Forte { 1828fcf3ce44SJohn Forte caddr_t buf; 1829fcf3ce44SJohn Forte va_list ap; 1830fcf3ce44SJohn Forte 1831fcf3ce44SJohn Forte buf = kmem_zalloc(256, KM_NOSLEEP); 1832fcf3ce44SJohn Forte if (buf == NULL) { 1833fcf3ce44SJohn Forte return; 1834fcf3ce44SJohn Forte } 1835fcf3ce44SJohn Forte 1836fcf3ce44SJohn Forte if (fcsm) { 1837fcf3ce44SJohn Forte (void) sprintf(buf + strlen(buf), "fcsm(%d): ", 1838fcf3ce44SJohn Forte ddi_get_instance(fcsm->sm_port_info.port_dip)); 1839fcf3ce44SJohn Forte } else { 1840fcf3ce44SJohn Forte (void) sprintf(buf, "fcsm: "); 1841fcf3ce44SJohn Forte } 1842fcf3ce44SJohn Forte 1843fcf3ce44SJohn Forte va_start(ap, fmt); 1844fcf3ce44SJohn Forte (void) vsprintf(buf + strlen(buf), fmt, ap); 1845fcf3ce44SJohn Forte va_end(ap); 1846fcf3ce44SJohn Forte 1847fcf3ce44SJohn Forte if (pkt) { 1848fcf3ce44SJohn Forte caddr_t state, reason, action, expln; 1849fcf3ce44SJohn Forte 1850fcf3ce44SJohn Forte (void) fc_ulp_pkt_error(pkt, &state, &reason, &action, &expln); 1851fcf3ce44SJohn Forte 1852fcf3ce44SJohn Forte (void) sprintf(buf + strlen(buf), 1853fcf3ce44SJohn Forte " state: %s(0x%x); reason: %s(0x%x)", 1854fcf3ce44SJohn Forte state, pkt->pkt_state, reason, pkt->pkt_reason); 1855fcf3ce44SJohn Forte } 1856fcf3ce44SJohn Forte 1857fcf3ce44SJohn Forte switch (flags) { 1858fcf3ce44SJohn Forte case SM_LOG: 1859fcf3ce44SJohn Forte cmn_err(level, "!%s", buf); 1860fcf3ce44SJohn Forte break; 1861fcf3ce44SJohn Forte 1862fcf3ce44SJohn Forte case SM_CONSOLE: 1863fcf3ce44SJohn Forte cmn_err(level, "^%s", buf); 1864fcf3ce44SJohn Forte break; 1865fcf3ce44SJohn Forte 1866fcf3ce44SJohn Forte default: 1867fcf3ce44SJohn Forte cmn_err(level, "%s", buf); 1868fcf3ce44SJohn Forte break; 1869fcf3ce44SJohn Forte } 1870fcf3ce44SJohn Forte 1871fcf3ce44SJohn Forte kmem_free(buf, 256); 1872fcf3ce44SJohn Forte } 1873fcf3ce44SJohn Forte 1874fcf3ce44SJohn Forte 1875fcf3ce44SJohn Forte /* 1876fcf3ce44SJohn Forte * Convert FC packet state to FC errno 1877fcf3ce44SJohn Forte */ 1878fcf3ce44SJohn Forte int 1879fcf3ce44SJohn Forte fcsm_pkt_state_to_rval(uchar_t state, uint32_t reason) 1880fcf3ce44SJohn Forte { 1881fcf3ce44SJohn Forte int count; 1882fcf3ce44SJohn Forte 1883fcf3ce44SJohn Forte if (state == FC_PKT_LOCAL_RJT && (reason == FC_REASON_NO_CONNECTION || 1884fcf3ce44SJohn Forte reason == FC_REASON_LOGIN_REQUIRED)) { 1885fcf3ce44SJohn Forte return (FC_LOGINREQ); 1886fcf3ce44SJohn Forte } else if (state == FC_PKT_PORT_OFFLINE && 1887fcf3ce44SJohn Forte reason == FC_REASON_LOGIN_REQUIRED) { 1888fcf3ce44SJohn Forte return (FC_LOGINREQ); 1889fcf3ce44SJohn Forte } 1890fcf3ce44SJohn Forte 1891fcf3ce44SJohn Forte for (count = 0; count < sizeof (fcsm_xlat_pkt_state) / 1892fcf3ce44SJohn Forte sizeof (fcsm_xlat_pkt_state[0]); count++) { 1893fcf3ce44SJohn Forte if (fcsm_xlat_pkt_state[count].xlat_state == state) { 1894fcf3ce44SJohn Forte return (fcsm_xlat_pkt_state[count].xlat_rval); 1895fcf3ce44SJohn Forte } 1896fcf3ce44SJohn Forte } 1897fcf3ce44SJohn Forte 1898fcf3ce44SJohn Forte return (FC_FAILURE); 1899fcf3ce44SJohn Forte } 1900fcf3ce44SJohn Forte 1901fcf3ce44SJohn Forte 1902fcf3ce44SJohn Forte /* 1903fcf3ce44SJohn Forte * Convert port state state to descriptive string 1904fcf3ce44SJohn Forte */ 1905fcf3ce44SJohn Forte caddr_t 1906fcf3ce44SJohn Forte fcsm_port_state_to_str(uint32_t port_state) 1907fcf3ce44SJohn Forte { 1908fcf3ce44SJohn Forte int count; 1909fcf3ce44SJohn Forte 1910fcf3ce44SJohn Forte for (count = 0; count < sizeof (fcsm_xlat_port_state) / 1911fcf3ce44SJohn Forte sizeof (fcsm_xlat_port_state[0]); count++) { 1912fcf3ce44SJohn Forte if (fcsm_xlat_port_state[count].xlat_pstate == port_state) { 1913fcf3ce44SJohn Forte return (fcsm_xlat_port_state[count].xlat_state_str); 1914fcf3ce44SJohn Forte } 1915fcf3ce44SJohn Forte } 1916fcf3ce44SJohn Forte 1917fcf3ce44SJohn Forte return (NULL); 1918fcf3ce44SJohn Forte } 1919fcf3ce44SJohn Forte 1920fcf3ce44SJohn Forte 1921fcf3ce44SJohn Forte /* 1922fcf3ce44SJohn Forte * Convert port topology state to descriptive string 1923fcf3ce44SJohn Forte */ 1924fcf3ce44SJohn Forte caddr_t 1925fcf3ce44SJohn Forte fcsm_topology_to_str(uint32_t topology) 1926fcf3ce44SJohn Forte { 1927fcf3ce44SJohn Forte int count; 1928fcf3ce44SJohn Forte 1929fcf3ce44SJohn Forte for (count = 0; count < sizeof (fcsm_xlat_topology) / 1930fcf3ce44SJohn Forte sizeof (fcsm_xlat_topology[0]); count++) { 1931fcf3ce44SJohn Forte if (fcsm_xlat_topology[count].xlat_top == topology) { 1932fcf3ce44SJohn Forte return (fcsm_xlat_topology[count].xlat_top_str); 1933fcf3ce44SJohn Forte } 1934fcf3ce44SJohn Forte } 1935fcf3ce44SJohn Forte 1936fcf3ce44SJohn Forte return (NULL); 1937fcf3ce44SJohn Forte } 1938fcf3ce44SJohn Forte 1939fcf3ce44SJohn Forte 1940fcf3ce44SJohn Forte /* 1941fcf3ce44SJohn Forte * Convert port topology state to descriptive string 1942fcf3ce44SJohn Forte */ 1943fcf3ce44SJohn Forte static caddr_t 1944fcf3ce44SJohn Forte fcsm_dev_type_to_str(uint32_t type) 1945fcf3ce44SJohn Forte { 1946fcf3ce44SJohn Forte int count; 1947fcf3ce44SJohn Forte 1948fcf3ce44SJohn Forte for (count = 0; count < sizeof (fcsm_xlat_dev_type) / 1949fcf3ce44SJohn Forte sizeof (fcsm_xlat_dev_type[0]); count++) { 1950fcf3ce44SJohn Forte if (fcsm_xlat_dev_type[count].xlat_type == type) { 1951fcf3ce44SJohn Forte return (fcsm_xlat_dev_type[count].xlat_str); 1952fcf3ce44SJohn Forte } 1953fcf3ce44SJohn Forte } 1954fcf3ce44SJohn Forte 1955fcf3ce44SJohn Forte return (NULL); 1956fcf3ce44SJohn Forte } 1957fcf3ce44SJohn Forte 1958fcf3ce44SJohn Forte static int 1959fcf3ce44SJohn Forte fcsm_cmd_cache_constructor(void *buf, void *cdarg, int kmflags) 1960fcf3ce44SJohn Forte { 1961fcf3ce44SJohn Forte fcsm_cmd_t *cmd = (fcsm_cmd_t *)buf; 1962fcf3ce44SJohn Forte fcsm_t *fcsm = (fcsm_t *)cdarg; 1963fcf3ce44SJohn Forte int (*callback)(caddr_t); 1964fcf3ce44SJohn Forte fc_packet_t *pkt; 1965fcf3ce44SJohn Forte fc_ulp_port_info_t *pinfo; 1966fcf3ce44SJohn Forte 1967fcf3ce44SJohn Forte ASSERT(fcsm != NULL && buf != NULL); 1968fcf3ce44SJohn Forte callback = (kmflags == KM_SLEEP) ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT; 1969fcf3ce44SJohn Forte 1970fcf3ce44SJohn Forte cmd->cmd_fp_pkt = &cmd->cmd_fc_packet; 1971fcf3ce44SJohn Forte cmd->cmd_job = NULL; 1972fcf3ce44SJohn Forte cmd->cmd_fcsm = fcsm; 1973fcf3ce44SJohn Forte cmd->cmd_dma_flags = 0; 1974fcf3ce44SJohn Forte 1975fcf3ce44SJohn Forte pkt = &cmd->cmd_fc_packet; 1976fcf3ce44SJohn Forte 1977fcf3ce44SJohn Forte pkt->pkt_ulp_rscn_infop = NULL; 1978fcf3ce44SJohn Forte pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + sizeof (fcsm_cmd_t)); 1979fcf3ce44SJohn Forte pkt->pkt_ulp_private = (opaque_t)cmd; 1980fcf3ce44SJohn Forte 1981*7ff83669SZhong Wang if (!(fcsm->sm_flags & FCSM_USING_NODMA_FCA)) { 1982fcf3ce44SJohn Forte pinfo = &fcsm->sm_port_info; 1983*7ff83669SZhong Wang if (ddi_dma_alloc_handle(pinfo->port_dip, 1984*7ff83669SZhong Wang pinfo->port_cmd_dma_attr, 1985fcf3ce44SJohn Forte callback, NULL, &pkt->pkt_cmd_dma) != DDI_SUCCESS) { 1986fcf3ce44SJohn Forte return (1); 1987fcf3ce44SJohn Forte } 1988fcf3ce44SJohn Forte 1989*7ff83669SZhong Wang if (ddi_dma_alloc_handle(pinfo->port_dip, 1990*7ff83669SZhong Wang pinfo->port_resp_dma_attr, 1991fcf3ce44SJohn Forte callback, NULL, &pkt->pkt_resp_dma) != DDI_SUCCESS) { 1992fcf3ce44SJohn Forte ddi_dma_free_handle(&pkt->pkt_cmd_dma); 1993fcf3ce44SJohn Forte return (1); 1994fcf3ce44SJohn Forte } 1995*7ff83669SZhong Wang } else { 1996*7ff83669SZhong Wang pkt->pkt_cmd_dma = NULL; 1997*7ff83669SZhong Wang pkt->pkt_cmd = NULL; 1998*7ff83669SZhong Wang pkt->pkt_resp_dma = NULL; 1999*7ff83669SZhong Wang pkt->pkt_resp = NULL; 2000*7ff83669SZhong Wang } 2001fcf3ce44SJohn Forte 2002fcf3ce44SJohn Forte pkt->pkt_cmd_acc = pkt->pkt_resp_acc = NULL; 2003fcf3ce44SJohn Forte pkt->pkt_cmd_cookie_cnt = pkt->pkt_resp_cookie_cnt = 2004fcf3ce44SJohn Forte pkt->pkt_data_cookie_cnt = 0; 2005fcf3ce44SJohn Forte pkt->pkt_cmd_cookie = pkt->pkt_resp_cookie = 2006fcf3ce44SJohn Forte pkt->pkt_data_cookie = NULL; 2007fcf3ce44SJohn Forte 2008fcf3ce44SJohn Forte return (0); 2009fcf3ce44SJohn Forte } 2010fcf3ce44SJohn Forte 2011fcf3ce44SJohn Forte 2012fcf3ce44SJohn Forte /* ARGSUSED */ 2013fcf3ce44SJohn Forte static void 2014fcf3ce44SJohn Forte fcsm_cmd_cache_destructor(void *buf, void *cdarg) 2015fcf3ce44SJohn Forte { 2016fcf3ce44SJohn Forte fcsm_cmd_t *cmd = (fcsm_cmd_t *)buf; 2017fcf3ce44SJohn Forte fcsm_t *fcsm = (fcsm_t *)cdarg; 2018fcf3ce44SJohn Forte fc_packet_t *pkt; 2019fcf3ce44SJohn Forte 2020fcf3ce44SJohn Forte ASSERT(fcsm == cmd->cmd_fcsm); 2021fcf3ce44SJohn Forte 2022fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 2023fcf3ce44SJohn Forte 2024fcf3ce44SJohn Forte if (pkt->pkt_cmd_dma != NULL) { 2025fcf3ce44SJohn Forte ddi_dma_free_handle(&pkt->pkt_cmd_dma); 2026fcf3ce44SJohn Forte } 2027fcf3ce44SJohn Forte 2028fcf3ce44SJohn Forte if (pkt->pkt_resp_dma != NULL) { 2029fcf3ce44SJohn Forte ddi_dma_free_handle(&pkt->pkt_resp_dma); 2030fcf3ce44SJohn Forte } 2031fcf3ce44SJohn Forte } 2032fcf3ce44SJohn Forte 2033fcf3ce44SJohn Forte 2034fcf3ce44SJohn Forte static fcsm_cmd_t * 2035fcf3ce44SJohn Forte fcsm_alloc_cmd(fcsm_t *fcsm, uint32_t cmd_len, uint32_t resp_len, int sleep) 2036fcf3ce44SJohn Forte { 2037fcf3ce44SJohn Forte fcsm_cmd_t *cmd; 2038fcf3ce44SJohn Forte fc_packet_t *pkt; 2039fcf3ce44SJohn Forte int rval; 2040fcf3ce44SJohn Forte ulong_t real_len; 2041fcf3ce44SJohn Forte int (*callback)(caddr_t); 2042fcf3ce44SJohn Forte ddi_dma_cookie_t pkt_cookie; 2043fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 2044fcf3ce44SJohn Forte uint32_t cnt; 2045fcf3ce44SJohn Forte fc_ulp_port_info_t *pinfo; 2046fcf3ce44SJohn Forte 2047fcf3ce44SJohn Forte ASSERT(fcsm != NULL); 2048fcf3ce44SJohn Forte pinfo = &fcsm->sm_port_info; 2049fcf3ce44SJohn Forte 2050fcf3ce44SJohn Forte callback = (sleep == KM_SLEEP) ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT; 2051fcf3ce44SJohn Forte 2052fcf3ce44SJohn Forte cmd = (fcsm_cmd_t *)kmem_cache_alloc(fcsm->sm_cmd_cache, sleep); 2053fcf3ce44SJohn Forte if (cmd == NULL) { 2054fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_WARN, SM_LOG, fcsm, NULL, 2055fcf3ce44SJohn Forte "alloc_cmd: kmem_cache_alloc failed")); 2056fcf3ce44SJohn Forte return (NULL); 2057fcf3ce44SJohn Forte } 2058fcf3ce44SJohn Forte 2059fcf3ce44SJohn Forte cmd->cmd_retry_count = 0; 2060fcf3ce44SJohn Forte cmd->cmd_max_retries = 0; 2061fcf3ce44SJohn Forte cmd->cmd_retry_interval = 0; 2062fcf3ce44SJohn Forte cmd->cmd_transport = NULL; 2063fcf3ce44SJohn Forte 2064fcf3ce44SJohn Forte ASSERT(cmd->cmd_dma_flags == 0); 2065fcf3ce44SJohn Forte ASSERT(cmd->cmd_fp_pkt == &cmd->cmd_fc_packet); 2066fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 2067fcf3ce44SJohn Forte 2068fcf3ce44SJohn Forte /* Zero out the important fc_packet fields */ 2069fcf3ce44SJohn Forte pkt->pkt_pd = NULL; 2070fcf3ce44SJohn Forte pkt->pkt_datalen = 0; 2071fcf3ce44SJohn Forte pkt->pkt_data = NULL; 2072fcf3ce44SJohn Forte pkt->pkt_state = 0; 2073fcf3ce44SJohn Forte pkt->pkt_action = 0; 2074fcf3ce44SJohn Forte pkt->pkt_reason = 0; 2075fcf3ce44SJohn Forte pkt->pkt_expln = 0; 2076fcf3ce44SJohn Forte 2077fcf3ce44SJohn Forte /* 2078fcf3ce44SJohn Forte * Now that pkt_pd is initialized, we can call fc_ulp_init_packet 2079fcf3ce44SJohn Forte */ 2080fcf3ce44SJohn Forte 2081fcf3ce44SJohn Forte if (fc_ulp_init_packet((opaque_t)pinfo->port_handle, pkt, sleep) 2082fcf3ce44SJohn Forte != FC_SUCCESS) { 2083fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2084fcf3ce44SJohn Forte return (NULL); 2085fcf3ce44SJohn Forte } 2086fcf3ce44SJohn Forte 2087*7ff83669SZhong Wang if ((cmd_len) && !(fcsm->sm_flags & FCSM_USING_NODMA_FCA)) { 2088fcf3ce44SJohn Forte ASSERT(pkt->pkt_cmd_dma != NULL); 2089fcf3ce44SJohn Forte 2090fcf3ce44SJohn Forte rval = ddi_dma_mem_alloc(pkt->pkt_cmd_dma, cmd_len, 2091fcf3ce44SJohn Forte fcsm->sm_port_info.port_acc_attr, DDI_DMA_CONSISTENT, 2092fcf3ce44SJohn Forte callback, NULL, (caddr_t *)&pkt->pkt_cmd, &real_len, 2093fcf3ce44SJohn Forte &pkt->pkt_cmd_acc); 2094fcf3ce44SJohn Forte 2095fcf3ce44SJohn Forte if (rval != DDI_SUCCESS) { 2096fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2097fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2098fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2099fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2100fcf3ce44SJohn Forte return (NULL); 2101fcf3ce44SJohn Forte } 2102fcf3ce44SJohn Forte 2103fcf3ce44SJohn Forte cmd->cmd_dma_flags |= FCSM_CF_CMD_VALID_DMA_MEM; 2104fcf3ce44SJohn Forte 2105fcf3ce44SJohn Forte if (real_len < cmd_len) { 2106fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2107fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2108fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2109fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2110fcf3ce44SJohn Forte return (NULL); 2111fcf3ce44SJohn Forte } 2112fcf3ce44SJohn Forte 2113fcf3ce44SJohn Forte rval = ddi_dma_addr_bind_handle(pkt->pkt_cmd_dma, NULL, 2114fcf3ce44SJohn Forte pkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 2115fcf3ce44SJohn Forte callback, NULL, &pkt_cookie, &pkt->pkt_cmd_cookie_cnt); 2116fcf3ce44SJohn Forte 2117fcf3ce44SJohn Forte if (rval != DDI_DMA_MAPPED) { 2118fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2119fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2120fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2121fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2122fcf3ce44SJohn Forte return (NULL); 2123fcf3ce44SJohn Forte } 2124fcf3ce44SJohn Forte 2125fcf3ce44SJohn Forte cmd->cmd_dma_flags |= FCSM_CF_CMD_VALID_DMA_BIND; 2126fcf3ce44SJohn Forte 2127fcf3ce44SJohn Forte if (pkt->pkt_cmd_cookie_cnt > 2128fcf3ce44SJohn Forte pinfo->port_cmd_dma_attr->dma_attr_sgllen) { 2129fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2130fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2131fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2132fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2133fcf3ce44SJohn Forte return (NULL); 2134fcf3ce44SJohn Forte } 2135fcf3ce44SJohn Forte 2136fcf3ce44SJohn Forte ASSERT(pkt->pkt_cmd_cookie_cnt != 0); 2137fcf3ce44SJohn Forte 2138fcf3ce44SJohn Forte cp = pkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 2139fcf3ce44SJohn Forte pkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 2140fcf3ce44SJohn Forte KM_NOSLEEP); 2141fcf3ce44SJohn Forte 2142fcf3ce44SJohn Forte if (cp == NULL) { 2143fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2144fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2145fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2146fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2147fcf3ce44SJohn Forte return (NULL); 2148fcf3ce44SJohn Forte } 2149fcf3ce44SJohn Forte 2150fcf3ce44SJohn Forte *cp = pkt_cookie; 2151fcf3ce44SJohn Forte cp++; 2152fcf3ce44SJohn Forte for (cnt = 1; cnt < pkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 2153fcf3ce44SJohn Forte ddi_dma_nextcookie(pkt->pkt_cmd_dma, &pkt_cookie); 2154fcf3ce44SJohn Forte *cp = pkt_cookie; 2155fcf3ce44SJohn Forte } 2156*7ff83669SZhong Wang } else if (cmd_len != 0) { 2157*7ff83669SZhong Wang pkt->pkt_cmd = kmem_zalloc(cmd_len, KM_SLEEP); 2158fcf3ce44SJohn Forte } 2159fcf3ce44SJohn Forte 2160*7ff83669SZhong Wang if ((resp_len) && !(fcsm->sm_flags & FCSM_USING_NODMA_FCA)) { 2161fcf3ce44SJohn Forte ASSERT(pkt->pkt_resp_dma != NULL); 2162fcf3ce44SJohn Forte 2163fcf3ce44SJohn Forte rval = ddi_dma_mem_alloc(pkt->pkt_resp_dma, resp_len, 2164fcf3ce44SJohn Forte fcsm->sm_port_info.port_acc_attr, DDI_DMA_CONSISTENT, 2165fcf3ce44SJohn Forte callback, NULL, (caddr_t *)&pkt->pkt_resp, &real_len, 2166fcf3ce44SJohn Forte &pkt->pkt_resp_acc); 2167fcf3ce44SJohn Forte 2168fcf3ce44SJohn Forte if (rval != DDI_SUCCESS) { 2169fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2170fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2171fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2172fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2173fcf3ce44SJohn Forte return (NULL); 2174fcf3ce44SJohn Forte } 2175fcf3ce44SJohn Forte 2176fcf3ce44SJohn Forte cmd->cmd_dma_flags |= FCSM_CF_RESP_VALID_DMA_MEM; 2177fcf3ce44SJohn Forte 2178fcf3ce44SJohn Forte if (real_len < resp_len) { 2179fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2180fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2181fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2182fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2183fcf3ce44SJohn Forte return (NULL); 2184fcf3ce44SJohn Forte } 2185fcf3ce44SJohn Forte 2186fcf3ce44SJohn Forte rval = ddi_dma_addr_bind_handle(pkt->pkt_resp_dma, NULL, 2187fcf3ce44SJohn Forte pkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 2188fcf3ce44SJohn Forte callback, NULL, &pkt_cookie, &pkt->pkt_resp_cookie_cnt); 2189fcf3ce44SJohn Forte 2190fcf3ce44SJohn Forte if (rval != DDI_DMA_MAPPED) { 2191fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2192fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2193fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2194fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2195fcf3ce44SJohn Forte return (NULL); 2196fcf3ce44SJohn Forte } 2197fcf3ce44SJohn Forte 2198fcf3ce44SJohn Forte cmd->cmd_dma_flags |= FCSM_CF_RESP_VALID_DMA_BIND; 2199fcf3ce44SJohn Forte 2200fcf3ce44SJohn Forte if (pkt->pkt_resp_cookie_cnt > 2201fcf3ce44SJohn Forte pinfo->port_resp_dma_attr->dma_attr_sgllen) { 2202fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2203fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2204fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2205fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2206fcf3ce44SJohn Forte return (NULL); 2207fcf3ce44SJohn Forte } 2208fcf3ce44SJohn Forte 2209fcf3ce44SJohn Forte ASSERT(pkt->pkt_resp_cookie_cnt != 0); 2210fcf3ce44SJohn Forte 2211fcf3ce44SJohn Forte cp = pkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 2212fcf3ce44SJohn Forte pkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 2213fcf3ce44SJohn Forte KM_NOSLEEP); 2214fcf3ce44SJohn Forte 2215fcf3ce44SJohn Forte if (cp == NULL) { 2216fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet( 2217fcf3ce44SJohn Forte (opaque_t)pinfo->port_handle, pkt); 2218fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2219fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2220fcf3ce44SJohn Forte return (NULL); 2221fcf3ce44SJohn Forte } 2222fcf3ce44SJohn Forte 2223fcf3ce44SJohn Forte *cp = pkt_cookie; 2224fcf3ce44SJohn Forte cp++; 2225fcf3ce44SJohn Forte for (cnt = 1; cnt < pkt->pkt_resp_cookie_cnt; cnt++, cp++) { 2226fcf3ce44SJohn Forte ddi_dma_nextcookie(pkt->pkt_resp_dma, &pkt_cookie); 2227fcf3ce44SJohn Forte *cp = pkt_cookie; 2228fcf3ce44SJohn Forte } 2229*7ff83669SZhong Wang } else if (resp_len != 0) { 2230*7ff83669SZhong Wang pkt->pkt_resp = kmem_zalloc(resp_len, KM_SLEEP); 2231fcf3ce44SJohn Forte } 2232fcf3ce44SJohn Forte 2233fcf3ce44SJohn Forte pkt->pkt_cmdlen = cmd_len; 2234fcf3ce44SJohn Forte pkt->pkt_rsplen = resp_len; 2235fcf3ce44SJohn Forte 2236fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2237fcf3ce44SJohn Forte "alloc_cmd: cmd 0x%p", (void *)cmd)); 2238fcf3ce44SJohn Forte return (cmd); 2239fcf3ce44SJohn Forte } 2240fcf3ce44SJohn Forte 2241fcf3ce44SJohn Forte static void 2242fcf3ce44SJohn Forte fcsm_free_cmd(fcsm_cmd_t *cmd) 2243fcf3ce44SJohn Forte { 2244fcf3ce44SJohn Forte fcsm_t *fcsm; 2245fcf3ce44SJohn Forte 2246fcf3ce44SJohn Forte fcsm = cmd->cmd_fcsm; 2247fcf3ce44SJohn Forte ASSERT(fcsm != NULL); 2248fcf3ce44SJohn Forte 2249fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2250fcf3ce44SJohn Forte "free_cmd: cmd 0x%p", (void *)cmd)); 2251fcf3ce44SJohn Forte 2252fcf3ce44SJohn Forte fcsm_free_cmd_dma(cmd); 2253fcf3ce44SJohn Forte 2254fcf3ce44SJohn Forte (void) fc_ulp_uninit_packet((opaque_t)fcsm->sm_port_info.port_handle, 2255fcf3ce44SJohn Forte cmd->cmd_fp_pkt); 2256fcf3ce44SJohn Forte kmem_cache_free(fcsm->sm_cmd_cache, (void *)cmd); 2257fcf3ce44SJohn Forte } 2258fcf3ce44SJohn Forte 2259fcf3ce44SJohn Forte static void 2260fcf3ce44SJohn Forte fcsm_free_cmd_dma(fcsm_cmd_t *cmd) 2261fcf3ce44SJohn Forte { 2262fcf3ce44SJohn Forte fc_packet_t *pkt; 2263fcf3ce44SJohn Forte 2264fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 2265fcf3ce44SJohn Forte ASSERT(pkt != NULL); 2266fcf3ce44SJohn Forte 2267*7ff83669SZhong Wang if (cmd->cmd_fcsm->sm_flags & FCSM_USING_NODMA_FCA) { 2268*7ff83669SZhong Wang if (pkt->pkt_cmd) { 2269*7ff83669SZhong Wang kmem_free(pkt->pkt_cmd, pkt->pkt_cmdlen); 2270*7ff83669SZhong Wang pkt->pkt_cmd = NULL; 2271*7ff83669SZhong Wang } 2272*7ff83669SZhong Wang 2273*7ff83669SZhong Wang if (pkt->pkt_resp) { 2274*7ff83669SZhong Wang kmem_free(pkt->pkt_resp, pkt->pkt_rsplen); 2275*7ff83669SZhong Wang pkt->pkt_resp = NULL; 2276*7ff83669SZhong Wang } 2277*7ff83669SZhong Wang } 2278*7ff83669SZhong Wang 2279fcf3ce44SJohn Forte pkt->pkt_cmdlen = 0; 2280fcf3ce44SJohn Forte pkt->pkt_rsplen = 0; 2281fcf3ce44SJohn Forte pkt->pkt_tran_type = 0; 2282fcf3ce44SJohn Forte pkt->pkt_tran_flags = 0; 2283fcf3ce44SJohn Forte 2284fcf3ce44SJohn Forte if (pkt->pkt_cmd_cookie != NULL) { 2285fcf3ce44SJohn Forte kmem_free(pkt->pkt_cmd_cookie, pkt->pkt_cmd_cookie_cnt * 2286fcf3ce44SJohn Forte sizeof (ddi_dma_cookie_t)); 2287fcf3ce44SJohn Forte pkt->pkt_cmd_cookie = NULL; 2288fcf3ce44SJohn Forte } 2289fcf3ce44SJohn Forte 2290fcf3ce44SJohn Forte if (pkt->pkt_resp_cookie != NULL) { 2291fcf3ce44SJohn Forte kmem_free(pkt->pkt_resp_cookie, pkt->pkt_resp_cookie_cnt * 2292fcf3ce44SJohn Forte sizeof (ddi_dma_cookie_t)); 2293fcf3ce44SJohn Forte pkt->pkt_resp_cookie = NULL; 2294fcf3ce44SJohn Forte } 2295fcf3ce44SJohn Forte 2296fcf3ce44SJohn Forte if (cmd->cmd_dma_flags & FCSM_CF_CMD_VALID_DMA_BIND) { 2297fcf3ce44SJohn Forte (void) ddi_dma_unbind_handle(pkt->pkt_cmd_dma); 2298fcf3ce44SJohn Forte } 2299fcf3ce44SJohn Forte 2300fcf3ce44SJohn Forte if (cmd->cmd_dma_flags & FCSM_CF_CMD_VALID_DMA_MEM) { 2301fcf3ce44SJohn Forte if (pkt->pkt_cmd_acc) { 2302fcf3ce44SJohn Forte ddi_dma_mem_free(&pkt->pkt_cmd_acc); 2303fcf3ce44SJohn Forte } 2304fcf3ce44SJohn Forte } 2305fcf3ce44SJohn Forte 2306fcf3ce44SJohn Forte if (cmd->cmd_dma_flags & FCSM_CF_RESP_VALID_DMA_BIND) { 2307fcf3ce44SJohn Forte (void) ddi_dma_unbind_handle(pkt->pkt_resp_dma); 2308fcf3ce44SJohn Forte } 2309fcf3ce44SJohn Forte 2310fcf3ce44SJohn Forte if (cmd->cmd_dma_flags & FCSM_CF_RESP_VALID_DMA_MEM) { 2311fcf3ce44SJohn Forte if (pkt->pkt_resp_acc) { 2312fcf3ce44SJohn Forte ddi_dma_mem_free(&pkt->pkt_resp_acc); 2313fcf3ce44SJohn Forte } 2314fcf3ce44SJohn Forte } 2315fcf3ce44SJohn Forte 2316fcf3ce44SJohn Forte cmd->cmd_dma_flags = 0; 2317fcf3ce44SJohn Forte } 2318fcf3ce44SJohn Forte 2319fcf3ce44SJohn Forte /* ARGSUSED */ 2320fcf3ce44SJohn Forte static int 2321fcf3ce44SJohn Forte fcsm_job_cache_constructor(void *buf, void *cdarg, int kmflag) 2322fcf3ce44SJohn Forte { 2323fcf3ce44SJohn Forte fcsm_job_t *job = (fcsm_job_t *)buf; 2324fcf3ce44SJohn Forte 2325fcf3ce44SJohn Forte mutex_init(&job->job_mutex, NULL, MUTEX_DRIVER, NULL); 2326fcf3ce44SJohn Forte sema_init(&job->job_sema, 0, NULL, SEMA_DEFAULT, NULL); 2327fcf3ce44SJohn Forte 2328fcf3ce44SJohn Forte return (0); 2329fcf3ce44SJohn Forte } 2330fcf3ce44SJohn Forte 2331fcf3ce44SJohn Forte /* ARGSUSED */ 2332fcf3ce44SJohn Forte static void 2333fcf3ce44SJohn Forte fcsm_job_cache_destructor(void *buf, void *cdarg) 2334fcf3ce44SJohn Forte { 2335fcf3ce44SJohn Forte fcsm_job_t *job = (fcsm_job_t *)buf; 2336fcf3ce44SJohn Forte 2337fcf3ce44SJohn Forte sema_destroy(&job->job_sema); 2338fcf3ce44SJohn Forte mutex_destroy(&job->job_mutex); 2339fcf3ce44SJohn Forte } 2340fcf3ce44SJohn Forte 2341fcf3ce44SJohn Forte 2342fcf3ce44SJohn Forte static fcsm_job_t * 2343fcf3ce44SJohn Forte fcsm_alloc_job(int sleep) 2344fcf3ce44SJohn Forte { 2345fcf3ce44SJohn Forte fcsm_job_t *job; 2346fcf3ce44SJohn Forte 2347fcf3ce44SJohn Forte job = (fcsm_job_t *)kmem_cache_alloc(fcsm_job_cache, sleep); 2348fcf3ce44SJohn Forte if (job != NULL) { 2349fcf3ce44SJohn Forte job->job_code = FCSM_JOB_NONE; 2350fcf3ce44SJohn Forte job->job_flags = 0; 2351fcf3ce44SJohn Forte job->job_port_instance = -1; 2352fcf3ce44SJohn Forte job->job_result = -1; 2353fcf3ce44SJohn Forte job->job_arg = (opaque_t)0; 2354fcf3ce44SJohn Forte job->job_caller_priv = (opaque_t)0; 2355fcf3ce44SJohn Forte job->job_comp = NULL; 2356fcf3ce44SJohn Forte job->job_comp_arg = (opaque_t)0; 2357fcf3ce44SJohn Forte job->job_priv = (void *)0; 2358fcf3ce44SJohn Forte job->job_priv_flags = 0; 2359fcf3ce44SJohn Forte job->job_next = 0; 2360fcf3ce44SJohn Forte } 2361fcf3ce44SJohn Forte 2362fcf3ce44SJohn Forte return (job); 2363fcf3ce44SJohn Forte } 2364fcf3ce44SJohn Forte 2365fcf3ce44SJohn Forte static void 2366fcf3ce44SJohn Forte fcsm_dealloc_job(fcsm_job_t *job) 2367fcf3ce44SJohn Forte { 2368fcf3ce44SJohn Forte kmem_cache_free(fcsm_job_cache, (void *)job); 2369fcf3ce44SJohn Forte } 2370fcf3ce44SJohn Forte 2371fcf3ce44SJohn Forte 2372fcf3ce44SJohn Forte static void 2373fcf3ce44SJohn Forte fcsm_init_job(fcsm_job_t *job, int instance, uint32_t command, uint32_t flags, 2374fcf3ce44SJohn Forte opaque_t arg, opaque_t caller_priv, 2375fcf3ce44SJohn Forte void (*comp)(opaque_t, fcsm_job_t *, int), opaque_t comp_arg) 2376fcf3ce44SJohn Forte { 2377fcf3ce44SJohn Forte ASSERT(job != NULL); 2378fcf3ce44SJohn Forte job->job_port_instance = instance; 2379fcf3ce44SJohn Forte job->job_code = command; 2380fcf3ce44SJohn Forte job->job_flags = flags; 2381fcf3ce44SJohn Forte job->job_arg = arg; 2382fcf3ce44SJohn Forte job->job_caller_priv = caller_priv; 2383fcf3ce44SJohn Forte job->job_comp = comp; 2384fcf3ce44SJohn Forte job->job_comp_arg = comp_arg; 2385fcf3ce44SJohn Forte job->job_retry_count = 0; 2386fcf3ce44SJohn Forte } 2387fcf3ce44SJohn Forte 2388fcf3ce44SJohn Forte static int 2389fcf3ce44SJohn Forte fcsm_process_job(fcsm_job_t *job, int priority_flag) 2390fcf3ce44SJohn Forte { 2391fcf3ce44SJohn Forte fcsm_t *fcsm; 2392fcf3ce44SJohn Forte int sync; 2393fcf3ce44SJohn Forte 2394fcf3ce44SJohn Forte ASSERT(job != NULL); 2395fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&job->job_mutex)); 2396fcf3ce44SJohn Forte 2397fcf3ce44SJohn Forte fcsm = ddi_get_soft_state(fcsm_state, job->job_port_instance); 2398fcf3ce44SJohn Forte 2399fcf3ce44SJohn Forte if (fcsm == NULL) { 2400fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_NOTE, SM_LOG, NULL, NULL, 2401fcf3ce44SJohn Forte "process_job: port instance 0x%x not found", 2402fcf3ce44SJohn Forte job->job_port_instance)); 2403fcf3ce44SJohn Forte return (FC_BADDEV); 2404fcf3ce44SJohn Forte } 2405fcf3ce44SJohn Forte 2406fcf3ce44SJohn Forte mutex_enter(&job->job_mutex); 2407fcf3ce44SJohn Forte /* Both SYNC and ASYNC flags should not be set */ 2408fcf3ce44SJohn Forte ASSERT(((job->job_flags & (FCSM_JOBFLAG_SYNC | FCSM_JOBFLAG_ASYNC)) == 2409fcf3ce44SJohn Forte FCSM_JOBFLAG_SYNC) || ((job->job_flags & 2410fcf3ce44SJohn Forte (FCSM_JOBFLAG_SYNC | FCSM_JOBFLAG_ASYNC)) == FCSM_JOBFLAG_ASYNC)); 2411fcf3ce44SJohn Forte /* 2412fcf3ce44SJohn Forte * Check if job is a synchronous job. We might not be able to 2413fcf3ce44SJohn Forte * check it reliably after enque_job(), if job is an ASYNC job. 2414fcf3ce44SJohn Forte */ 2415fcf3ce44SJohn Forte sync = job->job_flags & FCSM_JOBFLAG_SYNC; 2416fcf3ce44SJohn Forte mutex_exit(&job->job_mutex); 2417fcf3ce44SJohn Forte 2418fcf3ce44SJohn Forte /* Queue the job for processing by job thread */ 2419fcf3ce44SJohn Forte fcsm_enque_job(fcsm, job, priority_flag); 2420fcf3ce44SJohn Forte 2421fcf3ce44SJohn Forte /* Wait for job completion, if it is a synchronous job */ 2422fcf3ce44SJohn Forte if (sync) { 2423fcf3ce44SJohn Forte /* 2424fcf3ce44SJohn Forte * This is a Synchronous Job. So job structure is available. 2425fcf3ce44SJohn Forte * Caller is responsible for freeing it. 2426fcf3ce44SJohn Forte */ 2427fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_ERR, (CE_CONT, SM_LOG, fcsm, NULL, 2428fcf3ce44SJohn Forte "process_job: Waiting for sync job <%p> completion", 2429fcf3ce44SJohn Forte (void *)job)); 2430fcf3ce44SJohn Forte sema_p(&job->job_sema); 2431fcf3ce44SJohn Forte } 2432fcf3ce44SJohn Forte 2433fcf3ce44SJohn Forte return (FC_SUCCESS); 2434fcf3ce44SJohn Forte } 2435fcf3ce44SJohn Forte 2436fcf3ce44SJohn Forte static void 2437fcf3ce44SJohn Forte fcsm_enque_job(fcsm_t *fcsm, fcsm_job_t *job, int priority_flag) 2438fcf3ce44SJohn Forte { 2439fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&fcsm->sm_mutex)); 2440fcf3ce44SJohn Forte 2441fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2442fcf3ce44SJohn Forte /* Queue the job at the head or tail depending on the job priority */ 2443fcf3ce44SJohn Forte if (priority_flag) { 2444fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_INFO, (CE_CONT, SM_LOG, fcsm, NULL, 2445fcf3ce44SJohn Forte "enque_job: job 0x%p is high priority", job)); 2446fcf3ce44SJohn Forte /* Queue at the head */ 2447fcf3ce44SJohn Forte if (fcsm->sm_job_tail == NULL) { 2448fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_head == NULL); 2449fcf3ce44SJohn Forte fcsm->sm_job_head = fcsm->sm_job_tail = job; 2450fcf3ce44SJohn Forte } else { 2451fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_head != NULL); 2452fcf3ce44SJohn Forte job->job_next = fcsm->sm_job_head; 2453fcf3ce44SJohn Forte fcsm->sm_job_head = job; 2454fcf3ce44SJohn Forte } 2455fcf3ce44SJohn Forte } else { 2456fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_INFO, (CE_CONT, SM_LOG, fcsm, NULL, 2457fcf3ce44SJohn Forte "enque_job: job 0x%p is normal", job)); 2458fcf3ce44SJohn Forte /* Queue at the tail */ 2459fcf3ce44SJohn Forte if (fcsm->sm_job_tail == NULL) { 2460fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_head == NULL); 2461fcf3ce44SJohn Forte fcsm->sm_job_head = fcsm->sm_job_tail = job; 2462fcf3ce44SJohn Forte } else { 2463fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_head != NULL); 2464fcf3ce44SJohn Forte fcsm->sm_job_tail->job_next = job; 2465fcf3ce44SJohn Forte fcsm->sm_job_tail = job; 2466fcf3ce44SJohn Forte } 2467fcf3ce44SJohn Forte job->job_next = NULL; 2468fcf3ce44SJohn Forte } 2469fcf3ce44SJohn Forte 2470fcf3ce44SJohn Forte /* Signal the job thread to process the job */ 2471fcf3ce44SJohn Forte cv_signal(&fcsm->sm_job_cv); 2472fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2473fcf3ce44SJohn Forte } 2474fcf3ce44SJohn Forte 2475fcf3ce44SJohn Forte static int 2476fcf3ce44SJohn Forte fcsm_retry_job(fcsm_t *fcsm, fcsm_job_t *job) 2477fcf3ce44SJohn Forte { 2478fcf3ce44SJohn Forte /* 2479fcf3ce44SJohn Forte * If it is a CT passthru job and status is login required, then 2480fcf3ce44SJohn Forte * retry the job so that login can be performed again. 2481fcf3ce44SJohn Forte * Ensure that this retry is performed a finite number of times, 2482fcf3ce44SJohn Forte * so that a faulty fabric does not cause us to retry forever. 2483fcf3ce44SJohn Forte */ 2484fcf3ce44SJohn Forte 2485fcf3ce44SJohn Forte switch (job->job_code) { 2486fcf3ce44SJohn Forte case FCSM_JOB_CT_PASSTHRU: { 2487fcf3ce44SJohn Forte uint32_t jobflag; 2488fcf3ce44SJohn Forte fc_ct_header_t *ct_header; 2489fcf3ce44SJohn Forte 2490fcf3ce44SJohn Forte if (job->job_result != FC_LOGINREQ) { 2491fcf3ce44SJohn Forte break; 2492fcf3ce44SJohn Forte } 2493fcf3ce44SJohn Forte 2494fcf3ce44SJohn Forte /* 2495fcf3ce44SJohn Forte * If it is a management server command 2496fcf3ce44SJohn Forte * then Reset the Management server login flag, so that login 2497fcf3ce44SJohn Forte * gets re-established. 2498fcf3ce44SJohn Forte * If it is a Name server command, 2499fcf3ce44SJohn Forte * then it is 'fp' responsibility to perform the login. 2500fcf3ce44SJohn Forte */ 2501fcf3ce44SJohn Forte ASSERT(job->job_arg != NULL); 2502fcf3ce44SJohn Forte ct_header = 2503fcf3ce44SJohn Forte (fc_ct_header_t *)((fcio_t *)job->job_arg)->fcio_ibuf; 2504fcf3ce44SJohn Forte if (ct_header->ct_fcstype == FCSTYPE_MGMTSERVICE) { 2505fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2506fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_MGMT_SERVER_LOGGED_IN; 2507fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2508fcf3ce44SJohn Forte } 2509fcf3ce44SJohn Forte 2510fcf3ce44SJohn Forte if (job->job_retry_count >= fcsm_max_job_retries) { 2511fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2512fcf3ce44SJohn Forte "retry_job: job 0x%p max retries (%d) reached", 2513fcf3ce44SJohn Forte (void *)job, job->job_retry_count)); 2514fcf3ce44SJohn Forte break; 2515fcf3ce44SJohn Forte } 2516fcf3ce44SJohn Forte 2517fcf3ce44SJohn Forte /* 2518fcf3ce44SJohn Forte * Login is required again. Retry the command, so that 2519fcf3ce44SJohn Forte * login will get performed again. 2520fcf3ce44SJohn Forte */ 2521fcf3ce44SJohn Forte mutex_enter(&job->job_mutex); 2522fcf3ce44SJohn Forte job->job_retry_count++; 2523fcf3ce44SJohn Forte jobflag = job->job_flags; 2524fcf3ce44SJohn Forte mutex_exit(&job->job_mutex); 2525fcf3ce44SJohn Forte 2526fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2527fcf3ce44SJohn Forte "retry_job: retry(%d) job 0x%p", 2528fcf3ce44SJohn Forte job->job_retry_count, (void *)job)); 2529fcf3ce44SJohn Forte /* 2530fcf3ce44SJohn Forte * This job should get picked up before the 2531fcf3ce44SJohn Forte * other jobs sitting in the queue. 2532fcf3ce44SJohn Forte * Requeue the command at the head and then 2533fcf3ce44SJohn Forte * reset the SERIALIZE flag. 2534fcf3ce44SJohn Forte */ 2535fcf3ce44SJohn Forte fcsm_enque_job(fcsm, job, 1); 2536fcf3ce44SJohn Forte if (jobflag & FCSM_JOBFLAG_SERIALIZE) { 2537fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2538fcf3ce44SJohn Forte ASSERT(fcsm->sm_flags & FCSM_SERIALIZE_JOBTHREAD); 2539fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_SERIALIZE_JOBTHREAD; 2540fcf3ce44SJohn Forte 2541fcf3ce44SJohn Forte /* Signal the job thread to process the job */ 2542fcf3ce44SJohn Forte cv_signal(&fcsm->sm_job_cv); 2543fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2544fcf3ce44SJohn Forte } 2545fcf3ce44SJohn Forte 2546fcf3ce44SJohn Forte /* Command is queued for retrying */ 2547fcf3ce44SJohn Forte return (0); 2548fcf3ce44SJohn Forte } 2549fcf3ce44SJohn Forte 2550fcf3ce44SJohn Forte default: 2551fcf3ce44SJohn Forte break; 2552fcf3ce44SJohn Forte } 2553fcf3ce44SJohn Forte return (1); 2554fcf3ce44SJohn Forte } 2555fcf3ce44SJohn Forte 2556fcf3ce44SJohn Forte static void 2557fcf3ce44SJohn Forte fcsm_jobdone(fcsm_job_t *job) 2558fcf3ce44SJohn Forte { 2559fcf3ce44SJohn Forte fcsm_t *fcsm; 2560fcf3ce44SJohn Forte 2561fcf3ce44SJohn Forte fcsm = ddi_get_soft_state(fcsm_state, job->job_port_instance); 2562fcf3ce44SJohn Forte ASSERT(fcsm != NULL); 2563fcf3ce44SJohn Forte 2564fcf3ce44SJohn Forte if (job->job_result != FC_SUCCESS) { 2565fcf3ce44SJohn Forte if (fcsm_retry_job(fcsm, job) == 0) { 2566fcf3ce44SJohn Forte /* Job retried. so just return from here */ 2567fcf3ce44SJohn Forte return; 2568fcf3ce44SJohn Forte } 2569fcf3ce44SJohn Forte } 2570fcf3ce44SJohn Forte 2571fcf3ce44SJohn Forte if (job->job_comp) { 2572fcf3ce44SJohn Forte job->job_comp(job->job_comp_arg, job, job->job_result); 2573fcf3ce44SJohn Forte } 2574fcf3ce44SJohn Forte 2575fcf3ce44SJohn Forte mutex_enter(&job->job_mutex); 2576fcf3ce44SJohn Forte if (job->job_flags & FCSM_JOBFLAG_SERIALIZE) { 2577fcf3ce44SJohn Forte mutex_exit(&job->job_mutex); 2578fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2579fcf3ce44SJohn Forte ASSERT(fcsm->sm_flags & FCSM_SERIALIZE_JOBTHREAD); 2580fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_SERIALIZE_JOBTHREAD; 2581fcf3ce44SJohn Forte 2582fcf3ce44SJohn Forte /* Signal the job thread to process the job */ 2583fcf3ce44SJohn Forte cv_signal(&fcsm->sm_job_cv); 2584fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2585fcf3ce44SJohn Forte mutex_enter(&job->job_mutex); 2586fcf3ce44SJohn Forte } 2587fcf3ce44SJohn Forte 2588fcf3ce44SJohn Forte if (job->job_flags & FCSM_JOBFLAG_SYNC) { 2589fcf3ce44SJohn Forte mutex_exit(&job->job_mutex); 2590fcf3ce44SJohn Forte sema_v(&job->job_sema); 2591fcf3ce44SJohn Forte } else { 2592fcf3ce44SJohn Forte mutex_exit(&job->job_mutex); 2593fcf3ce44SJohn Forte /* Async job, free the job structure */ 2594fcf3ce44SJohn Forte fcsm_dealloc_job(job); 2595fcf3ce44SJohn Forte } 2596fcf3ce44SJohn Forte } 2597fcf3ce44SJohn Forte 2598fcf3ce44SJohn Forte fcsm_job_t * 2599fcf3ce44SJohn Forte fcsm_deque_job(fcsm_t *fcsm) 2600fcf3ce44SJohn Forte { 2601fcf3ce44SJohn Forte fcsm_job_t *job; 2602fcf3ce44SJohn Forte 2603fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&fcsm->sm_mutex)); 2604fcf3ce44SJohn Forte 2605fcf3ce44SJohn Forte if (fcsm->sm_job_head == NULL) { 2606fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_tail == NULL); 2607fcf3ce44SJohn Forte job = NULL; 2608fcf3ce44SJohn Forte } else { 2609fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_tail != NULL); 2610fcf3ce44SJohn Forte job = fcsm->sm_job_head; 2611fcf3ce44SJohn Forte if (job->job_next == NULL) { 2612fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_tail == job); 2613fcf3ce44SJohn Forte fcsm->sm_job_tail = NULL; 2614fcf3ce44SJohn Forte } 2615fcf3ce44SJohn Forte fcsm->sm_job_head = job->job_next; 2616fcf3ce44SJohn Forte job->job_next = NULL; 2617fcf3ce44SJohn Forte } 2618fcf3ce44SJohn Forte 2619fcf3ce44SJohn Forte return (job); 2620fcf3ce44SJohn Forte } 2621fcf3ce44SJohn Forte 2622fcf3ce44SJohn Forte 2623fcf3ce44SJohn Forte /* Dedicated per port thread to process various commands */ 2624fcf3ce44SJohn Forte static void 2625fcf3ce44SJohn Forte fcsm_job_thread(fcsm_t *fcsm) 2626fcf3ce44SJohn Forte { 2627fcf3ce44SJohn Forte fcsm_job_t *job; 2628fcf3ce44SJohn Forte 2629fcf3ce44SJohn Forte ASSERT(fcsm != NULL); 2630fcf3ce44SJohn Forte #ifndef __lock_lint 2631fcf3ce44SJohn Forte CALLB_CPR_INIT(&fcsm->sm_cpr_info, &fcsm->sm_mutex, 2632fcf3ce44SJohn Forte callb_generic_cpr, "fcsm_job_thread"); 2633fcf3ce44SJohn Forte #endif /* __lock_lint */ 2634fcf3ce44SJohn Forte 2635fcf3ce44SJohn Forte for (;;) { 2636fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2637fcf3ce44SJohn Forte 2638fcf3ce44SJohn Forte while (fcsm->sm_job_head == NULL || 2639fcf3ce44SJohn Forte fcsm->sm_flags & FCSM_SERIALIZE_JOBTHREAD) { 2640fcf3ce44SJohn Forte CALLB_CPR_SAFE_BEGIN(&fcsm->sm_cpr_info); 2641fcf3ce44SJohn Forte cv_wait(&fcsm->sm_job_cv, &fcsm->sm_mutex); 2642fcf3ce44SJohn Forte CALLB_CPR_SAFE_END(&fcsm->sm_cpr_info, &fcsm->sm_mutex); 2643fcf3ce44SJohn Forte } 2644fcf3ce44SJohn Forte 2645fcf3ce44SJohn Forte job = fcsm_deque_job(fcsm); 2646fcf3ce44SJohn Forte 2647fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2648fcf3ce44SJohn Forte 2649fcf3ce44SJohn Forte mutex_enter(&job->job_mutex); 2650fcf3ce44SJohn Forte if (job->job_flags & FCSM_JOBFLAG_SERIALIZE) { 2651fcf3ce44SJohn Forte mutex_exit(&job->job_mutex); 2652fcf3ce44SJohn Forte 2653fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2654fcf3ce44SJohn Forte ASSERT(!(fcsm->sm_flags & FCSM_SERIALIZE_JOBTHREAD)); 2655fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_SERIALIZE_JOBTHREAD; 2656fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2657fcf3ce44SJohn Forte } else { 2658fcf3ce44SJohn Forte mutex_exit(&job->job_mutex); 2659fcf3ce44SJohn Forte } 2660fcf3ce44SJohn Forte 2661fcf3ce44SJohn Forte ASSERT(fcsm->sm_instance == job->job_port_instance); 2662fcf3ce44SJohn Forte 2663fcf3ce44SJohn Forte switch (job->job_code) { 2664fcf3ce44SJohn Forte case FCSM_JOB_NONE: 2665fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, fcsm, NULL, 2666fcf3ce44SJohn Forte "job_thread: uninitialized job code"); 2667fcf3ce44SJohn Forte job->job_result = FC_FAILURE; 2668fcf3ce44SJohn Forte fcsm_jobdone(job); 2669fcf3ce44SJohn Forte break; 2670fcf3ce44SJohn Forte 2671fcf3ce44SJohn Forte case FCSM_JOB_THREAD_SHUTDOWN: 2672fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2673fcf3ce44SJohn Forte "job_thread: job code <JOB PORT SHUTDOWN>")); 2674fcf3ce44SJohn Forte 2675fcf3ce44SJohn Forte /* 2676fcf3ce44SJohn Forte * There should not be any pending jobs, when this 2677fcf3ce44SJohn Forte * is being called. 2678fcf3ce44SJohn Forte */ 2679fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2680fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_head == NULL); 2681fcf3ce44SJohn Forte ASSERT(fcsm->sm_job_tail == NULL); 2682fcf3ce44SJohn Forte ASSERT(fcsm->sm_retry_head == NULL); 2683fcf3ce44SJohn Forte ASSERT(fcsm->sm_retry_tail == NULL); 2684fcf3ce44SJohn Forte job->job_result = FC_SUCCESS; 2685fcf3ce44SJohn Forte #ifndef __lock_lint 2686fcf3ce44SJohn Forte CALLB_CPR_EXIT(&fcsm->sm_cpr_info); 2687fcf3ce44SJohn Forte #endif 2688fcf3ce44SJohn Forte /* CPR_EXIT has also dropped the fcsm->sm_mutex */ 2689fcf3ce44SJohn Forte 2690fcf3ce44SJohn Forte fcsm_jobdone(job); 2691fcf3ce44SJohn Forte thread_exit(); 2692fcf3ce44SJohn Forte /* NOTREACHED */ 2693fcf3ce44SJohn Forte break; 2694fcf3ce44SJohn Forte 2695fcf3ce44SJohn Forte case FCSM_JOB_LOGIN_NAME_SERVER: 2696fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2697fcf3ce44SJohn Forte "job_thread: job code <LOGIN_NAME_SERVER>")); 2698fcf3ce44SJohn Forte job->job_result = FC_SUCCESS; 2699fcf3ce44SJohn Forte fcsm_jobdone(job); 2700fcf3ce44SJohn Forte break; 2701fcf3ce44SJohn Forte 2702fcf3ce44SJohn Forte case FCSM_JOB_LOGIN_MGMT_SERVER: 2703fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2704fcf3ce44SJohn Forte "job_thread: job code <LOGIN_MGMT_SERVER>")); 2705fcf3ce44SJohn Forte fcsm_job_login_mgmt_server(job); 2706fcf3ce44SJohn Forte break; 2707fcf3ce44SJohn Forte 2708fcf3ce44SJohn Forte case FCSM_JOB_CT_PASSTHRU: 2709fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2710fcf3ce44SJohn Forte "job_thread: job code <CT_PASSTHRU>")); 2711fcf3ce44SJohn Forte fcsm_job_ct_passthru(job); 2712fcf3ce44SJohn Forte break; 2713fcf3ce44SJohn Forte 2714fcf3ce44SJohn Forte default: 2715fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2716fcf3ce44SJohn Forte "job_thread: job code <UNKNOWN>")); 2717fcf3ce44SJohn Forte job->job_result = FC_FAILURE; 2718fcf3ce44SJohn Forte fcsm_jobdone(job); 2719fcf3ce44SJohn Forte break; 2720fcf3ce44SJohn Forte } 2721fcf3ce44SJohn Forte } 2722fcf3ce44SJohn Forte 2723fcf3ce44SJohn Forte /* NOTREACHED */ 2724fcf3ce44SJohn Forte } 2725fcf3ce44SJohn Forte 2726fcf3ce44SJohn Forte 2727fcf3ce44SJohn Forte static void 2728fcf3ce44SJohn Forte fcsm_ct_init(fcsm_t *fcsm, fcsm_cmd_t *cmd, fc_ct_aiu_t *req_iu, size_t req_len, 2729fcf3ce44SJohn Forte void (*comp_func)()) 2730fcf3ce44SJohn Forte { 2731fcf3ce44SJohn Forte fc_packet_t *pkt; 2732fcf3ce44SJohn Forte 2733fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 2734fcf3ce44SJohn Forte ASSERT(pkt != NULL); 2735fcf3ce44SJohn Forte 2736fcf3ce44SJohn Forte ASSERT(req_iu->aiu_header.ct_fcstype == FCSTYPE_MGMTSERVICE || 2737fcf3ce44SJohn Forte (req_iu->aiu_header.ct_fcstype == FCSTYPE_DIRECTORY && 2738fcf3ce44SJohn Forte req_iu->aiu_header.ct_fcssubtype == FCSSUB_DS_NAME_SERVER)); 2739fcf3ce44SJohn Forte 2740fcf3ce44SJohn Forte 2741fcf3ce44SJohn Forte /* Set the pkt d_id properly */ 2742fcf3ce44SJohn Forte if (req_iu->aiu_header.ct_fcstype == FCSTYPE_MGMTSERVICE) { 2743fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.d_id = FS_MANAGEMENT_SERVER; 2744fcf3ce44SJohn Forte } else { 2745fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.d_id = FS_NAME_SERVER; 2746fcf3ce44SJohn Forte } 2747fcf3ce44SJohn Forte 2748fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL; 2749fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.rsvd = 0; 2750fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.s_id = fcsm->sm_sid; 2751fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES; 2752fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.f_ctl = F_CTL_SEQ_INITIATIVE | 2753fcf3ce44SJohn Forte F_CTL_FIRST_SEQ | F_CTL_END_SEQ; 2754fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.seq_id = 0; 2755fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.df_ctl = 0; 2756fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.seq_cnt = 0; 2757fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.ox_id = 0xffff; 2758fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.rx_id = 0xffff; 2759fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.ro = 0; 2760fcf3ce44SJohn Forte 2761fcf3ce44SJohn Forte pkt->pkt_timeout = FCSM_MS_TIMEOUT; 2762fcf3ce44SJohn Forte pkt->pkt_comp = comp_func; 2763fcf3ce44SJohn Forte 2764fcf3ce44SJohn Forte FCSM_REP_WR(pkt->pkt_cmd_acc, req_iu, pkt->pkt_cmd, req_len); 2765fcf3ce44SJohn Forte 2766fcf3ce44SJohn Forte cmd->cmd_transport = fc_ulp_transport; 2767fcf3ce44SJohn Forte } 2768fcf3ce44SJohn Forte 2769fcf3ce44SJohn Forte static void 2770fcf3ce44SJohn Forte fcsm_ct_intr(fcsm_cmd_t *cmd) 2771fcf3ce44SJohn Forte { 2772fcf3ce44SJohn Forte fc_packet_t *pkt; 2773fcf3ce44SJohn Forte fcsm_job_t *job; 2774fcf3ce44SJohn Forte fcio_t *fcio; 2775*7ff83669SZhong Wang fcsm_t *fcsm; 2776fcf3ce44SJohn Forte 2777fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 2778fcf3ce44SJohn Forte job = cmd->cmd_job; 2779fcf3ce44SJohn Forte ASSERT(job != NULL); 2780fcf3ce44SJohn Forte 2781fcf3ce44SJohn Forte fcio = job->job_arg; 2782fcf3ce44SJohn Forte ASSERT(fcio != NULL); 2783fcf3ce44SJohn Forte 2784fcf3ce44SJohn Forte if (pkt->pkt_state != FC_PKT_SUCCESS) { 278540b706cfSMilan Jurik FCSM_DEBUG(SMDL_ERR, (CE_NOTE, SM_LOG, cmd->cmd_fcsm, pkt, 2786fcf3ce44SJohn Forte "ct_intr: CT command <0x%x> to did 0x%x failed", 2787fcf3ce44SJohn Forte ((fc_ct_aiu_t *)fcio->fcio_ibuf)->aiu_header.ct_cmdrsp, 278840b706cfSMilan Jurik pkt->pkt_cmd_fhdr.d_id)); 2789fcf3ce44SJohn Forte } else { 2790fcf3ce44SJohn Forte /* Get the CT response payload */ 2791*7ff83669SZhong Wang fcsm = cmd->cmd_fcsm; 2792fcf3ce44SJohn Forte FCSM_REP_RD(pkt->pkt_resp_acc, fcio->fcio_obuf, 2793fcf3ce44SJohn Forte pkt->pkt_resp, fcio->fcio_olen); 2794fcf3ce44SJohn Forte } 2795fcf3ce44SJohn Forte 2796fcf3ce44SJohn Forte job->job_result = 2797fcf3ce44SJohn Forte fcsm_pkt_state_to_rval(pkt->pkt_state, pkt->pkt_reason); 2798fcf3ce44SJohn Forte 2799fcf3ce44SJohn Forte fcsm_free_cmd(cmd); 2800fcf3ce44SJohn Forte 2801fcf3ce44SJohn Forte fcsm_jobdone(job); 2802fcf3ce44SJohn Forte } 2803fcf3ce44SJohn Forte 2804fcf3ce44SJohn Forte 2805fcf3ce44SJohn Forte static void 2806fcf3ce44SJohn Forte fcsm_job_ct_passthru(fcsm_job_t *job) 2807fcf3ce44SJohn Forte { 2808fcf3ce44SJohn Forte fcsm_t *fcsm; 2809fcf3ce44SJohn Forte fcio_t *fcio; 2810fcf3ce44SJohn Forte fcsm_cmd_t *cmd; 2811fcf3ce44SJohn Forte int status; 2812fcf3ce44SJohn Forte fc_ct_header_t *ct_header; 2813fcf3ce44SJohn Forte 2814fcf3ce44SJohn Forte ASSERT(job != NULL); 2815fcf3ce44SJohn Forte ASSERT(job->job_port_instance != -1); 2816fcf3ce44SJohn Forte 2817fcf3ce44SJohn Forte job->job_result = FC_FAILURE; 2818fcf3ce44SJohn Forte fcsm = ddi_get_soft_state(fcsm_state, job->job_port_instance); 2819fcf3ce44SJohn Forte if (fcsm == NULL) { 2820fcf3ce44SJohn Forte fcsm_jobdone(job); 2821fcf3ce44SJohn Forte return; 2822fcf3ce44SJohn Forte } 2823fcf3ce44SJohn Forte 2824fcf3ce44SJohn Forte /* 2825fcf3ce44SJohn Forte * Process the CT Passthru job only if port is attached 2826fcf3ce44SJohn Forte * to a FABRIC. 2827fcf3ce44SJohn Forte */ 2828fcf3ce44SJohn Forte if (!FC_TOP_EXTERNAL(fcsm->sm_port_top)) { 2829fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2830fcf3ce44SJohn Forte "job_ct_passthru: end (non-fabric port)")); 2831fcf3ce44SJohn Forte job->job_result = FC_BADDEV; 2832fcf3ce44SJohn Forte fcsm_jobdone(job); 2833fcf3ce44SJohn Forte return; 2834fcf3ce44SJohn Forte } 2835fcf3ce44SJohn Forte 2836fcf3ce44SJohn Forte fcio = job->job_arg; 2837fcf3ce44SJohn Forte ASSERT(fcio != NULL); 2838fcf3ce44SJohn Forte 2839fcf3ce44SJohn Forte /* 2840fcf3ce44SJohn Forte * If it is NOT a Management Seriver (MS) or Name Server (NS) command 2841fcf3ce44SJohn Forte * then complete the command with failure. 2842fcf3ce44SJohn Forte */ 2843fcf3ce44SJohn Forte ct_header = (fc_ct_header_t *)fcio->fcio_ibuf; 2844fcf3ce44SJohn Forte 2845fcf3ce44SJohn Forte /* 2846fcf3ce44SJohn Forte * According to libHBAAPI spec, CT header from libHBAAPI would always 2847fcf3ce44SJohn Forte * be big endian, so we must swap CT header before continue in little 2848fcf3ce44SJohn Forte * endian platforms. 2849fcf3ce44SJohn Forte */ 2850fcf3ce44SJohn Forte mutex_enter(&job->job_mutex); 2851fcf3ce44SJohn Forte if (!(job->job_flags & FCSM_JOBFLAG_CTHEADER_BE)) { 2852fcf3ce44SJohn Forte job->job_flags |= FCSM_JOBFLAG_CTHEADER_BE; 2853fcf3ce44SJohn Forte *((uint32_t *)((uint32_t *)ct_header + 0)) = 2854fcf3ce44SJohn Forte BE_32(*((uint32_t *)((uint32_t *)ct_header + 0))); 2855fcf3ce44SJohn Forte *((uint32_t *)((uint32_t *)ct_header + 1)) = 2856fcf3ce44SJohn Forte BE_32(*((uint32_t *)((uint32_t *)ct_header + 1))); 2857fcf3ce44SJohn Forte *((uint32_t *)((uint32_t *)ct_header + 2)) = 2858fcf3ce44SJohn Forte BE_32(*((uint32_t *)((uint32_t *)ct_header + 2))); 2859fcf3ce44SJohn Forte *((uint32_t *)((uint32_t *)ct_header + 3)) = 2860fcf3ce44SJohn Forte BE_32(*((uint32_t *)((uint32_t *)ct_header + 3))); 2861fcf3ce44SJohn Forte } 2862fcf3ce44SJohn Forte mutex_exit(&job->job_mutex); 2863fcf3ce44SJohn Forte 2864fcf3ce44SJohn Forte if (ct_header->ct_fcstype == FCSTYPE_MGMTSERVICE) { 2865fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2866fcf3ce44SJohn Forte "job_ct_passthru: Management Server Cmd")); 2867fcf3ce44SJohn Forte } else if (ct_header->ct_fcstype == FCSTYPE_DIRECTORY) { 2868fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2869fcf3ce44SJohn Forte "job_ct_passthru: Name Server Cmd")); 2870fcf3ce44SJohn Forte } else { 2871fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2872fcf3ce44SJohn Forte "job_ct_passthru: Unsupported Destination " 2873fcf3ce44SJohn Forte "gs_type <0x%x> gs_subtype <0x%x>", 2874fcf3ce44SJohn Forte ct_header->ct_fcstype, ct_header->ct_fcssubtype)); 2875fcf3ce44SJohn Forte } 2876fcf3ce44SJohn Forte 2877fcf3ce44SJohn Forte if (ct_header->ct_fcstype != FCSTYPE_MGMTSERVICE && 2878fcf3ce44SJohn Forte (ct_header->ct_fcstype != FCSTYPE_DIRECTORY || 2879fcf3ce44SJohn Forte ct_header->ct_fcssubtype != FCSSUB_DS_NAME_SERVER)) { 2880fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2881fcf3ce44SJohn Forte "job_ct_passthru: end (Not a Name Server OR " 2882fcf3ce44SJohn Forte "Mgmt Server Cmd)")); 2883fcf3ce44SJohn Forte job->job_result = FC_BADCMD; 2884fcf3ce44SJohn Forte fcsm_jobdone(job); 2885fcf3ce44SJohn Forte return; 2886fcf3ce44SJohn Forte } 2887fcf3ce44SJohn Forte 2888fcf3ce44SJohn Forte /* 2889fcf3ce44SJohn Forte * If it is an MS command and we are not logged in to the management 2890fcf3ce44SJohn Forte * server, then start the login and requeue the command. 2891fcf3ce44SJohn Forte * If login to management server is in progress, then reque the 2892fcf3ce44SJohn Forte * command to wait for login to complete. 2893fcf3ce44SJohn Forte */ 2894fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2895fcf3ce44SJohn Forte if ((ct_header->ct_fcstype == FCSTYPE_MGMTSERVICE) && 2896fcf3ce44SJohn Forte !(fcsm->sm_flags & FCSM_MGMT_SERVER_LOGGED_IN)) { 2897fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2898fcf3ce44SJohn Forte if (fcsm_login_and_process_job(fcsm, job) != FC_SUCCESS) { 2899fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2900fcf3ce44SJohn Forte "job_ct_passthru: perform login failed")); 2901fcf3ce44SJohn Forte job->job_result = FC_FAILURE; 2902fcf3ce44SJohn Forte fcsm_jobdone(job); 2903fcf3ce44SJohn Forte } 2904fcf3ce44SJohn Forte return; 2905fcf3ce44SJohn Forte } 2906fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2907fcf3ce44SJohn Forte 2908fcf3ce44SJohn Forte /* 2909fcf3ce44SJohn Forte * We are already logged in to the management server. 2910fcf3ce44SJohn Forte * Issue the CT Passthru command 2911fcf3ce44SJohn Forte */ 2912fcf3ce44SJohn Forte cmd = fcsm_alloc_cmd(fcsm, fcio->fcio_ilen, fcio->fcio_olen, KM_SLEEP); 2913fcf3ce44SJohn Forte if (cmd == NULL) { 2914fcf3ce44SJohn Forte job->job_result = FC_NOMEM; 2915fcf3ce44SJohn Forte fcsm_jobdone(job); 2916fcf3ce44SJohn Forte return; 2917fcf3ce44SJohn Forte } 2918fcf3ce44SJohn Forte 2919fcf3ce44SJohn Forte FCSM_INIT_CMD(cmd, job, FC_TRAN_INTR | FC_TRAN_CLASS3, FC_PKT_EXCHANGE, 2920fcf3ce44SJohn Forte fcsm_max_cmd_retries, fcsm_ct_intr); 2921fcf3ce44SJohn Forte 2922fcf3ce44SJohn Forte fcsm_ct_init(fcsm, cmd, (fc_ct_aiu_t *)fcio->fcio_ibuf, fcio->fcio_ilen, 2923fcf3ce44SJohn Forte fcsm_pkt_common_intr); 2924fcf3ce44SJohn Forte 2925fcf3ce44SJohn Forte if ((status = fcsm_issue_cmd(cmd)) != FC_SUCCESS) { 2926fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, cmd->cmd_fcsm, NULL, 2927fcf3ce44SJohn Forte "job_ct_passthru: issue CT Passthru failed, status 0x%x", 2928fcf3ce44SJohn Forte status)); 2929fcf3ce44SJohn Forte job->job_result = status; 2930fcf3ce44SJohn Forte fcsm_free_cmd(cmd); 2931fcf3ce44SJohn Forte fcsm_jobdone(job); 2932fcf3ce44SJohn Forte return; 2933fcf3ce44SJohn Forte } 2934fcf3ce44SJohn Forte } 2935fcf3ce44SJohn Forte 2936fcf3ce44SJohn Forte static int 2937fcf3ce44SJohn Forte fcsm_login_and_process_job(fcsm_t *fcsm, fcsm_job_t *orig_job) 2938fcf3ce44SJohn Forte { 2939fcf3ce44SJohn Forte fcsm_job_t *login_job; 2940fcf3ce44SJohn Forte #ifdef DEBUG 2941fcf3ce44SJohn Forte int status; 2942fcf3ce44SJohn Forte #endif /* DEBUG */ 2943fcf3ce44SJohn Forte 2944fcf3ce44SJohn Forte if (orig_job->job_code != FCSM_JOB_CT_PASSTHRU) { 2945fcf3ce44SJohn Forte return (FC_FAILURE); 2946fcf3ce44SJohn Forte } 2947fcf3ce44SJohn Forte 2948fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 2949fcf3ce44SJohn Forte "login_and_process_job: start login.")); 2950fcf3ce44SJohn Forte 2951fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 2952fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_MGMT_SERVER_LOGGED_IN) { 2953fcf3ce44SJohn Forte /* 2954fcf3ce44SJohn Forte * Directory server login completed just now, while the 2955fcf3ce44SJohn Forte * mutex was dropped. Just queue the command again for 2956fcf3ce44SJohn Forte * processing. 2957fcf3ce44SJohn Forte */ 2958fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2959fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2960fcf3ce44SJohn Forte "login_and_process_job: got job 0x%p. login just " 2961fcf3ce44SJohn Forte "completed", (void *)orig_job)); 2962fcf3ce44SJohn Forte fcsm_enque_job(fcsm, orig_job, 0); 2963fcf3ce44SJohn Forte return (FC_SUCCESS); 2964fcf3ce44SJohn Forte } 2965fcf3ce44SJohn Forte 2966fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_MGMT_SERVER_LOGIN_IN_PROG) { 2967fcf3ce44SJohn Forte /* 2968fcf3ce44SJohn Forte * Ideally we shouldn't have come here, since login 2969fcf3ce44SJohn Forte * job has the serialize flag set. 2970fcf3ce44SJohn Forte * Anyway, put the command back on the queue. 2971fcf3ce44SJohn Forte */ 2972fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2973fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 2974fcf3ce44SJohn Forte "login_and_process_job: got job 0x%p while login to " 2975fcf3ce44SJohn Forte "management server in progress", (void *)orig_job)); 2976fcf3ce44SJohn Forte fcsm_enque_job(fcsm, orig_job, 0); 2977fcf3ce44SJohn Forte return (FC_SUCCESS); 2978fcf3ce44SJohn Forte } 2979fcf3ce44SJohn Forte 2980fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_MGMT_SERVER_LOGIN_IN_PROG; 2981fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 2982fcf3ce44SJohn Forte 2983fcf3ce44SJohn Forte login_job = fcsm_alloc_job(KM_SLEEP); 2984fcf3ce44SJohn Forte ASSERT(login_job != NULL); 2985fcf3ce44SJohn Forte 2986fcf3ce44SJohn Forte /* 2987fcf3ce44SJohn Forte * Mark the login job as SERIALIZE, so that all other jobs will 2988fcf3ce44SJohn Forte * be processed after completing the login. 2989fcf3ce44SJohn Forte * Save the original job (CT Passthru job) in the caller private 2990fcf3ce44SJohn Forte * field in the job structure, so that CT command can be issued 2991fcf3ce44SJohn Forte * after login has completed. 2992fcf3ce44SJohn Forte */ 2993fcf3ce44SJohn Forte fcsm_init_job(login_job, fcsm->sm_instance, FCSM_JOB_LOGIN_MGMT_SERVER, 2994fcf3ce44SJohn Forte FCSM_JOBFLAG_ASYNC | FCSM_JOBFLAG_SERIALIZE, 2995fcf3ce44SJohn Forte (opaque_t)NULL, (opaque_t)orig_job, fcsm_login_ms_comp, NULL); 2996fcf3ce44SJohn Forte orig_job->job_priv = (void *)login_job; 2997fcf3ce44SJohn Forte 2998fcf3ce44SJohn Forte #ifdef DEBUG 2999fcf3ce44SJohn Forte status = fcsm_process_job(login_job, 1); 3000fcf3ce44SJohn Forte ASSERT(status == FC_SUCCESS); 3001fcf3ce44SJohn Forte #else /* DEBUG */ 3002fcf3ce44SJohn Forte (void) fcsm_process_job(login_job, 1); 3003fcf3ce44SJohn Forte #endif /* DEBUG */ 3004fcf3ce44SJohn Forte return (FC_SUCCESS); 3005fcf3ce44SJohn Forte } 3006fcf3ce44SJohn Forte 3007fcf3ce44SJohn Forte 3008fcf3ce44SJohn Forte /* ARGSUSED */ 3009fcf3ce44SJohn Forte static void 3010fcf3ce44SJohn Forte fcsm_login_ms_comp(opaque_t comp_arg, fcsm_job_t *login_job, int result) 3011fcf3ce44SJohn Forte { 3012fcf3ce44SJohn Forte fcsm_t *fcsm; 3013fcf3ce44SJohn Forte fcsm_job_t *orig_job; 3014fcf3ce44SJohn Forte 3015fcf3ce44SJohn Forte ASSERT(login_job != NULL); 3016fcf3ce44SJohn Forte 3017fcf3ce44SJohn Forte orig_job = (fcsm_job_t *)login_job->job_caller_priv; 3018fcf3ce44SJohn Forte 3019fcf3ce44SJohn Forte ASSERT(orig_job != NULL); 3020fcf3ce44SJohn Forte ASSERT(orig_job->job_priv == (void *)login_job); 3021fcf3ce44SJohn Forte orig_job->job_priv = NULL; 3022fcf3ce44SJohn Forte 3023fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 3024fcf3ce44SJohn Forte "login_ms_comp: result 0x%x", login_job->job_result)); 3025fcf3ce44SJohn Forte 3026fcf3ce44SJohn Forte /* Set the login flag in the per port fcsm structure */ 3027fcf3ce44SJohn Forte ASSERT(login_job->job_port_instance == orig_job->job_port_instance); 3028fcf3ce44SJohn Forte fcsm = ddi_get_soft_state(fcsm_state, login_job->job_port_instance); 3029fcf3ce44SJohn Forte ASSERT(fcsm != NULL); 3030fcf3ce44SJohn Forte 3031fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 3032fcf3ce44SJohn Forte ASSERT((fcsm->sm_flags & FCSM_MGMT_SERVER_LOGGED_IN) == 0); 3033fcf3ce44SJohn Forte ASSERT(fcsm->sm_flags & FCSM_MGMT_SERVER_LOGIN_IN_PROG); 3034fcf3ce44SJohn Forte fcsm->sm_flags &= ~FCSM_MGMT_SERVER_LOGIN_IN_PROG; 3035fcf3ce44SJohn Forte if (login_job->job_result != FC_SUCCESS) { 3036fcf3ce44SJohn Forte caddr_t msg; 3037fcf3ce44SJohn Forte 3038fcf3ce44SJohn Forte /* 3039fcf3ce44SJohn Forte * Login failed. Complete the original job with FC_LOGINREQ 3040fcf3ce44SJohn Forte * status. Retry of that job will cause login to be 3041fcf3ce44SJohn Forte * retried. 3042fcf3ce44SJohn Forte */ 3043fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3044fcf3ce44SJohn Forte orig_job->job_result = FC_LOGINREQ; 3045fcf3ce44SJohn Forte fcsm_jobdone(orig_job); 3046fcf3ce44SJohn Forte 3047fcf3ce44SJohn Forte (void) fc_ulp_error(login_job->job_result, &msg); 3048fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, fcsm, NULL, 3049fcf3ce44SJohn Forte "login_ms_comp: Management server login failed: <%s>", msg); 3050fcf3ce44SJohn Forte return; 3051fcf3ce44SJohn Forte } 3052fcf3ce44SJohn Forte fcsm->sm_flags |= FCSM_MGMT_SERVER_LOGGED_IN; 3053fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3054fcf3ce44SJohn Forte 3055fcf3ce44SJohn Forte /* 3056fcf3ce44SJohn Forte * Queue the original job at the head of the queue for processing. 3057fcf3ce44SJohn Forte */ 3058fcf3ce44SJohn Forte fcsm_enque_job(fcsm, orig_job, 1); 3059fcf3ce44SJohn Forte } 3060fcf3ce44SJohn Forte 3061fcf3ce44SJohn Forte 3062fcf3ce44SJohn Forte static void 3063fcf3ce44SJohn Forte fcsm_els_init(fcsm_cmd_t *cmd, uint32_t d_id) 3064fcf3ce44SJohn Forte { 3065fcf3ce44SJohn Forte fc_packet_t *pkt; 3066fcf3ce44SJohn Forte fcsm_t *fcsm; 3067fcf3ce44SJohn Forte 3068fcf3ce44SJohn Forte fcsm = cmd->cmd_fcsm; 3069fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 3070fcf3ce44SJohn Forte ASSERT(fcsm != NULL && pkt != NULL); 3071fcf3ce44SJohn Forte 3072fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ; 3073fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.d_id = d_id; 3074fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.rsvd = 0; 3075fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.s_id = fcsm->sm_sid; 3076fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 3077fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3078fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.seq_id = 0; 3079fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.df_ctl = 0; 3080fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.seq_cnt = 0; 3081fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.ox_id = 0xffff; 3082fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.rx_id = 0xffff; 3083fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.ro = 0; 3084fcf3ce44SJohn Forte 3085fcf3ce44SJohn Forte pkt->pkt_timeout = FCSM_ELS_TIMEOUT; 3086fcf3ce44SJohn Forte } 3087fcf3ce44SJohn Forte 3088fcf3ce44SJohn Forte 3089fcf3ce44SJohn Forte static int 3090fcf3ce44SJohn Forte fcsm_xlogi_init(fcsm_t *fcsm, fcsm_cmd_t *cmd, uint32_t d_id, 3091fcf3ce44SJohn Forte void (*comp_func)(), uchar_t ls_code) 3092fcf3ce44SJohn Forte { 3093fcf3ce44SJohn Forte ls_code_t payload; 3094fcf3ce44SJohn Forte fc_packet_t *pkt; 3095fcf3ce44SJohn Forte la_els_logi_t *login_params; 3096fcf3ce44SJohn Forte int status; 3097fcf3ce44SJohn Forte 3098fcf3ce44SJohn Forte login_params = (la_els_logi_t *) 3099fcf3ce44SJohn Forte kmem_zalloc(sizeof (la_els_logi_t), KM_SLEEP); 3100fcf3ce44SJohn Forte if (login_params == NULL) { 3101fcf3ce44SJohn Forte return (FC_NOMEM); 3102fcf3ce44SJohn Forte } 3103fcf3ce44SJohn Forte 3104fcf3ce44SJohn Forte status = fc_ulp_get_port_login_params(fcsm->sm_port_info.port_handle, 3105fcf3ce44SJohn Forte login_params); 3106fcf3ce44SJohn Forte if (status != FC_SUCCESS) { 3107fcf3ce44SJohn Forte kmem_free(login_params, sizeof (la_els_logi_t)); 3108fcf3ce44SJohn Forte return (status); 3109fcf3ce44SJohn Forte } 3110fcf3ce44SJohn Forte 3111fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 3112fcf3ce44SJohn Forte 3113fcf3ce44SJohn Forte fcsm_els_init(cmd, d_id); 3114fcf3ce44SJohn Forte pkt->pkt_comp = comp_func; 3115fcf3ce44SJohn Forte 3116fcf3ce44SJohn Forte payload.ls_code = ls_code; 3117fcf3ce44SJohn Forte payload.mbz = 0; 3118fcf3ce44SJohn Forte 3119fcf3ce44SJohn Forte FCSM_REP_WR(pkt->pkt_cmd_acc, login_params, 3120fcf3ce44SJohn Forte pkt->pkt_cmd, sizeof (la_els_logi_t)); 3121fcf3ce44SJohn Forte FCSM_REP_WR(pkt->pkt_cmd_acc, &payload, 3122fcf3ce44SJohn Forte pkt->pkt_cmd, sizeof (payload)); 3123fcf3ce44SJohn Forte 3124fcf3ce44SJohn Forte cmd->cmd_transport = fc_ulp_issue_els; 3125fcf3ce44SJohn Forte 3126fcf3ce44SJohn Forte kmem_free(login_params, sizeof (la_els_logi_t)); 3127fcf3ce44SJohn Forte 3128fcf3ce44SJohn Forte return (FC_SUCCESS); 3129fcf3ce44SJohn Forte } 3130fcf3ce44SJohn Forte 3131fcf3ce44SJohn Forte static void 3132fcf3ce44SJohn Forte fcsm_xlogi_intr(fcsm_cmd_t *cmd) 3133fcf3ce44SJohn Forte { 3134fcf3ce44SJohn Forte fc_packet_t *pkt; 3135fcf3ce44SJohn Forte fcsm_job_t *job; 3136fcf3ce44SJohn Forte fcsm_t *fcsm; 3137fcf3ce44SJohn Forte 3138fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 3139fcf3ce44SJohn Forte job = cmd->cmd_job; 3140fcf3ce44SJohn Forte ASSERT(job != NULL); 3141fcf3ce44SJohn Forte 3142fcf3ce44SJohn Forte fcsm = cmd->cmd_fcsm; 3143fcf3ce44SJohn Forte ASSERT(fcsm != NULL); 3144fcf3ce44SJohn Forte 3145fcf3ce44SJohn Forte if (pkt->pkt_state != FC_PKT_SUCCESS) { 3146fcf3ce44SJohn Forte fcsm_display(CE_WARN, SM_LOG, fcsm, pkt, 3147fcf3ce44SJohn Forte "xlogi_intr: login to DID 0x%x failed", 3148fcf3ce44SJohn Forte pkt->pkt_cmd_fhdr.d_id); 3149fcf3ce44SJohn Forte } else { 3150fcf3ce44SJohn Forte /* Get the Login parameters of the Management Server */ 3151fcf3ce44SJohn Forte FCSM_REP_RD(pkt->pkt_resp_acc, &fcsm->sm_ms_service_params, 3152fcf3ce44SJohn Forte pkt->pkt_resp, sizeof (la_els_logi_t)); 3153fcf3ce44SJohn Forte } 3154fcf3ce44SJohn Forte 3155fcf3ce44SJohn Forte job->job_result = 3156fcf3ce44SJohn Forte fcsm_pkt_state_to_rval(pkt->pkt_state, pkt->pkt_reason); 3157fcf3ce44SJohn Forte 3158fcf3ce44SJohn Forte fcsm_free_cmd(cmd); 3159fcf3ce44SJohn Forte 3160fcf3ce44SJohn Forte fcsm_jobdone(job); 3161fcf3ce44SJohn Forte } 3162fcf3ce44SJohn Forte 3163fcf3ce44SJohn Forte static void 3164fcf3ce44SJohn Forte fcsm_job_login_mgmt_server(fcsm_job_t *job) 3165fcf3ce44SJohn Forte { 3166fcf3ce44SJohn Forte fcsm_t *fcsm; 3167fcf3ce44SJohn Forte fcsm_cmd_t *cmd; 3168fcf3ce44SJohn Forte int status; 3169fcf3ce44SJohn Forte 3170fcf3ce44SJohn Forte ASSERT(job != NULL); 3171fcf3ce44SJohn Forte ASSERT(job->job_port_instance != -1); 3172fcf3ce44SJohn Forte 3173fcf3ce44SJohn Forte fcsm = ddi_get_soft_state(fcsm_state, job->job_port_instance); 3174fcf3ce44SJohn Forte if (fcsm == NULL) { 3175fcf3ce44SJohn Forte job->job_result = FC_NOMEM; 3176fcf3ce44SJohn Forte fcsm_jobdone(job); 3177fcf3ce44SJohn Forte return; 3178fcf3ce44SJohn Forte } 3179fcf3ce44SJohn Forte 3180fcf3ce44SJohn Forte /* 3181fcf3ce44SJohn Forte * Issue the Login command to the management server. 3182fcf3ce44SJohn Forte */ 3183fcf3ce44SJohn Forte cmd = fcsm_alloc_cmd(fcsm, sizeof (la_els_logi_t), 3184fcf3ce44SJohn Forte sizeof (la_els_logi_t), KM_SLEEP); 3185fcf3ce44SJohn Forte if (cmd == NULL) { 3186fcf3ce44SJohn Forte job->job_result = FC_NOMEM; 3187fcf3ce44SJohn Forte fcsm_jobdone(job); 3188fcf3ce44SJohn Forte return; 3189fcf3ce44SJohn Forte } 3190fcf3ce44SJohn Forte 3191fcf3ce44SJohn Forte FCSM_INIT_CMD(cmd, job, FC_TRAN_INTR | FC_TRAN_CLASS3, FC_PKT_EXCHANGE, 3192fcf3ce44SJohn Forte fcsm_max_cmd_retries, fcsm_xlogi_intr); 3193fcf3ce44SJohn Forte 3194fcf3ce44SJohn Forte status = fcsm_xlogi_init(fcsm, cmd, FS_MANAGEMENT_SERVER, 3195fcf3ce44SJohn Forte fcsm_pkt_common_intr, LA_ELS_PLOGI); 3196fcf3ce44SJohn Forte 3197fcf3ce44SJohn Forte if (status != FC_SUCCESS) { 3198fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 3199fcf3ce44SJohn Forte "job_login_mgmt_server: plogi init failed. status 0x%x", 3200fcf3ce44SJohn Forte status)); 3201fcf3ce44SJohn Forte job->job_result = status; 3202fcf3ce44SJohn Forte fcsm_free_cmd(cmd); 3203fcf3ce44SJohn Forte fcsm_jobdone(job); 3204fcf3ce44SJohn Forte return; 3205fcf3ce44SJohn Forte } 3206fcf3ce44SJohn Forte 3207fcf3ce44SJohn Forte if ((status = fcsm_issue_cmd(cmd)) != FC_SUCCESS) { 3208fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, cmd->cmd_fcsm, NULL, 3209fcf3ce44SJohn Forte "job_ct_passthru: issue login cmd failed, status 0x%x", 3210fcf3ce44SJohn Forte status)); 3211fcf3ce44SJohn Forte job->job_result = status; 3212fcf3ce44SJohn Forte fcsm_free_cmd(cmd); 3213fcf3ce44SJohn Forte fcsm_jobdone(job); 3214fcf3ce44SJohn Forte return; 3215fcf3ce44SJohn Forte } 3216fcf3ce44SJohn Forte } 3217fcf3ce44SJohn Forte 3218fcf3ce44SJohn Forte 3219fcf3ce44SJohn Forte int 3220fcf3ce44SJohn Forte fcsm_ct_passthru(int instance, fcio_t *fcio, int sleep, int job_flags, 3221fcf3ce44SJohn Forte void (*func)(fcio_t *)) 3222fcf3ce44SJohn Forte { 3223fcf3ce44SJohn Forte fcsm_job_t *job; 3224fcf3ce44SJohn Forte int status; 3225fcf3ce44SJohn Forte 3226fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 3227fcf3ce44SJohn Forte "ct_passthru: instance 0x%x fcio 0x%p", instance, fcio)); 3228fcf3ce44SJohn Forte job = fcsm_alloc_job(sleep); 3229fcf3ce44SJohn Forte ASSERT(sleep == KM_NOSLEEP || job != NULL); 3230fcf3ce44SJohn Forte 3231fcf3ce44SJohn Forte fcsm_init_job(job, instance, FCSM_JOB_CT_PASSTHRU, job_flags, 3232fcf3ce44SJohn Forte (opaque_t)fcio, (opaque_t)func, fcsm_ct_passthru_comp, NULL); 3233fcf3ce44SJohn Forte status = fcsm_process_job(job, 0); 3234fcf3ce44SJohn Forte if (status != FC_SUCCESS) { 3235fcf3ce44SJohn Forte /* Job could not be issued. So free the job and return */ 3236fcf3ce44SJohn Forte fcsm_dealloc_job(job); 3237fcf3ce44SJohn Forte return (status); 3238fcf3ce44SJohn Forte } 3239fcf3ce44SJohn Forte 3240fcf3ce44SJohn Forte if (job_flags & FCSM_JOBFLAG_SYNC) { 3241fcf3ce44SJohn Forte status = job->job_result; 3242fcf3ce44SJohn Forte fcsm_dealloc_job(job); 3243fcf3ce44SJohn Forte } 3244fcf3ce44SJohn Forte 3245fcf3ce44SJohn Forte return (status); 3246fcf3ce44SJohn Forte } 3247fcf3ce44SJohn Forte 3248fcf3ce44SJohn Forte 3249fcf3ce44SJohn Forte /* ARGSUSED */ 3250fcf3ce44SJohn Forte static void 3251fcf3ce44SJohn Forte fcsm_ct_passthru_comp(opaque_t comp_arg, fcsm_job_t *job, int result) 3252fcf3ce44SJohn Forte { 3253fcf3ce44SJohn Forte ASSERT(job != NULL); 3254fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 3255fcf3ce44SJohn Forte "ct_passthru_comp: result 0x%x port 0x%x", 3256fcf3ce44SJohn Forte job->job_result, job->job_port_instance)); 3257fcf3ce44SJohn Forte } 3258fcf3ce44SJohn Forte 3259fcf3ce44SJohn Forte 3260fcf3ce44SJohn Forte static void 3261fcf3ce44SJohn Forte fcsm_pkt_common_intr(fc_packet_t *pkt) 3262fcf3ce44SJohn Forte { 3263fcf3ce44SJohn Forte fcsm_cmd_t *cmd; 3264fcf3ce44SJohn Forte int jobstatus; 3265fcf3ce44SJohn Forte fcsm_t *fcsm; 3266fcf3ce44SJohn Forte 3267fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, NULL, NULL, 3268fcf3ce44SJohn Forte "pkt_common_intr")); 3269fcf3ce44SJohn Forte 3270fcf3ce44SJohn Forte cmd = (fcsm_cmd_t *)pkt->pkt_ulp_private; 3271fcf3ce44SJohn Forte ASSERT(cmd != NULL); 3272fcf3ce44SJohn Forte 3273fcf3ce44SJohn Forte if (pkt->pkt_state == FC_PKT_SUCCESS) { 3274fcf3ce44SJohn Forte /* Command completed successfully. Just complete the command */ 3275fcf3ce44SJohn Forte cmd->cmd_comp(cmd); 3276fcf3ce44SJohn Forte return; 3277fcf3ce44SJohn Forte } 3278fcf3ce44SJohn Forte 3279fcf3ce44SJohn Forte fcsm = cmd->cmd_fcsm; 3280fcf3ce44SJohn Forte ASSERT(fcsm != NULL); 3281fcf3ce44SJohn Forte 328240b706cfSMilan Jurik FCSM_DEBUG(SMDL_ERR, (CE_NOTE, SM_LOG, cmd->cmd_fcsm, pkt, 3283fcf3ce44SJohn Forte "fc packet to DID 0x%x failed for pkt 0x%p", 328440b706cfSMilan Jurik pkt->pkt_cmd_fhdr.d_id, pkt)); 3285fcf3ce44SJohn Forte 3286fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 3287fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_LINK_DOWN) { 3288fcf3ce44SJohn Forte /* 3289fcf3ce44SJohn Forte * No need to retry the command. The link previously 3290fcf3ce44SJohn Forte * suffered an offline timeout. 3291fcf3ce44SJohn Forte */ 3292fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3293fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, cmd->cmd_fcsm, NULL, 3294fcf3ce44SJohn Forte "pkt_common_intr: end. Link is down")); 3295fcf3ce44SJohn Forte cmd->cmd_comp(cmd); 3296fcf3ce44SJohn Forte return; 3297fcf3ce44SJohn Forte } 3298fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3299fcf3ce44SJohn Forte 3300fcf3ce44SJohn Forte jobstatus = fcsm_pkt_state_to_rval(pkt->pkt_state, pkt->pkt_reason); 3301fcf3ce44SJohn Forte if (jobstatus == FC_LOGINREQ) { 3302fcf3ce44SJohn Forte /* 3303fcf3ce44SJohn Forte * Login to the destination is required. No need to 3304fcf3ce44SJohn Forte * retry this cmd again. 3305fcf3ce44SJohn Forte */ 3306fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, cmd->cmd_fcsm, NULL, 3307fcf3ce44SJohn Forte "pkt_common_intr: end. LOGIN required")); 3308fcf3ce44SJohn Forte cmd->cmd_comp(cmd); 3309fcf3ce44SJohn Forte return; 3310fcf3ce44SJohn Forte } 3311fcf3ce44SJohn Forte 3312fcf3ce44SJohn Forte switch (pkt->pkt_state) { 3313fcf3ce44SJohn Forte case FC_PKT_PORT_OFFLINE: 3314fcf3ce44SJohn Forte case FC_PKT_LOCAL_RJT: 3315fcf3ce44SJohn Forte case FC_PKT_TIMEOUT: { 3316fcf3ce44SJohn Forte uchar_t pkt_state; 3317fcf3ce44SJohn Forte 3318fcf3ce44SJohn Forte pkt_state = pkt->pkt_state; 3319fcf3ce44SJohn Forte cmd->cmd_retry_interval = fcsm_retry_interval; 3320fcf3ce44SJohn Forte if (fcsm_retry_cmd(cmd) != 0) { 3321fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, 3322fcf3ce44SJohn Forte cmd->cmd_fcsm, NULL, 3323fcf3ce44SJohn Forte "common_intr: max retries(%d) reached, status 0x%x", 3324fcf3ce44SJohn Forte cmd->cmd_retry_count)); 3325fcf3ce44SJohn Forte 3326fcf3ce44SJohn Forte /* 3327fcf3ce44SJohn Forte * Restore the pkt_state to the actual failure status 3328fcf3ce44SJohn Forte * received at the time of pkt completion. 3329fcf3ce44SJohn Forte */ 3330fcf3ce44SJohn Forte pkt->pkt_state = pkt_state; 3331fcf3ce44SJohn Forte pkt->pkt_reason = 0; 3332fcf3ce44SJohn Forte cmd->cmd_comp(cmd); 3333fcf3ce44SJohn Forte } else { 3334fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, 3335fcf3ce44SJohn Forte cmd->cmd_fcsm, NULL, 3336fcf3ce44SJohn Forte "pkt_common_intr: retry(%d) on pkt state (0x%x)", 3337fcf3ce44SJohn Forte cmd->cmd_retry_count, pkt_state)); 3338fcf3ce44SJohn Forte } 3339fcf3ce44SJohn Forte break; 3340fcf3ce44SJohn Forte } 3341fcf3ce44SJohn Forte default: 3342fcf3ce44SJohn Forte cmd->cmd_comp(cmd); 3343fcf3ce44SJohn Forte break; 3344fcf3ce44SJohn Forte } 3345fcf3ce44SJohn Forte } 3346fcf3ce44SJohn Forte 3347fcf3ce44SJohn Forte static int 3348fcf3ce44SJohn Forte fcsm_issue_cmd(fcsm_cmd_t *cmd) 3349fcf3ce44SJohn Forte { 3350fcf3ce44SJohn Forte fc_packet_t *pkt; 3351fcf3ce44SJohn Forte fcsm_t *fcsm; 3352fcf3ce44SJohn Forte int status; 3353fcf3ce44SJohn Forte 3354fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 3355fcf3ce44SJohn Forte fcsm = cmd->cmd_fcsm; 3356fcf3ce44SJohn Forte 3357fcf3ce44SJohn Forte /* Explicitly invalidate this field till fcsm decides to use it */ 3358fcf3ce44SJohn Forte pkt->pkt_ulp_rscn_infop = NULL; 3359fcf3ce44SJohn Forte 3360fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 3361fcf3ce44SJohn Forte "issue_cmd: entry")); 3362fcf3ce44SJohn Forte 3363fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&fcsm->sm_mutex)); 3364fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 3365fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_LINK_DOWN) { 3366fcf3ce44SJohn Forte /* 3367fcf3ce44SJohn Forte * Update the pkt_state/pkt_reason appropriately. 3368fcf3ce44SJohn Forte * Caller of this function can decide whether to call 3369fcf3ce44SJohn Forte * 'pkt->pkt_comp' or use the 'status' returned by this func. 3370fcf3ce44SJohn Forte */ 3371fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3372fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_PORT_OFFLINE; 3373fcf3ce44SJohn Forte pkt->pkt_reason = FC_REASON_OFFLINE; 3374fcf3ce44SJohn Forte return (FC_OFFLINE); 3375fcf3ce44SJohn Forte } 3376fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3377fcf3ce44SJohn Forte 3378fcf3ce44SJohn Forte ASSERT(cmd->cmd_transport != NULL); 3379fcf3ce44SJohn Forte status = cmd->cmd_transport(fcsm->sm_port_info.port_handle, pkt); 3380fcf3ce44SJohn Forte if (status != FC_SUCCESS) { 3381fcf3ce44SJohn Forte switch (status) { 3382fcf3ce44SJohn Forte case FC_LOGINREQ: 3383fcf3ce44SJohn Forte /* 3384fcf3ce44SJohn Forte * No need to retry. Return the cause of failure. 3385fcf3ce44SJohn Forte * Also update the pkt_state/pkt_reason. Caller of 3386fcf3ce44SJohn Forte * this function can decide, whether to call 3387fcf3ce44SJohn Forte * 'pkt->pkt_comp' or use the 'status' code returned 3388fcf3ce44SJohn Forte * by this function. 3389fcf3ce44SJohn Forte */ 3390fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_LOCAL_RJT; 3391fcf3ce44SJohn Forte pkt->pkt_reason = FC_REASON_LOGIN_REQUIRED; 3392fcf3ce44SJohn Forte break; 3393fcf3ce44SJohn Forte 3394fcf3ce44SJohn Forte case FC_DEVICE_BUSY_NEW_RSCN: 3395fcf3ce44SJohn Forte /* 3396fcf3ce44SJohn Forte * There was a newer RSCN than what fcsm knows about. 3397fcf3ce44SJohn Forte * So, just retry again 3398fcf3ce44SJohn Forte */ 3399fcf3ce44SJohn Forte cmd->cmd_retry_count = 0; 3400fcf3ce44SJohn Forte /*FALLTHROUGH*/ 3401fcf3ce44SJohn Forte case FC_OFFLINE: 3402fcf3ce44SJohn Forte case FC_STATEC_BUSY: 3403fcf3ce44SJohn Forte /* 3404fcf3ce44SJohn Forte * TODO: set flag, so that command is retried after 3405fcf3ce44SJohn Forte * port is back online. 3406fcf3ce44SJohn Forte * FALL Through for now. 3407fcf3ce44SJohn Forte */ 3408fcf3ce44SJohn Forte 3409fcf3ce44SJohn Forte case FC_TRAN_BUSY: 3410fcf3ce44SJohn Forte case FC_NOMEM: 3411fcf3ce44SJohn Forte case FC_DEVICE_BUSY: 3412fcf3ce44SJohn Forte cmd->cmd_retry_interval = fcsm_retry_interval; 3413fcf3ce44SJohn Forte if (fcsm_retry_cmd(cmd) != 0) { 3414fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, 3415fcf3ce44SJohn Forte (CE_WARN, SM_LOG, fcsm, NULL, 3416fcf3ce44SJohn Forte "issue_cmd: max retries (%d) reached", 3417fcf3ce44SJohn Forte cmd->cmd_retry_count)); 3418fcf3ce44SJohn Forte 3419fcf3ce44SJohn Forte /* 3420fcf3ce44SJohn Forte * status variable is not changed here. 3421fcf3ce44SJohn Forte * Return the cause of the original 3422fcf3ce44SJohn Forte * cmd_transport failure. 3423fcf3ce44SJohn Forte * Update the pkt_state/pkt_reason. Caller 3424fcf3ce44SJohn Forte * of this function can decide whether to 3425fcf3ce44SJohn Forte * call 'pkt->pkt_comp' or use the 'status' 3426fcf3ce44SJohn Forte * code returned by this function. 3427fcf3ce44SJohn Forte */ 3428fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_TRAN_BSY; 3429fcf3ce44SJohn Forte pkt->pkt_reason = 0; 3430fcf3ce44SJohn Forte } else { 3431fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, 3432fcf3ce44SJohn Forte (CE_WARN, SM_LOG, fcsm, NULL, 3433fcf3ce44SJohn Forte "issue_cmd: retry (%d) on fc status (0x%x)", 3434fcf3ce44SJohn Forte cmd->cmd_retry_count, status)); 3435fcf3ce44SJohn Forte 3436fcf3ce44SJohn Forte status = FC_SUCCESS; 3437fcf3ce44SJohn Forte } 3438fcf3ce44SJohn Forte break; 3439fcf3ce44SJohn Forte 3440fcf3ce44SJohn Forte default: 3441fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_WARN, SM_LOG, fcsm, NULL, 3442fcf3ce44SJohn Forte "issue_cmd: failure status 0x%x", status)); 3443fcf3ce44SJohn Forte 3444fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_TRAN_ERROR; 3445fcf3ce44SJohn Forte pkt->pkt_reason = 0; 3446fcf3ce44SJohn Forte break; 3447fcf3ce44SJohn Forte 3448fcf3ce44SJohn Forte 3449fcf3ce44SJohn Forte } 3450fcf3ce44SJohn Forte } 3451fcf3ce44SJohn Forte 3452fcf3ce44SJohn Forte return (status); 3453fcf3ce44SJohn Forte } 3454fcf3ce44SJohn Forte 3455fcf3ce44SJohn Forte 3456fcf3ce44SJohn Forte static int 3457fcf3ce44SJohn Forte fcsm_retry_cmd(fcsm_cmd_t *cmd) 3458fcf3ce44SJohn Forte { 3459fcf3ce44SJohn Forte if (cmd->cmd_retry_count < cmd->cmd_max_retries) { 3460fcf3ce44SJohn Forte cmd->cmd_retry_count++; 3461fcf3ce44SJohn Forte fcsm_enque_cmd(cmd->cmd_fcsm, cmd); 3462fcf3ce44SJohn Forte return (0); 3463fcf3ce44SJohn Forte } 3464fcf3ce44SJohn Forte 3465fcf3ce44SJohn Forte return (1); 3466fcf3ce44SJohn Forte } 3467fcf3ce44SJohn Forte 3468fcf3ce44SJohn Forte static void 3469fcf3ce44SJohn Forte fcsm_enque_cmd(fcsm_t *fcsm, fcsm_cmd_t *cmd) 3470fcf3ce44SJohn Forte { 3471fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&fcsm->sm_mutex)); 3472fcf3ce44SJohn Forte 3473fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, "enque_cmd")); 3474fcf3ce44SJohn Forte 3475fcf3ce44SJohn Forte cmd->cmd_next = NULL; 3476fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 3477fcf3ce44SJohn Forte if (fcsm->sm_retry_tail) { 3478fcf3ce44SJohn Forte ASSERT(fcsm->sm_retry_head != NULL); 3479fcf3ce44SJohn Forte fcsm->sm_retry_tail->cmd_next = cmd; 3480fcf3ce44SJohn Forte fcsm->sm_retry_tail = cmd; 3481fcf3ce44SJohn Forte } else { 3482fcf3ce44SJohn Forte ASSERT(fcsm->sm_retry_tail == NULL); 3483fcf3ce44SJohn Forte fcsm->sm_retry_head = fcsm->sm_retry_tail = cmd; 3484fcf3ce44SJohn Forte 3485fcf3ce44SJohn Forte /* Schedule retry thread, if not already running */ 3486fcf3ce44SJohn Forte if (fcsm->sm_retry_tid == NULL) { 3487fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 3488fcf3ce44SJohn Forte "enque_cmd: schedule retry thread")); 3489fcf3ce44SJohn Forte fcsm->sm_retry_tid = timeout(fcsm_retry_timeout, 3490fcf3ce44SJohn Forte (caddr_t)fcsm, fcsm_retry_ticks); 3491fcf3ce44SJohn Forte } 3492fcf3ce44SJohn Forte } 3493fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3494fcf3ce44SJohn Forte } 3495fcf3ce44SJohn Forte 3496fcf3ce44SJohn Forte 3497fcf3ce44SJohn Forte static fcsm_cmd_t * 3498fcf3ce44SJohn Forte fcsm_deque_cmd(fcsm_t *fcsm) 3499fcf3ce44SJohn Forte { 3500fcf3ce44SJohn Forte fcsm_cmd_t *cmd; 3501fcf3ce44SJohn Forte 3502fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&fcsm->sm_mutex)); 3503fcf3ce44SJohn Forte 3504fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, "deque_cmd")); 3505fcf3ce44SJohn Forte 3506fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 3507fcf3ce44SJohn Forte if (fcsm->sm_retry_head == NULL) { 3508fcf3ce44SJohn Forte ASSERT(fcsm->sm_retry_tail == NULL); 3509fcf3ce44SJohn Forte cmd = NULL; 3510fcf3ce44SJohn Forte } else { 3511fcf3ce44SJohn Forte cmd = fcsm->sm_retry_head; 3512fcf3ce44SJohn Forte fcsm->sm_retry_head = cmd->cmd_next; 3513fcf3ce44SJohn Forte if (fcsm->sm_retry_head == NULL) { 3514fcf3ce44SJohn Forte fcsm->sm_retry_tail = NULL; 3515fcf3ce44SJohn Forte } 3516fcf3ce44SJohn Forte cmd->cmd_next = NULL; 3517fcf3ce44SJohn Forte } 3518fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3519fcf3ce44SJohn Forte 3520fcf3ce44SJohn Forte return (cmd); 3521fcf3ce44SJohn Forte } 3522fcf3ce44SJohn Forte 3523fcf3ce44SJohn Forte static void 3524fcf3ce44SJohn Forte fcsm_retry_timeout(void *handle) 3525fcf3ce44SJohn Forte { 3526fcf3ce44SJohn Forte fcsm_t *fcsm; 3527fcf3ce44SJohn Forte fcsm_cmd_t *curr_tail; 3528fcf3ce44SJohn Forte fcsm_cmd_t *cmd; 3529fcf3ce44SJohn Forte int done = 0; 3530fcf3ce44SJohn Forte int linkdown; 3531fcf3ce44SJohn Forte 3532fcf3ce44SJohn Forte fcsm = (fcsm_t *)handle; 3533fcf3ce44SJohn Forte 3534fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, "retry_timeout")); 3535fcf3ce44SJohn Forte 3536fcf3ce44SJohn Forte /* 3537fcf3ce44SJohn Forte * If retry cmd queue is suspended, then go away. 3538fcf3ce44SJohn Forte * This retry thread will be restarted, when cmd queue resumes. 3539fcf3ce44SJohn Forte */ 3540fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 3541fcf3ce44SJohn Forte if (fcsm->sm_flags & FCSM_CMD_RETRY_Q_SUSPENDED) { 3542fcf3ce44SJohn Forte /* 3543fcf3ce44SJohn Forte * Clear the retry_tid, to indicate that this routine is not 3544fcf3ce44SJohn Forte * currently being rescheduled. 3545fcf3ce44SJohn Forte */ 3546fcf3ce44SJohn Forte fcsm->sm_retry_tid = (timeout_id_t)NULL; 3547fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3548fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 3549fcf3ce44SJohn Forte "retry_timeout: end. No processing. " 3550fcf3ce44SJohn Forte "Queue is currently suspended for this instance")); 3551fcf3ce44SJohn Forte return; 3552fcf3ce44SJohn Forte } 3553fcf3ce44SJohn Forte 3554fcf3ce44SJohn Forte linkdown = (fcsm->sm_flags & FCSM_LINK_DOWN) ? 1 : 0; 3555fcf3ce44SJohn Forte 3556fcf3ce44SJohn Forte /* 3557fcf3ce44SJohn Forte * Save the curr_tail, so that we only process the commands 3558fcf3ce44SJohn Forte * which are in the queue at this time. 3559fcf3ce44SJohn Forte */ 3560fcf3ce44SJohn Forte curr_tail = fcsm->sm_retry_tail; 3561fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3562fcf3ce44SJohn Forte 3563fcf3ce44SJohn Forte /* 3564fcf3ce44SJohn Forte * Check for done flag before dequeing the command. 3565fcf3ce44SJohn Forte * Dequeing before checking the done flag will cause a command 3566fcf3ce44SJohn Forte * to be lost. 3567fcf3ce44SJohn Forte */ 3568fcf3ce44SJohn Forte while ((!done) && ((cmd = fcsm_deque_cmd(fcsm)) != NULL)) { 3569fcf3ce44SJohn Forte 3570fcf3ce44SJohn Forte if (cmd == curr_tail) { 3571fcf3ce44SJohn Forte done = 1; 3572fcf3ce44SJohn Forte } 3573fcf3ce44SJohn Forte 3574fcf3ce44SJohn Forte cmd->cmd_retry_interval -= fcsm_retry_ticker; 3575fcf3ce44SJohn Forte 3576fcf3ce44SJohn Forte if (linkdown) { 3577fcf3ce44SJohn Forte fc_packet_t *pkt; 3578fcf3ce44SJohn Forte 3579fcf3ce44SJohn Forte /* 3580fcf3ce44SJohn Forte * No need to retry the command. The link has 3581fcf3ce44SJohn Forte * suffered an offline timeout. 3582fcf3ce44SJohn Forte */ 3583fcf3ce44SJohn Forte pkt = cmd->cmd_fp_pkt; 3584fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_PORT_OFFLINE; 3585fcf3ce44SJohn Forte pkt->pkt_reason = FC_REASON_OFFLINE; 3586fcf3ce44SJohn Forte pkt->pkt_comp(pkt); 3587fcf3ce44SJohn Forte continue; 3588fcf3ce44SJohn Forte } 3589fcf3ce44SJohn Forte 3590fcf3ce44SJohn Forte if (cmd->cmd_retry_interval <= 0) { 3591fcf3ce44SJohn Forte /* Retry the command */ 3592fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 3593fcf3ce44SJohn Forte "retry_timeout: issue cmd 0x%p", (void *)cmd)); 3594fcf3ce44SJohn Forte if (fcsm_issue_cmd(cmd) != FC_SUCCESS) { 3595fcf3ce44SJohn Forte cmd->cmd_fp_pkt->pkt_comp(cmd->cmd_fp_pkt); 3596fcf3ce44SJohn Forte } 3597fcf3ce44SJohn Forte } else { 3598fcf3ce44SJohn Forte /* 3599fcf3ce44SJohn Forte * Put the command back on the queue. Retry time 3600fcf3ce44SJohn Forte * has not yet reached. 3601fcf3ce44SJohn Forte */ 3602fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 3603fcf3ce44SJohn Forte "retry_timeout: queue cmd 0x%p", (void *)cmd)); 3604fcf3ce44SJohn Forte fcsm_enque_cmd(fcsm, cmd); 3605fcf3ce44SJohn Forte } 3606fcf3ce44SJohn Forte } 3607fcf3ce44SJohn Forte 3608fcf3ce44SJohn Forte mutex_enter(&fcsm->sm_mutex); 3609fcf3ce44SJohn Forte if (fcsm->sm_retry_head) { 3610fcf3ce44SJohn Forte /* Activate timer */ 3611fcf3ce44SJohn Forte fcsm->sm_retry_tid = timeout(fcsm_retry_timeout, 3612fcf3ce44SJohn Forte (caddr_t)fcsm, fcsm_retry_ticks); 3613fcf3ce44SJohn Forte FCSM_DEBUG(SMDL_TRACE, (CE_CONT, SM_LOG, fcsm, NULL, 3614fcf3ce44SJohn Forte "retry_timeout: retry thread rescheduled")); 3615fcf3ce44SJohn Forte } else { 3616fcf3ce44SJohn Forte /* 3617fcf3ce44SJohn Forte * Reset the tid variable. The first thread which queues the 3618fcf3ce44SJohn Forte * command, will restart the timer. 3619fcf3ce44SJohn Forte */ 3620fcf3ce44SJohn Forte fcsm->sm_retry_tid = (timeout_id_t)NULL; 3621fcf3ce44SJohn Forte } 3622fcf3ce44SJohn Forte mutex_exit(&fcsm->sm_mutex); 3623fcf3ce44SJohn Forte } 3624