1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte /* 22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*fcf3ce44SJohn Forte * Use is subject to license terms. 24*fcf3ce44SJohn Forte * 25*fcf3ce44SJohn Forte * Fibre channel Transport Library (fctl) 26*fcf3ce44SJohn Forte * 27*fcf3ce44SJohn Forte * Function naming conventions: 28*fcf3ce44SJohn Forte * Functions called from ULPs begin with fc_ulp_ 29*fcf3ce44SJohn Forte * Functions called from FCAs begin with fc_fca_ 30*fcf3ce44SJohn Forte * Internal functions begin with fctl_ 31*fcf3ce44SJohn Forte * 32*fcf3ce44SJohn Forte * Fibre channel packet layout: 33*fcf3ce44SJohn Forte * +---------------------+<--------+ 34*fcf3ce44SJohn Forte * | | | 35*fcf3ce44SJohn Forte * | ULP Packet private | | 36*fcf3ce44SJohn Forte * | | | 37*fcf3ce44SJohn Forte * +---------------------+ | 38*fcf3ce44SJohn Forte * | |---------+ 39*fcf3ce44SJohn Forte * | struct fc_packet |---------+ 40*fcf3ce44SJohn Forte * | | | 41*fcf3ce44SJohn Forte * +---------------------+<--------+ 42*fcf3ce44SJohn Forte * | | 43*fcf3ce44SJohn Forte * | FCA Packet private | 44*fcf3ce44SJohn Forte * | | 45*fcf3ce44SJohn Forte * +---------------------+ 46*fcf3ce44SJohn Forte * 47*fcf3ce44SJohn Forte * So you loved the ascii art ? It's strongly desirable to cache 48*fcf3ce44SJohn Forte * allocate the entire packet in one common place. So we define a set a 49*fcf3ce44SJohn Forte * of rules. In a contiguous block of memory, the top portion of the 50*fcf3ce44SJohn Forte * block points to ulp packet private area, next follows the fc_packet 51*fcf3ce44SJohn Forte * structure used extensively by all the consumers and what follows this 52*fcf3ce44SJohn Forte * is the FCA packet private. Note that given a packet structure, it is 53*fcf3ce44SJohn Forte * possible to get to the ULP and FCA Packet private fields using 54*fcf3ce44SJohn Forte * ulp_private and fca_private fields (which hold pointers) respectively. 55*fcf3ce44SJohn Forte * 56*fcf3ce44SJohn Forte * It should be noted with a grain of salt that ULP Packet private size 57*fcf3ce44SJohn Forte * varies between two different ULP types, So this poses a challenge to 58*fcf3ce44SJohn Forte * compute the correct size of the whole block on a per port basis. The 59*fcf3ce44SJohn Forte * transport layer doesn't have a problem in dealing with FCA packet 60*fcf3ce44SJohn Forte * private sizes as it is the sole manager of ports underneath. Since 61*fcf3ce44SJohn Forte * it's not a good idea to cache allocate different sizes of memory for 62*fcf3ce44SJohn Forte * different ULPs and have the ability to choose from one of these caches 63*fcf3ce44SJohn Forte * based on ULP type during every packet allocation, the transport some 64*fcf3ce44SJohn Forte * what wisely (?) hands off this job of cache allocation to the ULPs 65*fcf3ce44SJohn Forte * themselves. 66*fcf3ce44SJohn Forte * 67*fcf3ce44SJohn Forte * That means FCAs need to make their packet private size known to the 68*fcf3ce44SJohn Forte * transport to pass it up to the ULPs. This is done during 69*fcf3ce44SJohn Forte * fc_fca_attach(). And the transport passes this size up to ULPs during 70*fcf3ce44SJohn Forte * fc_ulp_port_attach() of each ULP. 71*fcf3ce44SJohn Forte * 72*fcf3ce44SJohn Forte * This leaves us with another possible question; How are packets 73*fcf3ce44SJohn Forte * allocated for ELS's started by the transport itself ? Well, the port 74*fcf3ce44SJohn Forte * driver during attach time, cache allocates on a per port basis to 75*fcf3ce44SJohn Forte * handle ELSs too. 76*fcf3ce44SJohn Forte */ 77*fcf3ce44SJohn Forte 78*fcf3ce44SJohn Forte #include <sys/note.h> 79*fcf3ce44SJohn Forte #include <sys/types.h> 80*fcf3ce44SJohn Forte #include <sys/varargs.h> 81*fcf3ce44SJohn Forte #include <sys/param.h> 82*fcf3ce44SJohn Forte #include <sys/errno.h> 83*fcf3ce44SJohn Forte #include <sys/uio.h> 84*fcf3ce44SJohn Forte #include <sys/buf.h> 85*fcf3ce44SJohn Forte #include <sys/modctl.h> 86*fcf3ce44SJohn Forte #include <sys/open.h> 87*fcf3ce44SJohn Forte #include <sys/kmem.h> 88*fcf3ce44SJohn Forte #include <sys/poll.h> 89*fcf3ce44SJohn Forte #include <sys/conf.h> 90*fcf3ce44SJohn Forte #include <sys/cmn_err.h> 91*fcf3ce44SJohn Forte #include <sys/stat.h> 92*fcf3ce44SJohn Forte #include <sys/ddi.h> 93*fcf3ce44SJohn Forte #include <sys/sunddi.h> 94*fcf3ce44SJohn Forte #include <sys/promif.h> 95*fcf3ce44SJohn Forte #include <sys/byteorder.h> 96*fcf3ce44SJohn Forte #include <sys/fibre-channel/fc.h> 97*fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_ulpif.h> 98*fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_fcaif.h> 99*fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fctl_private.h> 100*fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_portif.h> 101*fcf3ce44SJohn Forte 102*fcf3ce44SJohn Forte /* These are referenced by fp.c! */ 103*fcf3ce44SJohn Forte int did_table_size = D_ID_HASH_TABLE_SIZE; 104*fcf3ce44SJohn Forte int pwwn_table_size = PWWN_HASH_TABLE_SIZE; 105*fcf3ce44SJohn Forte 106*fcf3ce44SJohn Forte static fc_ulp_module_t *fctl_ulp_modules; 107*fcf3ce44SJohn Forte static fc_fca_port_t *fctl_fca_portlist; 108*fcf3ce44SJohn Forte static fc_ulp_list_t *fctl_ulp_list; 109*fcf3ce44SJohn Forte 110*fcf3ce44SJohn Forte static char fctl_greeting[] = 111*fcf3ce44SJohn Forte "fctl: %s ULP same type (0x%x) as existing module.\n"; 112*fcf3ce44SJohn Forte 113*fcf3ce44SJohn Forte static char *fctl_undefined = "Undefined"; 114*fcf3ce44SJohn Forte 115*fcf3ce44SJohn Forte /* 116*fcf3ce44SJohn Forte * This lock protects the fc_ulp_module_t linked list (i.e. mod_next field) 117*fcf3ce44SJohn Forte */ 118*fcf3ce44SJohn Forte 119*fcf3ce44SJohn Forte static krwlock_t fctl_ulp_lock; 120*fcf3ce44SJohn Forte 121*fcf3ce44SJohn Forte /* 122*fcf3ce44SJohn Forte * The fctl_mod_ports_lock protects the mod_ports element in the 123*fcf3ce44SJohn Forte * fc_ulp_ports_t structure 124*fcf3ce44SJohn Forte */ 125*fcf3ce44SJohn Forte 126*fcf3ce44SJohn Forte static krwlock_t fctl_mod_ports_lock; 127*fcf3ce44SJohn Forte 128*fcf3ce44SJohn Forte /* 129*fcf3ce44SJohn Forte * fctl_port_lock protects the linked list of local port structures 130*fcf3ce44SJohn Forte * (fctl_fca_portlist). When walking the list, this lock must be obtained 131*fcf3ce44SJohn Forte * prior to any local port locks. 132*fcf3ce44SJohn Forte */ 133*fcf3ce44SJohn Forte 134*fcf3ce44SJohn Forte static kmutex_t fctl_port_lock; 135*fcf3ce44SJohn Forte static kmutex_t fctl_ulp_list_mutex; 136*fcf3ce44SJohn Forte 137*fcf3ce44SJohn Forte static fctl_nwwn_list_t *fctl_nwwn_hash_table; 138*fcf3ce44SJohn Forte static kmutex_t fctl_nwwn_hash_mutex; 139*fcf3ce44SJohn Forte int fctl_nwwn_table_size = NWWN_HASH_TABLE_SIZE; 140*fcf3ce44SJohn Forte 141*fcf3ce44SJohn Forte #if !defined(lint) 142*fcf3ce44SJohn Forte _NOTE(MUTEX_PROTECTS_DATA(fctl_nwwn_hash_mutex, fctl_nwwn_hash_table)) 143*fcf3ce44SJohn Forte _NOTE(MUTEX_PROTECTS_DATA(fctl_ulp_list_mutex, fctl_ulp_list)) 144*fcf3ce44SJohn Forte _NOTE(RWLOCK_PROTECTS_DATA(fctl_ulp_lock, ulp_module::mod_next)) 145*fcf3ce44SJohn Forte _NOTE(RWLOCK_PROTECTS_DATA(fctl_mod_ports_lock, ulp_module::mod_ports 146*fcf3ce44SJohn Forte ulp_ports::port_handle)) 147*fcf3ce44SJohn Forte _NOTE(DATA_READABLE_WITHOUT_LOCK(ulp_module::mod_info)) 148*fcf3ce44SJohn Forte _NOTE(MUTEX_PROTECTS_DATA(ulp_ports::port_mutex, ulp_ports::port_statec 149*fcf3ce44SJohn Forte ulp_ports::port_dstate)) 150*fcf3ce44SJohn Forte #endif /* lint */ 151*fcf3ce44SJohn Forte 152*fcf3ce44SJohn Forte #define FCTL_VERSION "1.69" 153*fcf3ce44SJohn Forte #define FCTL_NAME_VERSION "SunFC Transport v" FCTL_VERSION 154*fcf3ce44SJohn Forte 155*fcf3ce44SJohn Forte 156*fcf3ce44SJohn Forte char *fctl_version = FCTL_NAME_VERSION; 157*fcf3ce44SJohn Forte 158*fcf3ce44SJohn Forte extern struct mod_ops mod_miscops; 159*fcf3ce44SJohn Forte 160*fcf3ce44SJohn Forte static struct modlmisc modlmisc = { 161*fcf3ce44SJohn Forte &mod_miscops, /* type of module */ 162*fcf3ce44SJohn Forte FCTL_NAME_VERSION /* Module name */ 163*fcf3ce44SJohn Forte }; 164*fcf3ce44SJohn Forte 165*fcf3ce44SJohn Forte static struct modlinkage modlinkage = { 166*fcf3ce44SJohn Forte MODREV_1, (void *)&modlmisc, NULL 167*fcf3ce44SJohn Forte }; 168*fcf3ce44SJohn Forte 169*fcf3ce44SJohn Forte static struct bus_ops fctl_fca_busops = { 170*fcf3ce44SJohn Forte BUSO_REV, 171*fcf3ce44SJohn Forte nullbusmap, /* bus_map */ 172*fcf3ce44SJohn Forte NULL, /* bus_get_intrspec */ 173*fcf3ce44SJohn Forte NULL, /* bus_add_intrspec */ 174*fcf3ce44SJohn Forte NULL, /* bus_remove_intrspec */ 175*fcf3ce44SJohn Forte i_ddi_map_fault, /* bus_map_fault */ 176*fcf3ce44SJohn Forte ddi_dma_map, /* bus_dma_map */ 177*fcf3ce44SJohn Forte ddi_dma_allochdl, /* bus_dma_allochdl */ 178*fcf3ce44SJohn Forte ddi_dma_freehdl, /* bus_dma_freehdl */ 179*fcf3ce44SJohn Forte ddi_dma_bindhdl, /* bus_dma_bindhdl */ 180*fcf3ce44SJohn Forte ddi_dma_unbindhdl, /* bus_unbindhdl */ 181*fcf3ce44SJohn Forte ddi_dma_flush, /* bus_dma_flush */ 182*fcf3ce44SJohn Forte ddi_dma_win, /* bus_dma_win */ 183*fcf3ce44SJohn Forte ddi_dma_mctl, /* bus_dma_ctl */ 184*fcf3ce44SJohn Forte fctl_fca_bus_ctl, /* bus_ctl */ 185*fcf3ce44SJohn Forte ddi_bus_prop_op, /* bus_prop_op */ 186*fcf3ce44SJohn Forte NULL, /* bus_get_eventcookie */ 187*fcf3ce44SJohn Forte NULL, /* bus_add_eventcall */ 188*fcf3ce44SJohn Forte NULL, /* bus_remove_event */ 189*fcf3ce44SJohn Forte NULL, /* bus_post_event */ 190*fcf3ce44SJohn Forte NULL, /* bus_intr_ctl */ 191*fcf3ce44SJohn Forte NULL, /* bus_config */ 192*fcf3ce44SJohn Forte NULL, /* bus_unconfig */ 193*fcf3ce44SJohn Forte NULL, /* bus_fm_init */ 194*fcf3ce44SJohn Forte NULL, /* bus_fm_fini */ 195*fcf3ce44SJohn Forte NULL, /* bus_fm_access_enter */ 196*fcf3ce44SJohn Forte NULL, /* bus_fm_access_exit */ 197*fcf3ce44SJohn Forte NULL, /* bus_power */ 198*fcf3ce44SJohn Forte NULL 199*fcf3ce44SJohn Forte }; 200*fcf3ce44SJohn Forte 201*fcf3ce44SJohn Forte struct kmem_cache *fctl_job_cache; 202*fcf3ce44SJohn Forte 203*fcf3ce44SJohn Forte static fc_errmap_t fc_errlist [] = { 204*fcf3ce44SJohn Forte { FC_FAILURE, "Operation failed" }, 205*fcf3ce44SJohn Forte { FC_SUCCESS, "Operation success" }, 206*fcf3ce44SJohn Forte { FC_CAP_ERROR, "Capability error" }, 207*fcf3ce44SJohn Forte { FC_CAP_FOUND, "Capability found" }, 208*fcf3ce44SJohn Forte { FC_CAP_SETTABLE, "Capability settable" }, 209*fcf3ce44SJohn Forte { FC_UNBOUND, "Port not bound" }, 210*fcf3ce44SJohn Forte { FC_NOMEM, "No memory" }, 211*fcf3ce44SJohn Forte { FC_BADPACKET, "Bad packet" }, 212*fcf3ce44SJohn Forte { FC_OFFLINE, "Port offline" }, 213*fcf3ce44SJohn Forte { FC_OLDPORT, "Old Port" }, 214*fcf3ce44SJohn Forte { FC_NO_MAP, "No map available" }, 215*fcf3ce44SJohn Forte { FC_TRANSPORT_ERROR, "Transport error" }, 216*fcf3ce44SJohn Forte { FC_ELS_FREJECT, "ELS Frejected" }, 217*fcf3ce44SJohn Forte { FC_ELS_PREJECT, "ELS PRejected" }, 218*fcf3ce44SJohn Forte { FC_ELS_BAD, "Bad ELS request" }, 219*fcf3ce44SJohn Forte { FC_ELS_MALFORMED, "Malformed ELS request" }, 220*fcf3ce44SJohn Forte { FC_TOOMANY, "Too many commands" }, 221*fcf3ce44SJohn Forte { FC_UB_BADTOKEN, "Bad Unsolicited buffer token" }, 222*fcf3ce44SJohn Forte { FC_UB_ERROR, "Unsolicited buffer error" }, 223*fcf3ce44SJohn Forte { FC_UB_BUSY, "Unsolicited buffer busy" }, 224*fcf3ce44SJohn Forte { FC_BADULP, "Bad ULP" }, 225*fcf3ce44SJohn Forte { FC_BADTYPE, "Bad Type" }, 226*fcf3ce44SJohn Forte { FC_UNCLAIMED, "Not Claimed" }, 227*fcf3ce44SJohn Forte { FC_ULP_SAMEMODULE, "Same ULP Module" }, 228*fcf3ce44SJohn Forte { FC_ULP_SAMETYPE, "Same ULP Type" }, 229*fcf3ce44SJohn Forte { FC_ABORTED, "Command Aborted" }, 230*fcf3ce44SJohn Forte { FC_ABORT_FAILED, "Abort Failed" }, 231*fcf3ce44SJohn Forte { FC_BADEXCHANGE, "Bad Exchange" }, 232*fcf3ce44SJohn Forte { FC_BADWWN, "Bad World Wide Name" }, 233*fcf3ce44SJohn Forte { FC_BADDEV, "Bad Device" }, 234*fcf3ce44SJohn Forte { FC_BADCMD, "Bad Command" }, 235*fcf3ce44SJohn Forte { FC_BADOBJECT, "Bad Object" }, 236*fcf3ce44SJohn Forte { FC_BADPORT, "Bad Port" }, 237*fcf3ce44SJohn Forte { FC_NOTTHISPORT, "Not on this Port" }, 238*fcf3ce44SJohn Forte { FC_PREJECT, "Operation Prejected" }, 239*fcf3ce44SJohn Forte { FC_FREJECT, "Operation Frejected" }, 240*fcf3ce44SJohn Forte { FC_PBUSY, "Operation Pbusyed" }, 241*fcf3ce44SJohn Forte { FC_FBUSY, "Operation Fbusyed" }, 242*fcf3ce44SJohn Forte { FC_ALREADY, "Already done" }, 243*fcf3ce44SJohn Forte { FC_LOGINREQ, "PLOGI Required" }, 244*fcf3ce44SJohn Forte { FC_RESETFAIL, "Reset operation failed" }, 245*fcf3ce44SJohn Forte { FC_INVALID_REQUEST, "Invalid Request" }, 246*fcf3ce44SJohn Forte { FC_OUTOFBOUNDS, "Out of Bounds" }, 247*fcf3ce44SJohn Forte { FC_TRAN_BUSY, "Command transport Busy" }, 248*fcf3ce44SJohn Forte { FC_STATEC_BUSY, "State change Busy" }, 249*fcf3ce44SJohn Forte { FC_DEVICE_BUSY, "Port driver is working on this device" } 250*fcf3ce44SJohn Forte }; 251*fcf3ce44SJohn Forte 252*fcf3ce44SJohn Forte fc_pkt_reason_t remote_stop_reasons [] = { 253*fcf3ce44SJohn Forte { FC_REASON_ABTS, "Abort Sequence" }, 254*fcf3ce44SJohn Forte { FC_REASON_ABTX, "Abort Exchange" }, 255*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 256*fcf3ce44SJohn Forte }; 257*fcf3ce44SJohn Forte 258*fcf3ce44SJohn Forte fc_pkt_reason_t general_reasons [] = { 259*fcf3ce44SJohn Forte { FC_REASON_HW_ERROR, "Hardware Error" }, 260*fcf3ce44SJohn Forte { FC_REASON_SEQ_TIMEOUT, "Sequence Timeout" }, 261*fcf3ce44SJohn Forte { FC_REASON_ABORTED, "Aborted" }, 262*fcf3ce44SJohn Forte { FC_REASON_ABORT_FAILED, "Abort Failed" }, 263*fcf3ce44SJohn Forte { FC_REASON_NO_CONNECTION, "No Connection" }, 264*fcf3ce44SJohn Forte { FC_REASON_XCHG_DROPPED, "Exchange Dropped" }, 265*fcf3ce44SJohn Forte { FC_REASON_ILLEGAL_FRAME, "Illegal Frame" }, 266*fcf3ce44SJohn Forte { FC_REASON_ILLEGAL_LENGTH, "Illegal Length" }, 267*fcf3ce44SJohn Forte { FC_REASON_UNSUPPORTED, "Unsuported" }, 268*fcf3ce44SJohn Forte { FC_REASON_RX_BUF_TIMEOUT, "Receive Buffer Timeout" }, 269*fcf3ce44SJohn Forte { FC_REASON_FCAL_OPN_FAIL, "FC AL Open Failed" }, 270*fcf3ce44SJohn Forte { FC_REASON_OVERRUN, "Over run" }, 271*fcf3ce44SJohn Forte { FC_REASON_QFULL, "Queue Full" }, 272*fcf3ce44SJohn Forte { FC_REASON_ILLEGAL_REQ, "Illegal Request", }, 273*fcf3ce44SJohn Forte { FC_REASON_PKT_BUSY, "Busy" }, 274*fcf3ce44SJohn Forte { FC_REASON_OFFLINE, "Offline" }, 275*fcf3ce44SJohn Forte { FC_REASON_BAD_XID, "Bad Exchange Id" }, 276*fcf3ce44SJohn Forte { FC_REASON_XCHG_BSY, "Exchange Busy" }, 277*fcf3ce44SJohn Forte { FC_REASON_NOMEM, "No Memory" }, 278*fcf3ce44SJohn Forte { FC_REASON_BAD_SID, "Bad S_ID" }, 279*fcf3ce44SJohn Forte { FC_REASON_NO_SEQ_INIT, "No Sequence Initiative" }, 280*fcf3ce44SJohn Forte { FC_REASON_DIAG_BUSY, "Diagnostic Busy" }, 281*fcf3ce44SJohn Forte { FC_REASON_DMA_ERROR, "DMA Error" }, 282*fcf3ce44SJohn Forte { FC_REASON_CRC_ERROR, "CRC Error" }, 283*fcf3ce44SJohn Forte { FC_REASON_ABORT_TIMEOUT, "Abort Timeout" }, 284*fcf3ce44SJohn Forte { FC_REASON_FCA_UNIQUE, "FCA Unique" }, 285*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 286*fcf3ce44SJohn Forte }; 287*fcf3ce44SJohn Forte 288*fcf3ce44SJohn Forte fc_pkt_reason_t rjt_reasons [] = { 289*fcf3ce44SJohn Forte { FC_REASON_INVALID_D_ID, "Invalid D_ID" }, 290*fcf3ce44SJohn Forte { FC_REASON_INVALID_S_ID, "Invalid S_ID" }, 291*fcf3ce44SJohn Forte { FC_REASON_TEMP_UNAVAILABLE, "Temporarily Unavailable" }, 292*fcf3ce44SJohn Forte { FC_REASON_PERM_UNAVAILABLE, "Permamnently Unavailable" }, 293*fcf3ce44SJohn Forte { FC_REASON_CLASS_NOT_SUPP, "Class Not Supported", }, 294*fcf3ce44SJohn Forte { FC_REASON_DELIMTER_USAGE_ERROR, 295*fcf3ce44SJohn Forte "Delimeter Usage Error" }, 296*fcf3ce44SJohn Forte { FC_REASON_TYPE_NOT_SUPP, "Type Not Supported" }, 297*fcf3ce44SJohn Forte { FC_REASON_INVALID_LINK_CTRL, "Invalid Link Control" }, 298*fcf3ce44SJohn Forte { FC_REASON_INVALID_R_CTL, "Invalid R_CTL" }, 299*fcf3ce44SJohn Forte { FC_REASON_INVALID_F_CTL, "Invalid F_CTL" }, 300*fcf3ce44SJohn Forte { FC_REASON_INVALID_OX_ID, "Invalid OX_ID" }, 301*fcf3ce44SJohn Forte { FC_REASON_INVALID_RX_ID, "Invalid RX_ID" }, 302*fcf3ce44SJohn Forte { FC_REASON_INVALID_SEQ_ID, "Invalid Sequence ID" }, 303*fcf3ce44SJohn Forte { FC_REASON_INVALID_DF_CTL, "Invalid DF_CTL" }, 304*fcf3ce44SJohn Forte { FC_REASON_INVALID_SEQ_CNT, "Invalid Sequence count" }, 305*fcf3ce44SJohn Forte { FC_REASON_INVALID_PARAM, "Invalid Parameter" }, 306*fcf3ce44SJohn Forte { FC_REASON_EXCH_ERROR, "Exchange Error" }, 307*fcf3ce44SJohn Forte { FC_REASON_PROTOCOL_ERROR, "Protocol Error" }, 308*fcf3ce44SJohn Forte { FC_REASON_INCORRECT_LENGTH, "Incorrect Length" }, 309*fcf3ce44SJohn Forte { FC_REASON_UNEXPECTED_ACK, "Unexpected Ack" }, 310*fcf3ce44SJohn Forte { FC_REASON_UNEXPECTED_LR, "Unexpected Link reset" }, 311*fcf3ce44SJohn Forte { FC_REASON_LOGIN_REQUIRED, "Login Required" }, 312*fcf3ce44SJohn Forte { FC_REASON_EXCESSIVE_SEQS, "Excessive Sequences" 313*fcf3ce44SJohn Forte " Attempted" }, 314*fcf3ce44SJohn Forte { FC_REASON_EXCH_UNABLE, "Exchange incapable" }, 315*fcf3ce44SJohn Forte { FC_REASON_ESH_NOT_SUPP, "Expiration Security Header " 316*fcf3ce44SJohn Forte "Not Supported" }, 317*fcf3ce44SJohn Forte { FC_REASON_NO_FABRIC_PATH, "No Fabric Path" }, 318*fcf3ce44SJohn Forte { FC_REASON_VENDOR_UNIQUE, "Vendor Unique" }, 319*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 320*fcf3ce44SJohn Forte }; 321*fcf3ce44SJohn Forte 322*fcf3ce44SJohn Forte fc_pkt_reason_t n_port_busy_reasons [] = { 323*fcf3ce44SJohn Forte { FC_REASON_PHYSICAL_BUSY, "Physical Busy" }, 324*fcf3ce44SJohn Forte { FC_REASON_N_PORT_RESOURCE_BSY, "Resource Busy" }, 325*fcf3ce44SJohn Forte { FC_REASON_N_PORT_VENDOR_UNIQUE, "Vendor Unique" }, 326*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 327*fcf3ce44SJohn Forte }; 328*fcf3ce44SJohn Forte 329*fcf3ce44SJohn Forte fc_pkt_reason_t f_busy_reasons [] = { 330*fcf3ce44SJohn Forte { FC_REASON_FABRIC_BSY, "Fabric Busy" }, 331*fcf3ce44SJohn Forte { FC_REASON_N_PORT_BSY, "N_Port Busy" }, 332*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 333*fcf3ce44SJohn Forte }; 334*fcf3ce44SJohn Forte 335*fcf3ce44SJohn Forte fc_pkt_reason_t ls_ba_rjt_reasons [] = { 336*fcf3ce44SJohn Forte { FC_REASON_INVALID_LA_CODE, "Invalid Link Application Code" }, 337*fcf3ce44SJohn Forte { FC_REASON_LOGICAL_ERROR, "Logical Error" }, 338*fcf3ce44SJohn Forte { FC_REASON_LOGICAL_BSY, "Logical Busy" }, 339*fcf3ce44SJohn Forte { FC_REASON_PROTOCOL_ERROR_RJT, "Protocol Error Reject" }, 340*fcf3ce44SJohn Forte { FC_REASON_CMD_UNABLE, "Unable to Perform Command" }, 341*fcf3ce44SJohn Forte { FC_REASON_CMD_UNSUPPORTED, "Unsupported Command" }, 342*fcf3ce44SJohn Forte { FC_REASON_VU_RJT, "Vendor Unique" }, 343*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 344*fcf3ce44SJohn Forte }; 345*fcf3ce44SJohn Forte 346*fcf3ce44SJohn Forte fc_pkt_reason_t fs_rjt_reasons [] = { 347*fcf3ce44SJohn Forte { FC_REASON_FS_INVALID_CMD, "Invalid Command" }, 348*fcf3ce44SJohn Forte { FC_REASON_FS_INVALID_VER, "Invalid Version" }, 349*fcf3ce44SJohn Forte { FC_REASON_FS_LOGICAL_ERR, "Logical Error" }, 350*fcf3ce44SJohn Forte { FC_REASON_FS_INVALID_IUSIZE, "Invalid IU Size" }, 351*fcf3ce44SJohn Forte { FC_REASON_FS_LOGICAL_BUSY, "Logical Busy" }, 352*fcf3ce44SJohn Forte { FC_REASON_FS_PROTOCOL_ERR, "Protocol Error" }, 353*fcf3ce44SJohn Forte { FC_REASON_FS_CMD_UNABLE, "Unable to Perform Command" }, 354*fcf3ce44SJohn Forte { FC_REASON_FS_CMD_UNSUPPORTED, "Unsupported Command" }, 355*fcf3ce44SJohn Forte { FC_REASON_FS_VENDOR_UNIQUE, "Vendor Unique" }, 356*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 357*fcf3ce44SJohn Forte }; 358*fcf3ce44SJohn Forte 359*fcf3ce44SJohn Forte fc_pkt_action_t n_port_busy_actions [] = { 360*fcf3ce44SJohn Forte { FC_ACTION_SEQ_TERM_RETRY, "Retry terminated Sequence" }, 361*fcf3ce44SJohn Forte { FC_ACTION_SEQ_ACTIVE_RETRY, "Retry Active Sequence" }, 362*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 363*fcf3ce44SJohn Forte }; 364*fcf3ce44SJohn Forte 365*fcf3ce44SJohn Forte fc_pkt_action_t rjt_timeout_actions [] = { 366*fcf3ce44SJohn Forte { FC_ACTION_RETRYABLE, "Retryable" }, 367*fcf3ce44SJohn Forte { FC_ACTION_NON_RETRYABLE, "Non Retryable" }, 368*fcf3ce44SJohn Forte { FC_REASON_INVALID, NULL } 369*fcf3ce44SJohn Forte }; 370*fcf3ce44SJohn Forte 371*fcf3ce44SJohn Forte fc_pkt_expln_t ba_rjt_explns [] = { 372*fcf3ce44SJohn Forte { FC_EXPLN_NONE, "No Explanation" }, 373*fcf3ce44SJohn Forte { FC_EXPLN_INVALID_OX_RX_ID, "Invalid X_ID" }, 374*fcf3ce44SJohn Forte { FC_EXPLN_SEQ_ABORTED, "Sequence Aborted" }, 375*fcf3ce44SJohn Forte { FC_EXPLN_INVALID, NULL } 376*fcf3ce44SJohn Forte }; 377*fcf3ce44SJohn Forte 378*fcf3ce44SJohn Forte fc_pkt_error_t fc_pkt_errlist[] = { 379*fcf3ce44SJohn Forte { 380*fcf3ce44SJohn Forte FC_PKT_SUCCESS, 381*fcf3ce44SJohn Forte "Operation Success", 382*fcf3ce44SJohn Forte NULL, 383*fcf3ce44SJohn Forte NULL, 384*fcf3ce44SJohn Forte NULL 385*fcf3ce44SJohn Forte }, 386*fcf3ce44SJohn Forte { FC_PKT_REMOTE_STOP, 387*fcf3ce44SJohn Forte "Remote Stop", 388*fcf3ce44SJohn Forte remote_stop_reasons, 389*fcf3ce44SJohn Forte NULL, 390*fcf3ce44SJohn Forte NULL 391*fcf3ce44SJohn Forte }, 392*fcf3ce44SJohn Forte { 393*fcf3ce44SJohn Forte FC_PKT_LOCAL_RJT, 394*fcf3ce44SJohn Forte "Local Reject", 395*fcf3ce44SJohn Forte general_reasons, 396*fcf3ce44SJohn Forte rjt_timeout_actions, 397*fcf3ce44SJohn Forte NULL 398*fcf3ce44SJohn Forte }, 399*fcf3ce44SJohn Forte { 400*fcf3ce44SJohn Forte FC_PKT_NPORT_RJT, 401*fcf3ce44SJohn Forte "N_Port Reject", 402*fcf3ce44SJohn Forte rjt_reasons, 403*fcf3ce44SJohn Forte rjt_timeout_actions, 404*fcf3ce44SJohn Forte NULL 405*fcf3ce44SJohn Forte }, 406*fcf3ce44SJohn Forte { 407*fcf3ce44SJohn Forte FC_PKT_FABRIC_RJT, 408*fcf3ce44SJohn Forte "Fabric Reject", 409*fcf3ce44SJohn Forte rjt_reasons, 410*fcf3ce44SJohn Forte rjt_timeout_actions, 411*fcf3ce44SJohn Forte NULL 412*fcf3ce44SJohn Forte }, 413*fcf3ce44SJohn Forte { 414*fcf3ce44SJohn Forte FC_PKT_LOCAL_BSY, 415*fcf3ce44SJohn Forte "Local Busy", 416*fcf3ce44SJohn Forte general_reasons, 417*fcf3ce44SJohn Forte NULL, 418*fcf3ce44SJohn Forte NULL, 419*fcf3ce44SJohn Forte }, 420*fcf3ce44SJohn Forte { 421*fcf3ce44SJohn Forte FC_PKT_TRAN_BSY, 422*fcf3ce44SJohn Forte "Transport Busy", 423*fcf3ce44SJohn Forte general_reasons, 424*fcf3ce44SJohn Forte NULL, 425*fcf3ce44SJohn Forte NULL, 426*fcf3ce44SJohn Forte }, 427*fcf3ce44SJohn Forte { 428*fcf3ce44SJohn Forte FC_PKT_NPORT_BSY, 429*fcf3ce44SJohn Forte "N_Port Busy", 430*fcf3ce44SJohn Forte n_port_busy_reasons, 431*fcf3ce44SJohn Forte n_port_busy_actions, 432*fcf3ce44SJohn Forte NULL 433*fcf3ce44SJohn Forte }, 434*fcf3ce44SJohn Forte { 435*fcf3ce44SJohn Forte FC_PKT_FABRIC_BSY, 436*fcf3ce44SJohn Forte "Fabric Busy", 437*fcf3ce44SJohn Forte f_busy_reasons, 438*fcf3ce44SJohn Forte NULL, 439*fcf3ce44SJohn Forte NULL, 440*fcf3ce44SJohn Forte }, 441*fcf3ce44SJohn Forte { 442*fcf3ce44SJohn Forte FC_PKT_LS_RJT, 443*fcf3ce44SJohn Forte "Link Service Reject", 444*fcf3ce44SJohn Forte ls_ba_rjt_reasons, 445*fcf3ce44SJohn Forte NULL, 446*fcf3ce44SJohn Forte NULL, 447*fcf3ce44SJohn Forte }, 448*fcf3ce44SJohn Forte { 449*fcf3ce44SJohn Forte FC_PKT_BA_RJT, 450*fcf3ce44SJohn Forte "Basic Reject", 451*fcf3ce44SJohn Forte ls_ba_rjt_reasons, 452*fcf3ce44SJohn Forte NULL, 453*fcf3ce44SJohn Forte ba_rjt_explns, 454*fcf3ce44SJohn Forte }, 455*fcf3ce44SJohn Forte { 456*fcf3ce44SJohn Forte FC_PKT_TIMEOUT, 457*fcf3ce44SJohn Forte "Timeout", 458*fcf3ce44SJohn Forte general_reasons, 459*fcf3ce44SJohn Forte rjt_timeout_actions, 460*fcf3ce44SJohn Forte NULL 461*fcf3ce44SJohn Forte }, 462*fcf3ce44SJohn Forte { 463*fcf3ce44SJohn Forte FC_PKT_FS_RJT, 464*fcf3ce44SJohn Forte "Fabric Switch Reject", 465*fcf3ce44SJohn Forte fs_rjt_reasons, 466*fcf3ce44SJohn Forte NULL, 467*fcf3ce44SJohn Forte NULL 468*fcf3ce44SJohn Forte }, 469*fcf3ce44SJohn Forte { 470*fcf3ce44SJohn Forte FC_PKT_TRAN_ERROR, 471*fcf3ce44SJohn Forte "Packet Transport error", 472*fcf3ce44SJohn Forte general_reasons, 473*fcf3ce44SJohn Forte NULL, 474*fcf3ce44SJohn Forte NULL 475*fcf3ce44SJohn Forte }, 476*fcf3ce44SJohn Forte { 477*fcf3ce44SJohn Forte FC_PKT_FAILURE, 478*fcf3ce44SJohn Forte "Packet Failure", 479*fcf3ce44SJohn Forte general_reasons, 480*fcf3ce44SJohn Forte NULL, 481*fcf3ce44SJohn Forte NULL 482*fcf3ce44SJohn Forte }, 483*fcf3ce44SJohn Forte { 484*fcf3ce44SJohn Forte FC_PKT_PORT_OFFLINE, 485*fcf3ce44SJohn Forte "Port Offline", 486*fcf3ce44SJohn Forte NULL, 487*fcf3ce44SJohn Forte NULL, 488*fcf3ce44SJohn Forte NULL 489*fcf3ce44SJohn Forte }, 490*fcf3ce44SJohn Forte { 491*fcf3ce44SJohn Forte FC_PKT_ELS_IN_PROGRESS, 492*fcf3ce44SJohn Forte "ELS is in Progress", 493*fcf3ce44SJohn Forte NULL, 494*fcf3ce44SJohn Forte NULL, 495*fcf3ce44SJohn Forte NULL 496*fcf3ce44SJohn Forte } 497*fcf3ce44SJohn Forte }; 498*fcf3ce44SJohn Forte 499*fcf3ce44SJohn Forte int 500*fcf3ce44SJohn Forte _init() 501*fcf3ce44SJohn Forte { 502*fcf3ce44SJohn Forte int rval; 503*fcf3ce44SJohn Forte 504*fcf3ce44SJohn Forte rw_init(&fctl_ulp_lock, NULL, RW_DRIVER, NULL); 505*fcf3ce44SJohn Forte rw_init(&fctl_mod_ports_lock, NULL, RW_DRIVER, NULL); 506*fcf3ce44SJohn Forte mutex_init(&fctl_port_lock, NULL, MUTEX_DRIVER, NULL); 507*fcf3ce44SJohn Forte mutex_init(&fctl_nwwn_hash_mutex, NULL, MUTEX_DRIVER, NULL); 508*fcf3ce44SJohn Forte 509*fcf3ce44SJohn Forte fctl_nwwn_hash_table = kmem_zalloc(sizeof (*fctl_nwwn_hash_table) * 510*fcf3ce44SJohn Forte fctl_nwwn_table_size, KM_SLEEP); 511*fcf3ce44SJohn Forte 512*fcf3ce44SJohn Forte fctl_ulp_modules = NULL; 513*fcf3ce44SJohn Forte fctl_fca_portlist = NULL; 514*fcf3ce44SJohn Forte 515*fcf3ce44SJohn Forte fctl_job_cache = kmem_cache_create("fctl_cache", 516*fcf3ce44SJohn Forte sizeof (job_request_t), 8, fctl_cache_constructor, 517*fcf3ce44SJohn Forte fctl_cache_destructor, NULL, NULL, NULL, 0); 518*fcf3ce44SJohn Forte 519*fcf3ce44SJohn Forte if (fctl_job_cache == NULL) { 520*fcf3ce44SJohn Forte kmem_free(fctl_nwwn_hash_table, 521*fcf3ce44SJohn Forte sizeof (*fctl_nwwn_hash_table) * fctl_nwwn_table_size); 522*fcf3ce44SJohn Forte mutex_destroy(&fctl_nwwn_hash_mutex); 523*fcf3ce44SJohn Forte mutex_destroy(&fctl_port_lock); 524*fcf3ce44SJohn Forte rw_destroy(&fctl_ulp_lock); 525*fcf3ce44SJohn Forte rw_destroy(&fctl_mod_ports_lock); 526*fcf3ce44SJohn Forte return (ENOMEM); 527*fcf3ce44SJohn Forte } 528*fcf3ce44SJohn Forte 529*fcf3ce44SJohn Forte if ((rval = mod_install(&modlinkage)) != 0) { 530*fcf3ce44SJohn Forte kmem_cache_destroy(fctl_job_cache); 531*fcf3ce44SJohn Forte kmem_free(fctl_nwwn_hash_table, 532*fcf3ce44SJohn Forte sizeof (*fctl_nwwn_hash_table) * fctl_nwwn_table_size); 533*fcf3ce44SJohn Forte mutex_destroy(&fctl_nwwn_hash_mutex); 534*fcf3ce44SJohn Forte mutex_destroy(&fctl_port_lock); 535*fcf3ce44SJohn Forte rw_destroy(&fctl_ulp_lock); 536*fcf3ce44SJohn Forte rw_destroy(&fctl_mod_ports_lock); 537*fcf3ce44SJohn Forte } 538*fcf3ce44SJohn Forte 539*fcf3ce44SJohn Forte return (rval); 540*fcf3ce44SJohn Forte } 541*fcf3ce44SJohn Forte 542*fcf3ce44SJohn Forte 543*fcf3ce44SJohn Forte /* 544*fcf3ce44SJohn Forte * The mod_uninstall code doesn't call _fini when 545*fcf3ce44SJohn Forte * there is living dependent module on fctl. So 546*fcf3ce44SJohn Forte * there is no need to be extra careful here ? 547*fcf3ce44SJohn Forte */ 548*fcf3ce44SJohn Forte int 549*fcf3ce44SJohn Forte _fini() 550*fcf3ce44SJohn Forte { 551*fcf3ce44SJohn Forte int rval; 552*fcf3ce44SJohn Forte 553*fcf3ce44SJohn Forte if ((rval = mod_remove(&modlinkage)) != 0) { 554*fcf3ce44SJohn Forte return (rval); 555*fcf3ce44SJohn Forte } 556*fcf3ce44SJohn Forte 557*fcf3ce44SJohn Forte kmem_cache_destroy(fctl_job_cache); 558*fcf3ce44SJohn Forte kmem_free(fctl_nwwn_hash_table, 559*fcf3ce44SJohn Forte sizeof (*fctl_nwwn_hash_table) * fctl_nwwn_table_size); 560*fcf3ce44SJohn Forte mutex_destroy(&fctl_nwwn_hash_mutex); 561*fcf3ce44SJohn Forte mutex_destroy(&fctl_port_lock); 562*fcf3ce44SJohn Forte rw_destroy(&fctl_ulp_lock); 563*fcf3ce44SJohn Forte rw_destroy(&fctl_mod_ports_lock); 564*fcf3ce44SJohn Forte 565*fcf3ce44SJohn Forte return (rval); 566*fcf3ce44SJohn Forte } 567*fcf3ce44SJohn Forte 568*fcf3ce44SJohn Forte 569*fcf3ce44SJohn Forte int 570*fcf3ce44SJohn Forte _info(struct modinfo *modinfo_p) 571*fcf3ce44SJohn Forte { 572*fcf3ce44SJohn Forte return (mod_info(&modlinkage, modinfo_p)); 573*fcf3ce44SJohn Forte } 574*fcf3ce44SJohn Forte 575*fcf3ce44SJohn Forte 576*fcf3ce44SJohn Forte /* ARGSUSED */ 577*fcf3ce44SJohn Forte static int 578*fcf3ce44SJohn Forte fctl_cache_constructor(void *buf, void *cdarg, int kmflag) 579*fcf3ce44SJohn Forte { 580*fcf3ce44SJohn Forte job_request_t *job = (job_request_t *)buf; 581*fcf3ce44SJohn Forte 582*fcf3ce44SJohn Forte mutex_init(&job->job_mutex, NULL, MUTEX_DRIVER, NULL); 583*fcf3ce44SJohn Forte sema_init(&job->job_fctl_sema, 0, NULL, SEMA_DEFAULT, NULL); 584*fcf3ce44SJohn Forte sema_init(&job->job_port_sema, 0, NULL, SEMA_DEFAULT, NULL); 585*fcf3ce44SJohn Forte 586*fcf3ce44SJohn Forte return (0); 587*fcf3ce44SJohn Forte } 588*fcf3ce44SJohn Forte 589*fcf3ce44SJohn Forte 590*fcf3ce44SJohn Forte /* ARGSUSED */ 591*fcf3ce44SJohn Forte static void 592*fcf3ce44SJohn Forte fctl_cache_destructor(void *buf, void *cdarg) 593*fcf3ce44SJohn Forte { 594*fcf3ce44SJohn Forte job_request_t *job = (job_request_t *)buf; 595*fcf3ce44SJohn Forte 596*fcf3ce44SJohn Forte sema_destroy(&job->job_fctl_sema); 597*fcf3ce44SJohn Forte sema_destroy(&job->job_port_sema); 598*fcf3ce44SJohn Forte mutex_destroy(&job->job_mutex); 599*fcf3ce44SJohn Forte } 600*fcf3ce44SJohn Forte 601*fcf3ce44SJohn Forte 602*fcf3ce44SJohn Forte /* 603*fcf3ce44SJohn Forte * fc_ulp_add: 604*fcf3ce44SJohn Forte * Add a ULP module 605*fcf3ce44SJohn Forte * 606*fcf3ce44SJohn Forte * Return Codes: 607*fcf3ce44SJohn Forte * FC_ULP_SAMEMODULE 608*fcf3ce44SJohn Forte * FC_SUCCESS 609*fcf3ce44SJohn Forte * FC_FAILURE 610*fcf3ce44SJohn Forte * 611*fcf3ce44SJohn Forte * fc_ulp_add prints a warning message if there is already a 612*fcf3ce44SJohn Forte * similar ULP type attached and this is unlikely to change as 613*fcf3ce44SJohn Forte * we trudge along. Further, this function returns a failure 614*fcf3ce44SJohn Forte * code if the same module attempts to add more than once for 615*fcf3ce44SJohn Forte * the same FC-4 type. 616*fcf3ce44SJohn Forte */ 617*fcf3ce44SJohn Forte int 618*fcf3ce44SJohn Forte fc_ulp_add(fc_ulp_modinfo_t *ulp_info) 619*fcf3ce44SJohn Forte { 620*fcf3ce44SJohn Forte fc_ulp_module_t *mod; 621*fcf3ce44SJohn Forte fc_ulp_module_t *prev; 622*fcf3ce44SJohn Forte job_request_t *job; 623*fcf3ce44SJohn Forte fc_ulp_list_t *new; 624*fcf3ce44SJohn Forte fc_fca_port_t *fca_port; 625*fcf3ce44SJohn Forte int ntry = 0; 626*fcf3ce44SJohn Forte 627*fcf3ce44SJohn Forte ASSERT(ulp_info != NULL); 628*fcf3ce44SJohn Forte 629*fcf3ce44SJohn Forte /* 630*fcf3ce44SJohn Forte * Make sure ulp_rev matches fctl version. 631*fcf3ce44SJohn Forte * Whenever non-private data structure or non-static interface changes, 632*fcf3ce44SJohn Forte * we should use an increased FCTL_ULP_MODREV_# number here and in all 633*fcf3ce44SJohn Forte * ulps to prevent version mismatch. 634*fcf3ce44SJohn Forte */ 635*fcf3ce44SJohn Forte if (ulp_info->ulp_rev != FCTL_ULP_MODREV_4) { 636*fcf3ce44SJohn Forte cmn_err(CE_WARN, "fctl: ULP %s version mismatch;" 637*fcf3ce44SJohn Forte " ULP %s would not be loaded", ulp_info->ulp_name, 638*fcf3ce44SJohn Forte ulp_info->ulp_name); 639*fcf3ce44SJohn Forte return (FC_BADULP); 640*fcf3ce44SJohn Forte } 641*fcf3ce44SJohn Forte 642*fcf3ce44SJohn Forte new = kmem_zalloc(sizeof (*new), KM_SLEEP); 643*fcf3ce44SJohn Forte ASSERT(new != NULL); 644*fcf3ce44SJohn Forte 645*fcf3ce44SJohn Forte mutex_enter(&fctl_ulp_list_mutex); 646*fcf3ce44SJohn Forte new->ulp_info = ulp_info; 647*fcf3ce44SJohn Forte if (fctl_ulp_list != NULL) { 648*fcf3ce44SJohn Forte new->ulp_next = fctl_ulp_list; 649*fcf3ce44SJohn Forte } 650*fcf3ce44SJohn Forte fctl_ulp_list = new; 651*fcf3ce44SJohn Forte mutex_exit(&fctl_ulp_list_mutex); 652*fcf3ce44SJohn Forte 653*fcf3ce44SJohn Forte while (rw_tryenter(&fctl_ulp_lock, RW_WRITER) == 0) { 654*fcf3ce44SJohn Forte delay(drv_usectohz(1000000)); 655*fcf3ce44SJohn Forte if (ntry++ > FC_ULP_ADD_RETRY_COUNT) { 656*fcf3ce44SJohn Forte fc_ulp_list_t *list; 657*fcf3ce44SJohn Forte fc_ulp_list_t *last; 658*fcf3ce44SJohn Forte mutex_enter(&fctl_ulp_list_mutex); 659*fcf3ce44SJohn Forte for (last = NULL, list = fctl_ulp_list; list != NULL; 660*fcf3ce44SJohn Forte list = list->ulp_next) { 661*fcf3ce44SJohn Forte if (list->ulp_info == ulp_info) { 662*fcf3ce44SJohn Forte break; 663*fcf3ce44SJohn Forte } 664*fcf3ce44SJohn Forte last = list; 665*fcf3ce44SJohn Forte } 666*fcf3ce44SJohn Forte 667*fcf3ce44SJohn Forte if (list) { 668*fcf3ce44SJohn Forte if (last) { 669*fcf3ce44SJohn Forte last->ulp_next = list->ulp_next; 670*fcf3ce44SJohn Forte } else { 671*fcf3ce44SJohn Forte fctl_ulp_list = list->ulp_next; 672*fcf3ce44SJohn Forte } 673*fcf3ce44SJohn Forte kmem_free(list, sizeof (*list)); 674*fcf3ce44SJohn Forte } 675*fcf3ce44SJohn Forte mutex_exit(&fctl_ulp_list_mutex); 676*fcf3ce44SJohn Forte cmn_err(CE_WARN, "fctl: ULP %s unable to load", 677*fcf3ce44SJohn Forte ulp_info->ulp_name); 678*fcf3ce44SJohn Forte return (FC_FAILURE); 679*fcf3ce44SJohn Forte } 680*fcf3ce44SJohn Forte } 681*fcf3ce44SJohn Forte 682*fcf3ce44SJohn Forte for (mod = fctl_ulp_modules, prev = NULL; mod; mod = mod->mod_next) { 683*fcf3ce44SJohn Forte ASSERT(mod->mod_info != NULL); 684*fcf3ce44SJohn Forte 685*fcf3ce44SJohn Forte if (ulp_info == mod->mod_info && 686*fcf3ce44SJohn Forte ulp_info->ulp_type == mod->mod_info->ulp_type) { 687*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 688*fcf3ce44SJohn Forte return (FC_ULP_SAMEMODULE); 689*fcf3ce44SJohn Forte } 690*fcf3ce44SJohn Forte 691*fcf3ce44SJohn Forte if (ulp_info->ulp_type == mod->mod_info->ulp_type) { 692*fcf3ce44SJohn Forte cmn_err(CE_NOTE, fctl_greeting, ulp_info->ulp_name, 693*fcf3ce44SJohn Forte ulp_info->ulp_type); 694*fcf3ce44SJohn Forte } 695*fcf3ce44SJohn Forte prev = mod; 696*fcf3ce44SJohn Forte } 697*fcf3ce44SJohn Forte 698*fcf3ce44SJohn Forte mod = kmem_zalloc(sizeof (*mod), KM_SLEEP); 699*fcf3ce44SJohn Forte mod->mod_info = ulp_info; 700*fcf3ce44SJohn Forte mod->mod_next = NULL; 701*fcf3ce44SJohn Forte 702*fcf3ce44SJohn Forte if (prev) { 703*fcf3ce44SJohn Forte prev->mod_next = mod; 704*fcf3ce44SJohn Forte } else { 705*fcf3ce44SJohn Forte fctl_ulp_modules = mod; 706*fcf3ce44SJohn Forte } 707*fcf3ce44SJohn Forte 708*fcf3ce44SJohn Forte /* 709*fcf3ce44SJohn Forte * Schedule a job to each port's job_handler 710*fcf3ce44SJohn Forte * thread to attach their ports with this ULP. 711*fcf3ce44SJohn Forte */ 712*fcf3ce44SJohn Forte mutex_enter(&fctl_port_lock); 713*fcf3ce44SJohn Forte for (fca_port = fctl_fca_portlist; fca_port != NULL; 714*fcf3ce44SJohn Forte fca_port = fca_port->port_next) { 715*fcf3ce44SJohn Forte 716*fcf3ce44SJohn Forte job = fctl_alloc_job(JOB_ATTACH_ULP, JOB_TYPE_FCTL_ASYNC, 717*fcf3ce44SJohn Forte NULL, NULL, KM_SLEEP); 718*fcf3ce44SJohn Forte 719*fcf3ce44SJohn Forte fctl_enque_job(fca_port->port_handle, job); 720*fcf3ce44SJohn Forte } 721*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 722*fcf3ce44SJohn Forte 723*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 724*fcf3ce44SJohn Forte 725*fcf3ce44SJohn Forte return (FC_SUCCESS); 726*fcf3ce44SJohn Forte } 727*fcf3ce44SJohn Forte 728*fcf3ce44SJohn Forte 729*fcf3ce44SJohn Forte /* 730*fcf3ce44SJohn Forte * fc_ulp_remove 731*fcf3ce44SJohn Forte * Remove a ULP module 732*fcf3ce44SJohn Forte * 733*fcf3ce44SJohn Forte * A misbehaving ULP may call this routine while I/Os are in progress. 734*fcf3ce44SJohn Forte * Currently there is no mechanism to detect it to fail such a request. 735*fcf3ce44SJohn Forte * 736*fcf3ce44SJohn Forte * Return Codes: 737*fcf3ce44SJohn Forte * FC_SUCCESS 738*fcf3ce44SJohn Forte * FC_FAILURE 739*fcf3ce44SJohn Forte */ 740*fcf3ce44SJohn Forte int 741*fcf3ce44SJohn Forte fc_ulp_remove(fc_ulp_modinfo_t *ulp_info) 742*fcf3ce44SJohn Forte { 743*fcf3ce44SJohn Forte fc_ulp_module_t *mod; 744*fcf3ce44SJohn Forte fc_ulp_list_t *list; 745*fcf3ce44SJohn Forte fc_ulp_list_t *last; 746*fcf3ce44SJohn Forte fc_ulp_module_t *prev; 747*fcf3ce44SJohn Forte 748*fcf3ce44SJohn Forte mutex_enter(&fctl_ulp_list_mutex); 749*fcf3ce44SJohn Forte 750*fcf3ce44SJohn Forte for (last = NULL, list = fctl_ulp_list; list != NULL; 751*fcf3ce44SJohn Forte list = list->ulp_next) { 752*fcf3ce44SJohn Forte if (list->ulp_info == ulp_info) { 753*fcf3ce44SJohn Forte break; 754*fcf3ce44SJohn Forte } 755*fcf3ce44SJohn Forte last = list; 756*fcf3ce44SJohn Forte } 757*fcf3ce44SJohn Forte 758*fcf3ce44SJohn Forte if (list) { 759*fcf3ce44SJohn Forte if (last) { 760*fcf3ce44SJohn Forte last->ulp_next = list->ulp_next; 761*fcf3ce44SJohn Forte } else { 762*fcf3ce44SJohn Forte fctl_ulp_list = list->ulp_next; 763*fcf3ce44SJohn Forte } 764*fcf3ce44SJohn Forte kmem_free(list, sizeof (*list)); 765*fcf3ce44SJohn Forte } 766*fcf3ce44SJohn Forte 767*fcf3ce44SJohn Forte mutex_exit(&fctl_ulp_list_mutex); 768*fcf3ce44SJohn Forte 769*fcf3ce44SJohn Forte rw_enter(&fctl_ulp_lock, RW_WRITER); 770*fcf3ce44SJohn Forte 771*fcf3ce44SJohn Forte for (mod = fctl_ulp_modules, prev = NULL; mod != NULL; 772*fcf3ce44SJohn Forte mod = mod->mod_next) { 773*fcf3ce44SJohn Forte if (mod->mod_info == ulp_info) { 774*fcf3ce44SJohn Forte break; 775*fcf3ce44SJohn Forte } 776*fcf3ce44SJohn Forte prev = mod; 777*fcf3ce44SJohn Forte } 778*fcf3ce44SJohn Forte 779*fcf3ce44SJohn Forte if (mod) { 780*fcf3ce44SJohn Forte fc_ulp_ports_t *next; 781*fcf3ce44SJohn Forte 782*fcf3ce44SJohn Forte if (prev) { 783*fcf3ce44SJohn Forte prev->mod_next = mod->mod_next; 784*fcf3ce44SJohn Forte } else { 785*fcf3ce44SJohn Forte fctl_ulp_modules = mod->mod_next; 786*fcf3ce44SJohn Forte } 787*fcf3ce44SJohn Forte 788*fcf3ce44SJohn Forte rw_enter(&fctl_mod_ports_lock, RW_WRITER); 789*fcf3ce44SJohn Forte 790*fcf3ce44SJohn Forte while ((next = mod->mod_ports) != NULL) { 791*fcf3ce44SJohn Forte mod->mod_ports = next->port_next; 792*fcf3ce44SJohn Forte fctl_dealloc_ulp_port(next); 793*fcf3ce44SJohn Forte } 794*fcf3ce44SJohn Forte 795*fcf3ce44SJohn Forte rw_exit(&fctl_mod_ports_lock); 796*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 797*fcf3ce44SJohn Forte 798*fcf3ce44SJohn Forte kmem_free(mod, sizeof (*mod)); 799*fcf3ce44SJohn Forte 800*fcf3ce44SJohn Forte return (FC_SUCCESS); 801*fcf3ce44SJohn Forte } 802*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 803*fcf3ce44SJohn Forte 804*fcf3ce44SJohn Forte return (FC_FAILURE); 805*fcf3ce44SJohn Forte } 806*fcf3ce44SJohn Forte 807*fcf3ce44SJohn Forte 808*fcf3ce44SJohn Forte /* 809*fcf3ce44SJohn Forte * The callers typically cache allocate the packet, complete the 810*fcf3ce44SJohn Forte * DMA setup for pkt_cmd and pkt_resp fields of the packet and 811*fcf3ce44SJohn Forte * call this function to see if the FCA is interested in doing 812*fcf3ce44SJohn Forte * its own intialization. For example, socal may like to initialize 813*fcf3ce44SJohn Forte * the soc_hdr which is pointed to by the pkt_fca_private field 814*fcf3ce44SJohn Forte * and sitting right below fc_packet_t in memory. 815*fcf3ce44SJohn Forte * 816*fcf3ce44SJohn Forte * The caller is required to ensure that pkt_pd is populated with the 817*fcf3ce44SJohn Forte * handle that it was given when the transport notified it about the 818*fcf3ce44SJohn Forte * device this packet is associated with. If there is no associated 819*fcf3ce44SJohn Forte * device, pkt_pd must be set to NULL. A non-NULL pkt_pd will cause an 820*fcf3ce44SJohn Forte * increment of the reference count for said pd. When the packet is freed, 821*fcf3ce44SJohn Forte * the reference count will be decremented. This reference count, in 822*fcf3ce44SJohn Forte * combination with the PD_GIVEN_TO_ULPS flag guarantees that the pd 823*fcf3ce44SJohn Forte * will not wink out of existence while there is a packet outstanding. 824*fcf3ce44SJohn Forte * 825*fcf3ce44SJohn Forte * This function and fca_init_pkt must not perform any operations that 826*fcf3ce44SJohn Forte * would result in a call back to the ULP, as the ULP may be required 827*fcf3ce44SJohn Forte * to hold a mutex across this call to ensure that the pd in question 828*fcf3ce44SJohn Forte * won't go away prior the call to fc_ulp_transport. 829*fcf3ce44SJohn Forte * 830*fcf3ce44SJohn Forte * ULPs are responsible for using the handles they are given during state 831*fcf3ce44SJohn Forte * change callback processing in a manner that ensures consistency. That 832*fcf3ce44SJohn Forte * is, they must be aware that they could be processing a state change 833*fcf3ce44SJohn Forte * notification that tells them the device associated with a particular 834*fcf3ce44SJohn Forte * handle has gone away at the same time they are being asked to 835*fcf3ce44SJohn Forte * initialize a packet using that handle. ULPs must therefore ensure 836*fcf3ce44SJohn Forte * that their state change processing and packet initialization code 837*fcf3ce44SJohn Forte * paths are sufficiently synchronized to avoid the use of an 838*fcf3ce44SJohn Forte * invalidated handle in any fc_packet_t struct that is passed to the 839*fcf3ce44SJohn Forte * fc_ulp_init_packet() function. 840*fcf3ce44SJohn Forte */ 841*fcf3ce44SJohn Forte int 842*fcf3ce44SJohn Forte fc_ulp_init_packet(opaque_t port_handle, fc_packet_t *pkt, int sleep) 843*fcf3ce44SJohn Forte { 844*fcf3ce44SJohn Forte int rval; 845*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 846*fcf3ce44SJohn Forte fc_remote_port_t *pd; 847*fcf3ce44SJohn Forte 848*fcf3ce44SJohn Forte ASSERT(pkt != NULL); 849*fcf3ce44SJohn Forte 850*fcf3ce44SJohn Forte pd = pkt->pkt_pd; 851*fcf3ce44SJohn Forte 852*fcf3ce44SJohn Forte /* Call the FCA driver's fca_init_pkt entry point function. */ 853*fcf3ce44SJohn Forte rval = port->fp_fca_tran->fca_init_pkt(port->fp_fca_handle, pkt, sleep); 854*fcf3ce44SJohn Forte 855*fcf3ce44SJohn Forte if ((rval == FC_SUCCESS) && (pd != NULL)) { 856*fcf3ce44SJohn Forte /* 857*fcf3ce44SJohn Forte * A !NULL pd here must still be a valid 858*fcf3ce44SJohn Forte * reference to the fc_remote_port_t. 859*fcf3ce44SJohn Forte */ 860*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 861*fcf3ce44SJohn Forte ASSERT(pd->pd_ref_count >= 0); 862*fcf3ce44SJohn Forte pd->pd_ref_count++; 863*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 864*fcf3ce44SJohn Forte } 865*fcf3ce44SJohn Forte 866*fcf3ce44SJohn Forte return (rval); 867*fcf3ce44SJohn Forte } 868*fcf3ce44SJohn Forte 869*fcf3ce44SJohn Forte 870*fcf3ce44SJohn Forte /* 871*fcf3ce44SJohn Forte * This function is called before destroying the cache allocated 872*fcf3ce44SJohn Forte * fc_packet to free up (and uninitialize) any resource specially 873*fcf3ce44SJohn Forte * allocated by the FCA driver during tran_init_pkt(). 874*fcf3ce44SJohn Forte * 875*fcf3ce44SJohn Forte * If the pkt_pd field in the given fc_packet_t struct is not NULL, then 876*fcf3ce44SJohn Forte * the pd_ref_count reference count is decremented for the indicated 877*fcf3ce44SJohn Forte * fc_remote_port_t struct. 878*fcf3ce44SJohn Forte */ 879*fcf3ce44SJohn Forte int 880*fcf3ce44SJohn Forte fc_ulp_uninit_packet(opaque_t port_handle, fc_packet_t *pkt) 881*fcf3ce44SJohn Forte { 882*fcf3ce44SJohn Forte int rval; 883*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 884*fcf3ce44SJohn Forte fc_remote_port_t *pd; 885*fcf3ce44SJohn Forte 886*fcf3ce44SJohn Forte ASSERT(pkt != NULL); 887*fcf3ce44SJohn Forte 888*fcf3ce44SJohn Forte pd = pkt->pkt_pd; 889*fcf3ce44SJohn Forte 890*fcf3ce44SJohn Forte /* Call the FCA driver's fca_un_init_pkt entry point function */ 891*fcf3ce44SJohn Forte rval = port->fp_fca_tran->fca_un_init_pkt(port->fp_fca_handle, pkt); 892*fcf3ce44SJohn Forte 893*fcf3ce44SJohn Forte if ((rval == FC_SUCCESS) && (pd != NULL)) { 894*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 895*fcf3ce44SJohn Forte 896*fcf3ce44SJohn Forte ASSERT(pd->pd_ref_count > 0); 897*fcf3ce44SJohn Forte pd->pd_ref_count--; 898*fcf3ce44SJohn Forte 899*fcf3ce44SJohn Forte /* 900*fcf3ce44SJohn Forte * If at this point the state of this fc_remote_port_t 901*fcf3ce44SJohn Forte * struct is PORT_DEVICE_INVALID, it probably means somebody 902*fcf3ce44SJohn Forte * is cleaning up old (e.g. retried) packets. If the 903*fcf3ce44SJohn Forte * pd_ref_count has also dropped to zero, it's time to 904*fcf3ce44SJohn Forte * deallocate this fc_remote_port_t struct. 905*fcf3ce44SJohn Forte */ 906*fcf3ce44SJohn Forte if (pd->pd_state == PORT_DEVICE_INVALID && 907*fcf3ce44SJohn Forte pd->pd_ref_count == 0) { 908*fcf3ce44SJohn Forte fc_remote_node_t *node = pd->pd_remote_nodep; 909*fcf3ce44SJohn Forte 910*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 911*fcf3ce44SJohn Forte 912*fcf3ce44SJohn Forte /* 913*fcf3ce44SJohn Forte * Also deallocate the associated fc_remote_node_t 914*fcf3ce44SJohn Forte * struct if it has no other associated 915*fcf3ce44SJohn Forte * fc_remote_port_t structs. 916*fcf3ce44SJohn Forte */ 917*fcf3ce44SJohn Forte if ((fctl_destroy_remote_port(port, pd) == 0) && 918*fcf3ce44SJohn Forte (node != NULL)) { 919*fcf3ce44SJohn Forte fctl_destroy_remote_node(node); 920*fcf3ce44SJohn Forte } 921*fcf3ce44SJohn Forte return (rval); 922*fcf3ce44SJohn Forte } 923*fcf3ce44SJohn Forte 924*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 925*fcf3ce44SJohn Forte } 926*fcf3ce44SJohn Forte 927*fcf3ce44SJohn Forte return (rval); 928*fcf3ce44SJohn Forte } 929*fcf3ce44SJohn Forte 930*fcf3ce44SJohn Forte 931*fcf3ce44SJohn Forte int 932*fcf3ce44SJohn Forte fc_ulp_getportmap(opaque_t port_handle, fc_portmap_t **map, uint32_t *len, 933*fcf3ce44SJohn Forte int flag) 934*fcf3ce44SJohn Forte { 935*fcf3ce44SJohn Forte int job_code; 936*fcf3ce44SJohn Forte fc_local_port_t *port; 937*fcf3ce44SJohn Forte job_request_t *job; 938*fcf3ce44SJohn Forte fc_portmap_t *tmp_map; 939*fcf3ce44SJohn Forte uint32_t tmp_len; 940*fcf3ce44SJohn Forte fc_portmap_t *change_list = NULL; 941*fcf3ce44SJohn Forte uint32_t listlen = 0; 942*fcf3ce44SJohn Forte 943*fcf3ce44SJohn Forte port = port_handle; 944*fcf3ce44SJohn Forte 945*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 946*fcf3ce44SJohn Forte if (port->fp_statec_busy) { 947*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 948*fcf3ce44SJohn Forte return (FC_STATEC_BUSY); 949*fcf3ce44SJohn Forte } 950*fcf3ce44SJohn Forte 951*fcf3ce44SJohn Forte if (FC_PORT_STATE_MASK(port->fp_state) == FC_STATE_OFFLINE) { 952*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 953*fcf3ce44SJohn Forte return (FC_OFFLINE); 954*fcf3ce44SJohn Forte } 955*fcf3ce44SJohn Forte 956*fcf3ce44SJohn Forte if (port->fp_dev_count && (port->fp_dev_count == 957*fcf3ce44SJohn Forte port->fp_total_devices)) { 958*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 959*fcf3ce44SJohn Forte fctl_fillout_map(port, &change_list, &listlen, 1, 1, 0); 960*fcf3ce44SJohn Forte if (listlen > *len) { 961*fcf3ce44SJohn Forte tmp_map = (fc_portmap_t *)kmem_zalloc( 962*fcf3ce44SJohn Forte listlen * sizeof (fc_portmap_t), KM_NOSLEEP); 963*fcf3ce44SJohn Forte if (tmp_map == NULL) { 964*fcf3ce44SJohn Forte return (FC_NOMEM); 965*fcf3ce44SJohn Forte } 966*fcf3ce44SJohn Forte if (*map) { 967*fcf3ce44SJohn Forte kmem_free(*map, (*len) * sizeof (fc_portmap_t)); 968*fcf3ce44SJohn Forte } 969*fcf3ce44SJohn Forte *map = tmp_map; 970*fcf3ce44SJohn Forte } 971*fcf3ce44SJohn Forte if (change_list) { 972*fcf3ce44SJohn Forte bcopy(change_list, *map, 973*fcf3ce44SJohn Forte listlen * sizeof (fc_portmap_t)); 974*fcf3ce44SJohn Forte kmem_free(change_list, listlen * sizeof (fc_portmap_t)); 975*fcf3ce44SJohn Forte } 976*fcf3ce44SJohn Forte *len = listlen; 977*fcf3ce44SJohn Forte } else { 978*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 979*fcf3ce44SJohn Forte 980*fcf3ce44SJohn Forte switch (flag) { 981*fcf3ce44SJohn Forte case FC_ULP_PLOGI_DONTCARE: 982*fcf3ce44SJohn Forte job_code = JOB_PORT_GETMAP; 983*fcf3ce44SJohn Forte break; 984*fcf3ce44SJohn Forte 985*fcf3ce44SJohn Forte case FC_ULP_PLOGI_PRESERVE: 986*fcf3ce44SJohn Forte job_code = JOB_PORT_GETMAP_PLOGI_ALL; 987*fcf3ce44SJohn Forte break; 988*fcf3ce44SJohn Forte 989*fcf3ce44SJohn Forte default: 990*fcf3ce44SJohn Forte return (FC_INVALID_REQUEST); 991*fcf3ce44SJohn Forte } 992*fcf3ce44SJohn Forte /* 993*fcf3ce44SJohn Forte * Submit a job request to the job handler 994*fcf3ce44SJohn Forte * thread to get the map and wait 995*fcf3ce44SJohn Forte */ 996*fcf3ce44SJohn Forte job = fctl_alloc_job(job_code, 0, NULL, NULL, KM_SLEEP); 997*fcf3ce44SJohn Forte job->job_private = (opaque_t)map; 998*fcf3ce44SJohn Forte job->job_arg = (opaque_t)len; 999*fcf3ce44SJohn Forte fctl_enque_job(port, job); 1000*fcf3ce44SJohn Forte 1001*fcf3ce44SJohn Forte fctl_jobwait(job); 1002*fcf3ce44SJohn Forte /* 1003*fcf3ce44SJohn Forte * The result of the last I/O operation is 1004*fcf3ce44SJohn Forte * in job_code. We don't care to look at it 1005*fcf3ce44SJohn Forte * Rather we look at the number of devices 1006*fcf3ce44SJohn Forte * that are found to fill out the map for 1007*fcf3ce44SJohn Forte * ULPs. 1008*fcf3ce44SJohn Forte */ 1009*fcf3ce44SJohn Forte fctl_dealloc_job(job); 1010*fcf3ce44SJohn Forte } 1011*fcf3ce44SJohn Forte 1012*fcf3ce44SJohn Forte /* 1013*fcf3ce44SJohn Forte * If we're here, we're returning a map to the caller, which means 1014*fcf3ce44SJohn Forte * we'd better make sure every pd in that map has the 1015*fcf3ce44SJohn Forte * PD_GIVEN_TO_ULPS flag set. 1016*fcf3ce44SJohn Forte */ 1017*fcf3ce44SJohn Forte 1018*fcf3ce44SJohn Forte tmp_len = *len; 1019*fcf3ce44SJohn Forte tmp_map = *map; 1020*fcf3ce44SJohn Forte 1021*fcf3ce44SJohn Forte while (tmp_len-- != 0) { 1022*fcf3ce44SJohn Forte if (tmp_map->map_state != PORT_DEVICE_INVALID) { 1023*fcf3ce44SJohn Forte fc_remote_port_t *pd = 1024*fcf3ce44SJohn Forte (fc_remote_port_t *)tmp_map->map_pd; 1025*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1026*fcf3ce44SJohn Forte pd->pd_aux_flags |= PD_GIVEN_TO_ULPS; 1027*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1028*fcf3ce44SJohn Forte } 1029*fcf3ce44SJohn Forte tmp_map++; 1030*fcf3ce44SJohn Forte } 1031*fcf3ce44SJohn Forte 1032*fcf3ce44SJohn Forte return (FC_SUCCESS); 1033*fcf3ce44SJohn Forte } 1034*fcf3ce44SJohn Forte 1035*fcf3ce44SJohn Forte 1036*fcf3ce44SJohn Forte int 1037*fcf3ce44SJohn Forte fc_ulp_login(opaque_t port_handle, fc_packet_t **ulp_pkt, uint32_t listlen) 1038*fcf3ce44SJohn Forte { 1039*fcf3ce44SJohn Forte int rval = FC_SUCCESS; 1040*fcf3ce44SJohn Forte int job_flags; 1041*fcf3ce44SJohn Forte uint32_t count; 1042*fcf3ce44SJohn Forte fc_packet_t **tmp_array; 1043*fcf3ce44SJohn Forte job_request_t *job; 1044*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1045*fcf3ce44SJohn Forte fc_ulp_rscn_info_t *rscnp = 1046*fcf3ce44SJohn Forte (fc_ulp_rscn_info_t *)(ulp_pkt[0])->pkt_ulp_rscn_infop; 1047*fcf3ce44SJohn Forte 1048*fcf3ce44SJohn Forte /* 1049*fcf3ce44SJohn Forte * If the port is OFFLINE, or if the port driver is 1050*fcf3ce44SJohn Forte * being SUSPENDED/PM_SUSPENDED/DETACHED, block all 1051*fcf3ce44SJohn Forte * PLOGI operations 1052*fcf3ce44SJohn Forte */ 1053*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1054*fcf3ce44SJohn Forte if (port->fp_statec_busy) { 1055*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1056*fcf3ce44SJohn Forte return (FC_STATEC_BUSY); 1057*fcf3ce44SJohn Forte } 1058*fcf3ce44SJohn Forte 1059*fcf3ce44SJohn Forte if ((FC_PORT_STATE_MASK(port->fp_state) == FC_STATE_OFFLINE) || 1060*fcf3ce44SJohn Forte (port->fp_soft_state & 1061*fcf3ce44SJohn Forte (FP_SOFT_IN_DETACH | FP_SOFT_SUSPEND | FP_SOFT_POWER_DOWN))) { 1062*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1063*fcf3ce44SJohn Forte return (FC_OFFLINE); 1064*fcf3ce44SJohn Forte } 1065*fcf3ce44SJohn Forte 1066*fcf3ce44SJohn Forte /* 1067*fcf3ce44SJohn Forte * If the rscn count in the packet is not the same as the rscn count 1068*fcf3ce44SJohn Forte * in the fc_local_port_t, then one or more new RSCNs has occurred. 1069*fcf3ce44SJohn Forte */ 1070*fcf3ce44SJohn Forte if ((rscnp != NULL) && 1071*fcf3ce44SJohn Forte (rscnp->ulp_rscn_count != FC_INVALID_RSCN_COUNT) && 1072*fcf3ce44SJohn Forte (rscnp->ulp_rscn_count != port->fp_rscn_count)) { 1073*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1074*fcf3ce44SJohn Forte return (FC_DEVICE_BUSY_NEW_RSCN); 1075*fcf3ce44SJohn Forte } 1076*fcf3ce44SJohn Forte 1077*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1078*fcf3ce44SJohn Forte 1079*fcf3ce44SJohn Forte tmp_array = kmem_zalloc(sizeof (*tmp_array) * listlen, KM_SLEEP); 1080*fcf3ce44SJohn Forte for (count = 0; count < listlen; count++) { 1081*fcf3ce44SJohn Forte tmp_array[count] = ulp_pkt[count]; 1082*fcf3ce44SJohn Forte } 1083*fcf3ce44SJohn Forte 1084*fcf3ce44SJohn Forte job_flags = ((ulp_pkt[0]->pkt_tran_flags) & FC_TRAN_NO_INTR) 1085*fcf3ce44SJohn Forte ? 0 : JOB_TYPE_FCTL_ASYNC; 1086*fcf3ce44SJohn Forte 1087*fcf3ce44SJohn Forte #ifdef DEBUG 1088*fcf3ce44SJohn Forte { 1089*fcf3ce44SJohn Forte int next; 1090*fcf3ce44SJohn Forte int count; 1091*fcf3ce44SJohn Forte int polled; 1092*fcf3ce44SJohn Forte 1093*fcf3ce44SJohn Forte polled = ((ulp_pkt[0]->pkt_tran_flags) & 1094*fcf3ce44SJohn Forte FC_TRAN_NO_INTR) ? 0 : JOB_TYPE_FCTL_ASYNC; 1095*fcf3ce44SJohn Forte 1096*fcf3ce44SJohn Forte for (count = 0; count < listlen; count++) { 1097*fcf3ce44SJohn Forte next = ((ulp_pkt[count]->pkt_tran_flags) 1098*fcf3ce44SJohn Forte & FC_TRAN_NO_INTR) ? 0 : JOB_TYPE_FCTL_ASYNC; 1099*fcf3ce44SJohn Forte ASSERT(next == polled); 1100*fcf3ce44SJohn Forte } 1101*fcf3ce44SJohn Forte } 1102*fcf3ce44SJohn Forte #endif 1103*fcf3ce44SJohn Forte 1104*fcf3ce44SJohn Forte job = fctl_alloc_job(JOB_PLOGI_GROUP, job_flags, NULL, NULL, KM_SLEEP); 1105*fcf3ce44SJohn Forte job->job_ulp_pkts = tmp_array; 1106*fcf3ce44SJohn Forte job->job_ulp_listlen = listlen; 1107*fcf3ce44SJohn Forte 1108*fcf3ce44SJohn Forte while (listlen--) { 1109*fcf3ce44SJohn Forte fc_packet_t *pkt; 1110*fcf3ce44SJohn Forte 1111*fcf3ce44SJohn Forte pkt = tmp_array[listlen]; 1112*fcf3ce44SJohn Forte if (pkt->pkt_pd == NULL) { 1113*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_SUCCESS; 1114*fcf3ce44SJohn Forte continue; 1115*fcf3ce44SJohn Forte } 1116*fcf3ce44SJohn Forte 1117*fcf3ce44SJohn Forte mutex_enter(&pkt->pkt_pd->pd_mutex); 1118*fcf3ce44SJohn Forte if (pkt->pkt_pd->pd_flags == PD_ELS_IN_PROGRESS || 1119*fcf3ce44SJohn Forte pkt->pkt_pd->pd_flags == PD_ELS_MARK) { 1120*fcf3ce44SJohn Forte /* 1121*fcf3ce44SJohn Forte * Set the packet state and let the port 1122*fcf3ce44SJohn Forte * driver call the completion routine 1123*fcf3ce44SJohn Forte * from its thread 1124*fcf3ce44SJohn Forte */ 1125*fcf3ce44SJohn Forte mutex_exit(&pkt->pkt_pd->pd_mutex); 1126*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_ELS_IN_PROGRESS; 1127*fcf3ce44SJohn Forte continue; 1128*fcf3ce44SJohn Forte } 1129*fcf3ce44SJohn Forte 1130*fcf3ce44SJohn Forte if (pkt->pkt_pd->pd_state == PORT_DEVICE_INVALID || 1131*fcf3ce44SJohn Forte pkt->pkt_pd->pd_type == PORT_DEVICE_OLD) { 1132*fcf3ce44SJohn Forte mutex_exit(&pkt->pkt_pd->pd_mutex); 1133*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_LOCAL_RJT; 1134*fcf3ce44SJohn Forte continue; 1135*fcf3ce44SJohn Forte } 1136*fcf3ce44SJohn Forte mutex_exit(&pkt->pkt_pd->pd_mutex); 1137*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_SUCCESS; 1138*fcf3ce44SJohn Forte } 1139*fcf3ce44SJohn Forte 1140*fcf3ce44SJohn Forte fctl_enque_job(port, job); 1141*fcf3ce44SJohn Forte 1142*fcf3ce44SJohn Forte if (!(job_flags & JOB_TYPE_FCTL_ASYNC)) { 1143*fcf3ce44SJohn Forte fctl_jobwait(job); 1144*fcf3ce44SJohn Forte rval = job->job_result; 1145*fcf3ce44SJohn Forte fctl_dealloc_job(job); 1146*fcf3ce44SJohn Forte } 1147*fcf3ce44SJohn Forte 1148*fcf3ce44SJohn Forte return (rval); 1149*fcf3ce44SJohn Forte } 1150*fcf3ce44SJohn Forte 1151*fcf3ce44SJohn Forte 1152*fcf3ce44SJohn Forte opaque_t 1153*fcf3ce44SJohn Forte fc_ulp_get_remote_port(opaque_t port_handle, la_wwn_t *pwwn, int *error, 1154*fcf3ce44SJohn Forte int create) 1155*fcf3ce44SJohn Forte { 1156*fcf3ce44SJohn Forte fc_local_port_t *port; 1157*fcf3ce44SJohn Forte job_request_t *job; 1158*fcf3ce44SJohn Forte fc_remote_port_t *pd; 1159*fcf3ce44SJohn Forte 1160*fcf3ce44SJohn Forte port = port_handle; 1161*fcf3ce44SJohn Forte pd = fctl_get_remote_port_by_pwwn(port, pwwn); 1162*fcf3ce44SJohn Forte 1163*fcf3ce44SJohn Forte if (pd != NULL) { 1164*fcf3ce44SJohn Forte *error = FC_SUCCESS; 1165*fcf3ce44SJohn Forte /* 1166*fcf3ce44SJohn Forte * A ULP now knows about this pd, so mark it 1167*fcf3ce44SJohn Forte */ 1168*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1169*fcf3ce44SJohn Forte pd->pd_aux_flags |= PD_GIVEN_TO_ULPS; 1170*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1171*fcf3ce44SJohn Forte return (pd); 1172*fcf3ce44SJohn Forte } 1173*fcf3ce44SJohn Forte 1174*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1175*fcf3ce44SJohn Forte if (FC_IS_TOP_SWITCH(port->fp_topology) && create) { 1176*fcf3ce44SJohn Forte uint32_t d_id; 1177*fcf3ce44SJohn Forte fctl_ns_req_t *ns_cmd; 1178*fcf3ce44SJohn Forte 1179*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1180*fcf3ce44SJohn Forte 1181*fcf3ce44SJohn Forte job = fctl_alloc_job(JOB_NS_CMD, 0, NULL, NULL, KM_SLEEP); 1182*fcf3ce44SJohn Forte 1183*fcf3ce44SJohn Forte if (job == NULL) { 1184*fcf3ce44SJohn Forte *error = FC_NOMEM; 1185*fcf3ce44SJohn Forte return (pd); 1186*fcf3ce44SJohn Forte } 1187*fcf3ce44SJohn Forte 1188*fcf3ce44SJohn Forte ns_cmd = fctl_alloc_ns_cmd(sizeof (ns_req_gid_pn_t), 1189*fcf3ce44SJohn Forte sizeof (ns_resp_gid_pn_t), sizeof (ns_resp_gid_pn_t), 1190*fcf3ce44SJohn Forte 0, KM_SLEEP); 1191*fcf3ce44SJohn Forte 1192*fcf3ce44SJohn Forte if (ns_cmd == NULL) { 1193*fcf3ce44SJohn Forte fctl_dealloc_job(job); 1194*fcf3ce44SJohn Forte *error = FC_NOMEM; 1195*fcf3ce44SJohn Forte return (pd); 1196*fcf3ce44SJohn Forte } 1197*fcf3ce44SJohn Forte ns_cmd->ns_cmd_code = NS_GID_PN; 1198*fcf3ce44SJohn Forte ((ns_req_gid_pn_t *)(ns_cmd->ns_cmd_buf))->pwwn = *pwwn; 1199*fcf3ce44SJohn Forte 1200*fcf3ce44SJohn Forte job->job_result = FC_SUCCESS; 1201*fcf3ce44SJohn Forte job->job_private = (void *)ns_cmd; 1202*fcf3ce44SJohn Forte job->job_counter = 1; 1203*fcf3ce44SJohn Forte fctl_enque_job(port, job); 1204*fcf3ce44SJohn Forte fctl_jobwait(job); 1205*fcf3ce44SJohn Forte 1206*fcf3ce44SJohn Forte if (job->job_result != FC_SUCCESS) { 1207*fcf3ce44SJohn Forte *error = job->job_result; 1208*fcf3ce44SJohn Forte fctl_free_ns_cmd(ns_cmd); 1209*fcf3ce44SJohn Forte fctl_dealloc_job(job); 1210*fcf3ce44SJohn Forte return (pd); 1211*fcf3ce44SJohn Forte } 1212*fcf3ce44SJohn Forte d_id = ((ns_resp_gid_pn_t *)ns_cmd->ns_data_buf)->pid.port_id; 1213*fcf3ce44SJohn Forte fctl_free_ns_cmd(ns_cmd); 1214*fcf3ce44SJohn Forte 1215*fcf3ce44SJohn Forte ns_cmd = fctl_alloc_ns_cmd(sizeof (ns_req_gan_t), 1216*fcf3ce44SJohn Forte sizeof (ns_resp_gan_t), 0, FCTL_NS_CREATE_DEVICE, 1217*fcf3ce44SJohn Forte KM_SLEEP); 1218*fcf3ce44SJohn Forte ASSERT(ns_cmd != NULL); 1219*fcf3ce44SJohn Forte 1220*fcf3ce44SJohn Forte ns_cmd->ns_gan_max = 1; 1221*fcf3ce44SJohn Forte ns_cmd->ns_cmd_code = NS_GA_NXT; 1222*fcf3ce44SJohn Forte ns_cmd->ns_gan_sid = FCTL_GAN_START_ID; 1223*fcf3ce44SJohn Forte ((ns_req_gan_t *)(ns_cmd->ns_cmd_buf))->pid.port_id = d_id - 1; 1224*fcf3ce44SJohn Forte ((ns_req_gan_t *)(ns_cmd->ns_cmd_buf))->pid.priv_lilp_posit = 0; 1225*fcf3ce44SJohn Forte 1226*fcf3ce44SJohn Forte job->job_result = FC_SUCCESS; 1227*fcf3ce44SJohn Forte job->job_private = (void *)ns_cmd; 1228*fcf3ce44SJohn Forte job->job_counter = 1; 1229*fcf3ce44SJohn Forte fctl_enque_job(port, job); 1230*fcf3ce44SJohn Forte fctl_jobwait(job); 1231*fcf3ce44SJohn Forte 1232*fcf3ce44SJohn Forte fctl_free_ns_cmd(ns_cmd); 1233*fcf3ce44SJohn Forte if (job->job_result != FC_SUCCESS) { 1234*fcf3ce44SJohn Forte *error = job->job_result; 1235*fcf3ce44SJohn Forte fctl_dealloc_job(job); 1236*fcf3ce44SJohn Forte return (pd); 1237*fcf3ce44SJohn Forte } 1238*fcf3ce44SJohn Forte fctl_dealloc_job(job); 1239*fcf3ce44SJohn Forte 1240*fcf3ce44SJohn Forte /* 1241*fcf3ce44SJohn Forte * Check if the port device is created now. 1242*fcf3ce44SJohn Forte */ 1243*fcf3ce44SJohn Forte pd = fctl_get_remote_port_by_pwwn(port, pwwn); 1244*fcf3ce44SJohn Forte 1245*fcf3ce44SJohn Forte if (pd == NULL) { 1246*fcf3ce44SJohn Forte *error = FC_FAILURE; 1247*fcf3ce44SJohn Forte } else { 1248*fcf3ce44SJohn Forte *error = FC_SUCCESS; 1249*fcf3ce44SJohn Forte 1250*fcf3ce44SJohn Forte /* 1251*fcf3ce44SJohn Forte * A ULP now knows about this pd, so mark it 1252*fcf3ce44SJohn Forte */ 1253*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1254*fcf3ce44SJohn Forte pd->pd_aux_flags |= PD_GIVEN_TO_ULPS; 1255*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1256*fcf3ce44SJohn Forte } 1257*fcf3ce44SJohn Forte } else { 1258*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1259*fcf3ce44SJohn Forte *error = FC_FAILURE; 1260*fcf3ce44SJohn Forte } 1261*fcf3ce44SJohn Forte 1262*fcf3ce44SJohn Forte return (pd); 1263*fcf3ce44SJohn Forte } 1264*fcf3ce44SJohn Forte 1265*fcf3ce44SJohn Forte 1266*fcf3ce44SJohn Forte /* 1267*fcf3ce44SJohn Forte * If a NS object exists in the host and query is performed 1268*fcf3ce44SJohn Forte * on that object, we should retrieve it from our basket 1269*fcf3ce44SJohn Forte * and return it right here, there by saving a request going 1270*fcf3ce44SJohn Forte * all the up to the Name Server. 1271*fcf3ce44SJohn Forte */ 1272*fcf3ce44SJohn Forte int 1273*fcf3ce44SJohn Forte fc_ulp_port_ns(opaque_t port_handle, opaque_t pd, fc_ns_cmd_t *ns_req) 1274*fcf3ce44SJohn Forte { 1275*fcf3ce44SJohn Forte int rval; 1276*fcf3ce44SJohn Forte int fabric; 1277*fcf3ce44SJohn Forte job_request_t *job; 1278*fcf3ce44SJohn Forte fctl_ns_req_t *ns_cmd; 1279*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1280*fcf3ce44SJohn Forte 1281*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1282*fcf3ce44SJohn Forte fabric = FC_IS_TOP_SWITCH(port->fp_topology) ? 1 : 0; 1283*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1284*fcf3ce44SJohn Forte 1285*fcf3ce44SJohn Forte /* 1286*fcf3ce44SJohn Forte * Name server query can't be performed for devices not in Fabric 1287*fcf3ce44SJohn Forte */ 1288*fcf3ce44SJohn Forte if (!fabric && pd) { 1289*fcf3ce44SJohn Forte return (FC_BADOBJECT); 1290*fcf3ce44SJohn Forte } 1291*fcf3ce44SJohn Forte 1292*fcf3ce44SJohn Forte if (FC_IS_CMD_A_REG(ns_req->ns_cmd)) { 1293*fcf3ce44SJohn Forte if (pd == NULL) { 1294*fcf3ce44SJohn Forte rval = fctl_update_host_ns_values(port, ns_req); 1295*fcf3ce44SJohn Forte if (rval != FC_SUCCESS) { 1296*fcf3ce44SJohn Forte return (rval); 1297*fcf3ce44SJohn Forte } 1298*fcf3ce44SJohn Forte } else { 1299*fcf3ce44SJohn Forte /* 1300*fcf3ce44SJohn Forte * Guess what, FC-GS-2 currently prohibits (not 1301*fcf3ce44SJohn Forte * in the strongest language though) setting of 1302*fcf3ce44SJohn Forte * NS object values by other ports. But we might 1303*fcf3ce44SJohn Forte * get that changed to at least accommodate setting 1304*fcf3ce44SJohn Forte * symbolic node/port names - But if disks/tapes 1305*fcf3ce44SJohn Forte * were going to provide a method to set these 1306*fcf3ce44SJohn Forte * values directly (which in turn might register 1307*fcf3ce44SJohn Forte * with the NS when they come up; yep, for that 1308*fcf3ce44SJohn Forte * to happen the disks will have to be very well 1309*fcf3ce44SJohn Forte * behaved Fabric citizen) we won't need to 1310*fcf3ce44SJohn Forte * register the symbolic port/node names for 1311*fcf3ce44SJohn Forte * other ports too (rather send down SCSI commands 1312*fcf3ce44SJohn Forte * to the devices to set the names) 1313*fcf3ce44SJohn Forte * 1314*fcf3ce44SJohn Forte * Be that as it may, let's continue to fail 1315*fcf3ce44SJohn Forte * registration requests for other ports. period. 1316*fcf3ce44SJohn Forte */ 1317*fcf3ce44SJohn Forte return (FC_BADOBJECT); 1318*fcf3ce44SJohn Forte } 1319*fcf3ce44SJohn Forte 1320*fcf3ce44SJohn Forte if (!fabric) { 1321*fcf3ce44SJohn Forte return (FC_SUCCESS); 1322*fcf3ce44SJohn Forte } 1323*fcf3ce44SJohn Forte } else if (!fabric) { 1324*fcf3ce44SJohn Forte return (fctl_retrieve_host_ns_values(port, ns_req)); 1325*fcf3ce44SJohn Forte } 1326*fcf3ce44SJohn Forte 1327*fcf3ce44SJohn Forte job = fctl_alloc_job(JOB_NS_CMD, 0, NULL, NULL, KM_SLEEP); 1328*fcf3ce44SJohn Forte ASSERT(job != NULL); 1329*fcf3ce44SJohn Forte 1330*fcf3ce44SJohn Forte ns_cmd = fctl_alloc_ns_cmd(ns_req->ns_req_len, 1331*fcf3ce44SJohn Forte ns_req->ns_resp_len, ns_req->ns_resp_len, 0, KM_SLEEP); 1332*fcf3ce44SJohn Forte ASSERT(ns_cmd != NULL); 1333*fcf3ce44SJohn Forte ns_cmd->ns_cmd_code = ns_req->ns_cmd; 1334*fcf3ce44SJohn Forte bcopy(ns_req->ns_req_payload, ns_cmd->ns_cmd_buf, 1335*fcf3ce44SJohn Forte ns_req->ns_req_len); 1336*fcf3ce44SJohn Forte 1337*fcf3ce44SJohn Forte job->job_private = (void *)ns_cmd; 1338*fcf3ce44SJohn Forte fctl_enque_job(port, job); 1339*fcf3ce44SJohn Forte fctl_jobwait(job); 1340*fcf3ce44SJohn Forte rval = job->job_result; 1341*fcf3ce44SJohn Forte 1342*fcf3ce44SJohn Forte if (ns_req->ns_resp_len >= ns_cmd->ns_data_len) { 1343*fcf3ce44SJohn Forte bcopy(ns_cmd->ns_data_buf, ns_req->ns_resp_payload, 1344*fcf3ce44SJohn Forte ns_cmd->ns_data_len); 1345*fcf3ce44SJohn Forte } 1346*fcf3ce44SJohn Forte bcopy(&ns_cmd->ns_resp_hdr, &ns_req->ns_resp_hdr, 1347*fcf3ce44SJohn Forte sizeof (fc_ct_header_t)); 1348*fcf3ce44SJohn Forte 1349*fcf3ce44SJohn Forte fctl_free_ns_cmd(ns_cmd); 1350*fcf3ce44SJohn Forte fctl_dealloc_job(job); 1351*fcf3ce44SJohn Forte 1352*fcf3ce44SJohn Forte return (rval); 1353*fcf3ce44SJohn Forte } 1354*fcf3ce44SJohn Forte 1355*fcf3ce44SJohn Forte 1356*fcf3ce44SJohn Forte int 1357*fcf3ce44SJohn Forte fc_ulp_transport(opaque_t port_handle, fc_packet_t *pkt) 1358*fcf3ce44SJohn Forte { 1359*fcf3ce44SJohn Forte int rval; 1360*fcf3ce44SJohn Forte fc_local_port_t *port; 1361*fcf3ce44SJohn Forte fc_remote_port_t *pd, *newpd; 1362*fcf3ce44SJohn Forte fc_ulp_rscn_info_t *rscnp = 1363*fcf3ce44SJohn Forte (fc_ulp_rscn_info_t *)pkt->pkt_ulp_rscn_infop; 1364*fcf3ce44SJohn Forte 1365*fcf3ce44SJohn Forte port = port_handle; 1366*fcf3ce44SJohn Forte 1367*fcf3ce44SJohn Forte if (pkt->pkt_tran_flags & FC_TRAN_DUMPING) { 1368*fcf3ce44SJohn Forte return (port->fp_fca_tran->fca_transport( 1369*fcf3ce44SJohn Forte port->fp_fca_handle, pkt)); 1370*fcf3ce44SJohn Forte } 1371*fcf3ce44SJohn Forte 1372*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1373*fcf3ce44SJohn Forte if (port->fp_statec_busy) { 1374*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1375*fcf3ce44SJohn Forte return (FC_STATEC_BUSY); 1376*fcf3ce44SJohn Forte } 1377*fcf3ce44SJohn Forte 1378*fcf3ce44SJohn Forte /* A locus of race conditions */ 1379*fcf3ce44SJohn Forte if (((FC_PORT_STATE_MASK(port->fp_state)) == FC_STATE_OFFLINE) || 1380*fcf3ce44SJohn Forte (port->fp_soft_state & 1381*fcf3ce44SJohn Forte (FP_SOFT_IN_DETACH | FP_SOFT_SUSPEND | FP_SOFT_POWER_DOWN))) { 1382*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1383*fcf3ce44SJohn Forte return (FC_OFFLINE); 1384*fcf3ce44SJohn Forte } 1385*fcf3ce44SJohn Forte 1386*fcf3ce44SJohn Forte /* 1387*fcf3ce44SJohn Forte * If the rscn count in the packet is not the same as the rscn count 1388*fcf3ce44SJohn Forte * in the fc_local_port_t, then one or more new RSCNs has occurred. 1389*fcf3ce44SJohn Forte */ 1390*fcf3ce44SJohn Forte if ((rscnp != NULL) && 1391*fcf3ce44SJohn Forte (rscnp->ulp_rscn_count != FC_INVALID_RSCN_COUNT) && 1392*fcf3ce44SJohn Forte (rscnp->ulp_rscn_count != port->fp_rscn_count)) { 1393*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1394*fcf3ce44SJohn Forte return (FC_DEVICE_BUSY_NEW_RSCN); 1395*fcf3ce44SJohn Forte } 1396*fcf3ce44SJohn Forte 1397*fcf3ce44SJohn Forte pd = pkt->pkt_pd; 1398*fcf3ce44SJohn Forte if (pd) { 1399*fcf3ce44SJohn Forte if (pd->pd_type == PORT_DEVICE_OLD || 1400*fcf3ce44SJohn Forte pd->pd_state == PORT_DEVICE_INVALID) { 1401*fcf3ce44SJohn Forte 1402*fcf3ce44SJohn Forte newpd = fctl_get_remote_port_by_pwwn_mutex_held(port, 1403*fcf3ce44SJohn Forte &pd->pd_port_name); 1404*fcf3ce44SJohn Forte 1405*fcf3ce44SJohn Forte /* 1406*fcf3ce44SJohn Forte * The remote port (pd) in the packet is no longer 1407*fcf3ce44SJohn Forte * usable, as the old pd still exists we can use the 1408*fcf3ce44SJohn Forte * WWN to check if we have a current pd for the device 1409*fcf3ce44SJohn Forte * we want. Either way we continue with the old logic 1410*fcf3ce44SJohn Forte * whether we have a new pd or not, as the new pd 1411*fcf3ce44SJohn Forte * could be bad, or have become unusable. 1412*fcf3ce44SJohn Forte */ 1413*fcf3ce44SJohn Forte if ((newpd) && (newpd != pd)) { 1414*fcf3ce44SJohn Forte 1415*fcf3ce44SJohn Forte /* 1416*fcf3ce44SJohn Forte * There is a better remote port (pd) to try, 1417*fcf3ce44SJohn Forte * so we need to fix the reference counts, etc. 1418*fcf3ce44SJohn Forte */ 1419*fcf3ce44SJohn Forte mutex_enter(&newpd->pd_mutex); 1420*fcf3ce44SJohn Forte newpd->pd_ref_count++; 1421*fcf3ce44SJohn Forte pkt->pkt_pd = newpd; 1422*fcf3ce44SJohn Forte mutex_exit(&newpd->pd_mutex); 1423*fcf3ce44SJohn Forte 1424*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1425*fcf3ce44SJohn Forte pd->pd_ref_count--; 1426*fcf3ce44SJohn Forte if ((pd->pd_state == PORT_DEVICE_INVALID) && 1427*fcf3ce44SJohn Forte (pd->pd_ref_count == 0)) { 1428*fcf3ce44SJohn Forte fc_remote_node_t *node = 1429*fcf3ce44SJohn Forte pd->pd_remote_nodep; 1430*fcf3ce44SJohn Forte 1431*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1432*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1433*fcf3ce44SJohn Forte 1434*fcf3ce44SJohn Forte /* 1435*fcf3ce44SJohn Forte * This will create another PD hole 1436*fcf3ce44SJohn Forte * where we have a reference to a pd, 1437*fcf3ce44SJohn Forte * but someone else could remove it. 1438*fcf3ce44SJohn Forte */ 1439*fcf3ce44SJohn Forte if ((fctl_destroy_remote_port(port, pd) 1440*fcf3ce44SJohn Forte == 0) && (node != NULL)) { 1441*fcf3ce44SJohn Forte fctl_destroy_remote_node(node); 1442*fcf3ce44SJohn Forte } 1443*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1444*fcf3ce44SJohn Forte } else { 1445*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1446*fcf3ce44SJohn Forte } 1447*fcf3ce44SJohn Forte pd = newpd; 1448*fcf3ce44SJohn Forte } 1449*fcf3ce44SJohn Forte } 1450*fcf3ce44SJohn Forte 1451*fcf3ce44SJohn Forte if (pd->pd_state != PORT_DEVICE_LOGGED_IN) { 1452*fcf3ce44SJohn Forte rval = (pd->pd_state == PORT_DEVICE_VALID) ? 1453*fcf3ce44SJohn Forte FC_LOGINREQ : FC_BADDEV; 1454*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1455*fcf3ce44SJohn Forte return (rval); 1456*fcf3ce44SJohn Forte } 1457*fcf3ce44SJohn Forte 1458*fcf3ce44SJohn Forte if (pd->pd_flags != PD_IDLE) { 1459*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1460*fcf3ce44SJohn Forte return (FC_DEVICE_BUSY); 1461*fcf3ce44SJohn Forte } 1462*fcf3ce44SJohn Forte 1463*fcf3ce44SJohn Forte if (pd->pd_type == PORT_DEVICE_OLD || 1464*fcf3ce44SJohn Forte pd->pd_state == PORT_DEVICE_INVALID) { 1465*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1466*fcf3ce44SJohn Forte return (FC_BADDEV); 1467*fcf3ce44SJohn Forte } 1468*fcf3ce44SJohn Forte 1469*fcf3ce44SJohn Forte } else if (FC_IS_REAL_DEVICE(pkt->pkt_cmd_fhdr.d_id)) { 1470*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1471*fcf3ce44SJohn Forte return (FC_BADPACKET); 1472*fcf3ce44SJohn Forte } 1473*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1474*fcf3ce44SJohn Forte 1475*fcf3ce44SJohn Forte return (port->fp_fca_tran->fca_transport(port->fp_fca_handle, pkt)); 1476*fcf3ce44SJohn Forte } 1477*fcf3ce44SJohn Forte 1478*fcf3ce44SJohn Forte 1479*fcf3ce44SJohn Forte int 1480*fcf3ce44SJohn Forte fc_ulp_issue_els(opaque_t port_handle, fc_packet_t *pkt) 1481*fcf3ce44SJohn Forte { 1482*fcf3ce44SJohn Forte int rval; 1483*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1484*fcf3ce44SJohn Forte fc_remote_port_t *pd; 1485*fcf3ce44SJohn Forte fc_ulp_rscn_info_t *rscnp = 1486*fcf3ce44SJohn Forte (fc_ulp_rscn_info_t *)pkt->pkt_ulp_rscn_infop; 1487*fcf3ce44SJohn Forte 1488*fcf3ce44SJohn Forte /* 1489*fcf3ce44SJohn Forte * If the port is OFFLINE, or if the port driver is 1490*fcf3ce44SJohn Forte * being SUSPENDED/PM_SUSPENDED/DETACHED, block all 1491*fcf3ce44SJohn Forte * ELS operations 1492*fcf3ce44SJohn Forte */ 1493*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1494*fcf3ce44SJohn Forte if ((FC_PORT_STATE_MASK(port->fp_state) == FC_STATE_OFFLINE) || 1495*fcf3ce44SJohn Forte (port->fp_soft_state & 1496*fcf3ce44SJohn Forte (FP_SOFT_IN_DETACH | FP_SOFT_SUSPEND | FP_SOFT_POWER_DOWN))) { 1497*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1498*fcf3ce44SJohn Forte return (FC_OFFLINE); 1499*fcf3ce44SJohn Forte } 1500*fcf3ce44SJohn Forte 1501*fcf3ce44SJohn Forte if (port->fp_statec_busy) { 1502*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1503*fcf3ce44SJohn Forte return (FC_STATEC_BUSY); 1504*fcf3ce44SJohn Forte } 1505*fcf3ce44SJohn Forte 1506*fcf3ce44SJohn Forte /* 1507*fcf3ce44SJohn Forte * If the rscn count in the packet is not the same as the rscn count 1508*fcf3ce44SJohn Forte * in the fc_local_port_t, then one or more new RSCNs has occurred. 1509*fcf3ce44SJohn Forte */ 1510*fcf3ce44SJohn Forte if ((rscnp != NULL) && 1511*fcf3ce44SJohn Forte (rscnp->ulp_rscn_count != FC_INVALID_RSCN_COUNT) && 1512*fcf3ce44SJohn Forte (rscnp->ulp_rscn_count != port->fp_rscn_count)) { 1513*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1514*fcf3ce44SJohn Forte return (FC_DEVICE_BUSY_NEW_RSCN); 1515*fcf3ce44SJohn Forte } 1516*fcf3ce44SJohn Forte 1517*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1518*fcf3ce44SJohn Forte 1519*fcf3ce44SJohn Forte if ((pd = pkt->pkt_pd) != NULL) { 1520*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1521*fcf3ce44SJohn Forte if (pd->pd_state != PORT_DEVICE_LOGGED_IN) { 1522*fcf3ce44SJohn Forte rval = (pd->pd_state == PORT_DEVICE_VALID) ? 1523*fcf3ce44SJohn Forte FC_LOGINREQ : FC_BADDEV; 1524*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1525*fcf3ce44SJohn Forte return (rval); 1526*fcf3ce44SJohn Forte } 1527*fcf3ce44SJohn Forte 1528*fcf3ce44SJohn Forte if (pd->pd_flags != PD_IDLE) { 1529*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1530*fcf3ce44SJohn Forte return (FC_DEVICE_BUSY); 1531*fcf3ce44SJohn Forte } 1532*fcf3ce44SJohn Forte if (pd->pd_type == PORT_DEVICE_OLD || 1533*fcf3ce44SJohn Forte pd->pd_state == PORT_DEVICE_INVALID) { 1534*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1535*fcf3ce44SJohn Forte return (FC_BADDEV); 1536*fcf3ce44SJohn Forte } 1537*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1538*fcf3ce44SJohn Forte } 1539*fcf3ce44SJohn Forte 1540*fcf3ce44SJohn Forte return (port->fp_fca_tran->fca_els_send(port->fp_fca_handle, pkt)); 1541*fcf3ce44SJohn Forte } 1542*fcf3ce44SJohn Forte 1543*fcf3ce44SJohn Forte 1544*fcf3ce44SJohn Forte int 1545*fcf3ce44SJohn Forte fc_ulp_uballoc(opaque_t port_handle, uint32_t *count, uint32_t size, 1546*fcf3ce44SJohn Forte uint32_t type, uint64_t *tokens) 1547*fcf3ce44SJohn Forte { 1548*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1549*fcf3ce44SJohn Forte 1550*fcf3ce44SJohn Forte return (port->fp_fca_tran->fca_ub_alloc(port->fp_fca_handle, 1551*fcf3ce44SJohn Forte tokens, size, count, type)); 1552*fcf3ce44SJohn Forte } 1553*fcf3ce44SJohn Forte 1554*fcf3ce44SJohn Forte 1555*fcf3ce44SJohn Forte int 1556*fcf3ce44SJohn Forte fc_ulp_ubfree(opaque_t port_handle, uint32_t count, uint64_t *tokens) 1557*fcf3ce44SJohn Forte { 1558*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1559*fcf3ce44SJohn Forte 1560*fcf3ce44SJohn Forte return (port->fp_fca_tran->fca_ub_free(port->fp_fca_handle, 1561*fcf3ce44SJohn Forte count, tokens)); 1562*fcf3ce44SJohn Forte } 1563*fcf3ce44SJohn Forte 1564*fcf3ce44SJohn Forte 1565*fcf3ce44SJohn Forte int 1566*fcf3ce44SJohn Forte fc_ulp_ubrelease(opaque_t port_handle, uint32_t count, uint64_t *tokens) 1567*fcf3ce44SJohn Forte { 1568*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1569*fcf3ce44SJohn Forte 1570*fcf3ce44SJohn Forte return (port->fp_fca_tran->fca_ub_release(port->fp_fca_handle, 1571*fcf3ce44SJohn Forte count, tokens)); 1572*fcf3ce44SJohn Forte } 1573*fcf3ce44SJohn Forte 1574*fcf3ce44SJohn Forte 1575*fcf3ce44SJohn Forte int 1576*fcf3ce44SJohn Forte fc_ulp_abort(opaque_t port_handle, fc_packet_t *pkt, int flags) 1577*fcf3ce44SJohn Forte { 1578*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1579*fcf3ce44SJohn Forte 1580*fcf3ce44SJohn Forte return (port->fp_fca_tran->fca_abort(port->fp_fca_handle, pkt, flags)); 1581*fcf3ce44SJohn Forte } 1582*fcf3ce44SJohn Forte 1583*fcf3ce44SJohn Forte 1584*fcf3ce44SJohn Forte /* 1585*fcf3ce44SJohn Forte * Submit an asynchronous request to the job handler if the sleep 1586*fcf3ce44SJohn Forte * flag is set to KM_NOSLEEP, as such calls could have been made 1587*fcf3ce44SJohn Forte * in interrupt contexts, and the goal is to avoid busy waiting, 1588*fcf3ce44SJohn Forte * blocking on a conditional variable, a semaphore or any of the 1589*fcf3ce44SJohn Forte * synchronization primitives. A noticeable draw back with this 1590*fcf3ce44SJohn Forte * asynchronous request is that an FC_SUCCESS is returned long 1591*fcf3ce44SJohn Forte * before the reset is complete (successful or not). 1592*fcf3ce44SJohn Forte */ 1593*fcf3ce44SJohn Forte int 1594*fcf3ce44SJohn Forte fc_ulp_linkreset(opaque_t port_handle, la_wwn_t *pwwn, int sleep) 1595*fcf3ce44SJohn Forte { 1596*fcf3ce44SJohn Forte int rval; 1597*fcf3ce44SJohn Forte fc_local_port_t *port; 1598*fcf3ce44SJohn Forte job_request_t *job; 1599*fcf3ce44SJohn Forte 1600*fcf3ce44SJohn Forte port = port_handle; 1601*fcf3ce44SJohn Forte /* 1602*fcf3ce44SJohn Forte * Many a times, this function is called from interrupt 1603*fcf3ce44SJohn Forte * contexts and there have been several dead locks and 1604*fcf3ce44SJohn Forte * hangs - One of the simplest work arounds is to fib 1605*fcf3ce44SJohn Forte * if a RESET is in progress. 1606*fcf3ce44SJohn Forte */ 1607*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1608*fcf3ce44SJohn Forte if (port->fp_soft_state & FP_SOFT_IN_LINK_RESET) { 1609*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1610*fcf3ce44SJohn Forte return (FC_SUCCESS); 1611*fcf3ce44SJohn Forte } 1612*fcf3ce44SJohn Forte 1613*fcf3ce44SJohn Forte /* 1614*fcf3ce44SJohn Forte * Ward off this reset if a state change is in progress. 1615*fcf3ce44SJohn Forte */ 1616*fcf3ce44SJohn Forte if (port->fp_statec_busy) { 1617*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1618*fcf3ce44SJohn Forte return (FC_STATEC_BUSY); 1619*fcf3ce44SJohn Forte } 1620*fcf3ce44SJohn Forte port->fp_soft_state |= FP_SOFT_IN_LINK_RESET; 1621*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1622*fcf3ce44SJohn Forte 1623*fcf3ce44SJohn Forte if (fctl_busy_port(port) != 0) { 1624*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1625*fcf3ce44SJohn Forte port->fp_soft_state &= ~FP_SOFT_IN_LINK_RESET; 1626*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1627*fcf3ce44SJohn Forte return (FC_FAILURE); 1628*fcf3ce44SJohn Forte } 1629*fcf3ce44SJohn Forte 1630*fcf3ce44SJohn Forte if (sleep == KM_SLEEP) { 1631*fcf3ce44SJohn Forte job = fctl_alloc_job(JOB_LINK_RESET, 0, NULL, NULL, sleep); 1632*fcf3ce44SJohn Forte ASSERT(job != NULL); 1633*fcf3ce44SJohn Forte 1634*fcf3ce44SJohn Forte job->job_private = (void *)pwwn; 1635*fcf3ce44SJohn Forte job->job_counter = 1; 1636*fcf3ce44SJohn Forte fctl_enque_job(port, job); 1637*fcf3ce44SJohn Forte fctl_jobwait(job); 1638*fcf3ce44SJohn Forte 1639*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1640*fcf3ce44SJohn Forte port->fp_soft_state &= ~FP_SOFT_IN_LINK_RESET; 1641*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1642*fcf3ce44SJohn Forte 1643*fcf3ce44SJohn Forte fctl_idle_port(port); 1644*fcf3ce44SJohn Forte 1645*fcf3ce44SJohn Forte rval = job->job_result; 1646*fcf3ce44SJohn Forte fctl_dealloc_job(job); 1647*fcf3ce44SJohn Forte } else { 1648*fcf3ce44SJohn Forte job = fctl_alloc_job(JOB_LINK_RESET, JOB_TYPE_FCTL_ASYNC, 1649*fcf3ce44SJohn Forte fctl_link_reset_done, port, sleep); 1650*fcf3ce44SJohn Forte if (job == NULL) { 1651*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1652*fcf3ce44SJohn Forte port->fp_soft_state &= ~FP_SOFT_IN_LINK_RESET; 1653*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1654*fcf3ce44SJohn Forte fctl_idle_port(port); 1655*fcf3ce44SJohn Forte return (FC_NOMEM); 1656*fcf3ce44SJohn Forte } 1657*fcf3ce44SJohn Forte job->job_private = (void *)pwwn; 1658*fcf3ce44SJohn Forte job->job_counter = 1; 1659*fcf3ce44SJohn Forte fctl_priority_enque_job(port, job); 1660*fcf3ce44SJohn Forte rval = FC_SUCCESS; 1661*fcf3ce44SJohn Forte } 1662*fcf3ce44SJohn Forte 1663*fcf3ce44SJohn Forte return (rval); 1664*fcf3ce44SJohn Forte } 1665*fcf3ce44SJohn Forte 1666*fcf3ce44SJohn Forte 1667*fcf3ce44SJohn Forte int 1668*fcf3ce44SJohn Forte fc_ulp_port_reset(opaque_t port_handle, uint32_t cmd) 1669*fcf3ce44SJohn Forte { 1670*fcf3ce44SJohn Forte int rval = FC_SUCCESS; 1671*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1672*fcf3ce44SJohn Forte 1673*fcf3ce44SJohn Forte switch (cmd) { 1674*fcf3ce44SJohn Forte case FC_RESET_PORT: 1675*fcf3ce44SJohn Forte rval = port->fp_fca_tran->fca_reset( 1676*fcf3ce44SJohn Forte port->fp_fca_handle, FC_FCA_LINK_RESET); 1677*fcf3ce44SJohn Forte break; 1678*fcf3ce44SJohn Forte 1679*fcf3ce44SJohn Forte case FC_RESET_ADAPTER: 1680*fcf3ce44SJohn Forte rval = port->fp_fca_tran->fca_reset( 1681*fcf3ce44SJohn Forte port->fp_fca_handle, FC_FCA_RESET); 1682*fcf3ce44SJohn Forte break; 1683*fcf3ce44SJohn Forte 1684*fcf3ce44SJohn Forte case FC_RESET_DUMP: 1685*fcf3ce44SJohn Forte rval = port->fp_fca_tran->fca_reset( 1686*fcf3ce44SJohn Forte port->fp_fca_handle, FC_FCA_CORE); 1687*fcf3ce44SJohn Forte break; 1688*fcf3ce44SJohn Forte 1689*fcf3ce44SJohn Forte case FC_RESET_CRASH: 1690*fcf3ce44SJohn Forte rval = port->fp_fca_tran->fca_reset( 1691*fcf3ce44SJohn Forte port->fp_fca_handle, FC_FCA_RESET_CORE); 1692*fcf3ce44SJohn Forte break; 1693*fcf3ce44SJohn Forte 1694*fcf3ce44SJohn Forte default: 1695*fcf3ce44SJohn Forte rval = FC_FAILURE; 1696*fcf3ce44SJohn Forte } 1697*fcf3ce44SJohn Forte 1698*fcf3ce44SJohn Forte return (rval); 1699*fcf3ce44SJohn Forte } 1700*fcf3ce44SJohn Forte 1701*fcf3ce44SJohn Forte 1702*fcf3ce44SJohn Forte int 1703*fcf3ce44SJohn Forte fc_ulp_get_port_login_params(opaque_t port_handle, la_els_logi_t *login_params) 1704*fcf3ce44SJohn Forte { 1705*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1706*fcf3ce44SJohn Forte 1707*fcf3ce44SJohn Forte /* Copy the login parameters */ 1708*fcf3ce44SJohn Forte *login_params = port->fp_service_params; 1709*fcf3ce44SJohn Forte return (FC_SUCCESS); 1710*fcf3ce44SJohn Forte } 1711*fcf3ce44SJohn Forte 1712*fcf3ce44SJohn Forte 1713*fcf3ce44SJohn Forte int 1714*fcf3ce44SJohn Forte fc_ulp_get_port_instance(opaque_t port_handle) 1715*fcf3ce44SJohn Forte { 1716*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1717*fcf3ce44SJohn Forte 1718*fcf3ce44SJohn Forte return (port->fp_instance); 1719*fcf3ce44SJohn Forte } 1720*fcf3ce44SJohn Forte 1721*fcf3ce44SJohn Forte 1722*fcf3ce44SJohn Forte opaque_t 1723*fcf3ce44SJohn Forte fc_ulp_get_port_handle(int port_instance) 1724*fcf3ce44SJohn Forte { 1725*fcf3ce44SJohn Forte opaque_t port_handle = NULL; 1726*fcf3ce44SJohn Forte fc_fca_port_t *cur; 1727*fcf3ce44SJohn Forte 1728*fcf3ce44SJohn Forte mutex_enter(&fctl_port_lock); 1729*fcf3ce44SJohn Forte for (cur = fctl_fca_portlist; cur; cur = cur->port_next) { 1730*fcf3ce44SJohn Forte if (cur->port_handle->fp_instance == port_instance) { 1731*fcf3ce44SJohn Forte port_handle = (opaque_t)cur->port_handle; 1732*fcf3ce44SJohn Forte break; 1733*fcf3ce44SJohn Forte } 1734*fcf3ce44SJohn Forte } 1735*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 1736*fcf3ce44SJohn Forte 1737*fcf3ce44SJohn Forte return (port_handle); 1738*fcf3ce44SJohn Forte } 1739*fcf3ce44SJohn Forte 1740*fcf3ce44SJohn Forte 1741*fcf3ce44SJohn Forte int 1742*fcf3ce44SJohn Forte fc_ulp_error(int fc_errno, char **errmsg) 1743*fcf3ce44SJohn Forte { 1744*fcf3ce44SJohn Forte return (fctl_error(fc_errno, errmsg)); 1745*fcf3ce44SJohn Forte } 1746*fcf3ce44SJohn Forte 1747*fcf3ce44SJohn Forte 1748*fcf3ce44SJohn Forte int 1749*fcf3ce44SJohn Forte fc_ulp_pkt_error(fc_packet_t *pkt, char **state, char **reason, 1750*fcf3ce44SJohn Forte char **action, char **expln) 1751*fcf3ce44SJohn Forte { 1752*fcf3ce44SJohn Forte return (fctl_pkt_error(pkt, state, reason, action, expln)); 1753*fcf3ce44SJohn Forte } 1754*fcf3ce44SJohn Forte 1755*fcf3ce44SJohn Forte 1756*fcf3ce44SJohn Forte /* 1757*fcf3ce44SJohn Forte * If an ULP by the specified name exists, return FC_SUCCESS, else FC_FAILURE 1758*fcf3ce44SJohn Forte */ 1759*fcf3ce44SJohn Forte int 1760*fcf3ce44SJohn Forte fc_ulp_is_name_present(caddr_t ulp_name) 1761*fcf3ce44SJohn Forte { 1762*fcf3ce44SJohn Forte int rval = FC_FAILURE; 1763*fcf3ce44SJohn Forte fc_ulp_list_t *list; 1764*fcf3ce44SJohn Forte 1765*fcf3ce44SJohn Forte mutex_enter(&fctl_ulp_list_mutex); 1766*fcf3ce44SJohn Forte for (list = fctl_ulp_list; list != NULL; list = list->ulp_next) { 1767*fcf3ce44SJohn Forte if (strcmp(list->ulp_info->ulp_name, ulp_name) == 0) { 1768*fcf3ce44SJohn Forte rval = FC_SUCCESS; 1769*fcf3ce44SJohn Forte break; 1770*fcf3ce44SJohn Forte } 1771*fcf3ce44SJohn Forte } 1772*fcf3ce44SJohn Forte mutex_exit(&fctl_ulp_list_mutex); 1773*fcf3ce44SJohn Forte 1774*fcf3ce44SJohn Forte return (rval); 1775*fcf3ce44SJohn Forte } 1776*fcf3ce44SJohn Forte 1777*fcf3ce44SJohn Forte 1778*fcf3ce44SJohn Forte /* 1779*fcf3ce44SJohn Forte * Return port WWN for a port Identifier 1780*fcf3ce44SJohn Forte */ 1781*fcf3ce44SJohn Forte int 1782*fcf3ce44SJohn Forte fc_ulp_get_pwwn_by_did(opaque_t port_handle, fc_portid_t d_id, la_wwn_t *pwwn) 1783*fcf3ce44SJohn Forte { 1784*fcf3ce44SJohn Forte int rval = FC_FAILURE; 1785*fcf3ce44SJohn Forte fc_remote_port_t *pd; 1786*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1787*fcf3ce44SJohn Forte 1788*fcf3ce44SJohn Forte pd = fctl_get_remote_port_by_did(port, d_id.port_id); 1789*fcf3ce44SJohn Forte if (pd != NULL) { 1790*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1791*fcf3ce44SJohn Forte *pwwn = pd->pd_port_name; 1792*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1793*fcf3ce44SJohn Forte rval = FC_SUCCESS; 1794*fcf3ce44SJohn Forte } 1795*fcf3ce44SJohn Forte 1796*fcf3ce44SJohn Forte return (rval); 1797*fcf3ce44SJohn Forte } 1798*fcf3ce44SJohn Forte 1799*fcf3ce44SJohn Forte 1800*fcf3ce44SJohn Forte /* 1801*fcf3ce44SJohn Forte * Return a port map for a port WWN 1802*fcf3ce44SJohn Forte */ 1803*fcf3ce44SJohn Forte int 1804*fcf3ce44SJohn Forte fc_ulp_pwwn_to_portmap(opaque_t port_handle, la_wwn_t *bytes, fc_portmap_t *map) 1805*fcf3ce44SJohn Forte { 1806*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1807*fcf3ce44SJohn Forte fc_remote_node_t *node; 1808*fcf3ce44SJohn Forte fc_remote_port_t *pd; 1809*fcf3ce44SJohn Forte 1810*fcf3ce44SJohn Forte pd = fctl_get_remote_port_by_pwwn(port, bytes); 1811*fcf3ce44SJohn Forte if (pd == NULL) { 1812*fcf3ce44SJohn Forte return (FC_FAILURE); 1813*fcf3ce44SJohn Forte } 1814*fcf3ce44SJohn Forte 1815*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1816*fcf3ce44SJohn Forte map->map_pwwn = pd->pd_port_name; 1817*fcf3ce44SJohn Forte map->map_did = pd->pd_port_id; 1818*fcf3ce44SJohn Forte map->map_hard_addr = pd->pd_hard_addr; 1819*fcf3ce44SJohn Forte map->map_state = pd->pd_state; 1820*fcf3ce44SJohn Forte map->map_type = pd->pd_type; 1821*fcf3ce44SJohn Forte map->map_flags = 0; 1822*fcf3ce44SJohn Forte 1823*fcf3ce44SJohn Forte ASSERT(map->map_type <= PORT_DEVICE_DELETE); 1824*fcf3ce44SJohn Forte 1825*fcf3ce44SJohn Forte bcopy(pd->pd_fc4types, map->map_fc4_types, sizeof (pd->pd_fc4types)); 1826*fcf3ce44SJohn Forte 1827*fcf3ce44SJohn Forte node = pd->pd_remote_nodep; 1828*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1829*fcf3ce44SJohn Forte 1830*fcf3ce44SJohn Forte if (node) { 1831*fcf3ce44SJohn Forte mutex_enter(&node->fd_mutex); 1832*fcf3ce44SJohn Forte map->map_nwwn = node->fd_node_name; 1833*fcf3ce44SJohn Forte mutex_exit(&node->fd_mutex); 1834*fcf3ce44SJohn Forte } 1835*fcf3ce44SJohn Forte map->map_pd = pd; 1836*fcf3ce44SJohn Forte 1837*fcf3ce44SJohn Forte return (FC_SUCCESS); 1838*fcf3ce44SJohn Forte } 1839*fcf3ce44SJohn Forte 1840*fcf3ce44SJohn Forte 1841*fcf3ce44SJohn Forte opaque_t 1842*fcf3ce44SJohn Forte fc_ulp_get_fca_device(opaque_t port_handle, fc_portid_t d_id) 1843*fcf3ce44SJohn Forte { 1844*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1845*fcf3ce44SJohn Forte 1846*fcf3ce44SJohn Forte if (port->fp_fca_tran->fca_get_device == NULL) { 1847*fcf3ce44SJohn Forte return (NULL); 1848*fcf3ce44SJohn Forte } 1849*fcf3ce44SJohn Forte 1850*fcf3ce44SJohn Forte return (port->fp_fca_tran->fca_get_device(port->fp_fca_handle, d_id)); 1851*fcf3ce44SJohn Forte } 1852*fcf3ce44SJohn Forte 1853*fcf3ce44SJohn Forte 1854*fcf3ce44SJohn Forte int 1855*fcf3ce44SJohn Forte fc_ulp_port_notify(opaque_t port_handle, uint32_t cmd) 1856*fcf3ce44SJohn Forte { 1857*fcf3ce44SJohn Forte int rval = FC_SUCCESS; 1858*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 1859*fcf3ce44SJohn Forte 1860*fcf3ce44SJohn Forte if (port->fp_fca_tran->fca_notify) { 1861*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 1862*fcf3ce44SJohn Forte switch (cmd) { 1863*fcf3ce44SJohn Forte case FC_NOTIFY_TARGET_MODE: 1864*fcf3ce44SJohn Forte port->fp_options |= FP_TARGET_MODE; 1865*fcf3ce44SJohn Forte break; 1866*fcf3ce44SJohn Forte case FC_NOTIFY_NO_TARGET_MODE: 1867*fcf3ce44SJohn Forte port->fp_options &= ~FP_TARGET_MODE; 1868*fcf3ce44SJohn Forte break; 1869*fcf3ce44SJohn Forte } 1870*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 1871*fcf3ce44SJohn Forte rval = port->fp_fca_tran->fca_notify(port->fp_fca_handle, cmd); 1872*fcf3ce44SJohn Forte } 1873*fcf3ce44SJohn Forte 1874*fcf3ce44SJohn Forte return (rval); 1875*fcf3ce44SJohn Forte } 1876*fcf3ce44SJohn Forte 1877*fcf3ce44SJohn Forte 1878*fcf3ce44SJohn Forte void 1879*fcf3ce44SJohn Forte fc_ulp_disable_relogin(opaque_t *fc_port, la_wwn_t *pwwn) 1880*fcf3ce44SJohn Forte { 1881*fcf3ce44SJohn Forte fc_remote_port_t *pd = 1882*fcf3ce44SJohn Forte fctl_get_remote_port_by_pwwn((fc_local_port_t *)fc_port, pwwn); 1883*fcf3ce44SJohn Forte 1884*fcf3ce44SJohn Forte if (pd) { 1885*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1886*fcf3ce44SJohn Forte pd->pd_aux_flags |= PD_DISABLE_RELOGIN; 1887*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1888*fcf3ce44SJohn Forte } 1889*fcf3ce44SJohn Forte } 1890*fcf3ce44SJohn Forte 1891*fcf3ce44SJohn Forte 1892*fcf3ce44SJohn Forte void 1893*fcf3ce44SJohn Forte fc_ulp_enable_relogin(opaque_t *fc_port, la_wwn_t *pwwn) 1894*fcf3ce44SJohn Forte { 1895*fcf3ce44SJohn Forte fc_remote_port_t *pd = 1896*fcf3ce44SJohn Forte fctl_get_remote_port_by_pwwn((fc_local_port_t *)fc_port, pwwn); 1897*fcf3ce44SJohn Forte 1898*fcf3ce44SJohn Forte if (pd) { 1899*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 1900*fcf3ce44SJohn Forte pd->pd_aux_flags &= ~PD_DISABLE_RELOGIN; 1901*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 1902*fcf3ce44SJohn Forte } 1903*fcf3ce44SJohn Forte } 1904*fcf3ce44SJohn Forte 1905*fcf3ce44SJohn Forte 1906*fcf3ce44SJohn Forte /* 1907*fcf3ce44SJohn Forte * fc_fca_init 1908*fcf3ce44SJohn Forte * Overload the FCA bus_ops vector in its dev_ops with 1909*fcf3ce44SJohn Forte * fctl_fca_busops to handle all the INITchilds for "sf" 1910*fcf3ce44SJohn Forte * in one common place. 1911*fcf3ce44SJohn Forte * 1912*fcf3ce44SJohn Forte * Should be called from FCA _init routine. 1913*fcf3ce44SJohn Forte */ 1914*fcf3ce44SJohn Forte void 1915*fcf3ce44SJohn Forte fc_fca_init(struct dev_ops *fca_devops_p) 1916*fcf3ce44SJohn Forte { 1917*fcf3ce44SJohn Forte #ifndef __lock_lint 1918*fcf3ce44SJohn Forte fca_devops_p->devo_bus_ops = &fctl_fca_busops; 1919*fcf3ce44SJohn Forte #endif /* __lock_lint */ 1920*fcf3ce44SJohn Forte } 1921*fcf3ce44SJohn Forte 1922*fcf3ce44SJohn Forte 1923*fcf3ce44SJohn Forte /* 1924*fcf3ce44SJohn Forte * fc_fca_attach 1925*fcf3ce44SJohn Forte */ 1926*fcf3ce44SJohn Forte int 1927*fcf3ce44SJohn Forte fc_fca_attach(dev_info_t *fca_dip, fc_fca_tran_t *tran) 1928*fcf3ce44SJohn Forte { 1929*fcf3ce44SJohn Forte /* 1930*fcf3ce44SJohn Forte * When we are in a position to offer downward compatibility 1931*fcf3ce44SJohn Forte * we should change the following check to allow lower revision 1932*fcf3ce44SJohn Forte * of FCAs; But we aren't there right now. 1933*fcf3ce44SJohn Forte */ 1934*fcf3ce44SJohn Forte if (tran->fca_version != FCTL_FCA_MODREV_5) { 1935*fcf3ce44SJohn Forte const char *name = ddi_driver_name(fca_dip); 1936*fcf3ce44SJohn Forte 1937*fcf3ce44SJohn Forte ASSERT(name != NULL); 1938*fcf3ce44SJohn Forte 1939*fcf3ce44SJohn Forte cmn_err(CE_WARN, "fctl: FCA %s version mismatch" 1940*fcf3ce44SJohn Forte " please upgrade %s", name, name); 1941*fcf3ce44SJohn Forte return (DDI_FAILURE); 1942*fcf3ce44SJohn Forte } 1943*fcf3ce44SJohn Forte 1944*fcf3ce44SJohn Forte ddi_set_driver_private(fca_dip, (caddr_t)tran); 1945*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1946*fcf3ce44SJohn Forte } 1947*fcf3ce44SJohn Forte 1948*fcf3ce44SJohn Forte 1949*fcf3ce44SJohn Forte /* 1950*fcf3ce44SJohn Forte * fc_fca_detach 1951*fcf3ce44SJohn Forte */ 1952*fcf3ce44SJohn Forte int 1953*fcf3ce44SJohn Forte fc_fca_detach(dev_info_t *fca_dip) 1954*fcf3ce44SJohn Forte { 1955*fcf3ce44SJohn Forte ddi_set_driver_private(fca_dip, NULL); 1956*fcf3ce44SJohn Forte return (DDI_SUCCESS); 1957*fcf3ce44SJohn Forte } 1958*fcf3ce44SJohn Forte 1959*fcf3ce44SJohn Forte 1960*fcf3ce44SJohn Forte /* 1961*fcf3ce44SJohn Forte * Check if the frame is a Link response Frame; Handle all cases (P_RJT, 1962*fcf3ce44SJohn Forte * F_RJT, P_BSY, F_BSY fall into this category). Check also for some Basic 1963*fcf3ce44SJohn Forte * Link Service responses such as BA_RJT and Extended Link Service response 1964*fcf3ce44SJohn Forte * such as LS_RJT. If the response is a Link_Data Frame or something that 1965*fcf3ce44SJohn Forte * this function doesn't understand return FC_FAILURE; Otherwise, fill out 1966*fcf3ce44SJohn Forte * various fields (state, action, reason, expln) from the response gotten 1967*fcf3ce44SJohn Forte * in the packet and return FC_SUCCESS. 1968*fcf3ce44SJohn Forte */ 1969*fcf3ce44SJohn Forte int 1970*fcf3ce44SJohn Forte fc_fca_update_errors(fc_packet_t *pkt) 1971*fcf3ce44SJohn Forte { 1972*fcf3ce44SJohn Forte int ret = FC_SUCCESS; 1973*fcf3ce44SJohn Forte 1974*fcf3ce44SJohn Forte switch (pkt->pkt_resp_fhdr.r_ctl) { 1975*fcf3ce44SJohn Forte case R_CTL_P_RJT: { 1976*fcf3ce44SJohn Forte uint32_t prjt; 1977*fcf3ce44SJohn Forte 1978*fcf3ce44SJohn Forte prjt = pkt->pkt_resp_fhdr.ro; 1979*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_NPORT_RJT; 1980*fcf3ce44SJohn Forte pkt->pkt_action = (prjt & 0xFF000000) >> 24; 1981*fcf3ce44SJohn Forte pkt->pkt_reason = (prjt & 0xFF0000) >> 16; 1982*fcf3ce44SJohn Forte break; 1983*fcf3ce44SJohn Forte } 1984*fcf3ce44SJohn Forte 1985*fcf3ce44SJohn Forte case R_CTL_F_RJT: { 1986*fcf3ce44SJohn Forte uint32_t frjt; 1987*fcf3ce44SJohn Forte 1988*fcf3ce44SJohn Forte frjt = pkt->pkt_resp_fhdr.ro; 1989*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_FABRIC_RJT; 1990*fcf3ce44SJohn Forte pkt->pkt_action = (frjt & 0xFF000000) >> 24; 1991*fcf3ce44SJohn Forte pkt->pkt_reason = (frjt & 0xFF0000) >> 16; 1992*fcf3ce44SJohn Forte break; 1993*fcf3ce44SJohn Forte } 1994*fcf3ce44SJohn Forte 1995*fcf3ce44SJohn Forte case R_CTL_P_BSY: { 1996*fcf3ce44SJohn Forte uint32_t pbsy; 1997*fcf3ce44SJohn Forte 1998*fcf3ce44SJohn Forte pbsy = pkt->pkt_resp_fhdr.ro; 1999*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_NPORT_BSY; 2000*fcf3ce44SJohn Forte pkt->pkt_action = (pbsy & 0xFF000000) >> 24; 2001*fcf3ce44SJohn Forte pkt->pkt_reason = (pbsy & 0xFF0000) >> 16; 2002*fcf3ce44SJohn Forte break; 2003*fcf3ce44SJohn Forte } 2004*fcf3ce44SJohn Forte 2005*fcf3ce44SJohn Forte case R_CTL_F_BSY_LC: 2006*fcf3ce44SJohn Forte case R_CTL_F_BSY_DF: { 2007*fcf3ce44SJohn Forte uchar_t fbsy; 2008*fcf3ce44SJohn Forte 2009*fcf3ce44SJohn Forte fbsy = pkt->pkt_resp_fhdr.type; 2010*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_FABRIC_BSY; 2011*fcf3ce44SJohn Forte pkt->pkt_reason = (fbsy & 0xF0) >> 4; 2012*fcf3ce44SJohn Forte break; 2013*fcf3ce44SJohn Forte } 2014*fcf3ce44SJohn Forte 2015*fcf3ce44SJohn Forte case R_CTL_LS_BA_RJT: { 2016*fcf3ce44SJohn Forte uint32_t brjt; 2017*fcf3ce44SJohn Forte 2018*fcf3ce44SJohn Forte brjt = *(uint32_t *)pkt->pkt_resp; 2019*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_BA_RJT; 2020*fcf3ce44SJohn Forte pkt->pkt_reason = (brjt & 0xFF0000) >> 16; 2021*fcf3ce44SJohn Forte pkt->pkt_expln = (brjt & 0xFF00) >> 8; 2022*fcf3ce44SJohn Forte break; 2023*fcf3ce44SJohn Forte } 2024*fcf3ce44SJohn Forte 2025*fcf3ce44SJohn Forte case R_CTL_ELS_RSP: { 2026*fcf3ce44SJohn Forte la_els_rjt_t *lsrjt; 2027*fcf3ce44SJohn Forte 2028*fcf3ce44SJohn Forte lsrjt = (la_els_rjt_t *)pkt->pkt_resp; 2029*fcf3ce44SJohn Forte if (lsrjt->ls_code.ls_code == LA_ELS_RJT) { 2030*fcf3ce44SJohn Forte pkt->pkt_state = FC_PKT_LS_RJT; 2031*fcf3ce44SJohn Forte pkt->pkt_reason = lsrjt->reason; 2032*fcf3ce44SJohn Forte pkt->pkt_action = lsrjt->action; 2033*fcf3ce44SJohn Forte break; 2034*fcf3ce44SJohn Forte } 2035*fcf3ce44SJohn Forte /* FALLTHROUGH */ 2036*fcf3ce44SJohn Forte } 2037*fcf3ce44SJohn Forte 2038*fcf3ce44SJohn Forte default: 2039*fcf3ce44SJohn Forte ret = FC_FAILURE; 2040*fcf3ce44SJohn Forte break; 2041*fcf3ce44SJohn Forte } 2042*fcf3ce44SJohn Forte 2043*fcf3ce44SJohn Forte return (ret); 2044*fcf3ce44SJohn Forte } 2045*fcf3ce44SJohn Forte 2046*fcf3ce44SJohn Forte 2047*fcf3ce44SJohn Forte int 2048*fcf3ce44SJohn Forte fc_fca_error(int fc_errno, char **errmsg) 2049*fcf3ce44SJohn Forte { 2050*fcf3ce44SJohn Forte return (fctl_error(fc_errno, errmsg)); 2051*fcf3ce44SJohn Forte } 2052*fcf3ce44SJohn Forte 2053*fcf3ce44SJohn Forte 2054*fcf3ce44SJohn Forte int 2055*fcf3ce44SJohn Forte fc_fca_pkt_error(fc_packet_t *pkt, char **state, char **reason, 2056*fcf3ce44SJohn Forte char **action, char **expln) 2057*fcf3ce44SJohn Forte { 2058*fcf3ce44SJohn Forte return (fctl_pkt_error(pkt, state, reason, action, expln)); 2059*fcf3ce44SJohn Forte } 2060*fcf3ce44SJohn Forte 2061*fcf3ce44SJohn Forte 2062*fcf3ce44SJohn Forte /* 2063*fcf3ce44SJohn Forte * WWN to string goodie. Unpredictable results will happen 2064*fcf3ce44SJohn Forte * if enough memory isn't supplied in str argument. If you 2065*fcf3ce44SJohn Forte * are wondering how much does this routine need, it is just 2066*fcf3ce44SJohn Forte * (2 * WWN size + 1). So for a WWN size of 8 bytes the str 2067*fcf3ce44SJohn Forte * argument should have atleast 17 bytes allocated. 2068*fcf3ce44SJohn Forte */ 2069*fcf3ce44SJohn Forte void 2070*fcf3ce44SJohn Forte fc_wwn_to_str(la_wwn_t *wwn, caddr_t str) 2071*fcf3ce44SJohn Forte { 2072*fcf3ce44SJohn Forte int count; 2073*fcf3ce44SJohn Forte 2074*fcf3ce44SJohn Forte for (count = 0; count < FCTL_WWN_SIZE(wwn); count++, str += 2) { 2075*fcf3ce44SJohn Forte (void) sprintf(str, "%02x", wwn->raw_wwn[count]); 2076*fcf3ce44SJohn Forte } 2077*fcf3ce44SJohn Forte *str = '\0'; 2078*fcf3ce44SJohn Forte } 2079*fcf3ce44SJohn Forte 2080*fcf3ce44SJohn Forte #define FC_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') :\ 2081*fcf3ce44SJohn Forte ((x) >= 'a' && (x) <= 'f') ?\ 2082*fcf3ce44SJohn Forte ((x) - 'a' + 10) : ((x) - 'A' + 10)) 2083*fcf3ce44SJohn Forte 2084*fcf3ce44SJohn Forte void 2085*fcf3ce44SJohn Forte fc_str_to_wwn(caddr_t str, la_wwn_t *wwn) 2086*fcf3ce44SJohn Forte { 2087*fcf3ce44SJohn Forte int count = 0; 2088*fcf3ce44SJohn Forte uchar_t byte; 2089*fcf3ce44SJohn Forte 2090*fcf3ce44SJohn Forte while (*str) { 2091*fcf3ce44SJohn Forte byte = FC_ATOB(*str); 2092*fcf3ce44SJohn Forte str++; 2093*fcf3ce44SJohn Forte byte = byte << 4 | FC_ATOB(*str); 2094*fcf3ce44SJohn Forte str++; 2095*fcf3ce44SJohn Forte wwn->raw_wwn[count++] = byte; 2096*fcf3ce44SJohn Forte } 2097*fcf3ce44SJohn Forte } 2098*fcf3ce44SJohn Forte 2099*fcf3ce44SJohn Forte /* 2100*fcf3ce44SJohn Forte * FCA driver's intercepted bus control operations. 2101*fcf3ce44SJohn Forte */ 2102*fcf3ce44SJohn Forte static int 2103*fcf3ce44SJohn Forte fctl_fca_bus_ctl(dev_info_t *fca_dip, dev_info_t *rip, 2104*fcf3ce44SJohn Forte ddi_ctl_enum_t op, void *arg, void *result) 2105*fcf3ce44SJohn Forte { 2106*fcf3ce44SJohn Forte switch (op) { 2107*fcf3ce44SJohn Forte case DDI_CTLOPS_REPORTDEV: 2108*fcf3ce44SJohn Forte break; 2109*fcf3ce44SJohn Forte 2110*fcf3ce44SJohn Forte case DDI_CTLOPS_IOMIN: 2111*fcf3ce44SJohn Forte break; 2112*fcf3ce44SJohn Forte 2113*fcf3ce44SJohn Forte case DDI_CTLOPS_INITCHILD: 2114*fcf3ce44SJohn Forte return (fctl_initchild(fca_dip, (dev_info_t *)arg)); 2115*fcf3ce44SJohn Forte 2116*fcf3ce44SJohn Forte case DDI_CTLOPS_UNINITCHILD: 2117*fcf3ce44SJohn Forte return (fctl_uninitchild(fca_dip, (dev_info_t *)arg)); 2118*fcf3ce44SJohn Forte 2119*fcf3ce44SJohn Forte default: 2120*fcf3ce44SJohn Forte return (ddi_ctlops(fca_dip, rip, op, arg, result)); 2121*fcf3ce44SJohn Forte } 2122*fcf3ce44SJohn Forte 2123*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2124*fcf3ce44SJohn Forte } 2125*fcf3ce44SJohn Forte 2126*fcf3ce44SJohn Forte 2127*fcf3ce44SJohn Forte /* 2128*fcf3ce44SJohn Forte * FCAs indicate the maximum number of ports supported in their 2129*fcf3ce44SJohn Forte * tran structure. Fail the INITCHILD if the child port number 2130*fcf3ce44SJohn Forte * is any greater than the maximum number of ports supported 2131*fcf3ce44SJohn Forte * by the FCA. 2132*fcf3ce44SJohn Forte */ 2133*fcf3ce44SJohn Forte static int 2134*fcf3ce44SJohn Forte fctl_initchild(dev_info_t *fca_dip, dev_info_t *port_dip) 2135*fcf3ce44SJohn Forte { 2136*fcf3ce44SJohn Forte int rval; 2137*fcf3ce44SJohn Forte int port_no; 2138*fcf3ce44SJohn Forte int port_len; 2139*fcf3ce44SJohn Forte char name[20]; 2140*fcf3ce44SJohn Forte fc_fca_tran_t *tran; 2141*fcf3ce44SJohn Forte dev_info_t *dip; 2142*fcf3ce44SJohn Forte int portprop; 2143*fcf3ce44SJohn Forte 2144*fcf3ce44SJohn Forte port_len = sizeof (port_no); 2145*fcf3ce44SJohn Forte 2146*fcf3ce44SJohn Forte /* physical port do not has this property */ 2147*fcf3ce44SJohn Forte portprop = ddi_prop_get_int(DDI_DEV_T_ANY, port_dip, 2148*fcf3ce44SJohn Forte DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 2149*fcf3ce44SJohn Forte "phyport-instance", -1); 2150*fcf3ce44SJohn Forte 2151*fcf3ce44SJohn Forte if ((portprop == -1) && ndi_dev_is_persistent_node(port_dip)) { 2152*fcf3ce44SJohn Forte /* 2153*fcf3ce44SJohn Forte * Clear any addr bindings created by fcode interpreter 2154*fcf3ce44SJohn Forte * in devi_last_addr so that a ndi_devi_find should never 2155*fcf3ce44SJohn Forte * return this fcode node. 2156*fcf3ce44SJohn Forte */ 2157*fcf3ce44SJohn Forte ddi_set_name_addr(port_dip, NULL); 2158*fcf3ce44SJohn Forte return (DDI_FAILURE); 2159*fcf3ce44SJohn Forte } 2160*fcf3ce44SJohn Forte 2161*fcf3ce44SJohn Forte rval = ddi_prop_op(DDI_DEV_T_ANY, port_dip, PROP_LEN_AND_VAL_BUF, 2162*fcf3ce44SJohn Forte DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "port", 2163*fcf3ce44SJohn Forte (caddr_t)&port_no, &port_len); 2164*fcf3ce44SJohn Forte 2165*fcf3ce44SJohn Forte if (rval != DDI_SUCCESS) { 2166*fcf3ce44SJohn Forte return (DDI_FAILURE); 2167*fcf3ce44SJohn Forte } 2168*fcf3ce44SJohn Forte 2169*fcf3ce44SJohn Forte tran = (fc_fca_tran_t *)ddi_get_driver_private(fca_dip); 2170*fcf3ce44SJohn Forte ASSERT(tran != NULL); 2171*fcf3ce44SJohn Forte 2172*fcf3ce44SJohn Forte (void) sprintf((char *)name, "%x,0", port_no); 2173*fcf3ce44SJohn Forte ddi_set_name_addr(port_dip, name); 2174*fcf3ce44SJohn Forte 2175*fcf3ce44SJohn Forte dip = ndi_devi_find(fca_dip, ddi_binding_name(port_dip), name); 2176*fcf3ce44SJohn Forte 2177*fcf3ce44SJohn Forte /* 2178*fcf3ce44SJohn Forte * Even though we never initialize FCode nodes of fp, such a node 2179*fcf3ce44SJohn Forte * could still be there after a DR operation. There will only be 2180*fcf3ce44SJohn Forte * one FCode node, so if this is the one, clear it and issue a 2181*fcf3ce44SJohn Forte * ndi_devi_find again. 2182*fcf3ce44SJohn Forte */ 2183*fcf3ce44SJohn Forte if ((portprop == -1) && dip && ndi_dev_is_persistent_node(dip)) { 2184*fcf3ce44SJohn Forte ddi_set_name_addr(dip, NULL); 2185*fcf3ce44SJohn Forte dip = ndi_devi_find(fca_dip, ddi_binding_name(port_dip), name); 2186*fcf3ce44SJohn Forte } 2187*fcf3ce44SJohn Forte 2188*fcf3ce44SJohn Forte if ((portprop == -1) && dip && (dip != port_dip)) { 2189*fcf3ce44SJohn Forte /* 2190*fcf3ce44SJohn Forte * Here we have a duplicate .conf entry. Clear the addr 2191*fcf3ce44SJohn Forte * set previously and return failure. 2192*fcf3ce44SJohn Forte */ 2193*fcf3ce44SJohn Forte ddi_set_name_addr(port_dip, NULL); 2194*fcf3ce44SJohn Forte return (DDI_FAILURE); 2195*fcf3ce44SJohn Forte } 2196*fcf3ce44SJohn Forte 2197*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2198*fcf3ce44SJohn Forte } 2199*fcf3ce44SJohn Forte 2200*fcf3ce44SJohn Forte 2201*fcf3ce44SJohn Forte /* ARGSUSED */ 2202*fcf3ce44SJohn Forte static int 2203*fcf3ce44SJohn Forte fctl_uninitchild(dev_info_t *fca_dip, dev_info_t *port_dip) 2204*fcf3ce44SJohn Forte { 2205*fcf3ce44SJohn Forte ddi_set_name_addr(port_dip, NULL); 2206*fcf3ce44SJohn Forte return (DDI_SUCCESS); 2207*fcf3ce44SJohn Forte } 2208*fcf3ce44SJohn Forte 2209*fcf3ce44SJohn Forte 2210*fcf3ce44SJohn Forte static dev_info_t * 2211*fcf3ce44SJohn Forte fctl_findchild(dev_info_t *pdip, char *cname, char *caddr) 2212*fcf3ce44SJohn Forte { 2213*fcf3ce44SJohn Forte dev_info_t *dip; 2214*fcf3ce44SJohn Forte char *addr; 2215*fcf3ce44SJohn Forte 2216*fcf3ce44SJohn Forte ASSERT(cname != NULL && caddr != NULL); 2217*fcf3ce44SJohn Forte /* ASSERT(DEVI_BUSY_OWNED(pdip)); */ 2218*fcf3ce44SJohn Forte 2219*fcf3ce44SJohn Forte for (dip = ddi_get_child(pdip); dip != NULL; 2220*fcf3ce44SJohn Forte dip = ddi_get_next_sibling(dip)) { 2221*fcf3ce44SJohn Forte if (strcmp(cname, ddi_node_name(dip)) != 0) 2222*fcf3ce44SJohn Forte continue; 2223*fcf3ce44SJohn Forte 2224*fcf3ce44SJohn Forte if ((addr = ddi_get_name_addr(dip)) == NULL) { 2225*fcf3ce44SJohn Forte if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 2226*fcf3ce44SJohn Forte DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 2227*fcf3ce44SJohn Forte "bus-addr", &addr) == DDI_PROP_SUCCESS) { 2228*fcf3ce44SJohn Forte if (strcmp(caddr, addr) == 0) { 2229*fcf3ce44SJohn Forte ddi_prop_free(addr); 2230*fcf3ce44SJohn Forte return (dip); 2231*fcf3ce44SJohn Forte } 2232*fcf3ce44SJohn Forte ddi_prop_free(addr); 2233*fcf3ce44SJohn Forte } 2234*fcf3ce44SJohn Forte } else { 2235*fcf3ce44SJohn Forte if (strcmp(caddr, addr) == 0) 2236*fcf3ce44SJohn Forte return (dip); 2237*fcf3ce44SJohn Forte } 2238*fcf3ce44SJohn Forte } 2239*fcf3ce44SJohn Forte 2240*fcf3ce44SJohn Forte return (NULL); 2241*fcf3ce44SJohn Forte } 2242*fcf3ce44SJohn Forte 2243*fcf3ce44SJohn Forte int 2244*fcf3ce44SJohn Forte fctl_check_npiv_portindex(dev_info_t *dip, int vindex) 2245*fcf3ce44SJohn Forte { 2246*fcf3ce44SJohn Forte int i, instance; 2247*fcf3ce44SJohn Forte fc_local_port_t *port; 2248*fcf3ce44SJohn Forte 2249*fcf3ce44SJohn Forte instance = ddi_get_instance(dip); 2250*fcf3ce44SJohn Forte port = (fc_local_port_t *)fc_ulp_get_port_handle(instance); 2251*fcf3ce44SJohn Forte if ((!port) || (vindex <= 0) || (vindex >= FC_NPIV_MAX_PORT)) { 2252*fcf3ce44SJohn Forte return (0); 2253*fcf3ce44SJohn Forte } 2254*fcf3ce44SJohn Forte 2255*fcf3ce44SJohn Forte i = vindex-1; 2256*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 2257*fcf3ce44SJohn Forte if (port->fp_npiv_portindex[i] == 0) { 2258*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 2259*fcf3ce44SJohn Forte return (vindex); 2260*fcf3ce44SJohn Forte } 2261*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 2262*fcf3ce44SJohn Forte return (0); 2263*fcf3ce44SJohn Forte } 2264*fcf3ce44SJohn Forte 2265*fcf3ce44SJohn Forte int 2266*fcf3ce44SJohn Forte fctl_get_npiv_portindex(dev_info_t *dip) 2267*fcf3ce44SJohn Forte { 2268*fcf3ce44SJohn Forte int i, instance; 2269*fcf3ce44SJohn Forte fc_local_port_t *port; 2270*fcf3ce44SJohn Forte 2271*fcf3ce44SJohn Forte instance = ddi_get_instance(dip); 2272*fcf3ce44SJohn Forte port = (fc_local_port_t *)fc_ulp_get_port_handle(instance); 2273*fcf3ce44SJohn Forte if (!port) { 2274*fcf3ce44SJohn Forte return (0); 2275*fcf3ce44SJohn Forte } 2276*fcf3ce44SJohn Forte 2277*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 2278*fcf3ce44SJohn Forte for (i = 0; i < FC_NPIV_MAX_PORT; i++) { 2279*fcf3ce44SJohn Forte if (port->fp_npiv_portindex[i] == 0) { 2280*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 2281*fcf3ce44SJohn Forte return (i+1); 2282*fcf3ce44SJohn Forte } 2283*fcf3ce44SJohn Forte } 2284*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 2285*fcf3ce44SJohn Forte return (0); 2286*fcf3ce44SJohn Forte } 2287*fcf3ce44SJohn Forte 2288*fcf3ce44SJohn Forte 2289*fcf3ce44SJohn Forte void 2290*fcf3ce44SJohn Forte fctl_set_npiv_portindex(dev_info_t *dip, int index) 2291*fcf3ce44SJohn Forte { 2292*fcf3ce44SJohn Forte int instance; 2293*fcf3ce44SJohn Forte fc_local_port_t *port; 2294*fcf3ce44SJohn Forte 2295*fcf3ce44SJohn Forte instance = ddi_get_instance(dip); 2296*fcf3ce44SJohn Forte port = (fc_local_port_t *)fc_ulp_get_port_handle(instance); 2297*fcf3ce44SJohn Forte if (!port) { 2298*fcf3ce44SJohn Forte return; 2299*fcf3ce44SJohn Forte } 2300*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 2301*fcf3ce44SJohn Forte port->fp_npiv_portindex[index - 1] = 1; 2302*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 2303*fcf3ce44SJohn Forte } 2304*fcf3ce44SJohn Forte 2305*fcf3ce44SJohn Forte 2306*fcf3ce44SJohn Forte int 2307*fcf3ce44SJohn Forte fctl_fca_create_npivport(dev_info_t *parent, 2308*fcf3ce44SJohn Forte dev_info_t *phydip, char *nname, char *pname, uint32_t *vindex) 2309*fcf3ce44SJohn Forte { 2310*fcf3ce44SJohn Forte int rval = 0, devstrlen; 2311*fcf3ce44SJohn Forte char *devname, *cname, *caddr, *devstr; 2312*fcf3ce44SJohn Forte dev_info_t *child = NULL; 2313*fcf3ce44SJohn Forte int portnum; 2314*fcf3ce44SJohn Forte 2315*fcf3ce44SJohn Forte if (*vindex == 0) { 2316*fcf3ce44SJohn Forte portnum = fctl_get_npiv_portindex(phydip); 2317*fcf3ce44SJohn Forte *vindex = portnum; 2318*fcf3ce44SJohn Forte } else { 2319*fcf3ce44SJohn Forte portnum = fctl_check_npiv_portindex(phydip, *vindex); 2320*fcf3ce44SJohn Forte } 2321*fcf3ce44SJohn Forte 2322*fcf3ce44SJohn Forte if (portnum == 0) { 2323*fcf3ce44SJohn Forte cmn_err(CE_WARN, 2324*fcf3ce44SJohn Forte "Cann't find valid port index, fail to create devnode"); 2325*fcf3ce44SJohn Forte return (NDI_FAILURE); 2326*fcf3ce44SJohn Forte } 2327*fcf3ce44SJohn Forte 2328*fcf3ce44SJohn Forte devname = kmem_zalloc(MAXNAMELEN, KM_SLEEP); 2329*fcf3ce44SJohn Forte (void) sprintf(devname, "fp@%x,0", portnum); 2330*fcf3ce44SJohn Forte devstrlen = strlen(devname) + 1; 2331*fcf3ce44SJohn Forte devstr = i_ddi_strdup(devname, KM_SLEEP); 2332*fcf3ce44SJohn Forte i_ddi_parse_name(devstr, &cname, &caddr, NULL); 2333*fcf3ce44SJohn Forte 2334*fcf3ce44SJohn Forte if (fctl_findchild(parent, cname, caddr) != NULL) { 2335*fcf3ce44SJohn Forte rval = NDI_FAILURE; 2336*fcf3ce44SJohn Forte goto freememory; 2337*fcf3ce44SJohn Forte } 2338*fcf3ce44SJohn Forte 2339*fcf3ce44SJohn Forte ndi_devi_alloc_sleep(parent, cname, DEVI_PSEUDO_NODEID, &child); 2340*fcf3ce44SJohn Forte if (child == NULL) { 2341*fcf3ce44SJohn Forte cmn_err(CE_WARN, 2342*fcf3ce44SJohn Forte "fctl_create_npiv_port fail to create new devinfo"); 2343*fcf3ce44SJohn Forte rval = NDI_FAILURE; 2344*fcf3ce44SJohn Forte goto freememory; 2345*fcf3ce44SJohn Forte } 2346*fcf3ce44SJohn Forte 2347*fcf3ce44SJohn Forte if (ndi_prop_update_string(DDI_DEV_T_NONE, child, 2348*fcf3ce44SJohn Forte "bus-addr", caddr) != DDI_PROP_SUCCESS) { 2349*fcf3ce44SJohn Forte cmn_err(CE_WARN, "fctl%d: prop update bus-addr %s@%s failed", 2350*fcf3ce44SJohn Forte ddi_get_instance(parent), cname, caddr); 2351*fcf3ce44SJohn Forte (void) ndi_devi_free(child); 2352*fcf3ce44SJohn Forte rval = NDI_FAILURE; 2353*fcf3ce44SJohn Forte goto freememory; 2354*fcf3ce44SJohn Forte } 2355*fcf3ce44SJohn Forte 2356*fcf3ce44SJohn Forte if (strlen(nname) != 0) { 2357*fcf3ce44SJohn Forte if (ndi_prop_update_string(DDI_DEV_T_NONE, child, 2358*fcf3ce44SJohn Forte "node-name", nname) != DDI_PROP_SUCCESS) { 2359*fcf3ce44SJohn Forte (void) ndi_devi_free(child); 2360*fcf3ce44SJohn Forte rval = NDI_FAILURE; 2361*fcf3ce44SJohn Forte goto freememory; 2362*fcf3ce44SJohn Forte } 2363*fcf3ce44SJohn Forte } 2364*fcf3ce44SJohn Forte 2365*fcf3ce44SJohn Forte if (strlen(pname) != 0) { 2366*fcf3ce44SJohn Forte if (ndi_prop_update_string(DDI_DEV_T_NONE, child, 2367*fcf3ce44SJohn Forte "port-name", pname) != DDI_PROP_SUCCESS) { 2368*fcf3ce44SJohn Forte (void) ndi_devi_free(child); 2369*fcf3ce44SJohn Forte rval = NDI_FAILURE; 2370*fcf3ce44SJohn Forte goto freememory; 2371*fcf3ce44SJohn Forte } 2372*fcf3ce44SJohn Forte } 2373*fcf3ce44SJohn Forte 2374*fcf3ce44SJohn Forte if (ddi_prop_update_int(DDI_DEV_T_NONE, child, 2375*fcf3ce44SJohn Forte "port", portnum) != DDI_PROP_SUCCESS) { 2376*fcf3ce44SJohn Forte cmn_err(CE_WARN, "fp%d: prop_update port %s@%s failed", 2377*fcf3ce44SJohn Forte ddi_get_instance(parent), cname, caddr); 2378*fcf3ce44SJohn Forte (void) ndi_devi_free(child); 2379*fcf3ce44SJohn Forte rval = NDI_FAILURE; 2380*fcf3ce44SJohn Forte goto freememory; 2381*fcf3ce44SJohn Forte } 2382*fcf3ce44SJohn Forte 2383*fcf3ce44SJohn Forte if (ddi_prop_update_int(DDI_DEV_T_NONE, child, 2384*fcf3ce44SJohn Forte "phyport-instance", ddi_get_instance(phydip)) != DDI_PROP_SUCCESS) { 2385*fcf3ce44SJohn Forte cmn_err(CE_WARN, 2386*fcf3ce44SJohn Forte "fp%d: prop_update phyport-instance %s@%s failed", 2387*fcf3ce44SJohn Forte ddi_get_instance(parent), cname, caddr); 2388*fcf3ce44SJohn Forte (void) ndi_devi_free(child); 2389*fcf3ce44SJohn Forte rval = NDI_FAILURE; 2390*fcf3ce44SJohn Forte goto freememory; 2391*fcf3ce44SJohn Forte } 2392*fcf3ce44SJohn Forte 2393*fcf3ce44SJohn Forte rval = ndi_devi_online(child, NDI_ONLINE_ATTACH); 2394*fcf3ce44SJohn Forte if (rval != NDI_SUCCESS) { 2395*fcf3ce44SJohn Forte cmn_err(CE_WARN, "fp%d: online_driver %s failed", 2396*fcf3ce44SJohn Forte ddi_get_instance(parent), cname); 2397*fcf3ce44SJohn Forte rval = NDI_FAILURE; 2398*fcf3ce44SJohn Forte goto freememory; 2399*fcf3ce44SJohn Forte } 2400*fcf3ce44SJohn Forte 2401*fcf3ce44SJohn Forte fctl_set_npiv_portindex(phydip, portnum); 2402*fcf3ce44SJohn Forte freememory: 2403*fcf3ce44SJohn Forte kmem_free(devstr, devstrlen); 2404*fcf3ce44SJohn Forte kmem_free(devname, MAXNAMELEN); 2405*fcf3ce44SJohn Forte 2406*fcf3ce44SJohn Forte return (rval); 2407*fcf3ce44SJohn Forte } 2408*fcf3ce44SJohn Forte 2409*fcf3ce44SJohn Forte 2410*fcf3ce44SJohn Forte void 2411*fcf3ce44SJohn Forte fctl_add_port(fc_local_port_t *port) 2412*fcf3ce44SJohn Forte { 2413*fcf3ce44SJohn Forte fc_fca_port_t *new; 2414*fcf3ce44SJohn Forte 2415*fcf3ce44SJohn Forte new = kmem_zalloc(sizeof (*new), KM_SLEEP); 2416*fcf3ce44SJohn Forte 2417*fcf3ce44SJohn Forte mutex_enter(&fctl_port_lock); 2418*fcf3ce44SJohn Forte new->port_handle = port; 2419*fcf3ce44SJohn Forte new->port_next = fctl_fca_portlist; 2420*fcf3ce44SJohn Forte fctl_fca_portlist = new; 2421*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 2422*fcf3ce44SJohn Forte } 2423*fcf3ce44SJohn Forte 2424*fcf3ce44SJohn Forte 2425*fcf3ce44SJohn Forte void 2426*fcf3ce44SJohn Forte fctl_remove_port(fc_local_port_t *port) 2427*fcf3ce44SJohn Forte { 2428*fcf3ce44SJohn Forte fc_ulp_module_t *mod; 2429*fcf3ce44SJohn Forte fc_fca_port_t *prev; 2430*fcf3ce44SJohn Forte fc_fca_port_t *list; 2431*fcf3ce44SJohn Forte fc_ulp_ports_t *ulp_port; 2432*fcf3ce44SJohn Forte 2433*fcf3ce44SJohn Forte rw_enter(&fctl_ulp_lock, RW_WRITER); 2434*fcf3ce44SJohn Forte rw_enter(&fctl_mod_ports_lock, RW_WRITER); 2435*fcf3ce44SJohn Forte 2436*fcf3ce44SJohn Forte for (mod = fctl_ulp_modules; mod; mod = mod->mod_next) { 2437*fcf3ce44SJohn Forte ulp_port = fctl_get_ulp_port(mod, port); 2438*fcf3ce44SJohn Forte if (ulp_port == NULL) { 2439*fcf3ce44SJohn Forte continue; 2440*fcf3ce44SJohn Forte } 2441*fcf3ce44SJohn Forte 2442*fcf3ce44SJohn Forte #ifndef __lock_lint 2443*fcf3ce44SJohn Forte ASSERT((ulp_port->port_dstate & ULP_PORT_ATTACH) == 0); 2444*fcf3ce44SJohn Forte #endif /* __lock_lint */ 2445*fcf3ce44SJohn Forte 2446*fcf3ce44SJohn Forte (void) fctl_remove_ulp_port(mod, port); 2447*fcf3ce44SJohn Forte } 2448*fcf3ce44SJohn Forte 2449*fcf3ce44SJohn Forte rw_exit(&fctl_mod_ports_lock); 2450*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 2451*fcf3ce44SJohn Forte 2452*fcf3ce44SJohn Forte mutex_enter(&fctl_port_lock); 2453*fcf3ce44SJohn Forte 2454*fcf3ce44SJohn Forte list = fctl_fca_portlist; 2455*fcf3ce44SJohn Forte prev = NULL; 2456*fcf3ce44SJohn Forte while (list != NULL) { 2457*fcf3ce44SJohn Forte if (list->port_handle == port) { 2458*fcf3ce44SJohn Forte if (prev == NULL) { 2459*fcf3ce44SJohn Forte fctl_fca_portlist = list->port_next; 2460*fcf3ce44SJohn Forte } else { 2461*fcf3ce44SJohn Forte prev->port_next = list->port_next; 2462*fcf3ce44SJohn Forte } 2463*fcf3ce44SJohn Forte kmem_free(list, sizeof (*list)); 2464*fcf3ce44SJohn Forte break; 2465*fcf3ce44SJohn Forte } 2466*fcf3ce44SJohn Forte prev = list; 2467*fcf3ce44SJohn Forte list = list->port_next; 2468*fcf3ce44SJohn Forte } 2469*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 2470*fcf3ce44SJohn Forte } 2471*fcf3ce44SJohn Forte 2472*fcf3ce44SJohn Forte 2473*fcf3ce44SJohn Forte void 2474*fcf3ce44SJohn Forte fctl_attach_ulps(fc_local_port_t *port, fc_attach_cmd_t cmd, 2475*fcf3ce44SJohn Forte struct modlinkage *linkage) 2476*fcf3ce44SJohn Forte { 2477*fcf3ce44SJohn Forte int rval; 2478*fcf3ce44SJohn Forte uint32_t s_id; 2479*fcf3ce44SJohn Forte uint32_t state; 2480*fcf3ce44SJohn Forte fc_ulp_module_t *mod; 2481*fcf3ce44SJohn Forte fc_ulp_port_info_t info; 2482*fcf3ce44SJohn Forte fc_ulp_ports_t *ulp_port; 2483*fcf3ce44SJohn Forte 2484*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 2485*fcf3ce44SJohn Forte 2486*fcf3ce44SJohn Forte info.port_linkage = linkage; 2487*fcf3ce44SJohn Forte info.port_dip = port->fp_port_dip; 2488*fcf3ce44SJohn Forte info.port_handle = (opaque_t)port; 2489*fcf3ce44SJohn Forte info.port_dma_behavior = port->fp_dma_behavior; 2490*fcf3ce44SJohn Forte info.port_fcp_dma = port->fp_fcp_dma; 2491*fcf3ce44SJohn Forte info.port_acc_attr = port->fp_fca_tran->fca_acc_attr; 2492*fcf3ce44SJohn Forte info.port_fca_pkt_size = port->fp_fca_tran->fca_pkt_size; 2493*fcf3ce44SJohn Forte info.port_reset_action = port->fp_reset_action; 2494*fcf3ce44SJohn Forte 2495*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 2496*fcf3ce44SJohn Forte 2497*fcf3ce44SJohn Forte /* 2498*fcf3ce44SJohn Forte * It is still possible that another thread could have gotten 2499*fcf3ce44SJohn Forte * into the detach process before we got here. 2500*fcf3ce44SJohn Forte */ 2501*fcf3ce44SJohn Forte if (port->fp_soft_state & FP_SOFT_IN_DETACH) { 2502*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 2503*fcf3ce44SJohn Forte return; 2504*fcf3ce44SJohn Forte } 2505*fcf3ce44SJohn Forte 2506*fcf3ce44SJohn Forte s_id = port->fp_port_id.port_id; 2507*fcf3ce44SJohn Forte if (port->fp_statec_busy) { 2508*fcf3ce44SJohn Forte info.port_state = port->fp_bind_state; 2509*fcf3ce44SJohn Forte } else { 2510*fcf3ce44SJohn Forte info.port_state = port->fp_state; 2511*fcf3ce44SJohn Forte } 2512*fcf3ce44SJohn Forte 2513*fcf3ce44SJohn Forte switch (state = FC_PORT_STATE_MASK(info.port_state)) { 2514*fcf3ce44SJohn Forte case FC_STATE_LOOP: 2515*fcf3ce44SJohn Forte case FC_STATE_NAMESERVICE: 2516*fcf3ce44SJohn Forte info.port_state &= ~state; 2517*fcf3ce44SJohn Forte info.port_state |= FC_STATE_ONLINE; 2518*fcf3ce44SJohn Forte break; 2519*fcf3ce44SJohn Forte 2520*fcf3ce44SJohn Forte default: 2521*fcf3ce44SJohn Forte break; 2522*fcf3ce44SJohn Forte } 2523*fcf3ce44SJohn Forte ASSERT((info.port_state & FC_STATE_LOOP) == 0); 2524*fcf3ce44SJohn Forte 2525*fcf3ce44SJohn Forte info.port_flags = port->fp_topology; 2526*fcf3ce44SJohn Forte info.port_pwwn = port->fp_service_params.nport_ww_name; 2527*fcf3ce44SJohn Forte info.port_nwwn = port->fp_service_params.node_ww_name; 2528*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 2529*fcf3ce44SJohn Forte 2530*fcf3ce44SJohn Forte rw_enter(&fctl_ulp_lock, RW_READER); 2531*fcf3ce44SJohn Forte rw_enter(&fctl_mod_ports_lock, RW_WRITER); 2532*fcf3ce44SJohn Forte 2533*fcf3ce44SJohn Forte for (mod = fctl_ulp_modules; mod; mod = mod->mod_next) { 2534*fcf3ce44SJohn Forte if ((ulp_port = fctl_get_ulp_port(mod, port)) == NULL) { 2535*fcf3ce44SJohn Forte ulp_port = fctl_add_ulp_port(mod, port, KM_SLEEP); 2536*fcf3ce44SJohn Forte ASSERT(ulp_port != NULL); 2537*fcf3ce44SJohn Forte 2538*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 2539*fcf3ce44SJohn Forte ulp_port->port_statec = (info.port_state & 2540*fcf3ce44SJohn Forte FC_STATE_ONLINE) ? FC_ULP_STATEC_ONLINE : 2541*fcf3ce44SJohn Forte FC_ULP_STATEC_OFFLINE; 2542*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 2543*fcf3ce44SJohn Forte } 2544*fcf3ce44SJohn Forte } 2545*fcf3ce44SJohn Forte 2546*fcf3ce44SJohn Forte rw_downgrade(&fctl_mod_ports_lock); 2547*fcf3ce44SJohn Forte 2548*fcf3ce44SJohn Forte for (mod = fctl_ulp_modules; mod; mod = mod->mod_next) { 2549*fcf3ce44SJohn Forte ulp_port = fctl_get_ulp_port(mod, port); 2550*fcf3ce44SJohn Forte ASSERT(ulp_port != NULL); 2551*fcf3ce44SJohn Forte 2552*fcf3ce44SJohn Forte if (fctl_pre_attach(ulp_port, cmd) == FC_FAILURE) { 2553*fcf3ce44SJohn Forte continue; 2554*fcf3ce44SJohn Forte } 2555*fcf3ce44SJohn Forte 2556*fcf3ce44SJohn Forte fctl_init_dma_attr(port, mod, &info); 2557*fcf3ce44SJohn Forte 2558*fcf3ce44SJohn Forte rval = mod->mod_info->ulp_port_attach( 2559*fcf3ce44SJohn Forte mod->mod_info->ulp_handle, &info, cmd, s_id); 2560*fcf3ce44SJohn Forte 2561*fcf3ce44SJohn Forte fctl_post_attach(mod, ulp_port, cmd, rval); 2562*fcf3ce44SJohn Forte 2563*fcf3ce44SJohn Forte if (rval == FC_SUCCESS && cmd == FC_CMD_ATTACH && 2564*fcf3ce44SJohn Forte strcmp(mod->mod_info->ulp_name, "fcp") == 0) { 2565*fcf3ce44SJohn Forte ASSERT(ddi_get_driver_private(info.port_dip) != NULL); 2566*fcf3ce44SJohn Forte } 2567*fcf3ce44SJohn Forte } 2568*fcf3ce44SJohn Forte 2569*fcf3ce44SJohn Forte rw_exit(&fctl_mod_ports_lock); 2570*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 2571*fcf3ce44SJohn Forte } 2572*fcf3ce44SJohn Forte 2573*fcf3ce44SJohn Forte 2574*fcf3ce44SJohn Forte static int 2575*fcf3ce44SJohn Forte fctl_pre_attach(fc_ulp_ports_t *ulp_port, fc_attach_cmd_t cmd) 2576*fcf3ce44SJohn Forte { 2577*fcf3ce44SJohn Forte int rval = FC_SUCCESS; 2578*fcf3ce44SJohn Forte 2579*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 2580*fcf3ce44SJohn Forte 2581*fcf3ce44SJohn Forte switch (cmd) { 2582*fcf3ce44SJohn Forte case FC_CMD_ATTACH: 2583*fcf3ce44SJohn Forte if (ulp_port->port_dstate & ULP_PORT_ATTACH) { 2584*fcf3ce44SJohn Forte rval = FC_FAILURE; 2585*fcf3ce44SJohn Forte } 2586*fcf3ce44SJohn Forte break; 2587*fcf3ce44SJohn Forte 2588*fcf3ce44SJohn Forte case FC_CMD_RESUME: 2589*fcf3ce44SJohn Forte ASSERT((ulp_port->port_dstate & ULP_PORT_POWER_DOWN) == 0); 2590*fcf3ce44SJohn Forte if (!(ulp_port->port_dstate & ULP_PORT_ATTACH) || 2591*fcf3ce44SJohn Forte !(ulp_port->port_dstate & ULP_PORT_SUSPEND)) { 2592*fcf3ce44SJohn Forte rval = FC_FAILURE; 2593*fcf3ce44SJohn Forte } 2594*fcf3ce44SJohn Forte break; 2595*fcf3ce44SJohn Forte 2596*fcf3ce44SJohn Forte case FC_CMD_POWER_UP: 2597*fcf3ce44SJohn Forte if (!(ulp_port->port_dstate & ULP_PORT_ATTACH) || 2598*fcf3ce44SJohn Forte !(ulp_port->port_dstate & ULP_PORT_POWER_DOWN)) { 2599*fcf3ce44SJohn Forte rval = FC_FAILURE; 2600*fcf3ce44SJohn Forte } 2601*fcf3ce44SJohn Forte break; 2602*fcf3ce44SJohn Forte } 2603*fcf3ce44SJohn Forte 2604*fcf3ce44SJohn Forte if (rval == FC_SUCCESS) { 2605*fcf3ce44SJohn Forte ulp_port->port_dstate |= ULP_PORT_BUSY; 2606*fcf3ce44SJohn Forte } 2607*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 2608*fcf3ce44SJohn Forte 2609*fcf3ce44SJohn Forte return (rval); 2610*fcf3ce44SJohn Forte } 2611*fcf3ce44SJohn Forte 2612*fcf3ce44SJohn Forte 2613*fcf3ce44SJohn Forte static void 2614*fcf3ce44SJohn Forte fctl_post_attach(fc_ulp_module_t *mod, fc_ulp_ports_t *ulp_port, 2615*fcf3ce44SJohn Forte fc_attach_cmd_t cmd, int rval) 2616*fcf3ce44SJohn Forte { 2617*fcf3ce44SJohn Forte int be_chatty; 2618*fcf3ce44SJohn Forte 2619*fcf3ce44SJohn Forte ASSERT(cmd == FC_CMD_ATTACH || cmd == FC_CMD_RESUME || 2620*fcf3ce44SJohn Forte cmd == FC_CMD_POWER_UP); 2621*fcf3ce44SJohn Forte 2622*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 2623*fcf3ce44SJohn Forte ulp_port->port_dstate &= ~ULP_PORT_BUSY; 2624*fcf3ce44SJohn Forte 2625*fcf3ce44SJohn Forte be_chatty = (rval == FC_FAILURE_SILENT) ? 0 : 1; 2626*fcf3ce44SJohn Forte 2627*fcf3ce44SJohn Forte if (rval != FC_SUCCESS) { 2628*fcf3ce44SJohn Forte caddr_t op; 2629*fcf3ce44SJohn Forte fc_local_port_t *port = ulp_port->port_handle; 2630*fcf3ce44SJohn Forte 2631*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 2632*fcf3ce44SJohn Forte 2633*fcf3ce44SJohn Forte switch (cmd) { 2634*fcf3ce44SJohn Forte case FC_CMD_ATTACH: 2635*fcf3ce44SJohn Forte op = "attach"; 2636*fcf3ce44SJohn Forte break; 2637*fcf3ce44SJohn Forte 2638*fcf3ce44SJohn Forte case FC_CMD_RESUME: 2639*fcf3ce44SJohn Forte op = "resume"; 2640*fcf3ce44SJohn Forte break; 2641*fcf3ce44SJohn Forte 2642*fcf3ce44SJohn Forte case FC_CMD_POWER_UP: 2643*fcf3ce44SJohn Forte op = "power up"; 2644*fcf3ce44SJohn Forte break; 2645*fcf3ce44SJohn Forte } 2646*fcf3ce44SJohn Forte 2647*fcf3ce44SJohn Forte if (be_chatty) { 2648*fcf3ce44SJohn Forte cmn_err(CE_WARN, "!fctl(%d): %s failed for %s", 2649*fcf3ce44SJohn Forte port->fp_instance, op, mod->mod_info->ulp_name); 2650*fcf3ce44SJohn Forte } 2651*fcf3ce44SJohn Forte 2652*fcf3ce44SJohn Forte return; 2653*fcf3ce44SJohn Forte } 2654*fcf3ce44SJohn Forte 2655*fcf3ce44SJohn Forte switch (cmd) { 2656*fcf3ce44SJohn Forte case FC_CMD_ATTACH: 2657*fcf3ce44SJohn Forte ulp_port->port_dstate |= ULP_PORT_ATTACH; 2658*fcf3ce44SJohn Forte break; 2659*fcf3ce44SJohn Forte 2660*fcf3ce44SJohn Forte case FC_CMD_RESUME: 2661*fcf3ce44SJohn Forte ulp_port->port_dstate &= ~ULP_PORT_SUSPEND; 2662*fcf3ce44SJohn Forte break; 2663*fcf3ce44SJohn Forte 2664*fcf3ce44SJohn Forte case FC_CMD_POWER_UP: 2665*fcf3ce44SJohn Forte ulp_port->port_dstate &= ~ULP_PORT_POWER_DOWN; 2666*fcf3ce44SJohn Forte break; 2667*fcf3ce44SJohn Forte } 2668*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 2669*fcf3ce44SJohn Forte } 2670*fcf3ce44SJohn Forte 2671*fcf3ce44SJohn Forte 2672*fcf3ce44SJohn Forte int 2673*fcf3ce44SJohn Forte fctl_detach_ulps(fc_local_port_t *port, fc_detach_cmd_t cmd, 2674*fcf3ce44SJohn Forte struct modlinkage *linkage) 2675*fcf3ce44SJohn Forte { 2676*fcf3ce44SJohn Forte int rval = FC_SUCCESS; 2677*fcf3ce44SJohn Forte fc_ulp_module_t *mod; 2678*fcf3ce44SJohn Forte fc_ulp_port_info_t info; 2679*fcf3ce44SJohn Forte fc_ulp_ports_t *ulp_port; 2680*fcf3ce44SJohn Forte 2681*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 2682*fcf3ce44SJohn Forte 2683*fcf3ce44SJohn Forte info.port_linkage = linkage; 2684*fcf3ce44SJohn Forte info.port_dip = port->fp_port_dip; 2685*fcf3ce44SJohn Forte info.port_handle = (opaque_t)port; 2686*fcf3ce44SJohn Forte info.port_acc_attr = port->fp_fca_tran->fca_acc_attr; 2687*fcf3ce44SJohn Forte info.port_fca_pkt_size = port->fp_fca_tran->fca_pkt_size; 2688*fcf3ce44SJohn Forte 2689*fcf3ce44SJohn Forte rw_enter(&fctl_ulp_lock, RW_READER); 2690*fcf3ce44SJohn Forte rw_enter(&fctl_mod_ports_lock, RW_READER); 2691*fcf3ce44SJohn Forte 2692*fcf3ce44SJohn Forte for (mod = fctl_ulp_modules; mod; mod = mod->mod_next) { 2693*fcf3ce44SJohn Forte if ((ulp_port = fctl_get_ulp_port(mod, port)) == NULL) { 2694*fcf3ce44SJohn Forte continue; 2695*fcf3ce44SJohn Forte } 2696*fcf3ce44SJohn Forte 2697*fcf3ce44SJohn Forte if (fctl_pre_detach(ulp_port, cmd) != FC_SUCCESS) { 2698*fcf3ce44SJohn Forte continue; 2699*fcf3ce44SJohn Forte } 2700*fcf3ce44SJohn Forte 2701*fcf3ce44SJohn Forte fctl_init_dma_attr(port, mod, &info); 2702*fcf3ce44SJohn Forte 2703*fcf3ce44SJohn Forte rval = mod->mod_info->ulp_port_detach( 2704*fcf3ce44SJohn Forte mod->mod_info->ulp_handle, &info, cmd); 2705*fcf3ce44SJohn Forte 2706*fcf3ce44SJohn Forte fctl_post_detach(mod, ulp_port, cmd, rval); 2707*fcf3ce44SJohn Forte 2708*fcf3ce44SJohn Forte if (rval != FC_SUCCESS) { 2709*fcf3ce44SJohn Forte break; 2710*fcf3ce44SJohn Forte } 2711*fcf3ce44SJohn Forte 2712*fcf3ce44SJohn Forte if (cmd == FC_CMD_DETACH && strcmp(mod->mod_info->ulp_name, 2713*fcf3ce44SJohn Forte "fcp") == 0) { 2714*fcf3ce44SJohn Forte ASSERT(ddi_get_driver_private(info.port_dip) == NULL); 2715*fcf3ce44SJohn Forte } 2716*fcf3ce44SJohn Forte 2717*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 2718*fcf3ce44SJohn Forte ulp_port->port_statec = FC_ULP_STATEC_DONT_CARE; 2719*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 2720*fcf3ce44SJohn Forte } 2721*fcf3ce44SJohn Forte 2722*fcf3ce44SJohn Forte rw_exit(&fctl_mod_ports_lock); 2723*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 2724*fcf3ce44SJohn Forte 2725*fcf3ce44SJohn Forte return (rval); 2726*fcf3ce44SJohn Forte } 2727*fcf3ce44SJohn Forte 2728*fcf3ce44SJohn Forte static void 2729*fcf3ce44SJohn Forte fctl_init_dma_attr(fc_local_port_t *port, fc_ulp_module_t *mod, 2730*fcf3ce44SJohn Forte fc_ulp_port_info_t *info) 2731*fcf3ce44SJohn Forte { 2732*fcf3ce44SJohn Forte 2733*fcf3ce44SJohn Forte if ((strcmp(mod->mod_info->ulp_name, "fcp") == 0) || 2734*fcf3ce44SJohn Forte (strcmp(mod->mod_info->ulp_name, "ltct") == 0)) { 2735*fcf3ce44SJohn Forte info->port_cmd_dma_attr = 2736*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_fcp_cmd_attr; 2737*fcf3ce44SJohn Forte info->port_data_dma_attr = 2738*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_fcp_data_attr; 2739*fcf3ce44SJohn Forte info->port_resp_dma_attr = 2740*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_fcp_rsp_attr; 2741*fcf3ce44SJohn Forte } else if (strcmp(mod->mod_info->ulp_name, "fcsm") == 0) { 2742*fcf3ce44SJohn Forte info->port_cmd_dma_attr = 2743*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_fcsm_cmd_attr; 2744*fcf3ce44SJohn Forte info->port_data_dma_attr = 2745*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_attr; 2746*fcf3ce44SJohn Forte info->port_resp_dma_attr = 2747*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_fcsm_rsp_attr; 2748*fcf3ce44SJohn Forte } else if (strcmp(mod->mod_info->ulp_name, "fcip") == 0) { 2749*fcf3ce44SJohn Forte info->port_cmd_dma_attr = 2750*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_fcip_cmd_attr; 2751*fcf3ce44SJohn Forte info->port_data_dma_attr = 2752*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_attr; 2753*fcf3ce44SJohn Forte info->port_resp_dma_attr = 2754*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_fcip_rsp_attr; 2755*fcf3ce44SJohn Forte } else { 2756*fcf3ce44SJohn Forte info->port_cmd_dma_attr = info->port_data_dma_attr = 2757*fcf3ce44SJohn Forte info->port_resp_dma_attr = 2758*fcf3ce44SJohn Forte port->fp_fca_tran->fca_dma_attr; /* default */ 2759*fcf3ce44SJohn Forte } 2760*fcf3ce44SJohn Forte } 2761*fcf3ce44SJohn Forte 2762*fcf3ce44SJohn Forte static int 2763*fcf3ce44SJohn Forte fctl_pre_detach(fc_ulp_ports_t *ulp_port, fc_detach_cmd_t cmd) 2764*fcf3ce44SJohn Forte { 2765*fcf3ce44SJohn Forte int rval = FC_SUCCESS; 2766*fcf3ce44SJohn Forte 2767*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 2768*fcf3ce44SJohn Forte 2769*fcf3ce44SJohn Forte switch (cmd) { 2770*fcf3ce44SJohn Forte case FC_CMD_DETACH: 2771*fcf3ce44SJohn Forte if ((ulp_port->port_dstate & ULP_PORT_ATTACH) == 0) { 2772*fcf3ce44SJohn Forte rval = FC_FAILURE; 2773*fcf3ce44SJohn Forte } 2774*fcf3ce44SJohn Forte break; 2775*fcf3ce44SJohn Forte 2776*fcf3ce44SJohn Forte case FC_CMD_SUSPEND: 2777*fcf3ce44SJohn Forte if (!(ulp_port->port_dstate & ULP_PORT_ATTACH) || 2778*fcf3ce44SJohn Forte ulp_port->port_dstate & ULP_PORT_SUSPEND) { 2779*fcf3ce44SJohn Forte rval = FC_FAILURE; 2780*fcf3ce44SJohn Forte } 2781*fcf3ce44SJohn Forte break; 2782*fcf3ce44SJohn Forte 2783*fcf3ce44SJohn Forte case FC_CMD_POWER_DOWN: 2784*fcf3ce44SJohn Forte if (!(ulp_port->port_dstate & ULP_PORT_ATTACH) || 2785*fcf3ce44SJohn Forte ulp_port->port_dstate & ULP_PORT_POWER_DOWN) { 2786*fcf3ce44SJohn Forte rval = FC_FAILURE; 2787*fcf3ce44SJohn Forte } 2788*fcf3ce44SJohn Forte break; 2789*fcf3ce44SJohn Forte } 2790*fcf3ce44SJohn Forte 2791*fcf3ce44SJohn Forte if (rval == FC_SUCCESS) { 2792*fcf3ce44SJohn Forte ulp_port->port_dstate |= ULP_PORT_BUSY; 2793*fcf3ce44SJohn Forte } 2794*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 2795*fcf3ce44SJohn Forte 2796*fcf3ce44SJohn Forte return (rval); 2797*fcf3ce44SJohn Forte } 2798*fcf3ce44SJohn Forte 2799*fcf3ce44SJohn Forte 2800*fcf3ce44SJohn Forte static void 2801*fcf3ce44SJohn Forte fctl_post_detach(fc_ulp_module_t *mod, fc_ulp_ports_t *ulp_port, 2802*fcf3ce44SJohn Forte fc_detach_cmd_t cmd, int rval) 2803*fcf3ce44SJohn Forte { 2804*fcf3ce44SJohn Forte ASSERT(cmd == FC_CMD_DETACH || cmd == FC_CMD_SUSPEND || 2805*fcf3ce44SJohn Forte cmd == FC_CMD_POWER_DOWN); 2806*fcf3ce44SJohn Forte 2807*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 2808*fcf3ce44SJohn Forte ulp_port->port_dstate &= ~ULP_PORT_BUSY; 2809*fcf3ce44SJohn Forte 2810*fcf3ce44SJohn Forte if (rval != FC_SUCCESS) { 2811*fcf3ce44SJohn Forte caddr_t op; 2812*fcf3ce44SJohn Forte fc_local_port_t *port = ulp_port->port_handle; 2813*fcf3ce44SJohn Forte 2814*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 2815*fcf3ce44SJohn Forte 2816*fcf3ce44SJohn Forte switch (cmd) { 2817*fcf3ce44SJohn Forte case FC_CMD_DETACH: 2818*fcf3ce44SJohn Forte op = "detach"; 2819*fcf3ce44SJohn Forte break; 2820*fcf3ce44SJohn Forte 2821*fcf3ce44SJohn Forte case FC_CMD_SUSPEND: 2822*fcf3ce44SJohn Forte op = "suspend"; 2823*fcf3ce44SJohn Forte break; 2824*fcf3ce44SJohn Forte 2825*fcf3ce44SJohn Forte case FC_CMD_POWER_DOWN: 2826*fcf3ce44SJohn Forte op = "power down"; 2827*fcf3ce44SJohn Forte break; 2828*fcf3ce44SJohn Forte } 2829*fcf3ce44SJohn Forte 2830*fcf3ce44SJohn Forte cmn_err(CE_WARN, "!fctl(%d): %s failed for %s", 2831*fcf3ce44SJohn Forte port->fp_instance, op, mod->mod_info->ulp_name); 2832*fcf3ce44SJohn Forte 2833*fcf3ce44SJohn Forte return; 2834*fcf3ce44SJohn Forte } 2835*fcf3ce44SJohn Forte 2836*fcf3ce44SJohn Forte switch (cmd) { 2837*fcf3ce44SJohn Forte case FC_CMD_DETACH: 2838*fcf3ce44SJohn Forte ulp_port->port_dstate &= ~ULP_PORT_ATTACH; 2839*fcf3ce44SJohn Forte break; 2840*fcf3ce44SJohn Forte 2841*fcf3ce44SJohn Forte case FC_CMD_SUSPEND: 2842*fcf3ce44SJohn Forte ulp_port->port_dstate |= ULP_PORT_SUSPEND; 2843*fcf3ce44SJohn Forte break; 2844*fcf3ce44SJohn Forte 2845*fcf3ce44SJohn Forte case FC_CMD_POWER_DOWN: 2846*fcf3ce44SJohn Forte ulp_port->port_dstate |= ULP_PORT_POWER_DOWN; 2847*fcf3ce44SJohn Forte break; 2848*fcf3ce44SJohn Forte } 2849*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 2850*fcf3ce44SJohn Forte } 2851*fcf3ce44SJohn Forte 2852*fcf3ce44SJohn Forte 2853*fcf3ce44SJohn Forte static fc_ulp_ports_t * 2854*fcf3ce44SJohn Forte fctl_add_ulp_port(fc_ulp_module_t *ulp_module, fc_local_port_t *port_handle, 2855*fcf3ce44SJohn Forte int sleep) 2856*fcf3ce44SJohn Forte { 2857*fcf3ce44SJohn Forte fc_ulp_ports_t *last; 2858*fcf3ce44SJohn Forte fc_ulp_ports_t *next; 2859*fcf3ce44SJohn Forte fc_ulp_ports_t *new; 2860*fcf3ce44SJohn Forte 2861*fcf3ce44SJohn Forte ASSERT(RW_READ_HELD(&fctl_ulp_lock)); 2862*fcf3ce44SJohn Forte ASSERT(RW_WRITE_HELD(&fctl_mod_ports_lock)); 2863*fcf3ce44SJohn Forte 2864*fcf3ce44SJohn Forte last = NULL; 2865*fcf3ce44SJohn Forte next = ulp_module->mod_ports; 2866*fcf3ce44SJohn Forte 2867*fcf3ce44SJohn Forte while (next != NULL) { 2868*fcf3ce44SJohn Forte last = next; 2869*fcf3ce44SJohn Forte next = next->port_next; 2870*fcf3ce44SJohn Forte } 2871*fcf3ce44SJohn Forte 2872*fcf3ce44SJohn Forte new = fctl_alloc_ulp_port(sleep); 2873*fcf3ce44SJohn Forte if (new == NULL) { 2874*fcf3ce44SJohn Forte return (new); 2875*fcf3ce44SJohn Forte } 2876*fcf3ce44SJohn Forte 2877*fcf3ce44SJohn Forte new->port_handle = port_handle; 2878*fcf3ce44SJohn Forte if (last == NULL) { 2879*fcf3ce44SJohn Forte ulp_module->mod_ports = new; 2880*fcf3ce44SJohn Forte } else { 2881*fcf3ce44SJohn Forte last->port_next = new; 2882*fcf3ce44SJohn Forte } 2883*fcf3ce44SJohn Forte 2884*fcf3ce44SJohn Forte return (new); 2885*fcf3ce44SJohn Forte } 2886*fcf3ce44SJohn Forte 2887*fcf3ce44SJohn Forte 2888*fcf3ce44SJohn Forte static fc_ulp_ports_t * 2889*fcf3ce44SJohn Forte fctl_alloc_ulp_port(int sleep) 2890*fcf3ce44SJohn Forte { 2891*fcf3ce44SJohn Forte fc_ulp_ports_t *new; 2892*fcf3ce44SJohn Forte 2893*fcf3ce44SJohn Forte new = kmem_zalloc(sizeof (*new), sleep); 2894*fcf3ce44SJohn Forte if (new == NULL) { 2895*fcf3ce44SJohn Forte return (new); 2896*fcf3ce44SJohn Forte } 2897*fcf3ce44SJohn Forte mutex_init(&new->port_mutex, NULL, MUTEX_DRIVER, NULL); 2898*fcf3ce44SJohn Forte 2899*fcf3ce44SJohn Forte return (new); 2900*fcf3ce44SJohn Forte } 2901*fcf3ce44SJohn Forte 2902*fcf3ce44SJohn Forte 2903*fcf3ce44SJohn Forte static int 2904*fcf3ce44SJohn Forte fctl_remove_ulp_port(struct ulp_module *ulp_module, 2905*fcf3ce44SJohn Forte fc_local_port_t *port_handle) 2906*fcf3ce44SJohn Forte { 2907*fcf3ce44SJohn Forte fc_ulp_ports_t *last; 2908*fcf3ce44SJohn Forte fc_ulp_ports_t *next; 2909*fcf3ce44SJohn Forte 2910*fcf3ce44SJohn Forte ASSERT(RW_WRITE_HELD(&fctl_ulp_lock)); 2911*fcf3ce44SJohn Forte ASSERT(RW_WRITE_HELD(&fctl_mod_ports_lock)); 2912*fcf3ce44SJohn Forte 2913*fcf3ce44SJohn Forte last = NULL; 2914*fcf3ce44SJohn Forte next = ulp_module->mod_ports; 2915*fcf3ce44SJohn Forte 2916*fcf3ce44SJohn Forte while (next != NULL) { 2917*fcf3ce44SJohn Forte if (next->port_handle == port_handle) { 2918*fcf3ce44SJohn Forte if (next->port_dstate & ULP_PORT_ATTACH) { 2919*fcf3ce44SJohn Forte return (FC_FAILURE); 2920*fcf3ce44SJohn Forte } 2921*fcf3ce44SJohn Forte break; 2922*fcf3ce44SJohn Forte } 2923*fcf3ce44SJohn Forte last = next; 2924*fcf3ce44SJohn Forte next = next->port_next; 2925*fcf3ce44SJohn Forte } 2926*fcf3ce44SJohn Forte 2927*fcf3ce44SJohn Forte if (next != NULL) { 2928*fcf3ce44SJohn Forte ASSERT((next->port_dstate & ULP_PORT_ATTACH) == 0); 2929*fcf3ce44SJohn Forte 2930*fcf3ce44SJohn Forte if (last == NULL) { 2931*fcf3ce44SJohn Forte ulp_module->mod_ports = next->port_next; 2932*fcf3ce44SJohn Forte } else { 2933*fcf3ce44SJohn Forte last->port_next = next->port_next; 2934*fcf3ce44SJohn Forte } 2935*fcf3ce44SJohn Forte fctl_dealloc_ulp_port(next); 2936*fcf3ce44SJohn Forte 2937*fcf3ce44SJohn Forte return (FC_SUCCESS); 2938*fcf3ce44SJohn Forte } else { 2939*fcf3ce44SJohn Forte return (FC_FAILURE); 2940*fcf3ce44SJohn Forte } 2941*fcf3ce44SJohn Forte } 2942*fcf3ce44SJohn Forte 2943*fcf3ce44SJohn Forte 2944*fcf3ce44SJohn Forte static void 2945*fcf3ce44SJohn Forte fctl_dealloc_ulp_port(fc_ulp_ports_t *next) 2946*fcf3ce44SJohn Forte { 2947*fcf3ce44SJohn Forte mutex_destroy(&next->port_mutex); 2948*fcf3ce44SJohn Forte kmem_free(next, sizeof (*next)); 2949*fcf3ce44SJohn Forte } 2950*fcf3ce44SJohn Forte 2951*fcf3ce44SJohn Forte 2952*fcf3ce44SJohn Forte static fc_ulp_ports_t * 2953*fcf3ce44SJohn Forte fctl_get_ulp_port(struct ulp_module *ulp_module, fc_local_port_t *port_handle) 2954*fcf3ce44SJohn Forte { 2955*fcf3ce44SJohn Forte fc_ulp_ports_t *next; 2956*fcf3ce44SJohn Forte 2957*fcf3ce44SJohn Forte ASSERT(RW_LOCK_HELD(&fctl_ulp_lock)); 2958*fcf3ce44SJohn Forte ASSERT(RW_LOCK_HELD(&fctl_mod_ports_lock)); 2959*fcf3ce44SJohn Forte 2960*fcf3ce44SJohn Forte for (next = ulp_module->mod_ports; next != NULL; 2961*fcf3ce44SJohn Forte next = next->port_next) { 2962*fcf3ce44SJohn Forte if (next->port_handle == port_handle) { 2963*fcf3ce44SJohn Forte return (next); 2964*fcf3ce44SJohn Forte } 2965*fcf3ce44SJohn Forte } 2966*fcf3ce44SJohn Forte 2967*fcf3ce44SJohn Forte return (NULL); 2968*fcf3ce44SJohn Forte } 2969*fcf3ce44SJohn Forte 2970*fcf3ce44SJohn Forte 2971*fcf3ce44SJohn Forte /* 2972*fcf3ce44SJohn Forte * Pass state change notfications on to registered ULPs. 2973*fcf3ce44SJohn Forte * 2974*fcf3ce44SJohn Forte * Can issue wakeups to client callers who might be waiting for completions 2975*fcf3ce44SJohn Forte * on other threads. 2976*fcf3ce44SJohn Forte * 2977*fcf3ce44SJohn Forte * Caution: will silently deallocate any fc_remote_port_t and/or 2978*fcf3ce44SJohn Forte * fc_remote_node_t structs it finds that are not in use. 2979*fcf3ce44SJohn Forte */ 2980*fcf3ce44SJohn Forte void 2981*fcf3ce44SJohn Forte fctl_ulp_statec_cb(void *arg) 2982*fcf3ce44SJohn Forte { 2983*fcf3ce44SJohn Forte uint32_t s_id; 2984*fcf3ce44SJohn Forte uint32_t new_state; 2985*fcf3ce44SJohn Forte fc_local_port_t *port; 2986*fcf3ce44SJohn Forte fc_ulp_ports_t *ulp_port; 2987*fcf3ce44SJohn Forte fc_ulp_module_t *mod; 2988*fcf3ce44SJohn Forte fc_port_clist_t *clist = (fc_port_clist_t *)arg; 2989*fcf3ce44SJohn Forte 2990*fcf3ce44SJohn Forte ASSERT(clist != NULL); 2991*fcf3ce44SJohn Forte 2992*fcf3ce44SJohn Forte port = clist->clist_port; 2993*fcf3ce44SJohn Forte 2994*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 2995*fcf3ce44SJohn Forte s_id = port->fp_port_id.port_id; 2996*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 2997*fcf3ce44SJohn Forte 2998*fcf3ce44SJohn Forte switch (clist->clist_state) { 2999*fcf3ce44SJohn Forte case FC_STATE_ONLINE: 3000*fcf3ce44SJohn Forte new_state = FC_ULP_STATEC_ONLINE; 3001*fcf3ce44SJohn Forte break; 3002*fcf3ce44SJohn Forte 3003*fcf3ce44SJohn Forte case FC_STATE_OFFLINE: 3004*fcf3ce44SJohn Forte if (clist->clist_len) { 3005*fcf3ce44SJohn Forte new_state = FC_ULP_STATEC_OFFLINE_TIMEOUT; 3006*fcf3ce44SJohn Forte } else { 3007*fcf3ce44SJohn Forte new_state = FC_ULP_STATEC_OFFLINE; 3008*fcf3ce44SJohn Forte } 3009*fcf3ce44SJohn Forte break; 3010*fcf3ce44SJohn Forte 3011*fcf3ce44SJohn Forte default: 3012*fcf3ce44SJohn Forte new_state = FC_ULP_STATEC_DONT_CARE; 3013*fcf3ce44SJohn Forte break; 3014*fcf3ce44SJohn Forte } 3015*fcf3ce44SJohn Forte 3016*fcf3ce44SJohn Forte #ifdef DEBUG 3017*fcf3ce44SJohn Forte /* 3018*fcf3ce44SJohn Forte * sanity check for presence of OLD devices in the hash lists 3019*fcf3ce44SJohn Forte */ 3020*fcf3ce44SJohn Forte if (clist->clist_size) { 3021*fcf3ce44SJohn Forte int count; 3022*fcf3ce44SJohn Forte fc_remote_port_t *pd; 3023*fcf3ce44SJohn Forte 3024*fcf3ce44SJohn Forte ASSERT(clist->clist_map != NULL); 3025*fcf3ce44SJohn Forte for (count = 0; count < clist->clist_len; count++) { 3026*fcf3ce44SJohn Forte if (clist->clist_map[count].map_state == 3027*fcf3ce44SJohn Forte PORT_DEVICE_INVALID) { 3028*fcf3ce44SJohn Forte la_wwn_t pwwn; 3029*fcf3ce44SJohn Forte fc_portid_t d_id; 3030*fcf3ce44SJohn Forte 3031*fcf3ce44SJohn Forte pd = clist->clist_map[count].map_pd; 3032*fcf3ce44SJohn Forte if (pd != NULL) { 3033*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3034*fcf3ce44SJohn Forte pwwn = pd->pd_port_name; 3035*fcf3ce44SJohn Forte d_id = pd->pd_port_id; 3036*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3037*fcf3ce44SJohn Forte 3038*fcf3ce44SJohn Forte pd = fctl_get_remote_port_by_pwwn(port, 3039*fcf3ce44SJohn Forte &pwwn); 3040*fcf3ce44SJohn Forte 3041*fcf3ce44SJohn Forte ASSERT(pd != clist->clist_map[count]. 3042*fcf3ce44SJohn Forte map_pd); 3043*fcf3ce44SJohn Forte 3044*fcf3ce44SJohn Forte pd = fctl_get_remote_port_by_did(port, 3045*fcf3ce44SJohn Forte d_id.port_id); 3046*fcf3ce44SJohn Forte ASSERT(pd != clist->clist_map[count]. 3047*fcf3ce44SJohn Forte map_pd); 3048*fcf3ce44SJohn Forte } 3049*fcf3ce44SJohn Forte } 3050*fcf3ce44SJohn Forte } 3051*fcf3ce44SJohn Forte } 3052*fcf3ce44SJohn Forte #endif 3053*fcf3ce44SJohn Forte 3054*fcf3ce44SJohn Forte /* 3055*fcf3ce44SJohn Forte * Check for duplicate map entries 3056*fcf3ce44SJohn Forte */ 3057*fcf3ce44SJohn Forte if (clist->clist_size) { 3058*fcf3ce44SJohn Forte int count; 3059*fcf3ce44SJohn Forte fc_remote_port_t *pd1, *pd2; 3060*fcf3ce44SJohn Forte 3061*fcf3ce44SJohn Forte ASSERT(clist->clist_map != NULL); 3062*fcf3ce44SJohn Forte for (count = 0; count < clist->clist_len-1; count++) { 3063*fcf3ce44SJohn Forte int count2; 3064*fcf3ce44SJohn Forte 3065*fcf3ce44SJohn Forte pd1 = clist->clist_map[count].map_pd; 3066*fcf3ce44SJohn Forte if (pd1 == NULL) { 3067*fcf3ce44SJohn Forte continue; 3068*fcf3ce44SJohn Forte } 3069*fcf3ce44SJohn Forte 3070*fcf3ce44SJohn Forte for (count2 = count+1; 3071*fcf3ce44SJohn Forte count2 < clist->clist_len; 3072*fcf3ce44SJohn Forte count2++) { 3073*fcf3ce44SJohn Forte 3074*fcf3ce44SJohn Forte pd2 = clist->clist_map[count2].map_pd; 3075*fcf3ce44SJohn Forte if (pd2 == NULL) { 3076*fcf3ce44SJohn Forte continue; 3077*fcf3ce44SJohn Forte } 3078*fcf3ce44SJohn Forte 3079*fcf3ce44SJohn Forte if (pd1 == pd2) { 3080*fcf3ce44SJohn Forte clist->clist_map[count].map_flags |= 3081*fcf3ce44SJohn Forte PORT_DEVICE_DUPLICATE_MAP_ENTRY; 3082*fcf3ce44SJohn Forte break; 3083*fcf3ce44SJohn Forte } 3084*fcf3ce44SJohn Forte } 3085*fcf3ce44SJohn Forte } 3086*fcf3ce44SJohn Forte } 3087*fcf3ce44SJohn Forte 3088*fcf3ce44SJohn Forte 3089*fcf3ce44SJohn Forte rw_enter(&fctl_ulp_lock, RW_READER); 3090*fcf3ce44SJohn Forte for (mod = fctl_ulp_modules; mod; mod = mod->mod_next) { 3091*fcf3ce44SJohn Forte rw_enter(&fctl_mod_ports_lock, RW_READER); 3092*fcf3ce44SJohn Forte ulp_port = fctl_get_ulp_port(mod, port); 3093*fcf3ce44SJohn Forte rw_exit(&fctl_mod_ports_lock); 3094*fcf3ce44SJohn Forte 3095*fcf3ce44SJohn Forte if (ulp_port == NULL) { 3096*fcf3ce44SJohn Forte continue; 3097*fcf3ce44SJohn Forte } 3098*fcf3ce44SJohn Forte 3099*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 3100*fcf3ce44SJohn Forte if (FCTL_DISALLOW_CALLBACKS(ulp_port->port_dstate)) { 3101*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 3102*fcf3ce44SJohn Forte continue; 3103*fcf3ce44SJohn Forte } 3104*fcf3ce44SJohn Forte 3105*fcf3ce44SJohn Forte switch (ulp_port->port_statec) { 3106*fcf3ce44SJohn Forte case FC_ULP_STATEC_DONT_CARE: 3107*fcf3ce44SJohn Forte if (ulp_port->port_statec != new_state) { 3108*fcf3ce44SJohn Forte ulp_port->port_statec = new_state; 3109*fcf3ce44SJohn Forte } 3110*fcf3ce44SJohn Forte break; 3111*fcf3ce44SJohn Forte 3112*fcf3ce44SJohn Forte case FC_ULP_STATEC_ONLINE: 3113*fcf3ce44SJohn Forte case FC_ULP_STATEC_OFFLINE: 3114*fcf3ce44SJohn Forte if (ulp_port->port_statec == new_state) { 3115*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 3116*fcf3ce44SJohn Forte continue; 3117*fcf3ce44SJohn Forte } 3118*fcf3ce44SJohn Forte ulp_port->port_statec = new_state; 3119*fcf3ce44SJohn Forte break; 3120*fcf3ce44SJohn Forte 3121*fcf3ce44SJohn Forte case FC_ULP_STATEC_OFFLINE_TIMEOUT: 3122*fcf3ce44SJohn Forte if (ulp_port->port_statec == new_state || 3123*fcf3ce44SJohn Forte new_state == FC_ULP_STATEC_OFFLINE) { 3124*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 3125*fcf3ce44SJohn Forte continue; 3126*fcf3ce44SJohn Forte } 3127*fcf3ce44SJohn Forte ulp_port->port_statec = new_state; 3128*fcf3ce44SJohn Forte break; 3129*fcf3ce44SJohn Forte 3130*fcf3ce44SJohn Forte default: 3131*fcf3ce44SJohn Forte ASSERT(0); 3132*fcf3ce44SJohn Forte break; 3133*fcf3ce44SJohn Forte } 3134*fcf3ce44SJohn Forte 3135*fcf3ce44SJohn Forte mod->mod_info->ulp_statec_callback( 3136*fcf3ce44SJohn Forte mod->mod_info->ulp_handle, (opaque_t)port, 3137*fcf3ce44SJohn Forte clist->clist_state, clist->clist_flags, 3138*fcf3ce44SJohn Forte clist->clist_map, clist->clist_len, s_id); 3139*fcf3ce44SJohn Forte 3140*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 3141*fcf3ce44SJohn Forte } 3142*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 3143*fcf3ce44SJohn Forte 3144*fcf3ce44SJohn Forte if (clist->clist_size) { 3145*fcf3ce44SJohn Forte int count; 3146*fcf3ce44SJohn Forte fc_remote_node_t *node; 3147*fcf3ce44SJohn Forte fc_remote_port_t *pd; 3148*fcf3ce44SJohn Forte 3149*fcf3ce44SJohn Forte ASSERT(clist->clist_map != NULL); 3150*fcf3ce44SJohn Forte for (count = 0; count < clist->clist_len; count++) { 3151*fcf3ce44SJohn Forte 3152*fcf3ce44SJohn Forte if ((pd = clist->clist_map[count].map_pd) == NULL) { 3153*fcf3ce44SJohn Forte continue; 3154*fcf3ce44SJohn Forte } 3155*fcf3ce44SJohn Forte 3156*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3157*fcf3ce44SJohn Forte 3158*fcf3ce44SJohn Forte pd->pd_ref_count--; 3159*fcf3ce44SJohn Forte ASSERT(pd->pd_ref_count >= 0); 3160*fcf3ce44SJohn Forte 3161*fcf3ce44SJohn Forte if (clist->clist_map[count].map_state != 3162*fcf3ce44SJohn Forte PORT_DEVICE_INVALID) { 3163*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3164*fcf3ce44SJohn Forte continue; 3165*fcf3ce44SJohn Forte } 3166*fcf3ce44SJohn Forte 3167*fcf3ce44SJohn Forte node = pd->pd_remote_nodep; 3168*fcf3ce44SJohn Forte pd->pd_aux_flags &= ~PD_GIVEN_TO_ULPS; 3169*fcf3ce44SJohn Forte 3170*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3171*fcf3ce44SJohn Forte 3172*fcf3ce44SJohn Forte /* 3173*fcf3ce44SJohn Forte * This fc_remote_port_t is no longer referenced 3174*fcf3ce44SJohn Forte * by any ULPs. Deallocate it if its pd_ref_count 3175*fcf3ce44SJohn Forte * has reached zero. 3176*fcf3ce44SJohn Forte */ 3177*fcf3ce44SJohn Forte if ((fctl_destroy_remote_port(port, pd) == 0) && 3178*fcf3ce44SJohn Forte (node != NULL)) { 3179*fcf3ce44SJohn Forte fctl_destroy_remote_node(node); 3180*fcf3ce44SJohn Forte } 3181*fcf3ce44SJohn Forte } 3182*fcf3ce44SJohn Forte 3183*fcf3ce44SJohn Forte kmem_free(clist->clist_map, 3184*fcf3ce44SJohn Forte sizeof (*(clist->clist_map)) * clist->clist_size); 3185*fcf3ce44SJohn Forte } 3186*fcf3ce44SJohn Forte 3187*fcf3ce44SJohn Forte if (clist->clist_wait) { 3188*fcf3ce44SJohn Forte mutex_enter(&clist->clist_mutex); 3189*fcf3ce44SJohn Forte clist->clist_wait = 0; 3190*fcf3ce44SJohn Forte cv_signal(&clist->clist_cv); 3191*fcf3ce44SJohn Forte mutex_exit(&clist->clist_mutex); 3192*fcf3ce44SJohn Forte } else { 3193*fcf3ce44SJohn Forte kmem_free(clist, sizeof (*clist)); 3194*fcf3ce44SJohn Forte } 3195*fcf3ce44SJohn Forte } 3196*fcf3ce44SJohn Forte 3197*fcf3ce44SJohn Forte 3198*fcf3ce44SJohn Forte /* 3199*fcf3ce44SJohn Forte * Allocate an fc_remote_node_t struct to represent a remote node for the 3200*fcf3ce44SJohn Forte * given nwwn. This will also add the nwwn to the global nwwn table. 3201*fcf3ce44SJohn Forte * 3202*fcf3ce44SJohn Forte * Returns a pointer to the newly-allocated struct. Returns NULL if 3203*fcf3ce44SJohn Forte * the kmem_zalloc fails or if the enlist_wwn attempt fails. 3204*fcf3ce44SJohn Forte */ 3205*fcf3ce44SJohn Forte fc_remote_node_t * 3206*fcf3ce44SJohn Forte fctl_create_remote_node(la_wwn_t *nwwn, int sleep) 3207*fcf3ce44SJohn Forte { 3208*fcf3ce44SJohn Forte fc_remote_node_t *rnodep; 3209*fcf3ce44SJohn Forte 3210*fcf3ce44SJohn Forte if ((rnodep = kmem_zalloc(sizeof (*rnodep), sleep)) == NULL) { 3211*fcf3ce44SJohn Forte return (NULL); 3212*fcf3ce44SJohn Forte } 3213*fcf3ce44SJohn Forte 3214*fcf3ce44SJohn Forte mutex_init(&rnodep->fd_mutex, NULL, MUTEX_DRIVER, NULL); 3215*fcf3ce44SJohn Forte 3216*fcf3ce44SJohn Forte rnodep->fd_node_name = *nwwn; 3217*fcf3ce44SJohn Forte rnodep->fd_flags = FC_REMOTE_NODE_VALID; 3218*fcf3ce44SJohn Forte rnodep->fd_numports = 1; 3219*fcf3ce44SJohn Forte 3220*fcf3ce44SJohn Forte if (fctl_enlist_nwwn_table(rnodep, sleep) != FC_SUCCESS) { 3221*fcf3ce44SJohn Forte mutex_destroy(&rnodep->fd_mutex); 3222*fcf3ce44SJohn Forte kmem_free(rnodep, sizeof (*rnodep)); 3223*fcf3ce44SJohn Forte return (NULL); 3224*fcf3ce44SJohn Forte } 3225*fcf3ce44SJohn Forte 3226*fcf3ce44SJohn Forte return (rnodep); 3227*fcf3ce44SJohn Forte } 3228*fcf3ce44SJohn Forte 3229*fcf3ce44SJohn Forte /* 3230*fcf3ce44SJohn Forte * Deconstruct and free the given fc_remote_node_t struct (remote node struct). 3231*fcf3ce44SJohn Forte * Silently skips the deconstruct/free if there are any fc_remote_port_t 3232*fcf3ce44SJohn Forte * (remote port device) structs still referenced by the given 3233*fcf3ce44SJohn Forte * fc_remote_node_t struct. 3234*fcf3ce44SJohn Forte */ 3235*fcf3ce44SJohn Forte void 3236*fcf3ce44SJohn Forte fctl_destroy_remote_node(fc_remote_node_t *rnodep) 3237*fcf3ce44SJohn Forte { 3238*fcf3ce44SJohn Forte mutex_enter(&rnodep->fd_mutex); 3239*fcf3ce44SJohn Forte 3240*fcf3ce44SJohn Forte /* 3241*fcf3ce44SJohn Forte * Look at the count and linked list of of remote ports 3242*fcf3ce44SJohn Forte * (fc_remote_port_t structs); bail if these indicate that 3243*fcf3ce44SJohn Forte * given fc_remote_node_t may be in use. 3244*fcf3ce44SJohn Forte */ 3245*fcf3ce44SJohn Forte if (rnodep->fd_numports != 0 || rnodep->fd_portlistp) { 3246*fcf3ce44SJohn Forte mutex_exit(&rnodep->fd_mutex); 3247*fcf3ce44SJohn Forte return; 3248*fcf3ce44SJohn Forte } 3249*fcf3ce44SJohn Forte 3250*fcf3ce44SJohn Forte mutex_exit(&rnodep->fd_mutex); 3251*fcf3ce44SJohn Forte 3252*fcf3ce44SJohn Forte mutex_destroy(&rnodep->fd_mutex); 3253*fcf3ce44SJohn Forte kmem_free(rnodep, sizeof (*rnodep)); 3254*fcf3ce44SJohn Forte } 3255*fcf3ce44SJohn Forte 3256*fcf3ce44SJohn Forte 3257*fcf3ce44SJohn Forte /* 3258*fcf3ce44SJohn Forte * Add the given fc_remote_node_t to the global fctl_nwwn_hash_table[]. This 3259*fcf3ce44SJohn Forte * uses the nwwn in the fd_node_name.raw_wwn of the given struct. 3260*fcf3ce44SJohn Forte * This only fails if the kmem_zalloc fails. This does not check for a 3261*fcf3ce44SJohn Forte * unique or pre-existing nwwn in the fctl_nwwn_hash_table[]. 3262*fcf3ce44SJohn Forte * This is only called from fctl_create_remote_node(). 3263*fcf3ce44SJohn Forte */ 3264*fcf3ce44SJohn Forte int 3265*fcf3ce44SJohn Forte fctl_enlist_nwwn_table(fc_remote_node_t *rnodep, int sleep) 3266*fcf3ce44SJohn Forte { 3267*fcf3ce44SJohn Forte int index; 3268*fcf3ce44SJohn Forte fctl_nwwn_elem_t *new; 3269*fcf3ce44SJohn Forte fctl_nwwn_list_t *head; 3270*fcf3ce44SJohn Forte 3271*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&rnodep->fd_mutex)); 3272*fcf3ce44SJohn Forte 3273*fcf3ce44SJohn Forte if ((new = kmem_zalloc(sizeof (*new), sleep)) == NULL) { 3274*fcf3ce44SJohn Forte return (FC_FAILURE); 3275*fcf3ce44SJohn Forte } 3276*fcf3ce44SJohn Forte 3277*fcf3ce44SJohn Forte mutex_enter(&fctl_nwwn_hash_mutex); 3278*fcf3ce44SJohn Forte new->fne_nodep = rnodep; 3279*fcf3ce44SJohn Forte 3280*fcf3ce44SJohn Forte mutex_enter(&rnodep->fd_mutex); 3281*fcf3ce44SJohn Forte ASSERT(fctl_is_wwn_zero(&rnodep->fd_node_name) == FC_FAILURE); 3282*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(rnodep->fd_node_name.raw_wwn), 3283*fcf3ce44SJohn Forte fctl_nwwn_table_size); 3284*fcf3ce44SJohn Forte mutex_exit(&rnodep->fd_mutex); 3285*fcf3ce44SJohn Forte 3286*fcf3ce44SJohn Forte head = &fctl_nwwn_hash_table[index]; 3287*fcf3ce44SJohn Forte 3288*fcf3ce44SJohn Forte /* Link it in at the head of the hash list */ 3289*fcf3ce44SJohn Forte new->fne_nextp = head->fnl_headp; 3290*fcf3ce44SJohn Forte head->fnl_headp = new; 3291*fcf3ce44SJohn Forte 3292*fcf3ce44SJohn Forte mutex_exit(&fctl_nwwn_hash_mutex); 3293*fcf3ce44SJohn Forte 3294*fcf3ce44SJohn Forte return (FC_SUCCESS); 3295*fcf3ce44SJohn Forte } 3296*fcf3ce44SJohn Forte 3297*fcf3ce44SJohn Forte 3298*fcf3ce44SJohn Forte /* 3299*fcf3ce44SJohn Forte * Remove the given fc_remote_node_t from the global fctl_nwwn_hash_table[]. 3300*fcf3ce44SJohn Forte * This uses the nwwn in the fd_node_name.raw_wwn of the given struct. 3301*fcf3ce44SJohn Forte */ 3302*fcf3ce44SJohn Forte void 3303*fcf3ce44SJohn Forte fctl_delist_nwwn_table(fc_remote_node_t *rnodep) 3304*fcf3ce44SJohn Forte { 3305*fcf3ce44SJohn Forte int index; 3306*fcf3ce44SJohn Forte fctl_nwwn_list_t *head; 3307*fcf3ce44SJohn Forte fctl_nwwn_elem_t *elem; 3308*fcf3ce44SJohn Forte fctl_nwwn_elem_t *prev; 3309*fcf3ce44SJohn Forte 3310*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&fctl_nwwn_hash_mutex)); 3311*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&rnodep->fd_mutex)); 3312*fcf3ce44SJohn Forte 3313*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(rnodep->fd_node_name.raw_wwn), 3314*fcf3ce44SJohn Forte fctl_nwwn_table_size); 3315*fcf3ce44SJohn Forte 3316*fcf3ce44SJohn Forte head = &fctl_nwwn_hash_table[index]; 3317*fcf3ce44SJohn Forte elem = head->fnl_headp; 3318*fcf3ce44SJohn Forte prev = NULL; 3319*fcf3ce44SJohn Forte 3320*fcf3ce44SJohn Forte while (elem != NULL) { 3321*fcf3ce44SJohn Forte if (elem->fne_nodep == rnodep) { 3322*fcf3ce44SJohn Forte /* 3323*fcf3ce44SJohn Forte * Found it -- unlink it from the list & decrement 3324*fcf3ce44SJohn Forte * the count for the hash chain. 3325*fcf3ce44SJohn Forte */ 3326*fcf3ce44SJohn Forte if (prev == NULL) { 3327*fcf3ce44SJohn Forte head->fnl_headp = elem->fne_nextp; 3328*fcf3ce44SJohn Forte } else { 3329*fcf3ce44SJohn Forte prev->fne_nextp = elem->fne_nextp; 3330*fcf3ce44SJohn Forte } 3331*fcf3ce44SJohn Forte break; 3332*fcf3ce44SJohn Forte } 3333*fcf3ce44SJohn Forte prev = elem; 3334*fcf3ce44SJohn Forte elem = elem->fne_nextp; 3335*fcf3ce44SJohn Forte } 3336*fcf3ce44SJohn Forte 3337*fcf3ce44SJohn Forte if (elem != NULL) { 3338*fcf3ce44SJohn Forte kmem_free(elem, sizeof (*elem)); 3339*fcf3ce44SJohn Forte } 3340*fcf3ce44SJohn Forte } 3341*fcf3ce44SJohn Forte 3342*fcf3ce44SJohn Forte 3343*fcf3ce44SJohn Forte /* 3344*fcf3ce44SJohn Forte * Returns a reference to an fc_remote_node_t struct for the given node_wwn. 3345*fcf3ce44SJohn Forte * Looks in the global fctl_nwwn_hash_table[]. Identical to the 3346*fcf3ce44SJohn Forte * fctl_lock_remote_node_by_nwwn() function, except that this does NOT increment 3347*fcf3ce44SJohn Forte * the fc_count reference count in the f_device_t before returning. 3348*fcf3ce44SJohn Forte * 3349*fcf3ce44SJohn Forte * This function is called by: fctl_create_remote_port_t(). 3350*fcf3ce44SJohn Forte * 3351*fcf3ce44SJohn Forte * OLD COMMENT: 3352*fcf3ce44SJohn Forte * Note: The calling thread needs to make sure it isn't holding any device 3353*fcf3ce44SJohn Forte * mutex (more so the fc_remote_node_t that could potentially have this wwn). 3354*fcf3ce44SJohn Forte */ 3355*fcf3ce44SJohn Forte fc_remote_node_t * 3356*fcf3ce44SJohn Forte fctl_get_remote_node_by_nwwn(la_wwn_t *node_wwn) 3357*fcf3ce44SJohn Forte { 3358*fcf3ce44SJohn Forte int index; 3359*fcf3ce44SJohn Forte fctl_nwwn_elem_t *elem; 3360*fcf3ce44SJohn Forte fc_remote_node_t *next; 3361*fcf3ce44SJohn Forte fc_remote_node_t *rnodep = NULL; 3362*fcf3ce44SJohn Forte 3363*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(node_wwn->raw_wwn), 3364*fcf3ce44SJohn Forte fctl_nwwn_table_size); 3365*fcf3ce44SJohn Forte ASSERT(index >= 0 && index < fctl_nwwn_table_size); 3366*fcf3ce44SJohn Forte 3367*fcf3ce44SJohn Forte mutex_enter(&fctl_nwwn_hash_mutex); 3368*fcf3ce44SJohn Forte elem = fctl_nwwn_hash_table[index].fnl_headp; 3369*fcf3ce44SJohn Forte while (elem != NULL) { 3370*fcf3ce44SJohn Forte next = elem->fne_nodep; 3371*fcf3ce44SJohn Forte if (next != NULL) { 3372*fcf3ce44SJohn Forte mutex_enter(&next->fd_mutex); 3373*fcf3ce44SJohn Forte if (fctl_wwn_cmp(node_wwn, &next->fd_node_name) == 0) { 3374*fcf3ce44SJohn Forte rnodep = next; 3375*fcf3ce44SJohn Forte mutex_exit(&next->fd_mutex); 3376*fcf3ce44SJohn Forte break; 3377*fcf3ce44SJohn Forte } 3378*fcf3ce44SJohn Forte mutex_exit(&next->fd_mutex); 3379*fcf3ce44SJohn Forte } 3380*fcf3ce44SJohn Forte elem = elem->fne_nextp; 3381*fcf3ce44SJohn Forte } 3382*fcf3ce44SJohn Forte mutex_exit(&fctl_nwwn_hash_mutex); 3383*fcf3ce44SJohn Forte 3384*fcf3ce44SJohn Forte return (rnodep); 3385*fcf3ce44SJohn Forte } 3386*fcf3ce44SJohn Forte 3387*fcf3ce44SJohn Forte 3388*fcf3ce44SJohn Forte /* 3389*fcf3ce44SJohn Forte * Returns a reference to an fc_remote_node_t struct for the given node_wwn. 3390*fcf3ce44SJohn Forte * Looks in the global fctl_nwwn_hash_table[]. Increments the fd_numports 3391*fcf3ce44SJohn Forte * reference count in the f_device_t before returning. 3392*fcf3ce44SJohn Forte * 3393*fcf3ce44SJohn Forte * This function is only called by fctl_create_remote_port_t(). 3394*fcf3ce44SJohn Forte */ 3395*fcf3ce44SJohn Forte fc_remote_node_t * 3396*fcf3ce44SJohn Forte fctl_lock_remote_node_by_nwwn(la_wwn_t *node_wwn) 3397*fcf3ce44SJohn Forte { 3398*fcf3ce44SJohn Forte int index; 3399*fcf3ce44SJohn Forte fctl_nwwn_elem_t *elem; 3400*fcf3ce44SJohn Forte fc_remote_node_t *next; 3401*fcf3ce44SJohn Forte fc_remote_node_t *rnodep = NULL; 3402*fcf3ce44SJohn Forte 3403*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(node_wwn->raw_wwn), 3404*fcf3ce44SJohn Forte fctl_nwwn_table_size); 3405*fcf3ce44SJohn Forte ASSERT(index >= 0 && index < fctl_nwwn_table_size); 3406*fcf3ce44SJohn Forte 3407*fcf3ce44SJohn Forte mutex_enter(&fctl_nwwn_hash_mutex); 3408*fcf3ce44SJohn Forte elem = fctl_nwwn_hash_table[index].fnl_headp; 3409*fcf3ce44SJohn Forte while (elem != NULL) { 3410*fcf3ce44SJohn Forte next = elem->fne_nodep; 3411*fcf3ce44SJohn Forte if (next != NULL) { 3412*fcf3ce44SJohn Forte mutex_enter(&next->fd_mutex); 3413*fcf3ce44SJohn Forte if (fctl_wwn_cmp(node_wwn, &next->fd_node_name) == 0) { 3414*fcf3ce44SJohn Forte rnodep = next; 3415*fcf3ce44SJohn Forte rnodep->fd_numports++; 3416*fcf3ce44SJohn Forte mutex_exit(&next->fd_mutex); 3417*fcf3ce44SJohn Forte break; 3418*fcf3ce44SJohn Forte } 3419*fcf3ce44SJohn Forte mutex_exit(&next->fd_mutex); 3420*fcf3ce44SJohn Forte } 3421*fcf3ce44SJohn Forte elem = elem->fne_nextp; 3422*fcf3ce44SJohn Forte } 3423*fcf3ce44SJohn Forte mutex_exit(&fctl_nwwn_hash_mutex); 3424*fcf3ce44SJohn Forte 3425*fcf3ce44SJohn Forte return (rnodep); 3426*fcf3ce44SJohn Forte } 3427*fcf3ce44SJohn Forte 3428*fcf3ce44SJohn Forte 3429*fcf3ce44SJohn Forte /* 3430*fcf3ce44SJohn Forte * Allocate and initialize an fc_remote_port_t struct & returns a pointer to 3431*fcf3ce44SJohn Forte * the newly allocated struct. Only fails if the kmem_zalloc() fails. 3432*fcf3ce44SJohn Forte */ 3433*fcf3ce44SJohn Forte fc_remote_port_t * 3434*fcf3ce44SJohn Forte fctl_alloc_remote_port(fc_local_port_t *port, la_wwn_t *port_wwn, 3435*fcf3ce44SJohn Forte uint32_t d_id, uchar_t recepient, int sleep) 3436*fcf3ce44SJohn Forte { 3437*fcf3ce44SJohn Forte fc_remote_port_t *pd; 3438*fcf3ce44SJohn Forte 3439*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 3440*fcf3ce44SJohn Forte ASSERT(FC_IS_REAL_DEVICE(d_id)); 3441*fcf3ce44SJohn Forte 3442*fcf3ce44SJohn Forte if ((pd = kmem_zalloc(sizeof (*pd), sleep)) == NULL) { 3443*fcf3ce44SJohn Forte return (NULL); 3444*fcf3ce44SJohn Forte } 3445*fcf3ce44SJohn Forte fctl_tc_constructor(&pd->pd_logo_tc, FC_LOGO_TOLERANCE_LIMIT, 3446*fcf3ce44SJohn Forte FC_LOGO_TOLERANCE_TIME_LIMIT); 3447*fcf3ce44SJohn Forte 3448*fcf3ce44SJohn Forte mutex_init(&pd->pd_mutex, NULL, MUTEX_DRIVER, NULL); 3449*fcf3ce44SJohn Forte 3450*fcf3ce44SJohn Forte pd->pd_port_id.port_id = d_id; 3451*fcf3ce44SJohn Forte pd->pd_port_name = *port_wwn; 3452*fcf3ce44SJohn Forte pd->pd_port = port; 3453*fcf3ce44SJohn Forte pd->pd_state = PORT_DEVICE_VALID; 3454*fcf3ce44SJohn Forte pd->pd_type = PORT_DEVICE_NEW; 3455*fcf3ce44SJohn Forte pd->pd_recepient = recepient; 3456*fcf3ce44SJohn Forte 3457*fcf3ce44SJohn Forte return (pd); 3458*fcf3ce44SJohn Forte } 3459*fcf3ce44SJohn Forte 3460*fcf3ce44SJohn Forte 3461*fcf3ce44SJohn Forte /* 3462*fcf3ce44SJohn Forte * Deconstruct and free the given fc_remote_port_t struct (unconditionally). 3463*fcf3ce44SJohn Forte */ 3464*fcf3ce44SJohn Forte void 3465*fcf3ce44SJohn Forte fctl_dealloc_remote_port(fc_remote_port_t *pd) 3466*fcf3ce44SJohn Forte { 3467*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&pd->pd_mutex)); 3468*fcf3ce44SJohn Forte 3469*fcf3ce44SJohn Forte fctl_tc_destructor(&pd->pd_logo_tc); 3470*fcf3ce44SJohn Forte mutex_destroy(&pd->pd_mutex); 3471*fcf3ce44SJohn Forte kmem_free(pd, sizeof (*pd)); 3472*fcf3ce44SJohn Forte } 3473*fcf3ce44SJohn Forte 3474*fcf3ce44SJohn Forte /* 3475*fcf3ce44SJohn Forte * Add the given fc_remote_port_t onto the linked list of remote port 3476*fcf3ce44SJohn Forte * devices associated with the given fc_remote_node_t. Does NOT add the 3477*fcf3ce44SJohn Forte * fc_remote_port_t to the list if already exists on the list. 3478*fcf3ce44SJohn Forte */ 3479*fcf3ce44SJohn Forte void 3480*fcf3ce44SJohn Forte fctl_link_remote_port_to_remote_node(fc_remote_node_t *rnodep, 3481*fcf3ce44SJohn Forte fc_remote_port_t *pd) 3482*fcf3ce44SJohn Forte { 3483*fcf3ce44SJohn Forte fc_remote_port_t *last; 3484*fcf3ce44SJohn Forte fc_remote_port_t *ports; 3485*fcf3ce44SJohn Forte 3486*fcf3ce44SJohn Forte mutex_enter(&rnodep->fd_mutex); 3487*fcf3ce44SJohn Forte 3488*fcf3ce44SJohn Forte last = NULL; 3489*fcf3ce44SJohn Forte for (ports = rnodep->fd_portlistp; ports != NULL; 3490*fcf3ce44SJohn Forte ports = ports->pd_port_next) { 3491*fcf3ce44SJohn Forte if (ports == pd) { 3492*fcf3ce44SJohn Forte /* 3493*fcf3ce44SJohn Forte * The given fc_remote_port_t is already on the linked 3494*fcf3ce44SJohn Forte * list chain for the given remote node, so bail now. 3495*fcf3ce44SJohn Forte */ 3496*fcf3ce44SJohn Forte mutex_exit(&rnodep->fd_mutex); 3497*fcf3ce44SJohn Forte return; 3498*fcf3ce44SJohn Forte } 3499*fcf3ce44SJohn Forte last = ports; 3500*fcf3ce44SJohn Forte } 3501*fcf3ce44SJohn Forte 3502*fcf3ce44SJohn Forte /* Add the fc_remote_port_t to the tail of the linked list */ 3503*fcf3ce44SJohn Forte if (last != NULL) { 3504*fcf3ce44SJohn Forte last->pd_port_next = pd; 3505*fcf3ce44SJohn Forte } else { 3506*fcf3ce44SJohn Forte rnodep->fd_portlistp = pd; 3507*fcf3ce44SJohn Forte } 3508*fcf3ce44SJohn Forte pd->pd_port_next = NULL; 3509*fcf3ce44SJohn Forte 3510*fcf3ce44SJohn Forte /* 3511*fcf3ce44SJohn Forte * Link the fc_remote_port_t back to the associated fc_remote_node_t. 3512*fcf3ce44SJohn Forte */ 3513*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3514*fcf3ce44SJohn Forte pd->pd_remote_nodep = rnodep; 3515*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3516*fcf3ce44SJohn Forte 3517*fcf3ce44SJohn Forte mutex_exit(&rnodep->fd_mutex); 3518*fcf3ce44SJohn Forte } 3519*fcf3ce44SJohn Forte 3520*fcf3ce44SJohn Forte 3521*fcf3ce44SJohn Forte /* 3522*fcf3ce44SJohn Forte * Remove the specified fc_remote_port_t from the linked list of remote ports 3523*fcf3ce44SJohn Forte * for the given fc_remote_node_t. 3524*fcf3ce44SJohn Forte * 3525*fcf3ce44SJohn Forte * Returns a count of the _remaining_ fc_remote_port_t structs on the linked 3526*fcf3ce44SJohn Forte * list of the fc_remote_node_t. 3527*fcf3ce44SJohn Forte * 3528*fcf3ce44SJohn Forte * The fd_numports on the given fc_remote_node_t is decremented, and if 3529*fcf3ce44SJohn Forte * it hits zero then this function also removes the fc_remote_node_t from the 3530*fcf3ce44SJohn Forte * global fctl_nwwn_hash_table[]. This appears to be the ONLY WAY that entries 3531*fcf3ce44SJohn Forte * are removed from the fctl_nwwn_hash_table[]. 3532*fcf3ce44SJohn Forte */ 3533*fcf3ce44SJohn Forte int 3534*fcf3ce44SJohn Forte fctl_unlink_remote_port_from_remote_node(fc_remote_node_t *rnodep, 3535*fcf3ce44SJohn Forte fc_remote_port_t *pd) 3536*fcf3ce44SJohn Forte { 3537*fcf3ce44SJohn Forte int rcount = 0; 3538*fcf3ce44SJohn Forte fc_remote_port_t *last; 3539*fcf3ce44SJohn Forte fc_remote_port_t *ports; 3540*fcf3ce44SJohn Forte 3541*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&rnodep->fd_mutex)); 3542*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&pd->pd_mutex)); 3543*fcf3ce44SJohn Forte 3544*fcf3ce44SJohn Forte last = NULL; 3545*fcf3ce44SJohn Forte 3546*fcf3ce44SJohn Forte mutex_enter(&fctl_nwwn_hash_mutex); 3547*fcf3ce44SJohn Forte 3548*fcf3ce44SJohn Forte mutex_enter(&rnodep->fd_mutex); 3549*fcf3ce44SJohn Forte 3550*fcf3ce44SJohn Forte /* 3551*fcf3ce44SJohn Forte * Go thru the linked list of fc_remote_port_t structs for the given 3552*fcf3ce44SJohn Forte * fc_remote_node_t; try to find the specified fc_remote_port_t (pd). 3553*fcf3ce44SJohn Forte */ 3554*fcf3ce44SJohn Forte ports = rnodep->fd_portlistp; 3555*fcf3ce44SJohn Forte while (ports != NULL) { 3556*fcf3ce44SJohn Forte if (ports == pd) { 3557*fcf3ce44SJohn Forte break; /* Found the requested fc_remote_port_t */ 3558*fcf3ce44SJohn Forte } 3559*fcf3ce44SJohn Forte last = ports; 3560*fcf3ce44SJohn Forte ports = ports->pd_port_next; 3561*fcf3ce44SJohn Forte } 3562*fcf3ce44SJohn Forte 3563*fcf3ce44SJohn Forte if (ports) { 3564*fcf3ce44SJohn Forte rcount = --rnodep->fd_numports; 3565*fcf3ce44SJohn Forte if (rcount == 0) { 3566*fcf3ce44SJohn Forte /* Note: this is only ever called from here */ 3567*fcf3ce44SJohn Forte fctl_delist_nwwn_table(rnodep); 3568*fcf3ce44SJohn Forte } 3569*fcf3ce44SJohn Forte if (last) { 3570*fcf3ce44SJohn Forte last->pd_port_next = pd->pd_port_next; 3571*fcf3ce44SJohn Forte } else { 3572*fcf3ce44SJohn Forte rnodep->fd_portlistp = pd->pd_port_next; 3573*fcf3ce44SJohn Forte } 3574*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3575*fcf3ce44SJohn Forte pd->pd_remote_nodep = NULL; 3576*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3577*fcf3ce44SJohn Forte } 3578*fcf3ce44SJohn Forte 3579*fcf3ce44SJohn Forte pd->pd_port_next = NULL; 3580*fcf3ce44SJohn Forte 3581*fcf3ce44SJohn Forte mutex_exit(&rnodep->fd_mutex); 3582*fcf3ce44SJohn Forte mutex_exit(&fctl_nwwn_hash_mutex); 3583*fcf3ce44SJohn Forte 3584*fcf3ce44SJohn Forte return (rcount); 3585*fcf3ce44SJohn Forte } 3586*fcf3ce44SJohn Forte 3587*fcf3ce44SJohn Forte 3588*fcf3ce44SJohn Forte /* 3589*fcf3ce44SJohn Forte * Add the given fc_remote_port_t struct to the d_id table in the given 3590*fcf3ce44SJohn Forte * fc_local_port_t struct. Hashes based upon the pd->pd_port_id.port_id in the 3591*fcf3ce44SJohn Forte * fc_remote_port_t. 3592*fcf3ce44SJohn Forte * 3593*fcf3ce44SJohn Forte * No memory allocs are required, so this never fails, but it does use the 3594*fcf3ce44SJohn Forte * (pd->pd_aux_flags & PD_IN_DID_QUEUE) to keep duplicates off the list. 3595*fcf3ce44SJohn Forte * (There does not seem to be a way to tell the caller that a duplicate 3596*fcf3ce44SJohn Forte * exists.) 3597*fcf3ce44SJohn Forte */ 3598*fcf3ce44SJohn Forte void 3599*fcf3ce44SJohn Forte fctl_enlist_did_table(fc_local_port_t *port, fc_remote_port_t *pd) 3600*fcf3ce44SJohn Forte { 3601*fcf3ce44SJohn Forte struct d_id_hash *head; 3602*fcf3ce44SJohn Forte 3603*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 3604*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&pd->pd_mutex)); 3605*fcf3ce44SJohn Forte 3606*fcf3ce44SJohn Forte if (pd->pd_aux_flags & PD_IN_DID_QUEUE) { 3607*fcf3ce44SJohn Forte return; 3608*fcf3ce44SJohn Forte } 3609*fcf3ce44SJohn Forte 3610*fcf3ce44SJohn Forte head = &port->fp_did_table[D_ID_HASH_FUNC(pd->pd_port_id.port_id, 3611*fcf3ce44SJohn Forte did_table_size)]; 3612*fcf3ce44SJohn Forte 3613*fcf3ce44SJohn Forte #ifdef DEBUG 3614*fcf3ce44SJohn Forte { 3615*fcf3ce44SJohn Forte int index; 3616*fcf3ce44SJohn Forte fc_remote_port_t *tmp_pd; 3617*fcf3ce44SJohn Forte struct d_id_hash *tmp_head; 3618*fcf3ce44SJohn Forte 3619*fcf3ce44SJohn Forte /* 3620*fcf3ce44SJohn Forte * Search down in each bucket for a duplicate pd 3621*fcf3ce44SJohn Forte * Also search for duplicate D_IDs 3622*fcf3ce44SJohn Forte * This DEBUG code will force an ASSERT if a duplicate 3623*fcf3ce44SJohn Forte * is ever found. 3624*fcf3ce44SJohn Forte */ 3625*fcf3ce44SJohn Forte for (index = 0; index < did_table_size; index++) { 3626*fcf3ce44SJohn Forte tmp_head = &port->fp_did_table[index]; 3627*fcf3ce44SJohn Forte 3628*fcf3ce44SJohn Forte tmp_pd = tmp_head->d_id_head; 3629*fcf3ce44SJohn Forte while (tmp_pd != NULL) { 3630*fcf3ce44SJohn Forte ASSERT(tmp_pd != pd); 3631*fcf3ce44SJohn Forte 3632*fcf3ce44SJohn Forte if (tmp_pd->pd_state != PORT_DEVICE_INVALID && 3633*fcf3ce44SJohn Forte tmp_pd->pd_type != PORT_DEVICE_OLD) { 3634*fcf3ce44SJohn Forte ASSERT(tmp_pd->pd_port_id.port_id != 3635*fcf3ce44SJohn Forte pd->pd_port_id.port_id); 3636*fcf3ce44SJohn Forte } 3637*fcf3ce44SJohn Forte 3638*fcf3ce44SJohn Forte tmp_pd = tmp_pd->pd_did_hnext; 3639*fcf3ce44SJohn Forte } 3640*fcf3ce44SJohn Forte } 3641*fcf3ce44SJohn Forte } 3642*fcf3ce44SJohn Forte 3643*fcf3ce44SJohn Forte bzero(pd->pd_d_stack, sizeof (pd->pd_d_stack)); 3644*fcf3ce44SJohn Forte pd->pd_d_depth = getpcstack(pd->pd_d_stack, FC_STACK_DEPTH); 3645*fcf3ce44SJohn Forte #endif 3646*fcf3ce44SJohn Forte 3647*fcf3ce44SJohn Forte pd->pd_did_hnext = head->d_id_head; 3648*fcf3ce44SJohn Forte head->d_id_head = pd; 3649*fcf3ce44SJohn Forte 3650*fcf3ce44SJohn Forte pd->pd_aux_flags |= PD_IN_DID_QUEUE; 3651*fcf3ce44SJohn Forte head->d_id_count++; 3652*fcf3ce44SJohn Forte } 3653*fcf3ce44SJohn Forte 3654*fcf3ce44SJohn Forte 3655*fcf3ce44SJohn Forte /* 3656*fcf3ce44SJohn Forte * Remove the given fc_remote_port_t struct from the d_id table in the given 3657*fcf3ce44SJohn Forte * fc_local_port_t struct. Hashes based upon the pd->pd_port_id.port_id in the 3658*fcf3ce44SJohn Forte * fc_remote_port_t. 3659*fcf3ce44SJohn Forte * 3660*fcf3ce44SJohn Forte * Does nothing if the requested fc_remote_port_t was not found. 3661*fcf3ce44SJohn Forte */ 3662*fcf3ce44SJohn Forte void 3663*fcf3ce44SJohn Forte fctl_delist_did_table(fc_local_port_t *port, fc_remote_port_t *pd) 3664*fcf3ce44SJohn Forte { 3665*fcf3ce44SJohn Forte uint32_t d_id; 3666*fcf3ce44SJohn Forte struct d_id_hash *head; 3667*fcf3ce44SJohn Forte fc_remote_port_t *pd_next; 3668*fcf3ce44SJohn Forte fc_remote_port_t *last; 3669*fcf3ce44SJohn Forte 3670*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 3671*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&pd->pd_mutex)); 3672*fcf3ce44SJohn Forte 3673*fcf3ce44SJohn Forte d_id = pd->pd_port_id.port_id; 3674*fcf3ce44SJohn Forte head = &port->fp_did_table[D_ID_HASH_FUNC(d_id, did_table_size)]; 3675*fcf3ce44SJohn Forte 3676*fcf3ce44SJohn Forte pd_next = head->d_id_head; 3677*fcf3ce44SJohn Forte last = NULL; 3678*fcf3ce44SJohn Forte while (pd_next != NULL) { 3679*fcf3ce44SJohn Forte if (pd == pd_next) { 3680*fcf3ce44SJohn Forte break; /* Found the given fc_remote_port_t */ 3681*fcf3ce44SJohn Forte } 3682*fcf3ce44SJohn Forte last = pd_next; 3683*fcf3ce44SJohn Forte pd_next = pd_next->pd_did_hnext; 3684*fcf3ce44SJohn Forte } 3685*fcf3ce44SJohn Forte 3686*fcf3ce44SJohn Forte if (pd_next) { 3687*fcf3ce44SJohn Forte /* 3688*fcf3ce44SJohn Forte * Found the given fc_remote_port_t; now remove it from the 3689*fcf3ce44SJohn Forte * d_id list. 3690*fcf3ce44SJohn Forte */ 3691*fcf3ce44SJohn Forte head->d_id_count--; 3692*fcf3ce44SJohn Forte if (last == NULL) { 3693*fcf3ce44SJohn Forte head->d_id_head = pd->pd_did_hnext; 3694*fcf3ce44SJohn Forte } else { 3695*fcf3ce44SJohn Forte last->pd_did_hnext = pd->pd_did_hnext; 3696*fcf3ce44SJohn Forte } 3697*fcf3ce44SJohn Forte pd->pd_aux_flags &= ~PD_IN_DID_QUEUE; 3698*fcf3ce44SJohn Forte pd->pd_did_hnext = NULL; 3699*fcf3ce44SJohn Forte } 3700*fcf3ce44SJohn Forte } 3701*fcf3ce44SJohn Forte 3702*fcf3ce44SJohn Forte 3703*fcf3ce44SJohn Forte /* 3704*fcf3ce44SJohn Forte * Add the given fc_remote_port_t struct to the pwwn table in the given 3705*fcf3ce44SJohn Forte * fc_local_port_t struct. Hashes based upon the pd->pd_port_name.raw_wwn 3706*fcf3ce44SJohn Forte * in the fc_remote_port_t. 3707*fcf3ce44SJohn Forte * 3708*fcf3ce44SJohn Forte * No memory allocs are required, so this never fails. 3709*fcf3ce44SJohn Forte */ 3710*fcf3ce44SJohn Forte void 3711*fcf3ce44SJohn Forte fctl_enlist_pwwn_table(fc_local_port_t *port, fc_remote_port_t *pd) 3712*fcf3ce44SJohn Forte { 3713*fcf3ce44SJohn Forte int index; 3714*fcf3ce44SJohn Forte struct pwwn_hash *head; 3715*fcf3ce44SJohn Forte 3716*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 3717*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&pd->pd_mutex)); 3718*fcf3ce44SJohn Forte 3719*fcf3ce44SJohn Forte ASSERT(fctl_is_wwn_zero(&pd->pd_port_name) == FC_FAILURE); 3720*fcf3ce44SJohn Forte 3721*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(pd->pd_port_name.raw_wwn), 3722*fcf3ce44SJohn Forte pwwn_table_size); 3723*fcf3ce44SJohn Forte 3724*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 3725*fcf3ce44SJohn Forte 3726*fcf3ce44SJohn Forte #ifdef DEBUG 3727*fcf3ce44SJohn Forte { 3728*fcf3ce44SJohn Forte int index; 3729*fcf3ce44SJohn Forte fc_remote_port_t *tmp_pd; 3730*fcf3ce44SJohn Forte struct pwwn_hash *tmp_head; 3731*fcf3ce44SJohn Forte 3732*fcf3ce44SJohn Forte /* 3733*fcf3ce44SJohn Forte * Search down in each bucket for a duplicate pd 3734*fcf3ce44SJohn Forte * Search also for a duplicate WWN 3735*fcf3ce44SJohn Forte * Throw an ASSERT if any duplicate is found. 3736*fcf3ce44SJohn Forte */ 3737*fcf3ce44SJohn Forte for (index = 0; index < pwwn_table_size; index++) { 3738*fcf3ce44SJohn Forte tmp_head = &port->fp_pwwn_table[index]; 3739*fcf3ce44SJohn Forte 3740*fcf3ce44SJohn Forte tmp_pd = tmp_head->pwwn_head; 3741*fcf3ce44SJohn Forte while (tmp_pd != NULL) { 3742*fcf3ce44SJohn Forte ASSERT(tmp_pd != pd); 3743*fcf3ce44SJohn Forte 3744*fcf3ce44SJohn Forte if (tmp_pd->pd_state != PORT_DEVICE_INVALID && 3745*fcf3ce44SJohn Forte tmp_pd->pd_type != PORT_DEVICE_OLD) { 3746*fcf3ce44SJohn Forte ASSERT(fctl_wwn_cmp( 3747*fcf3ce44SJohn Forte &tmp_pd->pd_port_name, 3748*fcf3ce44SJohn Forte &pd->pd_port_name) != 0); 3749*fcf3ce44SJohn Forte } 3750*fcf3ce44SJohn Forte 3751*fcf3ce44SJohn Forte tmp_pd = tmp_pd->pd_wwn_hnext; 3752*fcf3ce44SJohn Forte } 3753*fcf3ce44SJohn Forte } 3754*fcf3ce44SJohn Forte } 3755*fcf3ce44SJohn Forte 3756*fcf3ce44SJohn Forte bzero(pd->pd_w_stack, sizeof (pd->pd_w_stack)); 3757*fcf3ce44SJohn Forte pd->pd_w_depth = getpcstack(pd->pd_w_stack, FC_STACK_DEPTH); 3758*fcf3ce44SJohn Forte #endif /* DEBUG */ 3759*fcf3ce44SJohn Forte 3760*fcf3ce44SJohn Forte pd->pd_wwn_hnext = head->pwwn_head; 3761*fcf3ce44SJohn Forte head->pwwn_head = pd; 3762*fcf3ce44SJohn Forte 3763*fcf3ce44SJohn Forte head->pwwn_count++; 3764*fcf3ce44SJohn Forte /* 3765*fcf3ce44SJohn Forte * Make sure we tie fp_dev_count to the size of the 3766*fcf3ce44SJohn Forte * pwwn_table 3767*fcf3ce44SJohn Forte */ 3768*fcf3ce44SJohn Forte port->fp_dev_count++; 3769*fcf3ce44SJohn Forte } 3770*fcf3ce44SJohn Forte 3771*fcf3ce44SJohn Forte 3772*fcf3ce44SJohn Forte /* 3773*fcf3ce44SJohn Forte * Remove the given fc_remote_port_t struct from the pwwn table in the given 3774*fcf3ce44SJohn Forte * fc_local_port_t struct. Hashes based upon the pd->pd_port_name.raw_wwn 3775*fcf3ce44SJohn Forte * in the fc_remote_port_t. 3776*fcf3ce44SJohn Forte * 3777*fcf3ce44SJohn Forte * Does nothing if the requested fc_remote_port_t was not found. 3778*fcf3ce44SJohn Forte */ 3779*fcf3ce44SJohn Forte void 3780*fcf3ce44SJohn Forte fctl_delist_pwwn_table(fc_local_port_t *port, fc_remote_port_t *pd) 3781*fcf3ce44SJohn Forte { 3782*fcf3ce44SJohn Forte int index; 3783*fcf3ce44SJohn Forte la_wwn_t pwwn; 3784*fcf3ce44SJohn Forte struct pwwn_hash *head; 3785*fcf3ce44SJohn Forte fc_remote_port_t *pd_next; 3786*fcf3ce44SJohn Forte fc_remote_port_t *last; 3787*fcf3ce44SJohn Forte 3788*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 3789*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&pd->pd_mutex)); 3790*fcf3ce44SJohn Forte 3791*fcf3ce44SJohn Forte pwwn = pd->pd_port_name; 3792*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(pwwn.raw_wwn), pwwn_table_size); 3793*fcf3ce44SJohn Forte 3794*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 3795*fcf3ce44SJohn Forte 3796*fcf3ce44SJohn Forte last = NULL; 3797*fcf3ce44SJohn Forte pd_next = head->pwwn_head; 3798*fcf3ce44SJohn Forte while (pd_next != NULL) { 3799*fcf3ce44SJohn Forte if (pd_next == pd) { 3800*fcf3ce44SJohn Forte break; /* Found the given fc_remote_port_t */ 3801*fcf3ce44SJohn Forte } 3802*fcf3ce44SJohn Forte last = pd_next; 3803*fcf3ce44SJohn Forte pd_next = pd_next->pd_wwn_hnext; 3804*fcf3ce44SJohn Forte } 3805*fcf3ce44SJohn Forte 3806*fcf3ce44SJohn Forte if (pd_next) { 3807*fcf3ce44SJohn Forte /* 3808*fcf3ce44SJohn Forte * Found the given fc_remote_port_t; now remove it from the 3809*fcf3ce44SJohn Forte * pwwn list. 3810*fcf3ce44SJohn Forte */ 3811*fcf3ce44SJohn Forte head->pwwn_count--; 3812*fcf3ce44SJohn Forte /* 3813*fcf3ce44SJohn Forte * Make sure we tie fp_dev_count to the size of the 3814*fcf3ce44SJohn Forte * pwwn_table 3815*fcf3ce44SJohn Forte */ 3816*fcf3ce44SJohn Forte port->fp_dev_count--; 3817*fcf3ce44SJohn Forte if (last == NULL) { 3818*fcf3ce44SJohn Forte head->pwwn_head = pd->pd_wwn_hnext; 3819*fcf3ce44SJohn Forte } else { 3820*fcf3ce44SJohn Forte last->pd_wwn_hnext = pd->pd_wwn_hnext; 3821*fcf3ce44SJohn Forte } 3822*fcf3ce44SJohn Forte pd->pd_wwn_hnext = NULL; 3823*fcf3ce44SJohn Forte } 3824*fcf3ce44SJohn Forte } 3825*fcf3ce44SJohn Forte 3826*fcf3ce44SJohn Forte 3827*fcf3ce44SJohn Forte /* 3828*fcf3ce44SJohn Forte * Looks in the d_id table of the specified fc_local_port_t for the 3829*fcf3ce44SJohn Forte * fc_remote_port_t that matches the given d_id. Hashes based upon 3830*fcf3ce44SJohn Forte * the given d_id. 3831*fcf3ce44SJohn Forte * Returns a pointer to the fc_remote_port_t struct, but does not update any 3832*fcf3ce44SJohn Forte * reference counts or otherwise indicate that the fc_remote_port_t is in 3833*fcf3ce44SJohn Forte * use. 3834*fcf3ce44SJohn Forte */ 3835*fcf3ce44SJohn Forte fc_remote_port_t * 3836*fcf3ce44SJohn Forte fctl_get_remote_port_by_did(fc_local_port_t *port, uint32_t d_id) 3837*fcf3ce44SJohn Forte { 3838*fcf3ce44SJohn Forte struct d_id_hash *head; 3839*fcf3ce44SJohn Forte fc_remote_port_t *pd; 3840*fcf3ce44SJohn Forte 3841*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 3842*fcf3ce44SJohn Forte 3843*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 3844*fcf3ce44SJohn Forte 3845*fcf3ce44SJohn Forte head = &port->fp_did_table[D_ID_HASH_FUNC(d_id, did_table_size)]; 3846*fcf3ce44SJohn Forte 3847*fcf3ce44SJohn Forte pd = head->d_id_head; 3848*fcf3ce44SJohn Forte while (pd != NULL) { 3849*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3850*fcf3ce44SJohn Forte if (pd->pd_port_id.port_id == d_id) { 3851*fcf3ce44SJohn Forte /* Match found -- break out of the loop */ 3852*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3853*fcf3ce44SJohn Forte break; 3854*fcf3ce44SJohn Forte } 3855*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3856*fcf3ce44SJohn Forte pd = pd->pd_did_hnext; 3857*fcf3ce44SJohn Forte } 3858*fcf3ce44SJohn Forte 3859*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 3860*fcf3ce44SJohn Forte 3861*fcf3ce44SJohn Forte return (pd); 3862*fcf3ce44SJohn Forte } 3863*fcf3ce44SJohn Forte 3864*fcf3ce44SJohn Forte 3865*fcf3ce44SJohn Forte #ifndef __lock_lint /* uncomment when there is a consumer */ 3866*fcf3ce44SJohn Forte 3867*fcf3ce44SJohn Forte void 3868*fcf3ce44SJohn Forte fc_ulp_hold_remote_port(opaque_t port_handle) 3869*fcf3ce44SJohn Forte { 3870*fcf3ce44SJohn Forte fc_remote_port_t *pd = port_handle; 3871*fcf3ce44SJohn Forte 3872*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3873*fcf3ce44SJohn Forte pd->pd_ref_count++; 3874*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3875*fcf3ce44SJohn Forte } 3876*fcf3ce44SJohn Forte 3877*fcf3ce44SJohn Forte /* 3878*fcf3ce44SJohn Forte * Looks in the d_id table of the specified fc_local_port_t for the 3879*fcf3ce44SJohn Forte * fc_remote_port_t that matches the given d_id. Hashes based upon 3880*fcf3ce44SJohn Forte * the given d_id. Returns a pointer to the fc_remote_port_t struct. 3881*fcf3ce44SJohn Forte * 3882*fcf3ce44SJohn Forte * Increments pd_ref_count in the fc_remote_port_t if the 3883*fcf3ce44SJohn Forte * fc_remote_port_t is found at the given d_id. 3884*fcf3ce44SJohn Forte * 3885*fcf3ce44SJohn Forte * The fc_remote_port_t is ignored (treated as non-existent) if either 3886*fcf3ce44SJohn Forte * its pd_state == PORT_DEVICE_INVALID _OR_ its pd_type == PORT_DEVICE_OLD. 3887*fcf3ce44SJohn Forte */ 3888*fcf3ce44SJohn Forte fc_remote_port_t * 3889*fcf3ce44SJohn Forte fctl_hold_remote_port_by_did(fc_local_port_t *port, uint32_t d_id) 3890*fcf3ce44SJohn Forte { 3891*fcf3ce44SJohn Forte struct d_id_hash *head; 3892*fcf3ce44SJohn Forte fc_remote_port_t *pd; 3893*fcf3ce44SJohn Forte 3894*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 3895*fcf3ce44SJohn Forte 3896*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 3897*fcf3ce44SJohn Forte 3898*fcf3ce44SJohn Forte head = &port->fp_did_table[D_ID_HASH_FUNC(d_id, did_table_size)]; 3899*fcf3ce44SJohn Forte 3900*fcf3ce44SJohn Forte pd = head->d_id_head; 3901*fcf3ce44SJohn Forte while (pd != NULL) { 3902*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3903*fcf3ce44SJohn Forte if (pd->pd_port_id.port_id == d_id && pd->pd_state != 3904*fcf3ce44SJohn Forte PORT_DEVICE_INVALID && pd->pd_type != PORT_DEVICE_OLD) { 3905*fcf3ce44SJohn Forte ASSERT(pd->pd_ref_count >= 0); 3906*fcf3ce44SJohn Forte pd->pd_ref_count++; 3907*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3908*fcf3ce44SJohn Forte break; 3909*fcf3ce44SJohn Forte } 3910*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3911*fcf3ce44SJohn Forte pd = pd->pd_did_hnext; 3912*fcf3ce44SJohn Forte } 3913*fcf3ce44SJohn Forte 3914*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 3915*fcf3ce44SJohn Forte 3916*fcf3ce44SJohn Forte return (pd); 3917*fcf3ce44SJohn Forte } 3918*fcf3ce44SJohn Forte 3919*fcf3ce44SJohn Forte #endif /* __lock_lint */ 3920*fcf3ce44SJohn Forte 3921*fcf3ce44SJohn Forte /* 3922*fcf3ce44SJohn Forte * Looks in the pwwn table of the specified fc_local_port_t for the 3923*fcf3ce44SJohn Forte * fc_remote_port_t that matches the given pwwn. Hashes based upon the 3924*fcf3ce44SJohn Forte * given pwwn->raw_wwn. Returns a pointer to the fc_remote_port_t struct, 3925*fcf3ce44SJohn Forte * but does not update any reference counts or otherwise indicate that 3926*fcf3ce44SJohn Forte * the fc_remote_port_t is in use. 3927*fcf3ce44SJohn Forte */ 3928*fcf3ce44SJohn Forte fc_remote_port_t * 3929*fcf3ce44SJohn Forte fctl_get_remote_port_by_pwwn(fc_local_port_t *port, la_wwn_t *pwwn) 3930*fcf3ce44SJohn Forte { 3931*fcf3ce44SJohn Forte int index; 3932*fcf3ce44SJohn Forte struct pwwn_hash *head; 3933*fcf3ce44SJohn Forte fc_remote_port_t *pd; 3934*fcf3ce44SJohn Forte 3935*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 3936*fcf3ce44SJohn Forte 3937*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 3938*fcf3ce44SJohn Forte 3939*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(pwwn->raw_wwn), pwwn_table_size); 3940*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 3941*fcf3ce44SJohn Forte 3942*fcf3ce44SJohn Forte pd = head->pwwn_head; 3943*fcf3ce44SJohn Forte while (pd != NULL) { 3944*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3945*fcf3ce44SJohn Forte if (fctl_wwn_cmp(&pd->pd_port_name, pwwn) == 0) { 3946*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3947*fcf3ce44SJohn Forte break; 3948*fcf3ce44SJohn Forte } 3949*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3950*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 3951*fcf3ce44SJohn Forte } 3952*fcf3ce44SJohn Forte 3953*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 3954*fcf3ce44SJohn Forte 3955*fcf3ce44SJohn Forte return (pd); 3956*fcf3ce44SJohn Forte } 3957*fcf3ce44SJohn Forte 3958*fcf3ce44SJohn Forte 3959*fcf3ce44SJohn Forte /* 3960*fcf3ce44SJohn Forte * Basically the same as fctl_get_remote_port_by_pwwn(), but requires that 3961*fcf3ce44SJohn Forte * the caller already hold the fp_mutex in the fc_local_port_t struct. 3962*fcf3ce44SJohn Forte */ 3963*fcf3ce44SJohn Forte fc_remote_port_t * 3964*fcf3ce44SJohn Forte fctl_get_remote_port_by_pwwn_mutex_held(fc_local_port_t *port, la_wwn_t *pwwn) 3965*fcf3ce44SJohn Forte { 3966*fcf3ce44SJohn Forte int index; 3967*fcf3ce44SJohn Forte struct pwwn_hash *head; 3968*fcf3ce44SJohn Forte fc_remote_port_t *pd; 3969*fcf3ce44SJohn Forte 3970*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 3971*fcf3ce44SJohn Forte 3972*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(pwwn->raw_wwn), pwwn_table_size); 3973*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 3974*fcf3ce44SJohn Forte 3975*fcf3ce44SJohn Forte pd = head->pwwn_head; 3976*fcf3ce44SJohn Forte while (pd != NULL) { 3977*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 3978*fcf3ce44SJohn Forte if (fctl_wwn_cmp(&pd->pd_port_name, pwwn) == 0) { 3979*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3980*fcf3ce44SJohn Forte break; 3981*fcf3ce44SJohn Forte } 3982*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 3983*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 3984*fcf3ce44SJohn Forte } 3985*fcf3ce44SJohn Forte 3986*fcf3ce44SJohn Forte return (pd); 3987*fcf3ce44SJohn Forte } 3988*fcf3ce44SJohn Forte 3989*fcf3ce44SJohn Forte 3990*fcf3ce44SJohn Forte /* 3991*fcf3ce44SJohn Forte * Looks in the pwwn table of the specified fc_local_port_t for the 3992*fcf3ce44SJohn Forte * fc_remote_port_t that matches the given d_id. Hashes based upon the 3993*fcf3ce44SJohn Forte * given pwwn->raw_wwn. Returns a pointer to the fc_remote_port_t struct. 3994*fcf3ce44SJohn Forte * 3995*fcf3ce44SJohn Forte * Increments pd_ref_count in the fc_remote_port_t if the 3996*fcf3ce44SJohn Forte * fc_remote_port_t is found at the given pwwn. 3997*fcf3ce44SJohn Forte * 3998*fcf3ce44SJohn Forte * The fc_remote_port_t is ignored (treated as non-existent) if either 3999*fcf3ce44SJohn Forte * its pd_state == PORT_DEVICE_INVALID _OR_ its pd_type == PORT_DEVICE_OLD. 4000*fcf3ce44SJohn Forte */ 4001*fcf3ce44SJohn Forte fc_remote_port_t * 4002*fcf3ce44SJohn Forte fctl_hold_remote_port_by_pwwn(fc_local_port_t *port, la_wwn_t *pwwn) 4003*fcf3ce44SJohn Forte { 4004*fcf3ce44SJohn Forte int index; 4005*fcf3ce44SJohn Forte struct pwwn_hash *head; 4006*fcf3ce44SJohn Forte fc_remote_port_t *pd; 4007*fcf3ce44SJohn Forte 4008*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 4009*fcf3ce44SJohn Forte 4010*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4011*fcf3ce44SJohn Forte 4012*fcf3ce44SJohn Forte index = HASH_FUNC(WWN_HASH_KEY(pwwn->raw_wwn), pwwn_table_size); 4013*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 4014*fcf3ce44SJohn Forte 4015*fcf3ce44SJohn Forte pd = head->pwwn_head; 4016*fcf3ce44SJohn Forte while (pd != NULL) { 4017*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4018*fcf3ce44SJohn Forte if (fctl_wwn_cmp(&pd->pd_port_name, pwwn) == 0 && 4019*fcf3ce44SJohn Forte pd->pd_state != PORT_DEVICE_INVALID && 4020*fcf3ce44SJohn Forte pd->pd_type != PORT_DEVICE_OLD) { 4021*fcf3ce44SJohn Forte ASSERT(pd->pd_ref_count >= 0); 4022*fcf3ce44SJohn Forte pd->pd_ref_count++; 4023*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4024*fcf3ce44SJohn Forte break; 4025*fcf3ce44SJohn Forte } 4026*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4027*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 4028*fcf3ce44SJohn Forte } 4029*fcf3ce44SJohn Forte 4030*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4031*fcf3ce44SJohn Forte 4032*fcf3ce44SJohn Forte return (pd); 4033*fcf3ce44SJohn Forte } 4034*fcf3ce44SJohn Forte 4035*fcf3ce44SJohn Forte 4036*fcf3ce44SJohn Forte /* 4037*fcf3ce44SJohn Forte * Unconditionally decrement pd_ref_count in the given fc_remote_port_t 4038*fcf3ce44SJohn Forte * struct. 4039*fcf3ce44SJohn Forte * 4040*fcf3ce44SJohn Forte * If pd_ref_count reaches zero, then this function will see if the 4041*fcf3ce44SJohn Forte * fc_remote_port_t has been marked for deallocation. If so (and also if there 4042*fcf3ce44SJohn Forte * are no other potential operations in progress, as indicated by the 4043*fcf3ce44SJohn Forte * PD_ELS_IN_PROGRESS & PD_ELS_MARK settings in the pd_flags), then 4044*fcf3ce44SJohn Forte * fctl_destroy_remote_port_t() is called to deconstruct/free the given 4045*fcf3ce44SJohn Forte * fc_remote_port_t (which will also remove it from the d_id and pwwn tables 4046*fcf3ce44SJohn Forte * on the associated fc_local_port_t). If the associated fc_remote_node_t is no 4047*fcf3ce44SJohn Forte * longer in use, then it too is deconstructed/freed. 4048*fcf3ce44SJohn Forte */ 4049*fcf3ce44SJohn Forte void 4050*fcf3ce44SJohn Forte fctl_release_remote_port(fc_remote_port_t *pd) 4051*fcf3ce44SJohn Forte { 4052*fcf3ce44SJohn Forte int remove = 0; 4053*fcf3ce44SJohn Forte fc_remote_node_t *node; 4054*fcf3ce44SJohn Forte fc_local_port_t *port; 4055*fcf3ce44SJohn Forte 4056*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4057*fcf3ce44SJohn Forte port = pd->pd_port; 4058*fcf3ce44SJohn Forte 4059*fcf3ce44SJohn Forte ASSERT(pd->pd_ref_count > 0); 4060*fcf3ce44SJohn Forte pd->pd_ref_count--; 4061*fcf3ce44SJohn Forte if (pd->pd_ref_count == 0 && 4062*fcf3ce44SJohn Forte (pd->pd_aux_flags & PD_NEEDS_REMOVAL) && 4063*fcf3ce44SJohn Forte (pd->pd_flags != PD_ELS_IN_PROGRESS) && 4064*fcf3ce44SJohn Forte (pd->pd_flags != PD_ELS_MARK)) { 4065*fcf3ce44SJohn Forte remove = 1; 4066*fcf3ce44SJohn Forte pd->pd_aux_flags &= ~PD_NEEDS_REMOVAL; 4067*fcf3ce44SJohn Forte } 4068*fcf3ce44SJohn Forte node = pd->pd_remote_nodep; 4069*fcf3ce44SJohn Forte ASSERT(node != NULL); 4070*fcf3ce44SJohn Forte 4071*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4072*fcf3ce44SJohn Forte 4073*fcf3ce44SJohn Forte if (remove) { 4074*fcf3ce44SJohn Forte /* 4075*fcf3ce44SJohn Forte * The fc_remote_port_t struct has to go away now, so call the 4076*fcf3ce44SJohn Forte * cleanup function to get it off the various lists and remove 4077*fcf3ce44SJohn Forte * references to it in any other associated structs. 4078*fcf3ce44SJohn Forte */ 4079*fcf3ce44SJohn Forte if (fctl_destroy_remote_port(port, pd) == 0) { 4080*fcf3ce44SJohn Forte /* 4081*fcf3ce44SJohn Forte * No more fc_remote_port_t references found in the 4082*fcf3ce44SJohn Forte * associated fc_remote_node_t, so deallocate the 4083*fcf3ce44SJohn Forte * fc_remote_node_t (if it even exists). 4084*fcf3ce44SJohn Forte */ 4085*fcf3ce44SJohn Forte if (node) { 4086*fcf3ce44SJohn Forte fctl_destroy_remote_node(node); 4087*fcf3ce44SJohn Forte } 4088*fcf3ce44SJohn Forte } 4089*fcf3ce44SJohn Forte } 4090*fcf3ce44SJohn Forte } 4091*fcf3ce44SJohn Forte 4092*fcf3ce44SJohn Forte 4093*fcf3ce44SJohn Forte void 4094*fcf3ce44SJohn Forte fctl_fillout_map(fc_local_port_t *port, fc_portmap_t **map, uint32_t *len, 4095*fcf3ce44SJohn Forte int whole_map, int justcopy, int orphan) 4096*fcf3ce44SJohn Forte { 4097*fcf3ce44SJohn Forte int index; 4098*fcf3ce44SJohn Forte int listlen; 4099*fcf3ce44SJohn Forte int full_list; 4100*fcf3ce44SJohn Forte int initiator; 4101*fcf3ce44SJohn Forte uint32_t topology; 4102*fcf3ce44SJohn Forte struct pwwn_hash *head; 4103*fcf3ce44SJohn Forte fc_remote_port_t *pd; 4104*fcf3ce44SJohn Forte fc_remote_port_t *old_pd; 4105*fcf3ce44SJohn Forte fc_remote_port_t *last_pd; 4106*fcf3ce44SJohn Forte fc_portmap_t *listptr; 4107*fcf3ce44SJohn Forte 4108*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 4109*fcf3ce44SJohn Forte 4110*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4111*fcf3ce44SJohn Forte 4112*fcf3ce44SJohn Forte topology = port->fp_topology; 4113*fcf3ce44SJohn Forte 4114*fcf3ce44SJohn Forte if (orphan) { 4115*fcf3ce44SJohn Forte ASSERT(!FC_IS_TOP_SWITCH(topology)); 4116*fcf3ce44SJohn Forte } 4117*fcf3ce44SJohn Forte 4118*fcf3ce44SJohn Forte for (full_list = listlen = index = 0; 4119*fcf3ce44SJohn Forte index < pwwn_table_size; index++) { 4120*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 4121*fcf3ce44SJohn Forte pd = head->pwwn_head; 4122*fcf3ce44SJohn Forte while (pd != NULL) { 4123*fcf3ce44SJohn Forte full_list++; 4124*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4125*fcf3ce44SJohn Forte if (pd->pd_type != PORT_DEVICE_NOCHANGE) { 4126*fcf3ce44SJohn Forte listlen++; 4127*fcf3ce44SJohn Forte } 4128*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4129*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 4130*fcf3ce44SJohn Forte } 4131*fcf3ce44SJohn Forte } 4132*fcf3ce44SJohn Forte 4133*fcf3ce44SJohn Forte if (whole_map == 0) { 4134*fcf3ce44SJohn Forte if (listlen == 0 && *len == 0) { 4135*fcf3ce44SJohn Forte *map = NULL; 4136*fcf3ce44SJohn Forte *len = listlen; 4137*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4138*fcf3ce44SJohn Forte return; 4139*fcf3ce44SJohn Forte } 4140*fcf3ce44SJohn Forte } else { 4141*fcf3ce44SJohn Forte if (full_list == 0 && *len == 0) { 4142*fcf3ce44SJohn Forte *map = NULL; 4143*fcf3ce44SJohn Forte *len = full_list; 4144*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4145*fcf3ce44SJohn Forte return; 4146*fcf3ce44SJohn Forte } 4147*fcf3ce44SJohn Forte } 4148*fcf3ce44SJohn Forte 4149*fcf3ce44SJohn Forte if (*len == 0) { 4150*fcf3ce44SJohn Forte ASSERT(*map == NULL); 4151*fcf3ce44SJohn Forte if (whole_map == 0) { 4152*fcf3ce44SJohn Forte listptr = *map = kmem_zalloc( 4153*fcf3ce44SJohn Forte sizeof (*listptr) * listlen, KM_SLEEP); 4154*fcf3ce44SJohn Forte *len = listlen; 4155*fcf3ce44SJohn Forte } else { 4156*fcf3ce44SJohn Forte listptr = *map = kmem_zalloc( 4157*fcf3ce44SJohn Forte sizeof (*listptr) * full_list, KM_SLEEP); 4158*fcf3ce44SJohn Forte *len = full_list; 4159*fcf3ce44SJohn Forte } 4160*fcf3ce44SJohn Forte } else { 4161*fcf3ce44SJohn Forte /* 4162*fcf3ce44SJohn Forte * By design this routine mandates the callers to 4163*fcf3ce44SJohn Forte * ask for a whole map when they specify the length 4164*fcf3ce44SJohn Forte * and the listptr. 4165*fcf3ce44SJohn Forte */ 4166*fcf3ce44SJohn Forte ASSERT(whole_map == 1); 4167*fcf3ce44SJohn Forte if (*len < full_list) { 4168*fcf3ce44SJohn Forte *len = full_list; 4169*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4170*fcf3ce44SJohn Forte return; 4171*fcf3ce44SJohn Forte } 4172*fcf3ce44SJohn Forte listptr = *map; 4173*fcf3ce44SJohn Forte *len = full_list; 4174*fcf3ce44SJohn Forte } 4175*fcf3ce44SJohn Forte 4176*fcf3ce44SJohn Forte for (index = 0; index < pwwn_table_size; index++) { 4177*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 4178*fcf3ce44SJohn Forte last_pd = NULL; 4179*fcf3ce44SJohn Forte pd = head->pwwn_head; 4180*fcf3ce44SJohn Forte while (pd != NULL) { 4181*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4182*fcf3ce44SJohn Forte if ((whole_map == 0 && 4183*fcf3ce44SJohn Forte pd->pd_type == PORT_DEVICE_NOCHANGE) || 4184*fcf3ce44SJohn Forte pd->pd_state == PORT_DEVICE_INVALID) { 4185*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4186*fcf3ce44SJohn Forte last_pd = pd; 4187*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 4188*fcf3ce44SJohn Forte continue; 4189*fcf3ce44SJohn Forte } 4190*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4191*fcf3ce44SJohn Forte 4192*fcf3ce44SJohn Forte fctl_copy_portmap(listptr, pd); 4193*fcf3ce44SJohn Forte 4194*fcf3ce44SJohn Forte if (justcopy) { 4195*fcf3ce44SJohn Forte last_pd = pd; 4196*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 4197*fcf3ce44SJohn Forte listptr++; 4198*fcf3ce44SJohn Forte continue; 4199*fcf3ce44SJohn Forte } 4200*fcf3ce44SJohn Forte 4201*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4202*fcf3ce44SJohn Forte ASSERT(pd->pd_state != PORT_DEVICE_INVALID); 4203*fcf3ce44SJohn Forte if (pd->pd_type == PORT_DEVICE_OLD) { 4204*fcf3ce44SJohn Forte listptr->map_pd = pd; 4205*fcf3ce44SJohn Forte listptr->map_state = pd->pd_state = 4206*fcf3ce44SJohn Forte PORT_DEVICE_INVALID; 4207*fcf3ce44SJohn Forte /* 4208*fcf3ce44SJohn Forte * Remove this from the PWWN hash table. 4209*fcf3ce44SJohn Forte */ 4210*fcf3ce44SJohn Forte old_pd = pd; 4211*fcf3ce44SJohn Forte pd = old_pd->pd_wwn_hnext; 4212*fcf3ce44SJohn Forte 4213*fcf3ce44SJohn Forte if (last_pd == NULL) { 4214*fcf3ce44SJohn Forte ASSERT(old_pd == head->pwwn_head); 4215*fcf3ce44SJohn Forte 4216*fcf3ce44SJohn Forte head->pwwn_head = pd; 4217*fcf3ce44SJohn Forte } else { 4218*fcf3ce44SJohn Forte last_pd->pd_wwn_hnext = pd; 4219*fcf3ce44SJohn Forte } 4220*fcf3ce44SJohn Forte head->pwwn_count--; 4221*fcf3ce44SJohn Forte /* 4222*fcf3ce44SJohn Forte * Make sure we tie fp_dev_count to the size 4223*fcf3ce44SJohn Forte * of the pwwn_table 4224*fcf3ce44SJohn Forte */ 4225*fcf3ce44SJohn Forte port->fp_dev_count--; 4226*fcf3ce44SJohn Forte old_pd->pd_wwn_hnext = NULL; 4227*fcf3ce44SJohn Forte 4228*fcf3ce44SJohn Forte if (port->fp_topology == FC_TOP_PRIVATE_LOOP && 4229*fcf3ce44SJohn Forte port->fp_statec_busy && !orphan) { 4230*fcf3ce44SJohn Forte fctl_check_alpa_list(port, old_pd); 4231*fcf3ce44SJohn Forte } 4232*fcf3ce44SJohn Forte 4233*fcf3ce44SJohn Forte /* 4234*fcf3ce44SJohn Forte * Remove if the port device has stealthily 4235*fcf3ce44SJohn Forte * present in the D_ID hash table 4236*fcf3ce44SJohn Forte */ 4237*fcf3ce44SJohn Forte fctl_delist_did_table(port, old_pd); 4238*fcf3ce44SJohn Forte 4239*fcf3ce44SJohn Forte ASSERT(old_pd->pd_remote_nodep != NULL); 4240*fcf3ce44SJohn Forte 4241*fcf3ce44SJohn Forte initiator = (old_pd->pd_recepient == 4242*fcf3ce44SJohn Forte PD_PLOGI_INITIATOR) ? 1 : 0; 4243*fcf3ce44SJohn Forte 4244*fcf3ce44SJohn Forte mutex_exit(&old_pd->pd_mutex); 4245*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4246*fcf3ce44SJohn Forte 4247*fcf3ce44SJohn Forte if (orphan) { 4248*fcf3ce44SJohn Forte fctl_print_if_not_orphan(port, old_pd); 4249*fcf3ce44SJohn Forte 4250*fcf3ce44SJohn Forte (void) fctl_add_orphan(port, old_pd, 4251*fcf3ce44SJohn Forte KM_NOSLEEP); 4252*fcf3ce44SJohn Forte } 4253*fcf3ce44SJohn Forte 4254*fcf3ce44SJohn Forte if (FC_IS_TOP_SWITCH(topology) && initiator) { 4255*fcf3ce44SJohn Forte (void) fctl_add_orphan(port, old_pd, 4256*fcf3ce44SJohn Forte KM_NOSLEEP); 4257*fcf3ce44SJohn Forte } 4258*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4259*fcf3ce44SJohn Forte } else { 4260*fcf3ce44SJohn Forte listptr->map_pd = pd; 4261*fcf3ce44SJohn Forte pd->pd_type = PORT_DEVICE_NOCHANGE; 4262*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4263*fcf3ce44SJohn Forte last_pd = pd; 4264*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 4265*fcf3ce44SJohn Forte } 4266*fcf3ce44SJohn Forte listptr++; 4267*fcf3ce44SJohn Forte } 4268*fcf3ce44SJohn Forte } 4269*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4270*fcf3ce44SJohn Forte } 4271*fcf3ce44SJohn Forte 4272*fcf3ce44SJohn Forte 4273*fcf3ce44SJohn Forte job_request_t * 4274*fcf3ce44SJohn Forte fctl_alloc_job(int job_code, int job_flags, void (*comp) (opaque_t, uchar_t), 4275*fcf3ce44SJohn Forte opaque_t arg, int sleep) 4276*fcf3ce44SJohn Forte { 4277*fcf3ce44SJohn Forte job_request_t *job; 4278*fcf3ce44SJohn Forte 4279*fcf3ce44SJohn Forte job = (job_request_t *)kmem_cache_alloc(fctl_job_cache, sleep); 4280*fcf3ce44SJohn Forte if (job != NULL) { 4281*fcf3ce44SJohn Forte job->job_result = FC_SUCCESS; 4282*fcf3ce44SJohn Forte job->job_code = job_code; 4283*fcf3ce44SJohn Forte job->job_flags = job_flags; 4284*fcf3ce44SJohn Forte job->job_cb_arg = arg; 4285*fcf3ce44SJohn Forte job->job_comp = comp; 4286*fcf3ce44SJohn Forte job->job_private = NULL; 4287*fcf3ce44SJohn Forte job->job_ulp_pkts = NULL; 4288*fcf3ce44SJohn Forte job->job_ulp_listlen = 0; 4289*fcf3ce44SJohn Forte #ifndef __lock_lint 4290*fcf3ce44SJohn Forte job->job_counter = 0; 4291*fcf3ce44SJohn Forte job->job_next = NULL; 4292*fcf3ce44SJohn Forte #endif /* __lock_lint */ 4293*fcf3ce44SJohn Forte } 4294*fcf3ce44SJohn Forte 4295*fcf3ce44SJohn Forte return (job); 4296*fcf3ce44SJohn Forte } 4297*fcf3ce44SJohn Forte 4298*fcf3ce44SJohn Forte 4299*fcf3ce44SJohn Forte void 4300*fcf3ce44SJohn Forte fctl_dealloc_job(job_request_t *job) 4301*fcf3ce44SJohn Forte { 4302*fcf3ce44SJohn Forte kmem_cache_free(fctl_job_cache, (void *)job); 4303*fcf3ce44SJohn Forte } 4304*fcf3ce44SJohn Forte 4305*fcf3ce44SJohn Forte 4306*fcf3ce44SJohn Forte void 4307*fcf3ce44SJohn Forte fctl_enque_job(fc_local_port_t *port, job_request_t *job) 4308*fcf3ce44SJohn Forte { 4309*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 4310*fcf3ce44SJohn Forte 4311*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4312*fcf3ce44SJohn Forte 4313*fcf3ce44SJohn Forte if (port->fp_job_tail == NULL) { 4314*fcf3ce44SJohn Forte ASSERT(port->fp_job_head == NULL); 4315*fcf3ce44SJohn Forte port->fp_job_head = port->fp_job_tail = job; 4316*fcf3ce44SJohn Forte } else { 4317*fcf3ce44SJohn Forte port->fp_job_tail->job_next = job; 4318*fcf3ce44SJohn Forte port->fp_job_tail = job; 4319*fcf3ce44SJohn Forte } 4320*fcf3ce44SJohn Forte job->job_next = NULL; 4321*fcf3ce44SJohn Forte 4322*fcf3ce44SJohn Forte cv_signal(&port->fp_cv); 4323*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4324*fcf3ce44SJohn Forte } 4325*fcf3ce44SJohn Forte 4326*fcf3ce44SJohn Forte 4327*fcf3ce44SJohn Forte job_request_t * 4328*fcf3ce44SJohn Forte fctl_deque_job(fc_local_port_t *port) 4329*fcf3ce44SJohn Forte { 4330*fcf3ce44SJohn Forte job_request_t *job; 4331*fcf3ce44SJohn Forte 4332*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 4333*fcf3ce44SJohn Forte 4334*fcf3ce44SJohn Forte if (port->fp_job_head == NULL) { 4335*fcf3ce44SJohn Forte ASSERT(port->fp_job_tail == NULL); 4336*fcf3ce44SJohn Forte job = NULL; 4337*fcf3ce44SJohn Forte } else { 4338*fcf3ce44SJohn Forte job = port->fp_job_head; 4339*fcf3ce44SJohn Forte if (job->job_next == NULL) { 4340*fcf3ce44SJohn Forte ASSERT(job == port->fp_job_tail); 4341*fcf3ce44SJohn Forte port->fp_job_tail = NULL; 4342*fcf3ce44SJohn Forte } 4343*fcf3ce44SJohn Forte port->fp_job_head = job->job_next; 4344*fcf3ce44SJohn Forte } 4345*fcf3ce44SJohn Forte 4346*fcf3ce44SJohn Forte return (job); 4347*fcf3ce44SJohn Forte } 4348*fcf3ce44SJohn Forte 4349*fcf3ce44SJohn Forte 4350*fcf3ce44SJohn Forte void 4351*fcf3ce44SJohn Forte fctl_priority_enque_job(fc_local_port_t *port, job_request_t *job) 4352*fcf3ce44SJohn Forte { 4353*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 4354*fcf3ce44SJohn Forte 4355*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4356*fcf3ce44SJohn Forte if (port->fp_job_tail == NULL) { 4357*fcf3ce44SJohn Forte ASSERT(port->fp_job_head == NULL); 4358*fcf3ce44SJohn Forte port->fp_job_head = port->fp_job_tail = job; 4359*fcf3ce44SJohn Forte job->job_next = NULL; 4360*fcf3ce44SJohn Forte } else { 4361*fcf3ce44SJohn Forte job->job_next = port->fp_job_head; 4362*fcf3ce44SJohn Forte port->fp_job_head = job; 4363*fcf3ce44SJohn Forte } 4364*fcf3ce44SJohn Forte cv_signal(&port->fp_cv); 4365*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4366*fcf3ce44SJohn Forte } 4367*fcf3ce44SJohn Forte 4368*fcf3ce44SJohn Forte 4369*fcf3ce44SJohn Forte void 4370*fcf3ce44SJohn Forte fctl_jobwait(job_request_t *job) 4371*fcf3ce44SJohn Forte { 4372*fcf3ce44SJohn Forte ASSERT(!(job->job_flags & JOB_TYPE_FCTL_ASYNC)); 4373*fcf3ce44SJohn Forte sema_p(&job->job_fctl_sema); 4374*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&job->job_mutex)); 4375*fcf3ce44SJohn Forte } 4376*fcf3ce44SJohn Forte 4377*fcf3ce44SJohn Forte 4378*fcf3ce44SJohn Forte void 4379*fcf3ce44SJohn Forte fctl_jobdone(job_request_t *job) 4380*fcf3ce44SJohn Forte { 4381*fcf3ce44SJohn Forte if (job->job_flags & JOB_TYPE_FCTL_ASYNC) { 4382*fcf3ce44SJohn Forte if (job->job_comp) { 4383*fcf3ce44SJohn Forte job->job_comp(job->job_cb_arg, job->job_result); 4384*fcf3ce44SJohn Forte } 4385*fcf3ce44SJohn Forte fctl_dealloc_job(job); 4386*fcf3ce44SJohn Forte } else { 4387*fcf3ce44SJohn Forte sema_v(&job->job_fctl_sema); 4388*fcf3ce44SJohn Forte } 4389*fcf3ce44SJohn Forte } 4390*fcf3ce44SJohn Forte 4391*fcf3ce44SJohn Forte 4392*fcf3ce44SJohn Forte /* 4393*fcf3ce44SJohn Forte * Compare two WWNs. The NAA is omitted for comparison. 4394*fcf3ce44SJohn Forte * 4395*fcf3ce44SJohn Forte * Note particularly that the indentation used in this 4396*fcf3ce44SJohn Forte * function isn't according to Sun recommendations. It 4397*fcf3ce44SJohn Forte * is indented to make reading a bit easy. 4398*fcf3ce44SJohn Forte * 4399*fcf3ce44SJohn Forte * Return Values: 4400*fcf3ce44SJohn Forte * if src == dst return 0 4401*fcf3ce44SJohn Forte * if src > dst return 1 4402*fcf3ce44SJohn Forte * if src < dst return -1 4403*fcf3ce44SJohn Forte */ 4404*fcf3ce44SJohn Forte int 4405*fcf3ce44SJohn Forte fctl_wwn_cmp(la_wwn_t *src, la_wwn_t *dst) 4406*fcf3ce44SJohn Forte { 4407*fcf3ce44SJohn Forte la_wwn_t tmpsrc, tmpdst; 4408*fcf3ce44SJohn Forte 4409*fcf3ce44SJohn Forte /* 4410*fcf3ce44SJohn Forte * Fibre Channel protocol is big endian, so compare 4411*fcf3ce44SJohn Forte * as big endian values 4412*fcf3ce44SJohn Forte */ 4413*fcf3ce44SJohn Forte tmpsrc.i_wwn[0] = BE_32(src->i_wwn[0]); 4414*fcf3ce44SJohn Forte tmpsrc.i_wwn[1] = BE_32(src->i_wwn[1]); 4415*fcf3ce44SJohn Forte 4416*fcf3ce44SJohn Forte tmpdst.i_wwn[0] = BE_32(dst->i_wwn[0]); 4417*fcf3ce44SJohn Forte tmpdst.i_wwn[1] = BE_32(dst->i_wwn[1]); 4418*fcf3ce44SJohn Forte 4419*fcf3ce44SJohn Forte return ( 4420*fcf3ce44SJohn Forte (tmpsrc.w.nport_id == tmpdst.w.nport_id) ? 4421*fcf3ce44SJohn Forte ((tmpsrc.w.wwn_hi == tmpdst.w.wwn_hi) ? 4422*fcf3ce44SJohn Forte ((tmpsrc.w.wwn_lo == tmpdst.w.wwn_lo) ? 0 : 4423*fcf3ce44SJohn Forte (tmpsrc.w.wwn_lo > tmpdst.w.wwn_lo) ? 1 : -1) : 4424*fcf3ce44SJohn Forte (tmpsrc.w.wwn_hi > tmpdst.w.wwn_hi) ? 1 : -1) : 4425*fcf3ce44SJohn Forte (tmpsrc.w.nport_id > tmpdst.w.nport_id) ? 1 : -1); 4426*fcf3ce44SJohn Forte } 4427*fcf3ce44SJohn Forte 4428*fcf3ce44SJohn Forte 4429*fcf3ce44SJohn Forte /* 4430*fcf3ce44SJohn Forte * ASCII to Integer goodie with support for base 16, 10, 2 and 8 4431*fcf3ce44SJohn Forte */ 4432*fcf3ce44SJohn Forte int 4433*fcf3ce44SJohn Forte fctl_atoi(char *s, int base) 4434*fcf3ce44SJohn Forte { 4435*fcf3ce44SJohn Forte int val; 4436*fcf3ce44SJohn Forte int ch; 4437*fcf3ce44SJohn Forte 4438*fcf3ce44SJohn Forte for (val = 0; *s != '\0'; s++) { 4439*fcf3ce44SJohn Forte switch (base) { 4440*fcf3ce44SJohn Forte case 16: 4441*fcf3ce44SJohn Forte if (*s >= '0' && *s <= '9') { 4442*fcf3ce44SJohn Forte ch = *s - '0'; 4443*fcf3ce44SJohn Forte } else if (*s >= 'a' && *s <= 'f') { 4444*fcf3ce44SJohn Forte ch = *s - 'a' + 10; 4445*fcf3ce44SJohn Forte } else if (*s >= 'A' && *s <= 'F') { 4446*fcf3ce44SJohn Forte ch = *s - 'A' + 10; 4447*fcf3ce44SJohn Forte } else { 4448*fcf3ce44SJohn Forte return (-1); 4449*fcf3ce44SJohn Forte } 4450*fcf3ce44SJohn Forte break; 4451*fcf3ce44SJohn Forte 4452*fcf3ce44SJohn Forte case 10: 4453*fcf3ce44SJohn Forte if (*s < '0' || *s > '9') { 4454*fcf3ce44SJohn Forte return (-1); 4455*fcf3ce44SJohn Forte } 4456*fcf3ce44SJohn Forte ch = *s - '0'; 4457*fcf3ce44SJohn Forte break; 4458*fcf3ce44SJohn Forte 4459*fcf3ce44SJohn Forte case 2: 4460*fcf3ce44SJohn Forte if (*s < '0' || *s > '1') { 4461*fcf3ce44SJohn Forte return (-1); 4462*fcf3ce44SJohn Forte } 4463*fcf3ce44SJohn Forte ch = *s - '0'; 4464*fcf3ce44SJohn Forte break; 4465*fcf3ce44SJohn Forte 4466*fcf3ce44SJohn Forte case 8: 4467*fcf3ce44SJohn Forte if (*s < '0' || *s > '7') { 4468*fcf3ce44SJohn Forte return (-1); 4469*fcf3ce44SJohn Forte } 4470*fcf3ce44SJohn Forte ch = *s - '0'; 4471*fcf3ce44SJohn Forte break; 4472*fcf3ce44SJohn Forte 4473*fcf3ce44SJohn Forte default: 4474*fcf3ce44SJohn Forte return (-1); 4475*fcf3ce44SJohn Forte } 4476*fcf3ce44SJohn Forte val = (val * base) + ch; 4477*fcf3ce44SJohn Forte } 4478*fcf3ce44SJohn Forte return (val); 4479*fcf3ce44SJohn Forte } 4480*fcf3ce44SJohn Forte 4481*fcf3ce44SJohn Forte 4482*fcf3ce44SJohn Forte /* 4483*fcf3ce44SJohn Forte * Create the fc_remote_port_t struct for the given port_wwn and d_id. 4484*fcf3ce44SJohn Forte * 4485*fcf3ce44SJohn Forte * If the struct already exists (and is "valid"), then use it. Before using 4486*fcf3ce44SJohn Forte * it, the code below also checks: (a) if the d_id has changed, and (b) if 4487*fcf3ce44SJohn Forte * the device is maked as PORT_DEVICE_OLD. 4488*fcf3ce44SJohn Forte * 4489*fcf3ce44SJohn Forte * If no fc_remote_node_t struct exists for the given node_wwn, then that 4490*fcf3ce44SJohn Forte * struct is also created (and linked with the fc_remote_port_t). 4491*fcf3ce44SJohn Forte * 4492*fcf3ce44SJohn Forte * The given fc_local_port_t struct is updated with the info on the new 4493*fcf3ce44SJohn Forte * struct(s). The d_id and pwwn hash tables in the port_wwn are updated. 4494*fcf3ce44SJohn Forte * The global node_hash_table[] is updated (if necessary). 4495*fcf3ce44SJohn Forte */ 4496*fcf3ce44SJohn Forte fc_remote_port_t * 4497*fcf3ce44SJohn Forte fctl_create_remote_port(fc_local_port_t *port, la_wwn_t *node_wwn, 4498*fcf3ce44SJohn Forte la_wwn_t *port_wwn, uint32_t d_id, uchar_t recepient, int sleep) 4499*fcf3ce44SJohn Forte { 4500*fcf3ce44SJohn Forte int invalid = 0; 4501*fcf3ce44SJohn Forte fc_remote_node_t *rnodep; 4502*fcf3ce44SJohn Forte fc_remote_port_t *pd; 4503*fcf3ce44SJohn Forte 4504*fcf3ce44SJohn Forte rnodep = fctl_get_remote_node_by_nwwn(node_wwn); 4505*fcf3ce44SJohn Forte if (rnodep) { 4506*fcf3ce44SJohn Forte /* 4507*fcf3ce44SJohn Forte * We found an fc_remote_node_t for the remote node -- see if 4508*fcf3ce44SJohn Forte * anyone has marked it as going away or gone. 4509*fcf3ce44SJohn Forte */ 4510*fcf3ce44SJohn Forte mutex_enter(&rnodep->fd_mutex); 4511*fcf3ce44SJohn Forte invalid = (rnodep->fd_flags == FC_REMOTE_NODE_INVALID) ? 1 : 0; 4512*fcf3ce44SJohn Forte mutex_exit(&rnodep->fd_mutex); 4513*fcf3ce44SJohn Forte } 4514*fcf3ce44SJohn Forte if (rnodep == NULL || invalid) { 4515*fcf3ce44SJohn Forte /* 4516*fcf3ce44SJohn Forte * No valid remote node struct found -- create it. 4517*fcf3ce44SJohn Forte * Note: this is the only place that this func is called. 4518*fcf3ce44SJohn Forte */ 4519*fcf3ce44SJohn Forte rnodep = fctl_create_remote_node(node_wwn, sleep); 4520*fcf3ce44SJohn Forte if (rnodep == NULL) { 4521*fcf3ce44SJohn Forte return (NULL); 4522*fcf3ce44SJohn Forte } 4523*fcf3ce44SJohn Forte } 4524*fcf3ce44SJohn Forte 4525*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4526*fcf3ce44SJohn Forte 4527*fcf3ce44SJohn Forte /* 4528*fcf3ce44SJohn Forte * See if there already is an fc_remote_port_t struct in existence 4529*fcf3ce44SJohn Forte * on the specified fc_local_port_t for the given pwwn. If so, then 4530*fcf3ce44SJohn Forte * grab a reference to it. The 'held' here just means that fp_mutex 4531*fcf3ce44SJohn Forte * is held by the caller -- no reference counts are updated. 4532*fcf3ce44SJohn Forte */ 4533*fcf3ce44SJohn Forte pd = fctl_get_remote_port_by_pwwn_mutex_held(port, port_wwn); 4534*fcf3ce44SJohn Forte if (pd) { 4535*fcf3ce44SJohn Forte /* 4536*fcf3ce44SJohn Forte * An fc_remote_port_t struct was found -- see if anyone has 4537*fcf3ce44SJohn Forte * marked it as "invalid", which means that it is in the 4538*fcf3ce44SJohn Forte * process of going away & we don't want to use it. 4539*fcf3ce44SJohn Forte */ 4540*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4541*fcf3ce44SJohn Forte invalid = (pd->pd_state == PORT_DEVICE_INVALID) ? 1 : 0; 4542*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4543*fcf3ce44SJohn Forte } 4544*fcf3ce44SJohn Forte 4545*fcf3ce44SJohn Forte if (pd == NULL || invalid) { 4546*fcf3ce44SJohn Forte /* 4547*fcf3ce44SJohn Forte * No fc_remote_port_t was found (or the existing one is 4548*fcf3ce44SJohn Forte * marked as "invalid".) Allocate a new one and use that. 4549*fcf3ce44SJohn Forte * This call will also update the d_id and pwwn hash tables 4550*fcf3ce44SJohn Forte * in the given fc_local_port_t struct with the newly allocated 4551*fcf3ce44SJohn Forte * fc_remote_port_t. 4552*fcf3ce44SJohn Forte */ 4553*fcf3ce44SJohn Forte if ((pd = fctl_alloc_remote_port(port, port_wwn, d_id, 4554*fcf3ce44SJohn Forte recepient, sleep)) == NULL) { 4555*fcf3ce44SJohn Forte /* Just give up if the allocation fails. */ 4556*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4557*fcf3ce44SJohn Forte fctl_destroy_remote_node(rnodep); 4558*fcf3ce44SJohn Forte return (pd); 4559*fcf3ce44SJohn Forte } 4560*fcf3ce44SJohn Forte 4561*fcf3ce44SJohn Forte /* 4562*fcf3ce44SJohn Forte * Add the new fc_remote_port_t struct to the d_id and pwwn 4563*fcf3ce44SJohn Forte * hash tables on the associated fc_local_port_t struct. 4564*fcf3ce44SJohn Forte */ 4565*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4566*fcf3ce44SJohn Forte pd->pd_remote_nodep = rnodep; 4567*fcf3ce44SJohn Forte fctl_enlist_did_table(port, pd); 4568*fcf3ce44SJohn Forte fctl_enlist_pwwn_table(port, pd); 4569*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4570*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4571*fcf3ce44SJohn Forte 4572*fcf3ce44SJohn Forte /* 4573*fcf3ce44SJohn Forte * Retrieve a pointer to the fc_remote_node_t (i.e., remote 4574*fcf3ce44SJohn Forte * node) specified by the given node_wwn. This looks in the 4575*fcf3ce44SJohn Forte * global fctl_nwwn_hash_table[]. The fd_numports reference 4576*fcf3ce44SJohn Forte * count in the fc_remote_node_t struct is incremented. 4577*fcf3ce44SJohn Forte */ 4578*fcf3ce44SJohn Forte rnodep = fctl_lock_remote_node_by_nwwn(node_wwn); 4579*fcf3ce44SJohn Forte 4580*fcf3ce44SJohn Forte } else { 4581*fcf3ce44SJohn Forte /* 4582*fcf3ce44SJohn Forte * An existing and valid fc_remote_port_t struct already 4583*fcf3ce44SJohn Forte * exists on the fc_local_port_t for the given pwwn. 4584*fcf3ce44SJohn Forte */ 4585*fcf3ce44SJohn Forte 4586*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4587*fcf3ce44SJohn Forte ASSERT(pd->pd_remote_nodep != NULL); 4588*fcf3ce44SJohn Forte 4589*fcf3ce44SJohn Forte if (pd->pd_port_id.port_id != d_id) { 4590*fcf3ce44SJohn Forte /* 4591*fcf3ce44SJohn Forte * A very unlikely occurance in a well 4592*fcf3ce44SJohn Forte * behaved environment. 4593*fcf3ce44SJohn Forte */ 4594*fcf3ce44SJohn Forte 4595*fcf3ce44SJohn Forte /* 4596*fcf3ce44SJohn Forte * The existing fc_remote_port_t has a different 4597*fcf3ce44SJohn Forte * d_id than what we were given. This code will 4598*fcf3ce44SJohn Forte * update the existing one with the one that was 4599*fcf3ce44SJohn Forte * just given. 4600*fcf3ce44SJohn Forte */ 4601*fcf3ce44SJohn Forte char string[(FCTL_WWN_SIZE(port_wwn) << 1) + 1]; 4602*fcf3ce44SJohn Forte uint32_t old_id; 4603*fcf3ce44SJohn Forte 4604*fcf3ce44SJohn Forte fc_wwn_to_str(port_wwn, string); 4605*fcf3ce44SJohn Forte 4606*fcf3ce44SJohn Forte old_id = pd->pd_port_id.port_id; 4607*fcf3ce44SJohn Forte 4608*fcf3ce44SJohn Forte fctl_delist_did_table(port, pd); 4609*fcf3ce44SJohn Forte 4610*fcf3ce44SJohn Forte cmn_err(CE_NOTE, "!fctl(%d): D_ID of a device" 4611*fcf3ce44SJohn Forte " with PWWN %s changed. New D_ID = %x," 4612*fcf3ce44SJohn Forte " OLD D_ID = %x", port->fp_instance, string, 4613*fcf3ce44SJohn Forte d_id, old_id); 4614*fcf3ce44SJohn Forte 4615*fcf3ce44SJohn Forte pd->pd_port_id.port_id = d_id; 4616*fcf3ce44SJohn Forte 4617*fcf3ce44SJohn Forte /* 4618*fcf3ce44SJohn Forte * Looks like we have to presume here that the 4619*fcf3ce44SJohn Forte * remote port could be something entirely different 4620*fcf3ce44SJohn Forte * from what was previously existing & valid at this 4621*fcf3ce44SJohn Forte * pwwn. 4622*fcf3ce44SJohn Forte */ 4623*fcf3ce44SJohn Forte pd->pd_type = PORT_DEVICE_CHANGED; 4624*fcf3ce44SJohn Forte 4625*fcf3ce44SJohn Forte /* Record (update) the new d_id for the remote port */ 4626*fcf3ce44SJohn Forte fctl_enlist_did_table(port, pd); 4627*fcf3ce44SJohn Forte 4628*fcf3ce44SJohn Forte } else if (pd->pd_type == PORT_DEVICE_OLD) { 4629*fcf3ce44SJohn Forte /* 4630*fcf3ce44SJohn Forte * OK at least the old & new d_id's match. So for 4631*fcf3ce44SJohn Forte * PORT_DEVICE_OLD, this assumes that the remote 4632*fcf3ce44SJohn Forte * port had disappeared but now has come back. 4633*fcf3ce44SJohn Forte * Update the pd_type and pd_state to put the 4634*fcf3ce44SJohn Forte * remote port back into service. 4635*fcf3ce44SJohn Forte */ 4636*fcf3ce44SJohn Forte pd->pd_type = PORT_DEVICE_NOCHANGE; 4637*fcf3ce44SJohn Forte pd->pd_state = PORT_DEVICE_VALID; 4638*fcf3ce44SJohn Forte 4639*fcf3ce44SJohn Forte fctl_enlist_did_table(port, pd); 4640*fcf3ce44SJohn Forte 4641*fcf3ce44SJohn Forte } else { 4642*fcf3ce44SJohn Forte /* 4643*fcf3ce44SJohn Forte * OK the old & new d_id's match, and the remote 4644*fcf3ce44SJohn Forte * port struct is not marked as PORT_DEVICE_OLD, so 4645*fcf3ce44SJohn Forte * presume that it's still the same device and is 4646*fcf3ce44SJohn Forte * still in good shape. Also this presumes that we 4647*fcf3ce44SJohn Forte * do not need to update d_id or pwwn hash tables. 4648*fcf3ce44SJohn Forte */ 4649*fcf3ce44SJohn Forte /* sanitize device values */ 4650*fcf3ce44SJohn Forte pd->pd_type = PORT_DEVICE_NOCHANGE; 4651*fcf3ce44SJohn Forte pd->pd_state = PORT_DEVICE_VALID; 4652*fcf3ce44SJohn Forte } 4653*fcf3ce44SJohn Forte 4654*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4655*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4656*fcf3ce44SJohn Forte 4657*fcf3ce44SJohn Forte if (rnodep != pd->pd_remote_nodep) { 4658*fcf3ce44SJohn Forte if ((rnodep != NULL) && 4659*fcf3ce44SJohn Forte (fctl_wwn_cmp(&pd->pd_remote_nodep->fd_node_name, 4660*fcf3ce44SJohn Forte node_wwn) != 0)) { 4661*fcf3ce44SJohn Forte /* 4662*fcf3ce44SJohn Forte * Rut-roh, there is an fc_remote_node_t remote 4663*fcf3ce44SJohn Forte * node struct for the given node_wwn, but the 4664*fcf3ce44SJohn Forte * fc_remote_port_t remote port struct doesn't 4665*fcf3ce44SJohn Forte * know about it. This just prints a warning 4666*fcf3ce44SJohn Forte * message & fails the fc_remote_port_t 4667*fcf3ce44SJohn Forte * allocation (possible leak here?). 4668*fcf3ce44SJohn Forte */ 4669*fcf3ce44SJohn Forte char ww1_name[17]; 4670*fcf3ce44SJohn Forte char ww2_name[17]; 4671*fcf3ce44SJohn Forte 4672*fcf3ce44SJohn Forte fc_wwn_to_str( 4673*fcf3ce44SJohn Forte &pd->pd_remote_nodep->fd_node_name, 4674*fcf3ce44SJohn Forte ww1_name); 4675*fcf3ce44SJohn Forte fc_wwn_to_str(node_wwn, ww2_name); 4676*fcf3ce44SJohn Forte 4677*fcf3ce44SJohn Forte cmn_err(CE_WARN, "fctl(%d) NWWN Mismatch: " 4678*fcf3ce44SJohn Forte "Expected %s Got %s", port->fp_instance, 4679*fcf3ce44SJohn Forte ww1_name, ww2_name); 4680*fcf3ce44SJohn Forte } 4681*fcf3ce44SJohn Forte 4682*fcf3ce44SJohn Forte return (NULL); 4683*fcf3ce44SJohn Forte } 4684*fcf3ce44SJohn Forte } 4685*fcf3ce44SJohn Forte 4686*fcf3ce44SJohn Forte /* 4687*fcf3ce44SJohn Forte * Add the fc_remote_port_t onto the linked list of remote port 4688*fcf3ce44SJohn Forte * devices associated with the given fc_remote_node_t (remote node). 4689*fcf3ce44SJohn Forte */ 4690*fcf3ce44SJohn Forte fctl_link_remote_port_to_remote_node(rnodep, pd); 4691*fcf3ce44SJohn Forte 4692*fcf3ce44SJohn Forte return (pd); 4693*fcf3ce44SJohn Forte } 4694*fcf3ce44SJohn Forte 4695*fcf3ce44SJohn Forte 4696*fcf3ce44SJohn Forte /* 4697*fcf3ce44SJohn Forte * Disassociate the given fc_local_port_t and fc_remote_port_t structs. Removes 4698*fcf3ce44SJohn Forte * the fc_remote_port_t from the associated fc_remote_node_t. Also removes any 4699*fcf3ce44SJohn Forte * references to the fc_remote_port_t from the d_id and pwwn tables in the 4700*fcf3ce44SJohn Forte * given fc_local_port_t. Deallocates the given fc_remote_port_t. 4701*fcf3ce44SJohn Forte * 4702*fcf3ce44SJohn Forte * Returns a count of the number of remaining fc_remote_port_t structs 4703*fcf3ce44SJohn Forte * associated with the fc_remote_node_t struct. 4704*fcf3ce44SJohn Forte * 4705*fcf3ce44SJohn Forte * If pd_ref_count in the given fc_remote_port_t is nonzero, then this 4706*fcf3ce44SJohn Forte * function just sets the pd->pd_aux_flags |= PD_NEEDS_REMOVAL and the 4707*fcf3ce44SJohn Forte * pd->pd_type = PORT_DEVICE_OLD and lets some other function(s) worry about 4708*fcf3ce44SJohn Forte * the cleanup. The function then also returns '1' 4709*fcf3ce44SJohn Forte * instead of the actual number of remaining fc_remote_port_t structs 4710*fcf3ce44SJohn Forte * 4711*fcf3ce44SJohn Forte * If there are no more remote ports on the remote node, return 0. 4712*fcf3ce44SJohn Forte * Otherwise, return non-zero. 4713*fcf3ce44SJohn Forte */ 4714*fcf3ce44SJohn Forte int 4715*fcf3ce44SJohn Forte fctl_destroy_remote_port(fc_local_port_t *port, fc_remote_port_t *pd) 4716*fcf3ce44SJohn Forte { 4717*fcf3ce44SJohn Forte fc_remote_node_t *rnodep; 4718*fcf3ce44SJohn Forte int rcount = 0; 4719*fcf3ce44SJohn Forte 4720*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4721*fcf3ce44SJohn Forte 4722*fcf3ce44SJohn Forte /* 4723*fcf3ce44SJohn Forte * If pd_ref_count > 0, we can't pull the rug out from any 4724*fcf3ce44SJohn Forte * current users of this fc_remote_port_t. We'll mark it as old 4725*fcf3ce44SJohn Forte * and in need of removal. The same goes for any fc_remote_port_t 4726*fcf3ce44SJohn Forte * that has a reference handle(s) in a ULP(s) but for which the ULP(s) 4727*fcf3ce44SJohn Forte * have not yet been notified that the handle is no longer valid 4728*fcf3ce44SJohn Forte * (i.e., PD_GIVEN_TO_ULPS is set). 4729*fcf3ce44SJohn Forte */ 4730*fcf3ce44SJohn Forte if ((pd->pd_ref_count > 0) || 4731*fcf3ce44SJohn Forte (pd->pd_aux_flags & PD_GIVEN_TO_ULPS)) { 4732*fcf3ce44SJohn Forte pd->pd_aux_flags |= PD_NEEDS_REMOVAL; 4733*fcf3ce44SJohn Forte pd->pd_type = PORT_DEVICE_OLD; 4734*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4735*fcf3ce44SJohn Forte return (1); 4736*fcf3ce44SJohn Forte } 4737*fcf3ce44SJohn Forte 4738*fcf3ce44SJohn Forte pd->pd_type = PORT_DEVICE_OLD; 4739*fcf3ce44SJohn Forte 4740*fcf3ce44SJohn Forte rnodep = pd->pd_remote_nodep; 4741*fcf3ce44SJohn Forte 4742*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4743*fcf3ce44SJohn Forte 4744*fcf3ce44SJohn Forte if (rnodep != NULL) { 4745*fcf3ce44SJohn Forte /* 4746*fcf3ce44SJohn Forte * Remove the fc_remote_port_t from the linked list of remote 4747*fcf3ce44SJohn Forte * ports for the given fc_remote_node_t. This is only called 4748*fcf3ce44SJohn Forte * here and in fctl_destroy_all_remote_ports(). 4749*fcf3ce44SJohn Forte */ 4750*fcf3ce44SJohn Forte rcount = fctl_unlink_remote_port_from_remote_node(rnodep, pd); 4751*fcf3ce44SJohn Forte } 4752*fcf3ce44SJohn Forte 4753*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4754*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4755*fcf3ce44SJohn Forte 4756*fcf3ce44SJohn Forte fctl_delist_did_table(port, pd); 4757*fcf3ce44SJohn Forte fctl_delist_pwwn_table(port, pd); 4758*fcf3ce44SJohn Forte 4759*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4760*fcf3ce44SJohn Forte 4761*fcf3ce44SJohn Forte /* 4762*fcf3ce44SJohn Forte * Deconstruct & free the fc_remote_port_t. This is only called 4763*fcf3ce44SJohn Forte * here and in fctl_destroy_all_remote_ports(). 4764*fcf3ce44SJohn Forte */ 4765*fcf3ce44SJohn Forte fctl_dealloc_remote_port(pd); 4766*fcf3ce44SJohn Forte 4767*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4768*fcf3ce44SJohn Forte 4769*fcf3ce44SJohn Forte return (rcount); 4770*fcf3ce44SJohn Forte } 4771*fcf3ce44SJohn Forte 4772*fcf3ce44SJohn Forte 4773*fcf3ce44SJohn Forte /* 4774*fcf3ce44SJohn Forte * This goes thru the d_id table on the given fc_local_port_t. 4775*fcf3ce44SJohn Forte * For each fc_remote_port_t found, this will: 4776*fcf3ce44SJohn Forte * 4777*fcf3ce44SJohn Forte * - Remove the fc_remote_port_t from the linked list of remote ports for 4778*fcf3ce44SJohn Forte * the associated fc_remote_node_t. If the linked list goes empty, then this 4779*fcf3ce44SJohn Forte * tries to deconstruct & free the fc_remote_node_t (that also removes the 4780*fcf3ce44SJohn Forte * fc_remote_node_t from the global fctl_nwwn_hash_table[]). 4781*fcf3ce44SJohn Forte * 4782*fcf3ce44SJohn Forte * - Remove the fc_remote_port_t from the pwwn list on the given 4783*fcf3ce44SJohn Forte * fc_local_port_t. 4784*fcf3ce44SJohn Forte * 4785*fcf3ce44SJohn Forte * - Deconstruct and free the fc_remote_port_t. 4786*fcf3ce44SJohn Forte * 4787*fcf3ce44SJohn Forte * - Removes the link to the fc_remote_port_t in the d_id table. Note, this 4788*fcf3ce44SJohn Forte * does not appear to correctle decrement the d_id_count tho. 4789*fcf3ce44SJohn Forte */ 4790*fcf3ce44SJohn Forte void 4791*fcf3ce44SJohn Forte fctl_destroy_all_remote_ports(fc_local_port_t *port) 4792*fcf3ce44SJohn Forte { 4793*fcf3ce44SJohn Forte int index; 4794*fcf3ce44SJohn Forte fc_remote_port_t *pd; 4795*fcf3ce44SJohn Forte fc_remote_node_t *rnodep; 4796*fcf3ce44SJohn Forte struct d_id_hash *head; 4797*fcf3ce44SJohn Forte 4798*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4799*fcf3ce44SJohn Forte 4800*fcf3ce44SJohn Forte for (index = 0; index < did_table_size; index++) { 4801*fcf3ce44SJohn Forte 4802*fcf3ce44SJohn Forte head = &port->fp_did_table[index]; 4803*fcf3ce44SJohn Forte 4804*fcf3ce44SJohn Forte while (head->d_id_head != NULL) { 4805*fcf3ce44SJohn Forte pd = head->d_id_head; 4806*fcf3ce44SJohn Forte 4807*fcf3ce44SJohn Forte /* 4808*fcf3ce44SJohn Forte * See if this remote port (fc_remote_port_t) has a 4809*fcf3ce44SJohn Forte * reference to a remote node (fc_remote_node_t) in its 4810*fcf3ce44SJohn Forte * pd->pd_remote_nodep pointer. 4811*fcf3ce44SJohn Forte */ 4812*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4813*fcf3ce44SJohn Forte rnodep = pd->pd_remote_nodep; 4814*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4815*fcf3ce44SJohn Forte 4816*fcf3ce44SJohn Forte if (rnodep != NULL) { 4817*fcf3ce44SJohn Forte /* 4818*fcf3ce44SJohn Forte * An fc_remote_node_t reference exists. Remove 4819*fcf3ce44SJohn Forte * the fc_remote_port_t from the linked list of 4820*fcf3ce44SJohn Forte * remote ports for fc_remote_node_t. 4821*fcf3ce44SJohn Forte */ 4822*fcf3ce44SJohn Forte if (fctl_unlink_remote_port_from_remote_node( 4823*fcf3ce44SJohn Forte rnodep, pd) == 0) { 4824*fcf3ce44SJohn Forte /* 4825*fcf3ce44SJohn Forte * The fd_numports reference count 4826*fcf3ce44SJohn Forte * in the fc_remote_node_t has come 4827*fcf3ce44SJohn Forte * back as zero, so we can free the 4828*fcf3ce44SJohn Forte * fc_remote_node_t. This also means 4829*fcf3ce44SJohn Forte * that the fc_remote_node_t was 4830*fcf3ce44SJohn Forte * removed from the 4831*fcf3ce44SJohn Forte * fctl_nwwn_hash_table[]. 4832*fcf3ce44SJohn Forte * 4833*fcf3ce44SJohn Forte * This will silently skip the 4834*fcf3ce44SJohn Forte * kmem_free() if either the 4835*fcf3ce44SJohn Forte * fd_numports is nonzero or 4836*fcf3ce44SJohn Forte * the fd_port is not NULL in 4837*fcf3ce44SJohn Forte * the fc_remote_node_t. 4838*fcf3ce44SJohn Forte */ 4839*fcf3ce44SJohn Forte fctl_destroy_remote_node(rnodep); 4840*fcf3ce44SJohn Forte } 4841*fcf3ce44SJohn Forte } 4842*fcf3ce44SJohn Forte 4843*fcf3ce44SJohn Forte /* 4844*fcf3ce44SJohn Forte * Clean up the entry in the fc_local_port_t's pwwn 4845*fcf3ce44SJohn Forte * table for the given fc_remote_port_t (i.e., the pd). 4846*fcf3ce44SJohn Forte */ 4847*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 4848*fcf3ce44SJohn Forte fctl_delist_pwwn_table(port, pd); 4849*fcf3ce44SJohn Forte pd->pd_aux_flags &= ~PD_IN_DID_QUEUE; 4850*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 4851*fcf3ce44SJohn Forte 4852*fcf3ce44SJohn Forte /* 4853*fcf3ce44SJohn Forte * Remove the current entry from the d_id list. 4854*fcf3ce44SJohn Forte */ 4855*fcf3ce44SJohn Forte head->d_id_head = pd->pd_did_hnext; 4856*fcf3ce44SJohn Forte 4857*fcf3ce44SJohn Forte /* 4858*fcf3ce44SJohn Forte * Deconstruct & free the fc_remote_port_t (pd) 4859*fcf3ce44SJohn Forte * Note: this is only called here and in 4860*fcf3ce44SJohn Forte * fctl_destroy_remote_port_t(). 4861*fcf3ce44SJohn Forte */ 4862*fcf3ce44SJohn Forte fctl_dealloc_remote_port(pd); 4863*fcf3ce44SJohn Forte } 4864*fcf3ce44SJohn Forte } 4865*fcf3ce44SJohn Forte 4866*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4867*fcf3ce44SJohn Forte } 4868*fcf3ce44SJohn Forte 4869*fcf3ce44SJohn Forte 4870*fcf3ce44SJohn Forte int 4871*fcf3ce44SJohn Forte fctl_is_wwn_zero(la_wwn_t *wwn) 4872*fcf3ce44SJohn Forte { 4873*fcf3ce44SJohn Forte int count; 4874*fcf3ce44SJohn Forte 4875*fcf3ce44SJohn Forte for (count = 0; count < sizeof (la_wwn_t); count++) { 4876*fcf3ce44SJohn Forte if (wwn->raw_wwn[count] != 0) { 4877*fcf3ce44SJohn Forte return (FC_FAILURE); 4878*fcf3ce44SJohn Forte } 4879*fcf3ce44SJohn Forte } 4880*fcf3ce44SJohn Forte 4881*fcf3ce44SJohn Forte return (FC_SUCCESS); 4882*fcf3ce44SJohn Forte } 4883*fcf3ce44SJohn Forte 4884*fcf3ce44SJohn Forte 4885*fcf3ce44SJohn Forte void 4886*fcf3ce44SJohn Forte fctl_ulp_unsol_cb(fc_local_port_t *port, fc_unsol_buf_t *buf, uchar_t type) 4887*fcf3ce44SJohn Forte { 4888*fcf3ce44SJohn Forte int data_cb; 4889*fcf3ce44SJohn Forte int check_type; 4890*fcf3ce44SJohn Forte int rval; 4891*fcf3ce44SJohn Forte uint32_t claimed; 4892*fcf3ce44SJohn Forte fc_ulp_module_t *mod; 4893*fcf3ce44SJohn Forte fc_ulp_ports_t *ulp_port; 4894*fcf3ce44SJohn Forte 4895*fcf3ce44SJohn Forte claimed = 0; 4896*fcf3ce44SJohn Forte check_type = 1; 4897*fcf3ce44SJohn Forte 4898*fcf3ce44SJohn Forte switch ((buf->ub_frame.r_ctl) & R_CTL_ROUTING) { 4899*fcf3ce44SJohn Forte case R_CTL_DEVICE_DATA: 4900*fcf3ce44SJohn Forte data_cb = 1; 4901*fcf3ce44SJohn Forte break; 4902*fcf3ce44SJohn Forte 4903*fcf3ce44SJohn Forte case R_CTL_EXTENDED_SVC: 4904*fcf3ce44SJohn Forte check_type = 0; 4905*fcf3ce44SJohn Forte /* FALLTHROUGH */ 4906*fcf3ce44SJohn Forte 4907*fcf3ce44SJohn Forte case R_CTL_FC4_SVC: 4908*fcf3ce44SJohn Forte data_cb = 0; 4909*fcf3ce44SJohn Forte break; 4910*fcf3ce44SJohn Forte 4911*fcf3ce44SJohn Forte default: 4912*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4913*fcf3ce44SJohn Forte ASSERT(port->fp_active_ubs > 0); 4914*fcf3ce44SJohn Forte if (--(port->fp_active_ubs) == 0) { 4915*fcf3ce44SJohn Forte port->fp_soft_state &= ~FP_SOFT_IN_UNSOL_CB; 4916*fcf3ce44SJohn Forte } 4917*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4918*fcf3ce44SJohn Forte port->fp_fca_tran->fca_ub_release(port->fp_fca_handle, 4919*fcf3ce44SJohn Forte 1, &buf->ub_token); 4920*fcf3ce44SJohn Forte return; 4921*fcf3ce44SJohn Forte } 4922*fcf3ce44SJohn Forte 4923*fcf3ce44SJohn Forte rw_enter(&fctl_ulp_lock, RW_READER); 4924*fcf3ce44SJohn Forte for (mod = fctl_ulp_modules; mod; mod = mod->mod_next) { 4925*fcf3ce44SJohn Forte if (check_type && mod->mod_info->ulp_type != type) { 4926*fcf3ce44SJohn Forte continue; 4927*fcf3ce44SJohn Forte } 4928*fcf3ce44SJohn Forte 4929*fcf3ce44SJohn Forte rw_enter(&fctl_mod_ports_lock, RW_READER); 4930*fcf3ce44SJohn Forte ulp_port = fctl_get_ulp_port(mod, port); 4931*fcf3ce44SJohn Forte rw_exit(&fctl_mod_ports_lock); 4932*fcf3ce44SJohn Forte 4933*fcf3ce44SJohn Forte if (ulp_port == NULL) { 4934*fcf3ce44SJohn Forte continue; 4935*fcf3ce44SJohn Forte } 4936*fcf3ce44SJohn Forte 4937*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 4938*fcf3ce44SJohn Forte if (FCTL_DISALLOW_CALLBACKS(ulp_port->port_dstate)) { 4939*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 4940*fcf3ce44SJohn Forte continue; 4941*fcf3ce44SJohn Forte } 4942*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 4943*fcf3ce44SJohn Forte 4944*fcf3ce44SJohn Forte if (data_cb == 1) { 4945*fcf3ce44SJohn Forte rval = mod->mod_info->ulp_data_callback( 4946*fcf3ce44SJohn Forte mod->mod_info->ulp_handle, 4947*fcf3ce44SJohn Forte (opaque_t)port, buf, claimed); 4948*fcf3ce44SJohn Forte } else { 4949*fcf3ce44SJohn Forte rval = mod->mod_info->ulp_els_callback( 4950*fcf3ce44SJohn Forte mod->mod_info->ulp_handle, 4951*fcf3ce44SJohn Forte (opaque_t)port, buf, claimed); 4952*fcf3ce44SJohn Forte } 4953*fcf3ce44SJohn Forte 4954*fcf3ce44SJohn Forte if (rval == FC_SUCCESS && claimed == 0) { 4955*fcf3ce44SJohn Forte claimed = 1; 4956*fcf3ce44SJohn Forte } 4957*fcf3ce44SJohn Forte } 4958*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 4959*fcf3ce44SJohn Forte 4960*fcf3ce44SJohn Forte if (claimed == 0) { 4961*fcf3ce44SJohn Forte /* 4962*fcf3ce44SJohn Forte * We should actually RJT since nobody claimed it. 4963*fcf3ce44SJohn Forte */ 4964*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4965*fcf3ce44SJohn Forte ASSERT(port->fp_active_ubs > 0); 4966*fcf3ce44SJohn Forte if (--(port->fp_active_ubs) == 0) { 4967*fcf3ce44SJohn Forte port->fp_soft_state &= ~FP_SOFT_IN_UNSOL_CB; 4968*fcf3ce44SJohn Forte } 4969*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4970*fcf3ce44SJohn Forte port->fp_fca_tran->fca_ub_release(port->fp_fca_handle, 4971*fcf3ce44SJohn Forte 1, &buf->ub_token); 4972*fcf3ce44SJohn Forte 4973*fcf3ce44SJohn Forte } else { 4974*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 4975*fcf3ce44SJohn Forte if (--port->fp_active_ubs == 0) { 4976*fcf3ce44SJohn Forte port->fp_soft_state &= ~FP_SOFT_IN_UNSOL_CB; 4977*fcf3ce44SJohn Forte } 4978*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 4979*fcf3ce44SJohn Forte } 4980*fcf3ce44SJohn Forte } 4981*fcf3ce44SJohn Forte 4982*fcf3ce44SJohn Forte 4983*fcf3ce44SJohn Forte /* 4984*fcf3ce44SJohn Forte * Both fd_mutex and pd_mutex are held (in that order) coming in to this func 4985*fcf3ce44SJohn Forte * 4986*fcf3ce44SJohn Forte * With all these mutexes held, we should make sure this function does not eat 4987*fcf3ce44SJohn Forte * up much time. 4988*fcf3ce44SJohn Forte */ 4989*fcf3ce44SJohn Forte void 4990*fcf3ce44SJohn Forte fctl_copy_portmap_held(fc_portmap_t *map, fc_remote_port_t *pd) 4991*fcf3ce44SJohn Forte { 4992*fcf3ce44SJohn Forte fc_remote_node_t *node; 4993*fcf3ce44SJohn Forte 4994*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&pd->pd_mutex)); 4995*fcf3ce44SJohn Forte 4996*fcf3ce44SJohn Forte map->map_pwwn = pd->pd_port_name; 4997*fcf3ce44SJohn Forte map->map_did = pd->pd_port_id; 4998*fcf3ce44SJohn Forte map->map_hard_addr = pd->pd_hard_addr; 4999*fcf3ce44SJohn Forte map->map_state = pd->pd_state; 5000*fcf3ce44SJohn Forte map->map_type = pd->pd_type; 5001*fcf3ce44SJohn Forte map->map_flags = 0; 5002*fcf3ce44SJohn Forte 5003*fcf3ce44SJohn Forte ASSERT(map->map_type <= PORT_DEVICE_DELETE); 5004*fcf3ce44SJohn Forte 5005*fcf3ce44SJohn Forte bcopy(pd->pd_fc4types, map->map_fc4_types, sizeof (pd->pd_fc4types)); 5006*fcf3ce44SJohn Forte 5007*fcf3ce44SJohn Forte node = pd->pd_remote_nodep; 5008*fcf3ce44SJohn Forte 5009*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&node->fd_mutex)); 5010*fcf3ce44SJohn Forte 5011*fcf3ce44SJohn Forte if (node) { 5012*fcf3ce44SJohn Forte map->map_nwwn = node->fd_node_name; 5013*fcf3ce44SJohn Forte } 5014*fcf3ce44SJohn Forte map->map_pd = pd; 5015*fcf3ce44SJohn Forte } 5016*fcf3ce44SJohn Forte 5017*fcf3ce44SJohn Forte void 5018*fcf3ce44SJohn Forte fctl_copy_portmap(fc_portmap_t *map, fc_remote_port_t *pd) 5019*fcf3ce44SJohn Forte { 5020*fcf3ce44SJohn Forte fc_remote_node_t *node; 5021*fcf3ce44SJohn Forte 5022*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&pd->pd_mutex)); 5023*fcf3ce44SJohn Forte 5024*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 5025*fcf3ce44SJohn Forte map->map_pwwn = pd->pd_port_name; 5026*fcf3ce44SJohn Forte map->map_did = pd->pd_port_id; 5027*fcf3ce44SJohn Forte map->map_hard_addr = pd->pd_hard_addr; 5028*fcf3ce44SJohn Forte map->map_state = pd->pd_state; 5029*fcf3ce44SJohn Forte map->map_type = pd->pd_type; 5030*fcf3ce44SJohn Forte map->map_flags = 0; 5031*fcf3ce44SJohn Forte 5032*fcf3ce44SJohn Forte ASSERT(map->map_type <= PORT_DEVICE_DELETE); 5033*fcf3ce44SJohn Forte 5034*fcf3ce44SJohn Forte bcopy(pd->pd_fc4types, map->map_fc4_types, sizeof (pd->pd_fc4types)); 5035*fcf3ce44SJohn Forte 5036*fcf3ce44SJohn Forte node = pd->pd_remote_nodep; 5037*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 5038*fcf3ce44SJohn Forte 5039*fcf3ce44SJohn Forte if (node) { 5040*fcf3ce44SJohn Forte mutex_enter(&node->fd_mutex); 5041*fcf3ce44SJohn Forte map->map_nwwn = node->fd_node_name; 5042*fcf3ce44SJohn Forte mutex_exit(&node->fd_mutex); 5043*fcf3ce44SJohn Forte } 5044*fcf3ce44SJohn Forte map->map_pd = pd; 5045*fcf3ce44SJohn Forte } 5046*fcf3ce44SJohn Forte 5047*fcf3ce44SJohn Forte 5048*fcf3ce44SJohn Forte static int 5049*fcf3ce44SJohn Forte fctl_update_host_ns_values(fc_local_port_t *port, fc_ns_cmd_t *ns_req) 5050*fcf3ce44SJohn Forte { 5051*fcf3ce44SJohn Forte int rval = FC_SUCCESS; 5052*fcf3ce44SJohn Forte 5053*fcf3ce44SJohn Forte switch (ns_req->ns_cmd) { 5054*fcf3ce44SJohn Forte case NS_RFT_ID: { 5055*fcf3ce44SJohn Forte int count; 5056*fcf3ce44SJohn Forte uint32_t *src; 5057*fcf3ce44SJohn Forte uint32_t *dst; 5058*fcf3ce44SJohn Forte ns_rfc_type_t *rfc; 5059*fcf3ce44SJohn Forte 5060*fcf3ce44SJohn Forte rfc = (ns_rfc_type_t *)ns_req->ns_req_payload; 5061*fcf3ce44SJohn Forte 5062*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5063*fcf3ce44SJohn Forte src = (uint32_t *)port->fp_fc4_types; 5064*fcf3ce44SJohn Forte dst = (uint32_t *)rfc->rfc_types; 5065*fcf3ce44SJohn Forte 5066*fcf3ce44SJohn Forte for (count = 0; count < 8; count++) { 5067*fcf3ce44SJohn Forte *src++ |= *dst++; 5068*fcf3ce44SJohn Forte } 5069*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5070*fcf3ce44SJohn Forte 5071*fcf3ce44SJohn Forte break; 5072*fcf3ce44SJohn Forte } 5073*fcf3ce44SJohn Forte 5074*fcf3ce44SJohn Forte case NS_RSPN_ID: { 5075*fcf3ce44SJohn Forte ns_spn_t *spn; 5076*fcf3ce44SJohn Forte 5077*fcf3ce44SJohn Forte spn = (ns_spn_t *)ns_req->ns_req_payload; 5078*fcf3ce44SJohn Forte 5079*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5080*fcf3ce44SJohn Forte port->fp_sym_port_namelen = spn->spn_len; 5081*fcf3ce44SJohn Forte if (spn->spn_len) { 5082*fcf3ce44SJohn Forte bcopy((caddr_t)spn + sizeof (ns_spn_t), 5083*fcf3ce44SJohn Forte port->fp_sym_port_name, spn->spn_len); 5084*fcf3ce44SJohn Forte } 5085*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5086*fcf3ce44SJohn Forte 5087*fcf3ce44SJohn Forte break; 5088*fcf3ce44SJohn Forte } 5089*fcf3ce44SJohn Forte 5090*fcf3ce44SJohn Forte case NS_RSNN_NN: { 5091*fcf3ce44SJohn Forte ns_snn_t *snn; 5092*fcf3ce44SJohn Forte 5093*fcf3ce44SJohn Forte snn = (ns_snn_t *)ns_req->ns_req_payload; 5094*fcf3ce44SJohn Forte 5095*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5096*fcf3ce44SJohn Forte port->fp_sym_node_namelen = snn->snn_len; 5097*fcf3ce44SJohn Forte if (snn->snn_len) { 5098*fcf3ce44SJohn Forte bcopy((caddr_t)snn + sizeof (ns_snn_t), 5099*fcf3ce44SJohn Forte port->fp_sym_node_name, snn->snn_len); 5100*fcf3ce44SJohn Forte } 5101*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5102*fcf3ce44SJohn Forte 5103*fcf3ce44SJohn Forte break; 5104*fcf3ce44SJohn Forte } 5105*fcf3ce44SJohn Forte 5106*fcf3ce44SJohn Forte case NS_RIP_NN: { 5107*fcf3ce44SJohn Forte ns_rip_t *rip; 5108*fcf3ce44SJohn Forte 5109*fcf3ce44SJohn Forte rip = (ns_rip_t *)ns_req->ns_req_payload; 5110*fcf3ce44SJohn Forte 5111*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5112*fcf3ce44SJohn Forte bcopy(rip->rip_ip_addr, port->fp_ip_addr, 5113*fcf3ce44SJohn Forte sizeof (rip->rip_ip_addr)); 5114*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5115*fcf3ce44SJohn Forte 5116*fcf3ce44SJohn Forte break; 5117*fcf3ce44SJohn Forte } 5118*fcf3ce44SJohn Forte 5119*fcf3ce44SJohn Forte case NS_RIPA_NN: { 5120*fcf3ce44SJohn Forte ns_ipa_t *ipa; 5121*fcf3ce44SJohn Forte 5122*fcf3ce44SJohn Forte ipa = (ns_ipa_t *)ns_req->ns_req_payload; 5123*fcf3ce44SJohn Forte 5124*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5125*fcf3ce44SJohn Forte bcopy(ipa->ipa_value, port->fp_ipa, sizeof (ipa->ipa_value)); 5126*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5127*fcf3ce44SJohn Forte 5128*fcf3ce44SJohn Forte break; 5129*fcf3ce44SJohn Forte } 5130*fcf3ce44SJohn Forte 5131*fcf3ce44SJohn Forte default: 5132*fcf3ce44SJohn Forte rval = FC_BADOBJECT; 5133*fcf3ce44SJohn Forte break; 5134*fcf3ce44SJohn Forte } 5135*fcf3ce44SJohn Forte 5136*fcf3ce44SJohn Forte return (rval); 5137*fcf3ce44SJohn Forte } 5138*fcf3ce44SJohn Forte 5139*fcf3ce44SJohn Forte 5140*fcf3ce44SJohn Forte static int 5141*fcf3ce44SJohn Forte fctl_retrieve_host_ns_values(fc_local_port_t *port, fc_ns_cmd_t *ns_req) 5142*fcf3ce44SJohn Forte { 5143*fcf3ce44SJohn Forte int rval = FC_SUCCESS; 5144*fcf3ce44SJohn Forte 5145*fcf3ce44SJohn Forte switch (ns_req->ns_cmd) { 5146*fcf3ce44SJohn Forte case NS_GFT_ID: { 5147*fcf3ce44SJohn Forte ns_rfc_type_t *rfc; 5148*fcf3ce44SJohn Forte 5149*fcf3ce44SJohn Forte rfc = (ns_rfc_type_t *)ns_req->ns_resp_payload; 5150*fcf3ce44SJohn Forte 5151*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5152*fcf3ce44SJohn Forte bcopy(port->fp_fc4_types, rfc->rfc_types, 5153*fcf3ce44SJohn Forte sizeof (rfc->rfc_types)); 5154*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5155*fcf3ce44SJohn Forte break; 5156*fcf3ce44SJohn Forte } 5157*fcf3ce44SJohn Forte 5158*fcf3ce44SJohn Forte case NS_GSPN_ID: { 5159*fcf3ce44SJohn Forte ns_spn_t *spn; 5160*fcf3ce44SJohn Forte 5161*fcf3ce44SJohn Forte spn = (ns_spn_t *)ns_req->ns_resp_payload; 5162*fcf3ce44SJohn Forte 5163*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5164*fcf3ce44SJohn Forte spn->spn_len = port->fp_sym_port_namelen; 5165*fcf3ce44SJohn Forte if (spn->spn_len) { 5166*fcf3ce44SJohn Forte bcopy(port->fp_sym_port_name, (caddr_t)spn + 5167*fcf3ce44SJohn Forte sizeof (ns_spn_t), spn->spn_len); 5168*fcf3ce44SJohn Forte } 5169*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5170*fcf3ce44SJohn Forte 5171*fcf3ce44SJohn Forte break; 5172*fcf3ce44SJohn Forte } 5173*fcf3ce44SJohn Forte 5174*fcf3ce44SJohn Forte case NS_GSNN_NN: { 5175*fcf3ce44SJohn Forte ns_snn_t *snn; 5176*fcf3ce44SJohn Forte 5177*fcf3ce44SJohn Forte snn = (ns_snn_t *)ns_req->ns_resp_payload; 5178*fcf3ce44SJohn Forte 5179*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5180*fcf3ce44SJohn Forte snn->snn_len = port->fp_sym_node_namelen; 5181*fcf3ce44SJohn Forte if (snn->snn_len) { 5182*fcf3ce44SJohn Forte bcopy(port->fp_sym_node_name, (caddr_t)snn + 5183*fcf3ce44SJohn Forte sizeof (ns_snn_t), snn->snn_len); 5184*fcf3ce44SJohn Forte } 5185*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5186*fcf3ce44SJohn Forte 5187*fcf3ce44SJohn Forte break; 5188*fcf3ce44SJohn Forte } 5189*fcf3ce44SJohn Forte 5190*fcf3ce44SJohn Forte case NS_GIP_NN: { 5191*fcf3ce44SJohn Forte ns_rip_t *rip; 5192*fcf3ce44SJohn Forte 5193*fcf3ce44SJohn Forte rip = (ns_rip_t *)ns_req->ns_resp_payload; 5194*fcf3ce44SJohn Forte 5195*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5196*fcf3ce44SJohn Forte bcopy(port->fp_ip_addr, rip->rip_ip_addr, 5197*fcf3ce44SJohn Forte sizeof (rip->rip_ip_addr)); 5198*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5199*fcf3ce44SJohn Forte 5200*fcf3ce44SJohn Forte break; 5201*fcf3ce44SJohn Forte } 5202*fcf3ce44SJohn Forte 5203*fcf3ce44SJohn Forte case NS_GIPA_NN: { 5204*fcf3ce44SJohn Forte ns_ipa_t *ipa; 5205*fcf3ce44SJohn Forte 5206*fcf3ce44SJohn Forte ipa = (ns_ipa_t *)ns_req->ns_resp_payload; 5207*fcf3ce44SJohn Forte 5208*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5209*fcf3ce44SJohn Forte bcopy(port->fp_ipa, ipa->ipa_value, sizeof (ipa->ipa_value)); 5210*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5211*fcf3ce44SJohn Forte 5212*fcf3ce44SJohn Forte break; 5213*fcf3ce44SJohn Forte } 5214*fcf3ce44SJohn Forte 5215*fcf3ce44SJohn Forte default: 5216*fcf3ce44SJohn Forte rval = FC_BADOBJECT; 5217*fcf3ce44SJohn Forte break; 5218*fcf3ce44SJohn Forte } 5219*fcf3ce44SJohn Forte 5220*fcf3ce44SJohn Forte return (rval); 5221*fcf3ce44SJohn Forte } 5222*fcf3ce44SJohn Forte 5223*fcf3ce44SJohn Forte 5224*fcf3ce44SJohn Forte fctl_ns_req_t * 5225*fcf3ce44SJohn Forte fctl_alloc_ns_cmd(uint32_t cmd_len, uint32_t resp_len, uint32_t data_len, 5226*fcf3ce44SJohn Forte uint32_t ns_flags, int sleep) 5227*fcf3ce44SJohn Forte { 5228*fcf3ce44SJohn Forte fctl_ns_req_t *ns_cmd; 5229*fcf3ce44SJohn Forte 5230*fcf3ce44SJohn Forte ns_cmd = kmem_zalloc(sizeof (*ns_cmd), sleep); 5231*fcf3ce44SJohn Forte if (ns_cmd == NULL) { 5232*fcf3ce44SJohn Forte return (NULL); 5233*fcf3ce44SJohn Forte } 5234*fcf3ce44SJohn Forte 5235*fcf3ce44SJohn Forte if (cmd_len) { 5236*fcf3ce44SJohn Forte ns_cmd->ns_cmd_buf = kmem_zalloc(cmd_len, sleep); 5237*fcf3ce44SJohn Forte if (ns_cmd->ns_cmd_buf == NULL) { 5238*fcf3ce44SJohn Forte kmem_free(ns_cmd, sizeof (*ns_cmd)); 5239*fcf3ce44SJohn Forte return (NULL); 5240*fcf3ce44SJohn Forte } 5241*fcf3ce44SJohn Forte ns_cmd->ns_cmd_size = cmd_len; 5242*fcf3ce44SJohn Forte } 5243*fcf3ce44SJohn Forte 5244*fcf3ce44SJohn Forte ns_cmd->ns_resp_size = resp_len; 5245*fcf3ce44SJohn Forte 5246*fcf3ce44SJohn Forte if (data_len) { 5247*fcf3ce44SJohn Forte ns_cmd->ns_data_buf = kmem_zalloc(data_len, sleep); 5248*fcf3ce44SJohn Forte if (ns_cmd->ns_data_buf == NULL) { 5249*fcf3ce44SJohn Forte if (ns_cmd->ns_cmd_buf && cmd_len) { 5250*fcf3ce44SJohn Forte kmem_free(ns_cmd->ns_cmd_buf, cmd_len); 5251*fcf3ce44SJohn Forte } 5252*fcf3ce44SJohn Forte kmem_free(ns_cmd, sizeof (*ns_cmd)); 5253*fcf3ce44SJohn Forte return (NULL); 5254*fcf3ce44SJohn Forte } 5255*fcf3ce44SJohn Forte ns_cmd->ns_data_len = data_len; 5256*fcf3ce44SJohn Forte } 5257*fcf3ce44SJohn Forte ns_cmd->ns_flags = ns_flags; 5258*fcf3ce44SJohn Forte 5259*fcf3ce44SJohn Forte return (ns_cmd); 5260*fcf3ce44SJohn Forte } 5261*fcf3ce44SJohn Forte 5262*fcf3ce44SJohn Forte 5263*fcf3ce44SJohn Forte void 5264*fcf3ce44SJohn Forte fctl_free_ns_cmd(fctl_ns_req_t *ns_cmd) 5265*fcf3ce44SJohn Forte { 5266*fcf3ce44SJohn Forte if (ns_cmd->ns_cmd_size && ns_cmd->ns_cmd_buf) { 5267*fcf3ce44SJohn Forte kmem_free(ns_cmd->ns_cmd_buf, ns_cmd->ns_cmd_size); 5268*fcf3ce44SJohn Forte } 5269*fcf3ce44SJohn Forte if (ns_cmd->ns_data_len && ns_cmd->ns_data_buf) { 5270*fcf3ce44SJohn Forte kmem_free(ns_cmd->ns_data_buf, ns_cmd->ns_data_len); 5271*fcf3ce44SJohn Forte } 5272*fcf3ce44SJohn Forte kmem_free(ns_cmd, sizeof (*ns_cmd)); 5273*fcf3ce44SJohn Forte } 5274*fcf3ce44SJohn Forte 5275*fcf3ce44SJohn Forte 5276*fcf3ce44SJohn Forte int 5277*fcf3ce44SJohn Forte fctl_ulp_port_ioctl(fc_local_port_t *port, dev_t dev, int cmd, 5278*fcf3ce44SJohn Forte intptr_t data, int mode, cred_t *credp, int *rval) 5279*fcf3ce44SJohn Forte { 5280*fcf3ce44SJohn Forte int ret; 5281*fcf3ce44SJohn Forte int save; 5282*fcf3ce44SJohn Forte uint32_t claimed; 5283*fcf3ce44SJohn Forte fc_ulp_module_t *mod; 5284*fcf3ce44SJohn Forte fc_ulp_ports_t *ulp_port; 5285*fcf3ce44SJohn Forte 5286*fcf3ce44SJohn Forte save = *rval; 5287*fcf3ce44SJohn Forte *rval = ENOTTY; 5288*fcf3ce44SJohn Forte 5289*fcf3ce44SJohn Forte rw_enter(&fctl_ulp_lock, RW_READER); 5290*fcf3ce44SJohn Forte for (claimed = 0, mod = fctl_ulp_modules; mod; mod = mod->mod_next) { 5291*fcf3ce44SJohn Forte rw_enter(&fctl_mod_ports_lock, RW_READER); 5292*fcf3ce44SJohn Forte ulp_port = fctl_get_ulp_port(mod, port); 5293*fcf3ce44SJohn Forte rw_exit(&fctl_mod_ports_lock); 5294*fcf3ce44SJohn Forte 5295*fcf3ce44SJohn Forte if (ulp_port == NULL) { 5296*fcf3ce44SJohn Forte continue; 5297*fcf3ce44SJohn Forte } 5298*fcf3ce44SJohn Forte 5299*fcf3ce44SJohn Forte mutex_enter(&ulp_port->port_mutex); 5300*fcf3ce44SJohn Forte if (FCTL_DISALLOW_CALLBACKS(ulp_port->port_dstate) || 5301*fcf3ce44SJohn Forte mod->mod_info->ulp_port_ioctl == NULL) { 5302*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 5303*fcf3ce44SJohn Forte continue; 5304*fcf3ce44SJohn Forte } 5305*fcf3ce44SJohn Forte mutex_exit(&ulp_port->port_mutex); 5306*fcf3ce44SJohn Forte 5307*fcf3ce44SJohn Forte ret = mod->mod_info->ulp_port_ioctl( 5308*fcf3ce44SJohn Forte mod->mod_info->ulp_handle, (opaque_t)port, 5309*fcf3ce44SJohn Forte dev, cmd, data, mode, credp, rval, claimed); 5310*fcf3ce44SJohn Forte 5311*fcf3ce44SJohn Forte if (ret == FC_SUCCESS && claimed == 0) { 5312*fcf3ce44SJohn Forte claimed = 1; 5313*fcf3ce44SJohn Forte } 5314*fcf3ce44SJohn Forte } 5315*fcf3ce44SJohn Forte rw_exit(&fctl_ulp_lock); 5316*fcf3ce44SJohn Forte 5317*fcf3ce44SJohn Forte ret = *rval; 5318*fcf3ce44SJohn Forte *rval = save; 5319*fcf3ce44SJohn Forte 5320*fcf3ce44SJohn Forte return (ret); 5321*fcf3ce44SJohn Forte } 5322*fcf3ce44SJohn Forte 5323*fcf3ce44SJohn Forte /* 5324*fcf3ce44SJohn Forte * raise power if necessary, and set the port busy 5325*fcf3ce44SJohn Forte * 5326*fcf3ce44SJohn Forte * this may cause power to be raised, so no power related locks should 5327*fcf3ce44SJohn Forte * be held 5328*fcf3ce44SJohn Forte */ 5329*fcf3ce44SJohn Forte int 5330*fcf3ce44SJohn Forte fc_ulp_busy_port(opaque_t port_handle) 5331*fcf3ce44SJohn Forte { 5332*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 5333*fcf3ce44SJohn Forte 5334*fcf3ce44SJohn Forte return (fctl_busy_port(port)); 5335*fcf3ce44SJohn Forte } 5336*fcf3ce44SJohn Forte 5337*fcf3ce44SJohn Forte void 5338*fcf3ce44SJohn Forte fc_ulp_idle_port(opaque_t port_handle) 5339*fcf3ce44SJohn Forte { 5340*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 5341*fcf3ce44SJohn Forte fctl_idle_port(port); 5342*fcf3ce44SJohn Forte } 5343*fcf3ce44SJohn Forte 5344*fcf3ce44SJohn Forte void 5345*fcf3ce44SJohn Forte fc_ulp_copy_portmap(fc_portmap_t *map, opaque_t pd) 5346*fcf3ce44SJohn Forte { 5347*fcf3ce44SJohn Forte fctl_copy_portmap(map, (fc_remote_port_t *)pd); 5348*fcf3ce44SJohn Forte } 5349*fcf3ce44SJohn Forte 5350*fcf3ce44SJohn Forte 5351*fcf3ce44SJohn Forte int 5352*fcf3ce44SJohn Forte fc_ulp_get_npiv_port_num(opaque_t port_handle) 5353*fcf3ce44SJohn Forte { 5354*fcf3ce44SJohn Forte int portsnum = 0; 5355*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 5356*fcf3ce44SJohn Forte fc_local_port_t *tmpport; 5357*fcf3ce44SJohn Forte 5358*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5359*fcf3ce44SJohn Forte tmpport = port->fp_port_next; 5360*fcf3ce44SJohn Forte if (!tmpport) { 5361*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5362*fcf3ce44SJohn Forte return (portsnum); 5363*fcf3ce44SJohn Forte } 5364*fcf3ce44SJohn Forte while (tmpport != port) { 5365*fcf3ce44SJohn Forte portsnum ++; 5366*fcf3ce44SJohn Forte tmpport = tmpport->fp_port_next; 5367*fcf3ce44SJohn Forte } 5368*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5369*fcf3ce44SJohn Forte return (portsnum); 5370*fcf3ce44SJohn Forte } 5371*fcf3ce44SJohn Forte 5372*fcf3ce44SJohn Forte fc_local_port_t * 5373*fcf3ce44SJohn Forte fc_get_npiv_port(fc_local_port_t *phyport, la_wwn_t *pwwn) 5374*fcf3ce44SJohn Forte { 5375*fcf3ce44SJohn Forte fc_fca_port_t *fca_port; 5376*fcf3ce44SJohn Forte fc_local_port_t *tmpPort = phyport; 5377*fcf3ce44SJohn Forte 5378*fcf3ce44SJohn Forte mutex_enter(&fctl_port_lock); 5379*fcf3ce44SJohn Forte 5380*fcf3ce44SJohn Forte for (fca_port = fctl_fca_portlist; fca_port != NULL; 5381*fcf3ce44SJohn Forte fca_port = fca_port->port_next) { 5382*fcf3ce44SJohn Forte tmpPort = fca_port->port_handle; 5383*fcf3ce44SJohn Forte if (tmpPort == NULL) { 5384*fcf3ce44SJohn Forte continue; 5385*fcf3ce44SJohn Forte } 5386*fcf3ce44SJohn Forte mutex_enter(&tmpPort->fp_mutex); 5387*fcf3ce44SJohn Forte if (bcmp(tmpPort->fp_service_params.nport_ww_name.raw_wwn, 5388*fcf3ce44SJohn Forte pwwn->raw_wwn, sizeof (la_wwn_t)) == 0) { 5389*fcf3ce44SJohn Forte mutex_exit(&tmpPort->fp_mutex); 5390*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 5391*fcf3ce44SJohn Forte return (tmpPort); 5392*fcf3ce44SJohn Forte } 5393*fcf3ce44SJohn Forte mutex_exit(&tmpPort->fp_mutex); 5394*fcf3ce44SJohn Forte } 5395*fcf3ce44SJohn Forte 5396*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 5397*fcf3ce44SJohn Forte 5398*fcf3ce44SJohn Forte return (NULL); 5399*fcf3ce44SJohn Forte } 5400*fcf3ce44SJohn Forte 5401*fcf3ce44SJohn Forte int 5402*fcf3ce44SJohn Forte fc_ulp_get_npiv_port_list(opaque_t port_handle, char *pathList) 5403*fcf3ce44SJohn Forte { 5404*fcf3ce44SJohn Forte int portsnum = 0; 5405*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 5406*fcf3ce44SJohn Forte fc_local_port_t *tmpport; 5407*fcf3ce44SJohn Forte 5408*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5409*fcf3ce44SJohn Forte tmpport = port->fp_port_next; 5410*fcf3ce44SJohn Forte if (!tmpport || (port->fp_npiv_type == FC_NPIV_PORT)) { 5411*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5412*fcf3ce44SJohn Forte return (portsnum); 5413*fcf3ce44SJohn Forte } 5414*fcf3ce44SJohn Forte 5415*fcf3ce44SJohn Forte while (tmpport != port) { 5416*fcf3ce44SJohn Forte (void) ddi_pathname(tmpport->fp_port_dip, 5417*fcf3ce44SJohn Forte &pathList[MAXPATHLEN * portsnum]); 5418*fcf3ce44SJohn Forte portsnum ++; 5419*fcf3ce44SJohn Forte tmpport = tmpport->fp_port_next; 5420*fcf3ce44SJohn Forte } 5421*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5422*fcf3ce44SJohn Forte 5423*fcf3ce44SJohn Forte return (portsnum); 5424*fcf3ce44SJohn Forte } 5425*fcf3ce44SJohn Forte 5426*fcf3ce44SJohn Forte 5427*fcf3ce44SJohn Forte fc_local_port_t * 5428*fcf3ce44SJohn Forte fc_delete_npiv_port(fc_local_port_t *port, la_wwn_t *pwwn) 5429*fcf3ce44SJohn Forte { 5430*fcf3ce44SJohn Forte fc_local_port_t *tmpport; 5431*fcf3ce44SJohn Forte 5432*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5433*fcf3ce44SJohn Forte tmpport = port->fp_port_next; 5434*fcf3ce44SJohn Forte if (!tmpport || (port->fp_npiv_type == FC_NPIV_PORT)) { 5435*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5436*fcf3ce44SJohn Forte return (NULL); 5437*fcf3ce44SJohn Forte } 5438*fcf3ce44SJohn Forte 5439*fcf3ce44SJohn Forte while (tmpport != port) { 5440*fcf3ce44SJohn Forte if ((bcmp(tmpport->fp_service_params.nport_ww_name.raw_wwn, 5441*fcf3ce44SJohn Forte pwwn->raw_wwn, sizeof (la_wwn_t)) == 0) && 5442*fcf3ce44SJohn Forte (tmpport->fp_npiv_state == 0)) { 5443*fcf3ce44SJohn Forte tmpport->fp_npiv_state = FC_NPIV_DELETING; 5444*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5445*fcf3ce44SJohn Forte return (tmpport); 5446*fcf3ce44SJohn Forte } 5447*fcf3ce44SJohn Forte tmpport = tmpport->fp_port_next; 5448*fcf3ce44SJohn Forte } 5449*fcf3ce44SJohn Forte 5450*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5451*fcf3ce44SJohn Forte return (NULL); 5452*fcf3ce44SJohn Forte } 5453*fcf3ce44SJohn Forte 5454*fcf3ce44SJohn Forte /* 5455*fcf3ce44SJohn Forte * Get the list of Adapters. On multi-ported adapters, 5456*fcf3ce44SJohn Forte * only ONE port on the adapter will be returned. 5457*fcf3ce44SJohn Forte * pathList should be (count * MAXPATHLEN) long. 5458*fcf3ce44SJohn Forte * The return value will be set to the number of 5459*fcf3ce44SJohn Forte * HBAs that were found on the system. If the value 5460*fcf3ce44SJohn Forte * is greater than count, the routine should be retried 5461*fcf3ce44SJohn Forte * with a larger buffer. 5462*fcf3ce44SJohn Forte */ 5463*fcf3ce44SJohn Forte int 5464*fcf3ce44SJohn Forte fc_ulp_get_adapter_paths(char *pathList, int count) 5465*fcf3ce44SJohn Forte { 5466*fcf3ce44SJohn Forte fc_fca_port_t *fca_port; 5467*fcf3ce44SJohn Forte int in = 0, out = 0, check, skip, maxPorts = 0; 5468*fcf3ce44SJohn Forte fc_local_port_t **portList; 5469*fcf3ce44SJohn Forte fc_local_port_t *new_port, *stored_port; 5470*fcf3ce44SJohn Forte fca_hba_fru_details_t *new_fru, *stored_fru; 5471*fcf3ce44SJohn Forte 5472*fcf3ce44SJohn Forte ASSERT(pathList != NULL); 5473*fcf3ce44SJohn Forte 5474*fcf3ce44SJohn Forte /* First figure out how many ports we have */ 5475*fcf3ce44SJohn Forte mutex_enter(&fctl_port_lock); 5476*fcf3ce44SJohn Forte 5477*fcf3ce44SJohn Forte for (fca_port = fctl_fca_portlist; fca_port != NULL; 5478*fcf3ce44SJohn Forte fca_port = fca_port->port_next) { 5479*fcf3ce44SJohn Forte maxPorts ++; 5480*fcf3ce44SJohn Forte } 5481*fcf3ce44SJohn Forte 5482*fcf3ce44SJohn Forte /* Now allocate a buffer to store all the pointers for comparisons */ 5483*fcf3ce44SJohn Forte portList = kmem_zalloc(sizeof (fc_local_port_t *) * maxPorts, KM_SLEEP); 5484*fcf3ce44SJohn Forte 5485*fcf3ce44SJohn Forte for (fca_port = fctl_fca_portlist; fca_port != NULL; 5486*fcf3ce44SJohn Forte fca_port = fca_port->port_next) { 5487*fcf3ce44SJohn Forte skip = 0; 5488*fcf3ce44SJohn Forte 5489*fcf3ce44SJohn Forte /* Lock the new port for subsequent comparisons */ 5490*fcf3ce44SJohn Forte new_port = fca_port->port_handle; 5491*fcf3ce44SJohn Forte mutex_enter(&new_port->fp_mutex); 5492*fcf3ce44SJohn Forte new_fru = &new_port->fp_hba_port_attrs.hba_fru_details; 5493*fcf3ce44SJohn Forte 5494*fcf3ce44SJohn Forte /* Filter out secondary ports from the list */ 5495*fcf3ce44SJohn Forte for (check = 0; check < out; check++) { 5496*fcf3ce44SJohn Forte if (portList[check] == NULL) { 5497*fcf3ce44SJohn Forte continue; 5498*fcf3ce44SJohn Forte } 5499*fcf3ce44SJohn Forte /* Guard against duplicates (should never happen) */ 5500*fcf3ce44SJohn Forte if (portList[check] == fca_port->port_handle) { 5501*fcf3ce44SJohn Forte /* Same port */ 5502*fcf3ce44SJohn Forte skip = 1; 5503*fcf3ce44SJohn Forte break; 5504*fcf3ce44SJohn Forte } 5505*fcf3ce44SJohn Forte 5506*fcf3ce44SJohn Forte /* Lock the already stored port for comparison */ 5507*fcf3ce44SJohn Forte stored_port = portList[check]; 5508*fcf3ce44SJohn Forte mutex_enter(&stored_port->fp_mutex); 5509*fcf3ce44SJohn Forte stored_fru = &stored_port->fp_hba_port_attrs.hba_fru_details; 5510*fcf3ce44SJohn Forte 5511*fcf3ce44SJohn Forte /* Are these ports on the same HBA? */ 5512*fcf3ce44SJohn Forte if (new_fru->high == stored_fru->high && 5513*fcf3ce44SJohn Forte new_fru->low == stored_fru->low) { 5514*fcf3ce44SJohn Forte /* Now double check driver */ 5515*fcf3ce44SJohn Forte if (strncmp(new_port->fp_hba_port_attrs.driver_name, 5516*fcf3ce44SJohn Forte stored_port->fp_hba_port_attrs.driver_name, 5517*fcf3ce44SJohn Forte FCHBA_DRIVER_NAME_LEN) == 0) { 5518*fcf3ce44SJohn Forte /* we no we don't need to grow the list */ 5519*fcf3ce44SJohn Forte skip = 1; 5520*fcf3ce44SJohn Forte /* Are we looking at a lower port index? */ 5521*fcf3ce44SJohn Forte if (new_fru->port_index < stored_fru->port_index) { 5522*fcf3ce44SJohn Forte /* Replace the port in the list */ 5523*fcf3ce44SJohn Forte mutex_exit(&stored_port->fp_mutex); 5524*fcf3ce44SJohn Forte if (new_port->fp_npiv_type == FC_NPIV_PORT) { 5525*fcf3ce44SJohn Forte break; 5526*fcf3ce44SJohn Forte } 5527*fcf3ce44SJohn Forte portList[check] = new_port; 5528*fcf3ce44SJohn Forte break; 5529*fcf3ce44SJohn Forte } /* Else, just skip this port */ 5530*fcf3ce44SJohn Forte } 5531*fcf3ce44SJohn Forte } 5532*fcf3ce44SJohn Forte 5533*fcf3ce44SJohn Forte mutex_exit(&stored_port->fp_mutex); 5534*fcf3ce44SJohn Forte } 5535*fcf3ce44SJohn Forte mutex_exit(&new_port->fp_mutex); 5536*fcf3ce44SJohn Forte 5537*fcf3ce44SJohn Forte if (!skip) { 5538*fcf3ce44SJohn Forte /* 5539*fcf3ce44SJohn Forte * Either this is the first port for this HBA, or 5540*fcf3ce44SJohn Forte * it's a secondary port and we haven't stored the 5541*fcf3ce44SJohn Forte * primary/first port for that HBA. In the latter case, 5542*fcf3ce44SJohn Forte * will just filter it out as we proceed to loop. 5543*fcf3ce44SJohn Forte */ 5544*fcf3ce44SJohn Forte if (fca_port->port_handle->fp_npiv_type == FC_NPIV_PORT) { 5545*fcf3ce44SJohn Forte continue; 5546*fcf3ce44SJohn Forte } else { 5547*fcf3ce44SJohn Forte portList[out++] = fca_port->port_handle; 5548*fcf3ce44SJohn Forte } 5549*fcf3ce44SJohn Forte } 5550*fcf3ce44SJohn Forte } 5551*fcf3ce44SJohn Forte 5552*fcf3ce44SJohn Forte if (out <= count) { 5553*fcf3ce44SJohn Forte for (in = 0; in < out; in++) { 5554*fcf3ce44SJohn Forte (void) ddi_pathname(portList[in]->fp_port_dip, 5555*fcf3ce44SJohn Forte &pathList[MAXPATHLEN * in]); 5556*fcf3ce44SJohn Forte } 5557*fcf3ce44SJohn Forte } 5558*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 5559*fcf3ce44SJohn Forte kmem_free(portList, sizeof (*portList) * maxPorts); 5560*fcf3ce44SJohn Forte return (out); 5561*fcf3ce44SJohn Forte } 5562*fcf3ce44SJohn Forte 5563*fcf3ce44SJohn Forte uint32_t 5564*fcf3ce44SJohn Forte fc_ulp_get_rscn_count(opaque_t port_handle) 5565*fcf3ce44SJohn Forte { 5566*fcf3ce44SJohn Forte uint32_t count; 5567*fcf3ce44SJohn Forte fc_local_port_t *port; 5568*fcf3ce44SJohn Forte 5569*fcf3ce44SJohn Forte port = (fc_local_port_t *)port_handle; 5570*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5571*fcf3ce44SJohn Forte count = port->fp_rscn_count; 5572*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5573*fcf3ce44SJohn Forte 5574*fcf3ce44SJohn Forte return (count); 5575*fcf3ce44SJohn Forte } 5576*fcf3ce44SJohn Forte 5577*fcf3ce44SJohn Forte 5578*fcf3ce44SJohn Forte /* 5579*fcf3ce44SJohn Forte * This function is a very similar to fctl_add_orphan except that it expects 5580*fcf3ce44SJohn Forte * that the fp_mutex and pd_mutex of the pd passed in are held coming in. 5581*fcf3ce44SJohn Forte * 5582*fcf3ce44SJohn Forte * Note that there is a lock hierarchy here (fp_mutex should be held first) but 5583*fcf3ce44SJohn Forte * since this function could be called with a different pd's pd_mutex held, we 5584*fcf3ce44SJohn Forte * should take care not to release fp_mutex in this function. 5585*fcf3ce44SJohn Forte */ 5586*fcf3ce44SJohn Forte int 5587*fcf3ce44SJohn Forte fctl_add_orphan_held(fc_local_port_t *port, fc_remote_port_t *pd) 5588*fcf3ce44SJohn Forte { 5589*fcf3ce44SJohn Forte int rval = FC_FAILURE; 5590*fcf3ce44SJohn Forte la_wwn_t pwwn; 5591*fcf3ce44SJohn Forte fc_orphan_t *orp; 5592*fcf3ce44SJohn Forte fc_orphan_t *orphan; 5593*fcf3ce44SJohn Forte 5594*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 5595*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&pd->pd_mutex)); 5596*fcf3ce44SJohn Forte 5597*fcf3ce44SJohn Forte pwwn = pd->pd_port_name; 5598*fcf3ce44SJohn Forte 5599*fcf3ce44SJohn Forte for (orp = port->fp_orphan_list; orp != NULL; orp = orp->orp_next) { 5600*fcf3ce44SJohn Forte if (fctl_wwn_cmp(&orp->orp_pwwn, &pwwn) == 0) { 5601*fcf3ce44SJohn Forte return (FC_SUCCESS); 5602*fcf3ce44SJohn Forte } 5603*fcf3ce44SJohn Forte } 5604*fcf3ce44SJohn Forte 5605*fcf3ce44SJohn Forte orphan = kmem_zalloc(sizeof (*orphan), KM_NOSLEEP); 5606*fcf3ce44SJohn Forte if (orphan) { 5607*fcf3ce44SJohn Forte orphan->orp_pwwn = pwwn; 5608*fcf3ce44SJohn Forte orphan->orp_tstamp = ddi_get_lbolt(); 5609*fcf3ce44SJohn Forte 5610*fcf3ce44SJohn Forte if (port->fp_orphan_list) { 5611*fcf3ce44SJohn Forte ASSERT(port->fp_orphan_count > 0); 5612*fcf3ce44SJohn Forte orphan->orp_next = port->fp_orphan_list; 5613*fcf3ce44SJohn Forte } 5614*fcf3ce44SJohn Forte port->fp_orphan_list = orphan; 5615*fcf3ce44SJohn Forte port->fp_orphan_count++; 5616*fcf3ce44SJohn Forte 5617*fcf3ce44SJohn Forte rval = FC_SUCCESS; 5618*fcf3ce44SJohn Forte } 5619*fcf3ce44SJohn Forte 5620*fcf3ce44SJohn Forte return (rval); 5621*fcf3ce44SJohn Forte } 5622*fcf3ce44SJohn Forte 5623*fcf3ce44SJohn Forte int 5624*fcf3ce44SJohn Forte fctl_add_orphan(fc_local_port_t *port, fc_remote_port_t *pd, int sleep) 5625*fcf3ce44SJohn Forte { 5626*fcf3ce44SJohn Forte int rval = FC_FAILURE; 5627*fcf3ce44SJohn Forte la_wwn_t pwwn; 5628*fcf3ce44SJohn Forte fc_orphan_t *orp; 5629*fcf3ce44SJohn Forte fc_orphan_t *orphan; 5630*fcf3ce44SJohn Forte 5631*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5632*fcf3ce44SJohn Forte 5633*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 5634*fcf3ce44SJohn Forte pwwn = pd->pd_port_name; 5635*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 5636*fcf3ce44SJohn Forte 5637*fcf3ce44SJohn Forte for (orp = port->fp_orphan_list; orp != NULL; orp = orp->orp_next) { 5638*fcf3ce44SJohn Forte if (fctl_wwn_cmp(&orp->orp_pwwn, &pwwn) == 0) { 5639*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5640*fcf3ce44SJohn Forte return (FC_SUCCESS); 5641*fcf3ce44SJohn Forte } 5642*fcf3ce44SJohn Forte } 5643*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5644*fcf3ce44SJohn Forte 5645*fcf3ce44SJohn Forte orphan = kmem_zalloc(sizeof (*orphan), sleep); 5646*fcf3ce44SJohn Forte if (orphan != NULL) { 5647*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5648*fcf3ce44SJohn Forte 5649*fcf3ce44SJohn Forte orphan->orp_pwwn = pwwn; 5650*fcf3ce44SJohn Forte orphan->orp_tstamp = ddi_get_lbolt(); 5651*fcf3ce44SJohn Forte 5652*fcf3ce44SJohn Forte if (port->fp_orphan_list) { 5653*fcf3ce44SJohn Forte ASSERT(port->fp_orphan_count > 0); 5654*fcf3ce44SJohn Forte orphan->orp_next = port->fp_orphan_list; 5655*fcf3ce44SJohn Forte } 5656*fcf3ce44SJohn Forte port->fp_orphan_list = orphan; 5657*fcf3ce44SJohn Forte port->fp_orphan_count++; 5658*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5659*fcf3ce44SJohn Forte 5660*fcf3ce44SJohn Forte rval = FC_SUCCESS; 5661*fcf3ce44SJohn Forte } 5662*fcf3ce44SJohn Forte 5663*fcf3ce44SJohn Forte return (rval); 5664*fcf3ce44SJohn Forte } 5665*fcf3ce44SJohn Forte 5666*fcf3ce44SJohn Forte 5667*fcf3ce44SJohn Forte int 5668*fcf3ce44SJohn Forte fctl_remove_if_orphan(fc_local_port_t *port, la_wwn_t *pwwn) 5669*fcf3ce44SJohn Forte { 5670*fcf3ce44SJohn Forte int rval = FC_FAILURE; 5671*fcf3ce44SJohn Forte fc_orphan_t *prev = NULL; 5672*fcf3ce44SJohn Forte fc_orphan_t *orp; 5673*fcf3ce44SJohn Forte 5674*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5675*fcf3ce44SJohn Forte for (orp = port->fp_orphan_list; orp != NULL; orp = orp->orp_next) { 5676*fcf3ce44SJohn Forte if (fctl_wwn_cmp(&orp->orp_pwwn, pwwn) == 0) { 5677*fcf3ce44SJohn Forte if (prev) { 5678*fcf3ce44SJohn Forte prev->orp_next = orp->orp_next; 5679*fcf3ce44SJohn Forte } else { 5680*fcf3ce44SJohn Forte ASSERT(port->fp_orphan_list == orp); 5681*fcf3ce44SJohn Forte port->fp_orphan_list = orp->orp_next; 5682*fcf3ce44SJohn Forte } 5683*fcf3ce44SJohn Forte port->fp_orphan_count--; 5684*fcf3ce44SJohn Forte rval = FC_SUCCESS; 5685*fcf3ce44SJohn Forte break; 5686*fcf3ce44SJohn Forte } 5687*fcf3ce44SJohn Forte prev = orp; 5688*fcf3ce44SJohn Forte } 5689*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5690*fcf3ce44SJohn Forte 5691*fcf3ce44SJohn Forte if (rval == FC_SUCCESS) { 5692*fcf3ce44SJohn Forte kmem_free(orp, sizeof (*orp)); 5693*fcf3ce44SJohn Forte } 5694*fcf3ce44SJohn Forte 5695*fcf3ce44SJohn Forte return (rval); 5696*fcf3ce44SJohn Forte } 5697*fcf3ce44SJohn Forte 5698*fcf3ce44SJohn Forte 5699*fcf3ce44SJohn Forte static void 5700*fcf3ce44SJohn Forte fctl_print_if_not_orphan(fc_local_port_t *port, fc_remote_port_t *pd) 5701*fcf3ce44SJohn Forte { 5702*fcf3ce44SJohn Forte char ww_name[17]; 5703*fcf3ce44SJohn Forte la_wwn_t pwwn; 5704*fcf3ce44SJohn Forte fc_orphan_t *orp; 5705*fcf3ce44SJohn Forte 5706*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5707*fcf3ce44SJohn Forte 5708*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 5709*fcf3ce44SJohn Forte pwwn = pd->pd_port_name; 5710*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 5711*fcf3ce44SJohn Forte 5712*fcf3ce44SJohn Forte for (orp = port->fp_orphan_list; orp != NULL; orp = orp->orp_next) { 5713*fcf3ce44SJohn Forte if (fctl_wwn_cmp(&orp->orp_pwwn, &pwwn) == 0) { 5714*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5715*fcf3ce44SJohn Forte return; 5716*fcf3ce44SJohn Forte } 5717*fcf3ce44SJohn Forte } 5718*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5719*fcf3ce44SJohn Forte 5720*fcf3ce44SJohn Forte fc_wwn_to_str(&pwwn, ww_name); 5721*fcf3ce44SJohn Forte 5722*fcf3ce44SJohn Forte cmn_err(CE_WARN, "!fctl(%d): N_x Port with D_ID=%x, PWWN=%s" 5723*fcf3ce44SJohn Forte " disappeared from fabric", port->fp_instance, 5724*fcf3ce44SJohn Forte pd->pd_port_id.port_id, ww_name); 5725*fcf3ce44SJohn Forte } 5726*fcf3ce44SJohn Forte 5727*fcf3ce44SJohn Forte 5728*fcf3ce44SJohn Forte /* ARGSUSED */ 5729*fcf3ce44SJohn Forte static void 5730*fcf3ce44SJohn Forte fctl_link_reset_done(opaque_t port_handle, uchar_t result) 5731*fcf3ce44SJohn Forte { 5732*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 5733*fcf3ce44SJohn Forte 5734*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5735*fcf3ce44SJohn Forte port->fp_soft_state &= ~FP_SOFT_IN_LINK_RESET; 5736*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5737*fcf3ce44SJohn Forte 5738*fcf3ce44SJohn Forte fctl_idle_port(port); 5739*fcf3ce44SJohn Forte } 5740*fcf3ce44SJohn Forte 5741*fcf3ce44SJohn Forte 5742*fcf3ce44SJohn Forte static int 5743*fcf3ce44SJohn Forte fctl_error(int fc_errno, char **errmsg) 5744*fcf3ce44SJohn Forte { 5745*fcf3ce44SJohn Forte int count; 5746*fcf3ce44SJohn Forte 5747*fcf3ce44SJohn Forte for (count = 0; count < sizeof (fc_errlist) / 5748*fcf3ce44SJohn Forte sizeof (fc_errlist[0]); count++) { 5749*fcf3ce44SJohn Forte if (fc_errlist[count].fc_errno == fc_errno) { 5750*fcf3ce44SJohn Forte *errmsg = fc_errlist[count].fc_errname; 5751*fcf3ce44SJohn Forte return (FC_SUCCESS); 5752*fcf3ce44SJohn Forte } 5753*fcf3ce44SJohn Forte } 5754*fcf3ce44SJohn Forte *errmsg = fctl_undefined; 5755*fcf3ce44SJohn Forte 5756*fcf3ce44SJohn Forte return (FC_FAILURE); 5757*fcf3ce44SJohn Forte } 5758*fcf3ce44SJohn Forte 5759*fcf3ce44SJohn Forte 5760*fcf3ce44SJohn Forte /* 5761*fcf3ce44SJohn Forte * Return number of successful translations. 5762*fcf3ce44SJohn Forte * Anybody with some userland programming experience would have 5763*fcf3ce44SJohn Forte * figured it by now that the return value exactly resembles that 5764*fcf3ce44SJohn Forte * of scanf(3c). This function returns a count of successful 5765*fcf3ce44SJohn Forte * translations. It could range from 0 (no match for state, reason, 5766*fcf3ce44SJohn Forte * action, expln) to 4 (successful matches for all state, reason, 5767*fcf3ce44SJohn Forte * action, expln) and where translation isn't successful into a 5768*fcf3ce44SJohn Forte * friendlier message the relevent field is set to "Undefined" 5769*fcf3ce44SJohn Forte */ 5770*fcf3ce44SJohn Forte static int 5771*fcf3ce44SJohn Forte fctl_pkt_error(fc_packet_t *pkt, char **state, char **reason, 5772*fcf3ce44SJohn Forte char **action, char **expln) 5773*fcf3ce44SJohn Forte { 5774*fcf3ce44SJohn Forte int ret; 5775*fcf3ce44SJohn Forte int len; 5776*fcf3ce44SJohn Forte int index; 5777*fcf3ce44SJohn Forte fc_pkt_error_t *error; 5778*fcf3ce44SJohn Forte fc_pkt_reason_t *reason_b; /* Base pointer */ 5779*fcf3ce44SJohn Forte fc_pkt_action_t *action_b; /* Base pointer */ 5780*fcf3ce44SJohn Forte fc_pkt_expln_t *expln_b; /* Base pointer */ 5781*fcf3ce44SJohn Forte 5782*fcf3ce44SJohn Forte ret = 0; 5783*fcf3ce44SJohn Forte *state = *reason = *action = *expln = fctl_undefined; 5784*fcf3ce44SJohn Forte 5785*fcf3ce44SJohn Forte len = sizeof (fc_pkt_errlist) / sizeof fc_pkt_errlist[0]; 5786*fcf3ce44SJohn Forte for (index = 0; index < len; index++) { 5787*fcf3ce44SJohn Forte error = fc_pkt_errlist + index; 5788*fcf3ce44SJohn Forte if (pkt->pkt_state == error->pkt_state) { 5789*fcf3ce44SJohn Forte *state = error->pkt_msg; 5790*fcf3ce44SJohn Forte ret++; 5791*fcf3ce44SJohn Forte 5792*fcf3ce44SJohn Forte reason_b = error->pkt_reason; 5793*fcf3ce44SJohn Forte action_b = error->pkt_action; 5794*fcf3ce44SJohn Forte expln_b = error->pkt_expln; 5795*fcf3ce44SJohn Forte 5796*fcf3ce44SJohn Forte while (reason_b != NULL && 5797*fcf3ce44SJohn Forte reason_b->reason_val != FC_REASON_INVALID) { 5798*fcf3ce44SJohn Forte if (reason_b->reason_val == pkt->pkt_reason) { 5799*fcf3ce44SJohn Forte *reason = reason_b->reason_msg; 5800*fcf3ce44SJohn Forte ret++; 5801*fcf3ce44SJohn Forte break; 5802*fcf3ce44SJohn Forte } 5803*fcf3ce44SJohn Forte reason_b++; 5804*fcf3ce44SJohn Forte } 5805*fcf3ce44SJohn Forte 5806*fcf3ce44SJohn Forte while (action_b != NULL && 5807*fcf3ce44SJohn Forte action_b->action_val != FC_ACTION_INVALID) { 5808*fcf3ce44SJohn Forte if (action_b->action_val == pkt->pkt_action) { 5809*fcf3ce44SJohn Forte *action = action_b->action_msg; 5810*fcf3ce44SJohn Forte ret++; 5811*fcf3ce44SJohn Forte break; 5812*fcf3ce44SJohn Forte } 5813*fcf3ce44SJohn Forte action_b++; 5814*fcf3ce44SJohn Forte } 5815*fcf3ce44SJohn Forte 5816*fcf3ce44SJohn Forte while (expln_b != NULL && 5817*fcf3ce44SJohn Forte expln_b->expln_val != FC_EXPLN_INVALID) { 5818*fcf3ce44SJohn Forte if (expln_b->expln_val == pkt->pkt_expln) { 5819*fcf3ce44SJohn Forte *expln = expln_b->expln_msg; 5820*fcf3ce44SJohn Forte ret++; 5821*fcf3ce44SJohn Forte break; 5822*fcf3ce44SJohn Forte } 5823*fcf3ce44SJohn Forte expln_b++; 5824*fcf3ce44SJohn Forte } 5825*fcf3ce44SJohn Forte break; 5826*fcf3ce44SJohn Forte } 5827*fcf3ce44SJohn Forte } 5828*fcf3ce44SJohn Forte 5829*fcf3ce44SJohn Forte return (ret); 5830*fcf3ce44SJohn Forte } 5831*fcf3ce44SJohn Forte 5832*fcf3ce44SJohn Forte 5833*fcf3ce44SJohn Forte /* 5834*fcf3ce44SJohn Forte * Remove all port devices that are marked OLD, remove 5835*fcf3ce44SJohn Forte * corresponding node devices (fc_remote_node_t) 5836*fcf3ce44SJohn Forte */ 5837*fcf3ce44SJohn Forte void 5838*fcf3ce44SJohn Forte fctl_remove_oldies(fc_local_port_t *port) 5839*fcf3ce44SJohn Forte { 5840*fcf3ce44SJohn Forte int index; 5841*fcf3ce44SJohn Forte int initiator; 5842*fcf3ce44SJohn Forte fc_remote_node_t *node; 5843*fcf3ce44SJohn Forte struct pwwn_hash *head; 5844*fcf3ce44SJohn Forte fc_remote_port_t *pd; 5845*fcf3ce44SJohn Forte fc_remote_port_t *old_pd; 5846*fcf3ce44SJohn Forte fc_remote_port_t *last_pd; 5847*fcf3ce44SJohn Forte 5848*fcf3ce44SJohn Forte /* 5849*fcf3ce44SJohn Forte * Nuke all OLD devices 5850*fcf3ce44SJohn Forte */ 5851*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5852*fcf3ce44SJohn Forte 5853*fcf3ce44SJohn Forte for (index = 0; index < pwwn_table_size; index++) { 5854*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 5855*fcf3ce44SJohn Forte last_pd = NULL; 5856*fcf3ce44SJohn Forte pd = head->pwwn_head; 5857*fcf3ce44SJohn Forte 5858*fcf3ce44SJohn Forte while (pd != NULL) { 5859*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 5860*fcf3ce44SJohn Forte if (pd->pd_type != PORT_DEVICE_OLD) { 5861*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 5862*fcf3ce44SJohn Forte last_pd = pd; 5863*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 5864*fcf3ce44SJohn Forte continue; 5865*fcf3ce44SJohn Forte } 5866*fcf3ce44SJohn Forte 5867*fcf3ce44SJohn Forte /* 5868*fcf3ce44SJohn Forte * Remove this from the PWWN hash table 5869*fcf3ce44SJohn Forte */ 5870*fcf3ce44SJohn Forte old_pd = pd; 5871*fcf3ce44SJohn Forte pd = old_pd->pd_wwn_hnext; 5872*fcf3ce44SJohn Forte 5873*fcf3ce44SJohn Forte if (last_pd == NULL) { 5874*fcf3ce44SJohn Forte ASSERT(old_pd == head->pwwn_head); 5875*fcf3ce44SJohn Forte head->pwwn_head = pd; 5876*fcf3ce44SJohn Forte } else { 5877*fcf3ce44SJohn Forte last_pd->pd_wwn_hnext = pd; 5878*fcf3ce44SJohn Forte } 5879*fcf3ce44SJohn Forte head->pwwn_count--; 5880*fcf3ce44SJohn Forte /* 5881*fcf3ce44SJohn Forte * Make sure we tie fp_dev_count to the size of the 5882*fcf3ce44SJohn Forte * pwwn_table 5883*fcf3ce44SJohn Forte */ 5884*fcf3ce44SJohn Forte port->fp_dev_count--; 5885*fcf3ce44SJohn Forte old_pd->pd_wwn_hnext = NULL; 5886*fcf3ce44SJohn Forte 5887*fcf3ce44SJohn Forte fctl_delist_did_table(port, old_pd); 5888*fcf3ce44SJohn Forte node = old_pd->pd_remote_nodep; 5889*fcf3ce44SJohn Forte ASSERT(node != NULL); 5890*fcf3ce44SJohn Forte 5891*fcf3ce44SJohn Forte initiator = (old_pd->pd_recepient == 5892*fcf3ce44SJohn Forte PD_PLOGI_INITIATOR) ? 1 : 0; 5893*fcf3ce44SJohn Forte 5894*fcf3ce44SJohn Forte mutex_exit(&old_pd->pd_mutex); 5895*fcf3ce44SJohn Forte 5896*fcf3ce44SJohn Forte if (FC_IS_TOP_SWITCH(port->fp_topology) && initiator) { 5897*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5898*fcf3ce44SJohn Forte 5899*fcf3ce44SJohn Forte (void) fctl_add_orphan(port, old_pd, 5900*fcf3ce44SJohn Forte KM_NOSLEEP); 5901*fcf3ce44SJohn Forte } else { 5902*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5903*fcf3ce44SJohn Forte } 5904*fcf3ce44SJohn Forte 5905*fcf3ce44SJohn Forte if (fctl_destroy_remote_port(port, old_pd) == 0) { 5906*fcf3ce44SJohn Forte if (node) { 5907*fcf3ce44SJohn Forte fctl_destroy_remote_node(node); 5908*fcf3ce44SJohn Forte } 5909*fcf3ce44SJohn Forte } 5910*fcf3ce44SJohn Forte 5911*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 5912*fcf3ce44SJohn Forte } 5913*fcf3ce44SJohn Forte } 5914*fcf3ce44SJohn Forte 5915*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 5916*fcf3ce44SJohn Forte } 5917*fcf3ce44SJohn Forte 5918*fcf3ce44SJohn Forte 5919*fcf3ce44SJohn Forte static void 5920*fcf3ce44SJohn Forte fctl_check_alpa_list(fc_local_port_t *port, fc_remote_port_t *pd) 5921*fcf3ce44SJohn Forte { 5922*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 5923*fcf3ce44SJohn Forte ASSERT(port->fp_topology == FC_TOP_PRIVATE_LOOP); 5924*fcf3ce44SJohn Forte 5925*fcf3ce44SJohn Forte if (fctl_is_alpa_present(port, pd->pd_port_id.port_id) == FC_SUCCESS) { 5926*fcf3ce44SJohn Forte return; 5927*fcf3ce44SJohn Forte } 5928*fcf3ce44SJohn Forte 5929*fcf3ce44SJohn Forte cmn_err(CE_WARN, "!fctl(%d): AL_PA=0x%x doesn't exist in LILP map", 5930*fcf3ce44SJohn Forte port->fp_instance, pd->pd_port_id.port_id); 5931*fcf3ce44SJohn Forte } 5932*fcf3ce44SJohn Forte 5933*fcf3ce44SJohn Forte 5934*fcf3ce44SJohn Forte static int 5935*fcf3ce44SJohn Forte fctl_is_alpa_present(fc_local_port_t *port, uchar_t alpa) 5936*fcf3ce44SJohn Forte { 5937*fcf3ce44SJohn Forte int index; 5938*fcf3ce44SJohn Forte 5939*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 5940*fcf3ce44SJohn Forte ASSERT(port->fp_topology == FC_TOP_PRIVATE_LOOP); 5941*fcf3ce44SJohn Forte 5942*fcf3ce44SJohn Forte for (index = 0; index < port->fp_lilp_map.lilp_length; index++) { 5943*fcf3ce44SJohn Forte if (port->fp_lilp_map.lilp_alpalist[index] == alpa) { 5944*fcf3ce44SJohn Forte return (FC_SUCCESS); 5945*fcf3ce44SJohn Forte } 5946*fcf3ce44SJohn Forte } 5947*fcf3ce44SJohn Forte 5948*fcf3ce44SJohn Forte return (FC_FAILURE); 5949*fcf3ce44SJohn Forte } 5950*fcf3ce44SJohn Forte 5951*fcf3ce44SJohn Forte 5952*fcf3ce44SJohn Forte fc_remote_port_t * 5953*fcf3ce44SJohn Forte fctl_lookup_pd_by_did(fc_local_port_t *port, uint32_t d_id) 5954*fcf3ce44SJohn Forte { 5955*fcf3ce44SJohn Forte int index; 5956*fcf3ce44SJohn Forte struct pwwn_hash *head; 5957*fcf3ce44SJohn Forte fc_remote_port_t *pd; 5958*fcf3ce44SJohn Forte 5959*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 5960*fcf3ce44SJohn Forte 5961*fcf3ce44SJohn Forte for (index = 0; index < pwwn_table_size; index++) { 5962*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 5963*fcf3ce44SJohn Forte pd = head->pwwn_head; 5964*fcf3ce44SJohn Forte 5965*fcf3ce44SJohn Forte while (pd != NULL) { 5966*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 5967*fcf3ce44SJohn Forte if (pd->pd_port_id.port_id == d_id) { 5968*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 5969*fcf3ce44SJohn Forte return (pd); 5970*fcf3ce44SJohn Forte } 5971*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 5972*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 5973*fcf3ce44SJohn Forte } 5974*fcf3ce44SJohn Forte } 5975*fcf3ce44SJohn Forte 5976*fcf3ce44SJohn Forte return (pd); 5977*fcf3ce44SJohn Forte } 5978*fcf3ce44SJohn Forte 5979*fcf3ce44SJohn Forte 5980*fcf3ce44SJohn Forte /* 5981*fcf3ce44SJohn Forte * trace debugging 5982*fcf3ce44SJohn Forte */ 5983*fcf3ce44SJohn Forte void 5984*fcf3ce44SJohn Forte fc_trace_debug(fc_trace_logq_t *logq, caddr_t name, int dflag, int dlevel, 5985*fcf3ce44SJohn Forte int errno, const char *fmt, ...) 5986*fcf3ce44SJohn Forte { 5987*fcf3ce44SJohn Forte char buf[FC_MAX_TRACE_BUF_LEN + 3]; /* 3 is for "\n" */ 5988*fcf3ce44SJohn Forte char *bufptr = buf; 5989*fcf3ce44SJohn Forte va_list ap; 5990*fcf3ce44SJohn Forte int cnt = 0; 5991*fcf3ce44SJohn Forte 5992*fcf3ce44SJohn Forte if ((dlevel & dflag) == 0) { 5993*fcf3ce44SJohn Forte return; 5994*fcf3ce44SJohn Forte } 5995*fcf3ce44SJohn Forte 5996*fcf3ce44SJohn Forte if (name) { 5997*fcf3ce44SJohn Forte cnt = snprintf(buf, FC_MAX_TRACE_BUF_LEN + 1, "%d=>%s::", 5998*fcf3ce44SJohn Forte logq->il_id++, name); 5999*fcf3ce44SJohn Forte } else { 6000*fcf3ce44SJohn Forte cnt = snprintf(buf, FC_MAX_TRACE_BUF_LEN + 1, "%d=>trace::", 6001*fcf3ce44SJohn Forte logq->il_id++); 6002*fcf3ce44SJohn Forte } 6003*fcf3ce44SJohn Forte 6004*fcf3ce44SJohn Forte if (cnt < FC_MAX_TRACE_BUF_LEN) { 6005*fcf3ce44SJohn Forte va_start(ap, fmt); 6006*fcf3ce44SJohn Forte cnt += vsnprintf(buf + cnt, FC_MAX_TRACE_BUF_LEN + 1 - cnt, 6007*fcf3ce44SJohn Forte fmt, ap); 6008*fcf3ce44SJohn Forte va_end(ap); 6009*fcf3ce44SJohn Forte } 6010*fcf3ce44SJohn Forte 6011*fcf3ce44SJohn Forte if (cnt > FC_MAX_TRACE_BUF_LEN) { 6012*fcf3ce44SJohn Forte cnt = FC_MAX_TRACE_BUF_LEN; 6013*fcf3ce44SJohn Forte } 6014*fcf3ce44SJohn Forte if (errno && (cnt < FC_MAX_TRACE_BUF_LEN)) { 6015*fcf3ce44SJohn Forte cnt += snprintf(buf + cnt, FC_MAX_TRACE_BUF_LEN + 1 - cnt, 6016*fcf3ce44SJohn Forte "error=0x%x\n", errno); 6017*fcf3ce44SJohn Forte } 6018*fcf3ce44SJohn Forte (void) snprintf(buf + cnt, FC_MAX_TRACE_BUF_LEN + 3 - cnt, "\n"); 6019*fcf3ce44SJohn Forte 6020*fcf3ce44SJohn Forte if (logq && (dlevel & FC_TRACE_LOG_BUF) != 0) { 6021*fcf3ce44SJohn Forte fc_trace_logmsg(logq, buf, dlevel); 6022*fcf3ce44SJohn Forte } 6023*fcf3ce44SJohn Forte 6024*fcf3ce44SJohn Forte /* 6025*fcf3ce44SJohn Forte * We do not want to print the log numbers that appear as 6026*fcf3ce44SJohn Forte * random numbers at the console and messages files, to 6027*fcf3ce44SJohn Forte * the user. 6028*fcf3ce44SJohn Forte */ 6029*fcf3ce44SJohn Forte if ((bufptr = strchr(buf, '>')) == NULL) { 6030*fcf3ce44SJohn Forte /* 6031*fcf3ce44SJohn Forte * We would have added the a string with "=>" above and so, 6032*fcf3ce44SJohn Forte * ideally, we should not get here at all. But, if we do, 6033*fcf3ce44SJohn Forte * we'll just use the full buf. 6034*fcf3ce44SJohn Forte */ 6035*fcf3ce44SJohn Forte bufptr = buf; 6036*fcf3ce44SJohn Forte } else { 6037*fcf3ce44SJohn Forte bufptr++; 6038*fcf3ce44SJohn Forte } 6039*fcf3ce44SJohn Forte 6040*fcf3ce44SJohn Forte switch (dlevel & FC_TRACE_LOG_MASK) { 6041*fcf3ce44SJohn Forte case FC_TRACE_LOG_CONSOLE: 6042*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s", bufptr); 6043*fcf3ce44SJohn Forte break; 6044*fcf3ce44SJohn Forte 6045*fcf3ce44SJohn Forte case FC_TRACE_LOG_CONSOLE_MSG: 6046*fcf3ce44SJohn Forte cmn_err(CE_WARN, "%s", bufptr); 6047*fcf3ce44SJohn Forte break; 6048*fcf3ce44SJohn Forte 6049*fcf3ce44SJohn Forte case FC_TRACE_LOG_MSG: 6050*fcf3ce44SJohn Forte cmn_err(CE_WARN, "!%s", bufptr); 6051*fcf3ce44SJohn Forte break; 6052*fcf3ce44SJohn Forte 6053*fcf3ce44SJohn Forte default: 6054*fcf3ce44SJohn Forte break; 6055*fcf3ce44SJohn Forte } 6056*fcf3ce44SJohn Forte } 6057*fcf3ce44SJohn Forte 6058*fcf3ce44SJohn Forte 6059*fcf3ce44SJohn Forte /* 6060*fcf3ce44SJohn Forte * This function can block 6061*fcf3ce44SJohn Forte */ 6062*fcf3ce44SJohn Forte fc_trace_logq_t * 6063*fcf3ce44SJohn Forte fc_trace_alloc_logq(int maxsize) 6064*fcf3ce44SJohn Forte { 6065*fcf3ce44SJohn Forte fc_trace_logq_t *logq; 6066*fcf3ce44SJohn Forte 6067*fcf3ce44SJohn Forte logq = kmem_zalloc(sizeof (*logq), KM_SLEEP); 6068*fcf3ce44SJohn Forte 6069*fcf3ce44SJohn Forte mutex_init(&logq->il_lock, NULL, MUTEX_DRIVER, NULL); 6070*fcf3ce44SJohn Forte logq->il_hiwat = maxsize; 6071*fcf3ce44SJohn Forte logq->il_flags |= FC_TRACE_LOGQ_V2; 6072*fcf3ce44SJohn Forte 6073*fcf3ce44SJohn Forte return (logq); 6074*fcf3ce44SJohn Forte } 6075*fcf3ce44SJohn Forte 6076*fcf3ce44SJohn Forte 6077*fcf3ce44SJohn Forte void 6078*fcf3ce44SJohn Forte fc_trace_free_logq(fc_trace_logq_t *logq) 6079*fcf3ce44SJohn Forte { 6080*fcf3ce44SJohn Forte mutex_enter(&logq->il_lock); 6081*fcf3ce44SJohn Forte while (logq->il_msgh) { 6082*fcf3ce44SJohn Forte fc_trace_freemsg(logq); 6083*fcf3ce44SJohn Forte } 6084*fcf3ce44SJohn Forte mutex_exit(&logq->il_lock); 6085*fcf3ce44SJohn Forte 6086*fcf3ce44SJohn Forte mutex_destroy(&logq->il_lock); 6087*fcf3ce44SJohn Forte kmem_free(logq, sizeof (*logq)); 6088*fcf3ce44SJohn Forte } 6089*fcf3ce44SJohn Forte 6090*fcf3ce44SJohn Forte 6091*fcf3ce44SJohn Forte /* ARGSUSED */ 6092*fcf3ce44SJohn Forte void 6093*fcf3ce44SJohn Forte fc_trace_logmsg(fc_trace_logq_t *logq, caddr_t buf, int level) 6094*fcf3ce44SJohn Forte { 6095*fcf3ce44SJohn Forte int qfull = 0; 6096*fcf3ce44SJohn Forte fc_trace_dmsg_t *dmsg; 6097*fcf3ce44SJohn Forte 6098*fcf3ce44SJohn Forte dmsg = kmem_alloc(sizeof (*dmsg), KM_NOSLEEP); 6099*fcf3ce44SJohn Forte if (dmsg == NULL) { 6100*fcf3ce44SJohn Forte mutex_enter(&logq->il_lock); 6101*fcf3ce44SJohn Forte logq->il_afail++; 6102*fcf3ce44SJohn Forte mutex_exit(&logq->il_lock); 6103*fcf3ce44SJohn Forte 6104*fcf3ce44SJohn Forte return; 6105*fcf3ce44SJohn Forte } 6106*fcf3ce44SJohn Forte 6107*fcf3ce44SJohn Forte gethrestime(&dmsg->id_time); 6108*fcf3ce44SJohn Forte 6109*fcf3ce44SJohn Forte dmsg->id_size = strlen(buf) + 1; 6110*fcf3ce44SJohn Forte dmsg->id_buf = kmem_alloc(dmsg->id_size, KM_NOSLEEP); 6111*fcf3ce44SJohn Forte if (dmsg->id_buf == NULL) { 6112*fcf3ce44SJohn Forte kmem_free(dmsg, sizeof (*dmsg)); 6113*fcf3ce44SJohn Forte 6114*fcf3ce44SJohn Forte mutex_enter(&logq->il_lock); 6115*fcf3ce44SJohn Forte logq->il_afail++; 6116*fcf3ce44SJohn Forte mutex_exit(&logq->il_lock); 6117*fcf3ce44SJohn Forte 6118*fcf3ce44SJohn Forte return; 6119*fcf3ce44SJohn Forte } 6120*fcf3ce44SJohn Forte bcopy(buf, dmsg->id_buf, strlen(buf)); 6121*fcf3ce44SJohn Forte dmsg->id_buf[strlen(buf)] = '\0'; 6122*fcf3ce44SJohn Forte 6123*fcf3ce44SJohn Forte mutex_enter(&logq->il_lock); 6124*fcf3ce44SJohn Forte 6125*fcf3ce44SJohn Forte logq->il_size += dmsg->id_size; 6126*fcf3ce44SJohn Forte if (logq->il_size >= logq->il_hiwat) { 6127*fcf3ce44SJohn Forte qfull = 1; 6128*fcf3ce44SJohn Forte } 6129*fcf3ce44SJohn Forte 6130*fcf3ce44SJohn Forte if (qfull) { 6131*fcf3ce44SJohn Forte fc_trace_freemsg(logq); 6132*fcf3ce44SJohn Forte } 6133*fcf3ce44SJohn Forte 6134*fcf3ce44SJohn Forte dmsg->id_next = NULL; 6135*fcf3ce44SJohn Forte if (logq->il_msgt) { 6136*fcf3ce44SJohn Forte logq->il_msgt->id_next = dmsg; 6137*fcf3ce44SJohn Forte } else { 6138*fcf3ce44SJohn Forte ASSERT(logq->il_msgh == NULL); 6139*fcf3ce44SJohn Forte logq->il_msgh = dmsg; 6140*fcf3ce44SJohn Forte } 6141*fcf3ce44SJohn Forte logq->il_msgt = dmsg; 6142*fcf3ce44SJohn Forte 6143*fcf3ce44SJohn Forte mutex_exit(&logq->il_lock); 6144*fcf3ce44SJohn Forte } 6145*fcf3ce44SJohn Forte 6146*fcf3ce44SJohn Forte 6147*fcf3ce44SJohn Forte static void 6148*fcf3ce44SJohn Forte fc_trace_freemsg(fc_trace_logq_t *logq) 6149*fcf3ce44SJohn Forte { 6150*fcf3ce44SJohn Forte fc_trace_dmsg_t *dmsg; 6151*fcf3ce44SJohn Forte 6152*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&logq->il_lock)); 6153*fcf3ce44SJohn Forte 6154*fcf3ce44SJohn Forte if ((dmsg = logq->il_msgh) != NULL) { 6155*fcf3ce44SJohn Forte logq->il_msgh = dmsg->id_next; 6156*fcf3ce44SJohn Forte if (logq->il_msgh == NULL) { 6157*fcf3ce44SJohn Forte logq->il_msgt = NULL; 6158*fcf3ce44SJohn Forte } 6159*fcf3ce44SJohn Forte 6160*fcf3ce44SJohn Forte logq->il_size -= dmsg->id_size; 6161*fcf3ce44SJohn Forte kmem_free(dmsg->id_buf, dmsg->id_size); 6162*fcf3ce44SJohn Forte kmem_free(dmsg, sizeof (*dmsg)); 6163*fcf3ce44SJohn Forte } else { 6164*fcf3ce44SJohn Forte ASSERT(logq->il_msgt == NULL); 6165*fcf3ce44SJohn Forte } 6166*fcf3ce44SJohn Forte } 6167*fcf3ce44SJohn Forte 6168*fcf3ce44SJohn Forte /* 6169*fcf3ce44SJohn Forte * Used by T11 FC-HBA to fetch discovered ports by index. 6170*fcf3ce44SJohn Forte * Returns NULL if the index isn't valid. 6171*fcf3ce44SJohn Forte */ 6172*fcf3ce44SJohn Forte fc_remote_port_t * 6173*fcf3ce44SJohn Forte fctl_lookup_pd_by_index(fc_local_port_t *port, uint32_t index) 6174*fcf3ce44SJohn Forte { 6175*fcf3ce44SJohn Forte int outer; 6176*fcf3ce44SJohn Forte int match = 0; 6177*fcf3ce44SJohn Forte struct pwwn_hash *head; 6178*fcf3ce44SJohn Forte fc_remote_port_t *pd; 6179*fcf3ce44SJohn Forte 6180*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 6181*fcf3ce44SJohn Forte 6182*fcf3ce44SJohn Forte for (outer = 0; 6183*fcf3ce44SJohn Forte outer < pwwn_table_size && match <= index; 6184*fcf3ce44SJohn Forte outer++) { 6185*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[outer]; 6186*fcf3ce44SJohn Forte pd = head->pwwn_head; 6187*fcf3ce44SJohn Forte if (pd != NULL) match ++; 6188*fcf3ce44SJohn Forte 6189*fcf3ce44SJohn Forte while (pd != NULL && match <= index) { 6190*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 6191*fcf3ce44SJohn Forte if (pd != NULL) match ++; 6192*fcf3ce44SJohn Forte } 6193*fcf3ce44SJohn Forte } 6194*fcf3ce44SJohn Forte 6195*fcf3ce44SJohn Forte return (pd); 6196*fcf3ce44SJohn Forte } 6197*fcf3ce44SJohn Forte 6198*fcf3ce44SJohn Forte /* 6199*fcf3ce44SJohn Forte * Search for a matching Node or Port WWN in the discovered port list 6200*fcf3ce44SJohn Forte */ 6201*fcf3ce44SJohn Forte fc_remote_port_t * 6202*fcf3ce44SJohn Forte fctl_lookup_pd_by_wwn(fc_local_port_t *port, la_wwn_t wwn) 6203*fcf3ce44SJohn Forte { 6204*fcf3ce44SJohn Forte int index; 6205*fcf3ce44SJohn Forte struct pwwn_hash *head; 6206*fcf3ce44SJohn Forte fc_remote_port_t *pd; 6207*fcf3ce44SJohn Forte 6208*fcf3ce44SJohn Forte ASSERT(MUTEX_HELD(&port->fp_mutex)); 6209*fcf3ce44SJohn Forte 6210*fcf3ce44SJohn Forte for (index = 0; index < pwwn_table_size; index++) { 6211*fcf3ce44SJohn Forte head = &port->fp_pwwn_table[index]; 6212*fcf3ce44SJohn Forte pd = head->pwwn_head; 6213*fcf3ce44SJohn Forte 6214*fcf3ce44SJohn Forte while (pd != NULL) { 6215*fcf3ce44SJohn Forte mutex_enter(&pd->pd_mutex); 6216*fcf3ce44SJohn Forte if (bcmp(pd->pd_port_name.raw_wwn, wwn.raw_wwn, 6217*fcf3ce44SJohn Forte sizeof (la_wwn_t)) == 0) { 6218*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 6219*fcf3ce44SJohn Forte return (pd); 6220*fcf3ce44SJohn Forte } 6221*fcf3ce44SJohn Forte if (bcmp(pd->pd_remote_nodep->fd_node_name.raw_wwn, wwn.raw_wwn, 6222*fcf3ce44SJohn Forte sizeof (la_wwn_t)) == 0) { 6223*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 6224*fcf3ce44SJohn Forte return (pd); 6225*fcf3ce44SJohn Forte } 6226*fcf3ce44SJohn Forte mutex_exit(&pd->pd_mutex); 6227*fcf3ce44SJohn Forte pd = pd->pd_wwn_hnext; 6228*fcf3ce44SJohn Forte } 6229*fcf3ce44SJohn Forte } 6230*fcf3ce44SJohn Forte /* No match */ 6231*fcf3ce44SJohn Forte return (NULL); 6232*fcf3ce44SJohn Forte } 6233*fcf3ce44SJohn Forte 6234*fcf3ce44SJohn Forte 6235*fcf3ce44SJohn Forte /* 6236*fcf3ce44SJohn Forte * Count the number of ports on this adapter. 6237*fcf3ce44SJohn Forte * This routine will walk the port list and count up the number of adapters 6238*fcf3ce44SJohn Forte * with matching fp_hba_port_attrs.hba_fru_details.high and 6239*fcf3ce44SJohn Forte * fp_hba_port_attrs.hba_fru_details.low. 6240*fcf3ce44SJohn Forte * 6241*fcf3ce44SJohn Forte * port->fp_mutex must not be held. 6242*fcf3ce44SJohn Forte */ 6243*fcf3ce44SJohn Forte int 6244*fcf3ce44SJohn Forte fctl_count_fru_ports(fc_local_port_t *port, int npivflag) 6245*fcf3ce44SJohn Forte { 6246*fcf3ce44SJohn Forte fca_hba_fru_details_t *fru; 6247*fcf3ce44SJohn Forte fc_fca_port_t *fca_port; 6248*fcf3ce44SJohn Forte fc_local_port_t *tmpPort = NULL; 6249*fcf3ce44SJohn Forte uint32_t count = 1; 6250*fcf3ce44SJohn Forte 6251*fcf3ce44SJohn Forte mutex_enter(&fctl_port_lock); 6252*fcf3ce44SJohn Forte 6253*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 6254*fcf3ce44SJohn Forte fru = &port->fp_hba_port_attrs.hba_fru_details; 6255*fcf3ce44SJohn Forte 6256*fcf3ce44SJohn Forte /* Detect FCA drivers that don't support linking HBA ports */ 6257*fcf3ce44SJohn Forte if (fru->high == 0 && fru->low == 0 && fru->port_index == 0) { 6258*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6259*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 6260*fcf3ce44SJohn Forte return (1); 6261*fcf3ce44SJohn Forte } 6262*fcf3ce44SJohn Forte 6263*fcf3ce44SJohn Forte for (fca_port = fctl_fca_portlist; fca_port != NULL; 6264*fcf3ce44SJohn Forte fca_port = fca_port->port_next) { 6265*fcf3ce44SJohn Forte tmpPort = fca_port->port_handle; 6266*fcf3ce44SJohn Forte if (tmpPort == port) { 6267*fcf3ce44SJohn Forte continue; 6268*fcf3ce44SJohn Forte } 6269*fcf3ce44SJohn Forte mutex_enter(&tmpPort->fp_mutex); 6270*fcf3ce44SJohn Forte 6271*fcf3ce44SJohn Forte /* 6272*fcf3ce44SJohn Forte * If an FCA driver returns unique fru->high and fru->low for 6273*fcf3ce44SJohn Forte * ports on the same card, there is no way for the transport 6274*fcf3ce44SJohn Forte * layer to determine that the two ports on the same FRU. So, 6275*fcf3ce44SJohn Forte * the discovery of the ports on a same FRU is limited to what 6276*fcf3ce44SJohn Forte * the FCA driver can report back. 6277*fcf3ce44SJohn Forte */ 6278*fcf3ce44SJohn Forte if (tmpPort->fp_hba_port_attrs.hba_fru_details.high == 6279*fcf3ce44SJohn Forte fru->high && 6280*fcf3ce44SJohn Forte tmpPort->fp_hba_port_attrs.hba_fru_details.low == 6281*fcf3ce44SJohn Forte fru->low) { 6282*fcf3ce44SJohn Forte /* Now double check driver */ 6283*fcf3ce44SJohn Forte if (strncmp(port->fp_hba_port_attrs.driver_name, 6284*fcf3ce44SJohn Forte tmpPort->fp_hba_port_attrs.driver_name, 6285*fcf3ce44SJohn Forte FCHBA_DRIVER_NAME_LEN) == 0) { 6286*fcf3ce44SJohn Forte if (!npivflag || 6287*fcf3ce44SJohn Forte (tmpPort->fp_npiv_type != FC_NPIV_PORT)) { 6288*fcf3ce44SJohn Forte count++; 6289*fcf3ce44SJohn Forte } 6290*fcf3ce44SJohn Forte } /* Else, different FCA driver */ 6291*fcf3ce44SJohn Forte } /* Else not the same HBA FRU */ 6292*fcf3ce44SJohn Forte mutex_exit(&tmpPort->fp_mutex); 6293*fcf3ce44SJohn Forte } 6294*fcf3ce44SJohn Forte 6295*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6296*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 6297*fcf3ce44SJohn Forte 6298*fcf3ce44SJohn Forte return (count); 6299*fcf3ce44SJohn Forte } 6300*fcf3ce44SJohn Forte 6301*fcf3ce44SJohn Forte fc_fca_port_t * 6302*fcf3ce44SJohn Forte fctl_local_port_list_add(fc_fca_port_t *list, fc_local_port_t *port) 6303*fcf3ce44SJohn Forte { 6304*fcf3ce44SJohn Forte fc_fca_port_t *tmp = list, *newentry = NULL; 6305*fcf3ce44SJohn Forte 6306*fcf3ce44SJohn Forte newentry = kmem_zalloc(sizeof (fc_fca_port_t), KM_NOSLEEP); 6307*fcf3ce44SJohn Forte if (newentry == NULL) { 6308*fcf3ce44SJohn Forte return (list); 6309*fcf3ce44SJohn Forte } 6310*fcf3ce44SJohn Forte newentry->port_handle = port; 6311*fcf3ce44SJohn Forte 6312*fcf3ce44SJohn Forte if (tmp == NULL) { 6313*fcf3ce44SJohn Forte return (newentry); 6314*fcf3ce44SJohn Forte } 6315*fcf3ce44SJohn Forte while (tmp->port_next != NULL) tmp = tmp->port_next; 6316*fcf3ce44SJohn Forte tmp->port_next = newentry; 6317*fcf3ce44SJohn Forte 6318*fcf3ce44SJohn Forte return (list); 6319*fcf3ce44SJohn Forte } 6320*fcf3ce44SJohn Forte 6321*fcf3ce44SJohn Forte void 6322*fcf3ce44SJohn Forte fctl_local_port_list_free(fc_fca_port_t *list) 6323*fcf3ce44SJohn Forte { 6324*fcf3ce44SJohn Forte fc_fca_port_t *tmp = list, *nextentry; 6325*fcf3ce44SJohn Forte 6326*fcf3ce44SJohn Forte if (tmp == NULL) { 6327*fcf3ce44SJohn Forte return; 6328*fcf3ce44SJohn Forte } 6329*fcf3ce44SJohn Forte 6330*fcf3ce44SJohn Forte while (tmp != NULL) { 6331*fcf3ce44SJohn Forte nextentry = tmp->port_next; 6332*fcf3ce44SJohn Forte kmem_free(tmp, sizeof (*tmp)); 6333*fcf3ce44SJohn Forte tmp = nextentry; 6334*fcf3ce44SJohn Forte } 6335*fcf3ce44SJohn Forte } 6336*fcf3ce44SJohn Forte 6337*fcf3ce44SJohn Forte /* 6338*fcf3ce44SJohn Forte * Fetch another port on the HBA FRU based on index. 6339*fcf3ce44SJohn Forte * Returns NULL if index not found. 6340*fcf3ce44SJohn Forte * 6341*fcf3ce44SJohn Forte * port->fp_mutex must not be held. 6342*fcf3ce44SJohn Forte */ 6343*fcf3ce44SJohn Forte fc_local_port_t * 6344*fcf3ce44SJohn Forte fctl_get_adapter_port_by_index(fc_local_port_t *port, uint32_t port_index) 6345*fcf3ce44SJohn Forte { 6346*fcf3ce44SJohn Forte fca_hba_fru_details_t *fru; 6347*fcf3ce44SJohn Forte fc_fca_port_t *fca_port; 6348*fcf3ce44SJohn Forte fc_local_port_t *tmpPort = NULL; 6349*fcf3ce44SJohn Forte fc_fca_port_t *list = NULL, *tmpEntry; 6350*fcf3ce44SJohn Forte fc_local_port_t *phyPort, *virPort = NULL; 6351*fcf3ce44SJohn Forte int index, phyPortNum = 0; 6352*fcf3ce44SJohn Forte 6353*fcf3ce44SJohn Forte mutex_enter(&fctl_port_lock); 6354*fcf3ce44SJohn Forte 6355*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 6356*fcf3ce44SJohn Forte fru = &port->fp_hba_port_attrs.hba_fru_details; 6357*fcf3ce44SJohn Forte 6358*fcf3ce44SJohn Forte /* Are we looking for this port? */ 6359*fcf3ce44SJohn Forte if (fru->port_index == port_index) { 6360*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6361*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 6362*fcf3ce44SJohn Forte return (port); 6363*fcf3ce44SJohn Forte } 6364*fcf3ce44SJohn Forte 6365*fcf3ce44SJohn Forte /* Detect FCA drivers that don't support linking HBA ports */ 6366*fcf3ce44SJohn Forte if (fru->high == 0 && fru->low == 0 && fru->port_index == 0) { 6367*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6368*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 6369*fcf3ce44SJohn Forte return (NULL); 6370*fcf3ce44SJohn Forte } 6371*fcf3ce44SJohn Forte 6372*fcf3ce44SJohn Forte list = fctl_local_port_list_add(list, port); 6373*fcf3ce44SJohn Forte phyPortNum++; 6374*fcf3ce44SJohn Forte /* Loop through all known ports */ 6375*fcf3ce44SJohn Forte for (fca_port = fctl_fca_portlist; fca_port != NULL; 6376*fcf3ce44SJohn Forte fca_port = fca_port->port_next) { 6377*fcf3ce44SJohn Forte tmpPort = fca_port->port_handle; 6378*fcf3ce44SJohn Forte if (tmpPort == port) { 6379*fcf3ce44SJohn Forte /* Skip over the port that was passed in as the argument */ 6380*fcf3ce44SJohn Forte continue; 6381*fcf3ce44SJohn Forte } 6382*fcf3ce44SJohn Forte mutex_enter(&tmpPort->fp_mutex); 6383*fcf3ce44SJohn Forte 6384*fcf3ce44SJohn Forte /* See if this port is on the same HBA FRU (fast check) */ 6385*fcf3ce44SJohn Forte if (tmpPort->fp_hba_port_attrs.hba_fru_details.high == 6386*fcf3ce44SJohn Forte fru->high && 6387*fcf3ce44SJohn Forte tmpPort->fp_hba_port_attrs.hba_fru_details.low == 6388*fcf3ce44SJohn Forte fru->low) { 6389*fcf3ce44SJohn Forte /* Now double check driver (slower check) */ 6390*fcf3ce44SJohn Forte if (strncmp(port->fp_hba_port_attrs.driver_name, 6391*fcf3ce44SJohn Forte tmpPort->fp_hba_port_attrs.driver_name, 6392*fcf3ce44SJohn Forte FCHBA_DRIVER_NAME_LEN) == 0) { 6393*fcf3ce44SJohn Forte 6394*fcf3ce44SJohn Forte fru = &tmpPort->fp_hba_port_attrs.hba_fru_details; 6395*fcf3ce44SJohn Forte /* Check for the matching port_index */ 6396*fcf3ce44SJohn Forte if ((tmpPort->fp_npiv_type != FC_NPIV_PORT) && 6397*fcf3ce44SJohn Forte (fru->port_index == port_index)) { 6398*fcf3ce44SJohn Forte /* Found it! */ 6399*fcf3ce44SJohn Forte mutex_exit(&tmpPort->fp_mutex); 6400*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6401*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 6402*fcf3ce44SJohn Forte fctl_local_port_list_free(list); 6403*fcf3ce44SJohn Forte return (tmpPort); 6404*fcf3ce44SJohn Forte } 6405*fcf3ce44SJohn Forte if (tmpPort->fp_npiv_type != FC_NPIV_PORT) { 6406*fcf3ce44SJohn Forte (void) fctl_local_port_list_add(list, tmpPort); 6407*fcf3ce44SJohn Forte phyPortNum++; 6408*fcf3ce44SJohn Forte } 6409*fcf3ce44SJohn Forte } /* Else, different FCA driver */ 6410*fcf3ce44SJohn Forte } /* Else not the same HBA FRU */ 6411*fcf3ce44SJohn Forte mutex_exit(&tmpPort->fp_mutex); 6412*fcf3ce44SJohn Forte 6413*fcf3ce44SJohn Forte } 6414*fcf3ce44SJohn Forte 6415*fcf3ce44SJohn Forte /* scan all physical port on same chip to find virtual port */ 6416*fcf3ce44SJohn Forte tmpEntry = list; 6417*fcf3ce44SJohn Forte index = phyPortNum - 1; 6418*fcf3ce44SJohn Forte virPort = NULL; 6419*fcf3ce44SJohn Forte while (index < port_index) { 6420*fcf3ce44SJohn Forte if (tmpEntry == NULL) { 6421*fcf3ce44SJohn Forte break; 6422*fcf3ce44SJohn Forte } 6423*fcf3ce44SJohn Forte if (virPort == NULL) { 6424*fcf3ce44SJohn Forte phyPort = tmpEntry->port_handle; 6425*fcf3ce44SJohn Forte virPort = phyPort->fp_port_next; 6426*fcf3ce44SJohn Forte if (virPort == NULL) { 6427*fcf3ce44SJohn Forte tmpEntry = tmpEntry->port_next; 6428*fcf3ce44SJohn Forte continue; 6429*fcf3ce44SJohn Forte } 6430*fcf3ce44SJohn Forte } else { 6431*fcf3ce44SJohn Forte virPort = virPort->fp_port_next; 6432*fcf3ce44SJohn Forte } 6433*fcf3ce44SJohn Forte if (virPort == phyPort) { 6434*fcf3ce44SJohn Forte tmpEntry = tmpEntry->port_next; 6435*fcf3ce44SJohn Forte virPort = NULL; 6436*fcf3ce44SJohn Forte } else { 6437*fcf3ce44SJohn Forte index++; 6438*fcf3ce44SJohn Forte } 6439*fcf3ce44SJohn Forte } 6440*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6441*fcf3ce44SJohn Forte mutex_exit(&fctl_port_lock); 6442*fcf3ce44SJohn Forte 6443*fcf3ce44SJohn Forte fctl_local_port_list_free(list); 6444*fcf3ce44SJohn Forte if (virPort) { 6445*fcf3ce44SJohn Forte return (virPort); 6446*fcf3ce44SJohn Forte } 6447*fcf3ce44SJohn Forte return (NULL); 6448*fcf3ce44SJohn Forte } 6449*fcf3ce44SJohn Forte 6450*fcf3ce44SJohn Forte int 6451*fcf3ce44SJohn Forte fctl_busy_port(fc_local_port_t *port) 6452*fcf3ce44SJohn Forte { 6453*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 6454*fcf3ce44SJohn Forte 6455*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 6456*fcf3ce44SJohn Forte if (port->fp_soft_state & FP_SOFT_NO_PMCOMP) { 6457*fcf3ce44SJohn Forte /* 6458*fcf3ce44SJohn Forte * If fctl_busy_port() is called before we've registered our 6459*fcf3ce44SJohn Forte * PM components, we return success. We need to be aware of 6460*fcf3ce44SJohn Forte * this because the caller will eventually call fctl_idle_port. 6461*fcf3ce44SJohn Forte * This wouldn't be a problem except that if we have 6462*fcf3ce44SJohn Forte * registered our PM components in the meantime, we will 6463*fcf3ce44SJohn Forte * then be idling a component that was never busied. PM 6464*fcf3ce44SJohn Forte * will be very unhappy if we do this. Thus, we keep 6465*fcf3ce44SJohn Forte * track of this with port->fp_pm_busy_nocomp. 6466*fcf3ce44SJohn Forte */ 6467*fcf3ce44SJohn Forte port->fp_pm_busy_nocomp++; 6468*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6469*fcf3ce44SJohn Forte return (0); 6470*fcf3ce44SJohn Forte } 6471*fcf3ce44SJohn Forte port->fp_pm_busy++; 6472*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6473*fcf3ce44SJohn Forte 6474*fcf3ce44SJohn Forte if (pm_busy_component(port->fp_port_dip, 6475*fcf3ce44SJohn Forte FP_PM_COMPONENT) != DDI_SUCCESS) { 6476*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 6477*fcf3ce44SJohn Forte port->fp_pm_busy--; 6478*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6479*fcf3ce44SJohn Forte return (ENXIO); 6480*fcf3ce44SJohn Forte } 6481*fcf3ce44SJohn Forte 6482*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 6483*fcf3ce44SJohn Forte if (port->fp_pm_level == FP_PM_PORT_DOWN) { 6484*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6485*fcf3ce44SJohn Forte if (pm_raise_power(port->fp_port_dip, FP_PM_COMPONENT, 6486*fcf3ce44SJohn Forte FP_PM_PORT_UP) != DDI_SUCCESS) { 6487*fcf3ce44SJohn Forte 6488*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 6489*fcf3ce44SJohn Forte port->fp_pm_busy--; 6490*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6491*fcf3ce44SJohn Forte 6492*fcf3ce44SJohn Forte (void) pm_idle_component(port->fp_port_dip, 6493*fcf3ce44SJohn Forte FP_PM_COMPONENT); 6494*fcf3ce44SJohn Forte return (EIO); 6495*fcf3ce44SJohn Forte } 6496*fcf3ce44SJohn Forte return (0); 6497*fcf3ce44SJohn Forte } 6498*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6499*fcf3ce44SJohn Forte return (0); 6500*fcf3ce44SJohn Forte } 6501*fcf3ce44SJohn Forte 6502*fcf3ce44SJohn Forte void 6503*fcf3ce44SJohn Forte fctl_idle_port(fc_local_port_t *port) 6504*fcf3ce44SJohn Forte { 6505*fcf3ce44SJohn Forte ASSERT(!MUTEX_HELD(&port->fp_mutex)); 6506*fcf3ce44SJohn Forte 6507*fcf3ce44SJohn Forte mutex_enter(&port->fp_mutex); 6508*fcf3ce44SJohn Forte 6509*fcf3ce44SJohn Forte /* 6510*fcf3ce44SJohn Forte * If port->fp_pm_busy_nocomp is > 0, that means somebody had 6511*fcf3ce44SJohn Forte * called fctl_busy_port prior to us registering our PM components. 6512*fcf3ce44SJohn Forte * In that case, we just decrement fp_pm_busy_nocomp and return. 6513*fcf3ce44SJohn Forte */ 6514*fcf3ce44SJohn Forte 6515*fcf3ce44SJohn Forte if (port->fp_pm_busy_nocomp > 0) { 6516*fcf3ce44SJohn Forte port->fp_pm_busy_nocomp--; 6517*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6518*fcf3ce44SJohn Forte return; 6519*fcf3ce44SJohn Forte } 6520*fcf3ce44SJohn Forte 6521*fcf3ce44SJohn Forte port->fp_pm_busy--; 6522*fcf3ce44SJohn Forte mutex_exit(&port->fp_mutex); 6523*fcf3ce44SJohn Forte 6524*fcf3ce44SJohn Forte (void) pm_idle_component(port->fp_port_dip, FP_PM_COMPONENT); 6525*fcf3ce44SJohn Forte } 6526*fcf3ce44SJohn Forte 6527*fcf3ce44SJohn Forte /* 6528*fcf3ce44SJohn Forte * Function: fctl_tc_timer 6529*fcf3ce44SJohn Forte * 6530*fcf3ce44SJohn Forte * Description: Resets the value of the timed counter. 6531*fcf3ce44SJohn Forte * 6532*fcf3ce44SJohn Forte * Arguments: *tc Timed counter 6533*fcf3ce44SJohn Forte * 6534*fcf3ce44SJohn Forte * Return Value: Nothing 6535*fcf3ce44SJohn Forte * 6536*fcf3ce44SJohn Forte * Context: Kernel context. 6537*fcf3ce44SJohn Forte */ 6538*fcf3ce44SJohn Forte static void 6539*fcf3ce44SJohn Forte fctl_tc_timer( 6540*fcf3ce44SJohn Forte void *arg 6541*fcf3ce44SJohn Forte ) 6542*fcf3ce44SJohn Forte { 6543*fcf3ce44SJohn Forte timed_counter_t *tc = (timed_counter_t *)arg; 6544*fcf3ce44SJohn Forte 6545*fcf3ce44SJohn Forte ASSERT(tc != NULL); 6546*fcf3ce44SJohn Forte ASSERT(tc->sig == tc); 6547*fcf3ce44SJohn Forte 6548*fcf3ce44SJohn Forte mutex_enter(&tc->mutex); 6549*fcf3ce44SJohn Forte if (tc->active) { 6550*fcf3ce44SJohn Forte tc->active = B_FALSE; 6551*fcf3ce44SJohn Forte tc->counter = 0; 6552*fcf3ce44SJohn Forte } 6553*fcf3ce44SJohn Forte mutex_exit(&tc->mutex); 6554*fcf3ce44SJohn Forte } 6555*fcf3ce44SJohn Forte 6556*fcf3ce44SJohn Forte /* 6557*fcf3ce44SJohn Forte * Function: fctl_tc_constructor 6558*fcf3ce44SJohn Forte * 6559*fcf3ce44SJohn Forte * Description: Constructs a timed counter. 6560*fcf3ce44SJohn Forte * 6561*fcf3ce44SJohn Forte * Arguments: *tc Address where the timed counter will reside. 6562*fcf3ce44SJohn Forte * max_value Maximum value the counter is allowed to take. 6563*fcf3ce44SJohn Forte * timer Number of microseconds after which the counter 6564*fcf3ce44SJohn Forte * will be reset. The timer is started when the 6565*fcf3ce44SJohn Forte * value of the counter goes from 0 to 1. 6566*fcf3ce44SJohn Forte * 6567*fcf3ce44SJohn Forte * Return Value: Nothing 6568*fcf3ce44SJohn Forte * 6569*fcf3ce44SJohn Forte * Context: Kernel context. 6570*fcf3ce44SJohn Forte */ 6571*fcf3ce44SJohn Forte void 6572*fcf3ce44SJohn Forte fctl_tc_constructor( 6573*fcf3ce44SJohn Forte timed_counter_t *tc, 6574*fcf3ce44SJohn Forte uint32_t max_value, 6575*fcf3ce44SJohn Forte clock_t timer 6576*fcf3ce44SJohn Forte ) 6577*fcf3ce44SJohn Forte { 6578*fcf3ce44SJohn Forte ASSERT(tc != NULL); 6579*fcf3ce44SJohn Forte ASSERT(tc->sig != tc); 6580*fcf3ce44SJohn Forte 6581*fcf3ce44SJohn Forte bzero(tc, sizeof (*tc)); 6582*fcf3ce44SJohn Forte mutex_init(&tc->mutex, NULL, MUTEX_DRIVER, NULL); 6583*fcf3ce44SJohn Forte tc->timer = drv_usectohz(timer); 6584*fcf3ce44SJohn Forte tc->active = B_FALSE; 6585*fcf3ce44SJohn Forte tc->maxed_out = B_FALSE; 6586*fcf3ce44SJohn Forte tc->max_value = max_value; 6587*fcf3ce44SJohn Forte tc->sig = tc; 6588*fcf3ce44SJohn Forte } 6589*fcf3ce44SJohn Forte 6590*fcf3ce44SJohn Forte /* 6591*fcf3ce44SJohn Forte * Function: fctl_tc_destructor 6592*fcf3ce44SJohn Forte * 6593*fcf3ce44SJohn Forte * Description: Destroyes a timed counter. 6594*fcf3ce44SJohn Forte * 6595*fcf3ce44SJohn Forte * Arguments: *tc Timed counter to destroy. 6596*fcf3ce44SJohn Forte * 6597*fcf3ce44SJohn Forte * Return Value: Nothing 6598*fcf3ce44SJohn Forte * 6599*fcf3ce44SJohn Forte * Context: Kernel context. 6600*fcf3ce44SJohn Forte */ 6601*fcf3ce44SJohn Forte void 6602*fcf3ce44SJohn Forte fctl_tc_destructor( 6603*fcf3ce44SJohn Forte timed_counter_t *tc 6604*fcf3ce44SJohn Forte ) 6605*fcf3ce44SJohn Forte { 6606*fcf3ce44SJohn Forte ASSERT(tc != NULL); 6607*fcf3ce44SJohn Forte ASSERT(tc->sig == tc); 6608*fcf3ce44SJohn Forte ASSERT(!mutex_owned(&tc->mutex)); 6609*fcf3ce44SJohn Forte 6610*fcf3ce44SJohn Forte mutex_enter(&tc->mutex); 6611*fcf3ce44SJohn Forte if (tc->active) { 6612*fcf3ce44SJohn Forte tc->active = B_FALSE; 6613*fcf3ce44SJohn Forte (void) untimeout(tc->tid); 6614*fcf3ce44SJohn Forte tc->sig = NULL; 6615*fcf3ce44SJohn Forte } 6616*fcf3ce44SJohn Forte mutex_exit(&tc->mutex); 6617*fcf3ce44SJohn Forte mutex_destroy(&tc->mutex); 6618*fcf3ce44SJohn Forte } 6619*fcf3ce44SJohn Forte 6620*fcf3ce44SJohn Forte /* 6621*fcf3ce44SJohn Forte * Function: fctl_tc_increment 6622*fcf3ce44SJohn Forte * 6623*fcf3ce44SJohn Forte * Description: Increments a timed counter 6624*fcf3ce44SJohn Forte * 6625*fcf3ce44SJohn Forte * Arguments: *tc Timed counter to increment. 6626*fcf3ce44SJohn Forte * 6627*fcf3ce44SJohn Forte * Return Value: B_TRUE Counter reached the max value. 6628*fcf3ce44SJohn Forte * B_FALSE Counter hasn't reached the max value. 6629*fcf3ce44SJohn Forte * 6630*fcf3ce44SJohn Forte * Context: Kernel or interrupt context. 6631*fcf3ce44SJohn Forte */ 6632*fcf3ce44SJohn Forte boolean_t 6633*fcf3ce44SJohn Forte fctl_tc_increment( 6634*fcf3ce44SJohn Forte timed_counter_t *tc 6635*fcf3ce44SJohn Forte ) 6636*fcf3ce44SJohn Forte { 6637*fcf3ce44SJohn Forte ASSERT(tc != NULL); 6638*fcf3ce44SJohn Forte ASSERT(tc->sig == tc); 6639*fcf3ce44SJohn Forte 6640*fcf3ce44SJohn Forte mutex_enter(&tc->mutex); 6641*fcf3ce44SJohn Forte if (!tc->maxed_out) { 6642*fcf3ce44SJohn Forte /* Hasn't maxed out yet. */ 6643*fcf3ce44SJohn Forte ++tc->counter; 6644*fcf3ce44SJohn Forte if (tc->counter >= tc->max_value) { 6645*fcf3ce44SJohn Forte /* Just maxed out. */ 6646*fcf3ce44SJohn Forte tc->maxed_out = B_TRUE; 6647*fcf3ce44SJohn Forte } 6648*fcf3ce44SJohn Forte if (!tc->active) { 6649*fcf3ce44SJohn Forte tc->tid = timeout(fctl_tc_timer, tc, tc->timer); 6650*fcf3ce44SJohn Forte tc->active = B_TRUE; 6651*fcf3ce44SJohn Forte } 6652*fcf3ce44SJohn Forte } 6653*fcf3ce44SJohn Forte mutex_exit(&tc->mutex); 6654*fcf3ce44SJohn Forte 6655*fcf3ce44SJohn Forte return (tc->maxed_out); 6656*fcf3ce44SJohn Forte } 6657*fcf3ce44SJohn Forte 6658*fcf3ce44SJohn Forte /* 6659*fcf3ce44SJohn Forte * Function: fctl_tc_reset 6660*fcf3ce44SJohn Forte * 6661*fcf3ce44SJohn Forte * Description: Resets a timed counter. The caller of this function has to 6662*fcf3ce44SJohn Forte * to make sure that while in fctl_tc_reset() fctl_tc_increment() 6663*fcf3ce44SJohn Forte * is not called. 6664*fcf3ce44SJohn Forte * 6665*fcf3ce44SJohn Forte * Arguments: *tc Timed counter to reset. 6666*fcf3ce44SJohn Forte * 6667*fcf3ce44SJohn Forte * Return Value: 0 Counter reached the max value. 6668*fcf3ce44SJohn Forte * Not 0 Counter hasn't reached the max value. 6669*fcf3ce44SJohn Forte * 6670*fcf3ce44SJohn Forte * Context: Kernel or interrupt context. 6671*fcf3ce44SJohn Forte */ 6672*fcf3ce44SJohn Forte void 6673*fcf3ce44SJohn Forte fctl_tc_reset( 6674*fcf3ce44SJohn Forte timed_counter_t *tc 6675*fcf3ce44SJohn Forte ) 6676*fcf3ce44SJohn Forte { 6677*fcf3ce44SJohn Forte ASSERT(tc != NULL); 6678*fcf3ce44SJohn Forte ASSERT(tc->sig == tc); 6679*fcf3ce44SJohn Forte 6680*fcf3ce44SJohn Forte mutex_enter(&tc->mutex); 6681*fcf3ce44SJohn Forte tc->counter = 0; 6682*fcf3ce44SJohn Forte tc->maxed_out = B_FALSE; 6683*fcf3ce44SJohn Forte if (tc->active) { 6684*fcf3ce44SJohn Forte tc->active = B_FALSE; 6685*fcf3ce44SJohn Forte (void) untimeout(tc->tid); 6686*fcf3ce44SJohn Forte } 6687*fcf3ce44SJohn Forte mutex_exit(&tc->mutex); 6688*fcf3ce44SJohn Forte } 6689*fcf3ce44SJohn Forte 6690*fcf3ce44SJohn Forte void 6691*fcf3ce44SJohn Forte fc_ulp_log_device_event(opaque_t port_handle, int type) 6692*fcf3ce44SJohn Forte { 6693*fcf3ce44SJohn Forte fc_local_port_t *port = port_handle; 6694*fcf3ce44SJohn Forte nvlist_t *attr_list; 6695*fcf3ce44SJohn Forte 6696*fcf3ce44SJohn Forte if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, 6697*fcf3ce44SJohn Forte KM_SLEEP) != DDI_SUCCESS) { 6698*fcf3ce44SJohn Forte return; 6699*fcf3ce44SJohn Forte } 6700*fcf3ce44SJohn Forte 6701*fcf3ce44SJohn Forte if (nvlist_add_uint32(attr_list, "instance", 6702*fcf3ce44SJohn Forte port->fp_instance) != DDI_SUCCESS) { 6703*fcf3ce44SJohn Forte goto error; 6704*fcf3ce44SJohn Forte } 6705*fcf3ce44SJohn Forte 6706*fcf3ce44SJohn Forte if (nvlist_add_byte_array(attr_list, "port-wwn", 6707*fcf3ce44SJohn Forte port->fp_service_params.nport_ww_name.raw_wwn, 6708*fcf3ce44SJohn Forte sizeof (la_wwn_t)) != DDI_SUCCESS) { 6709*fcf3ce44SJohn Forte goto error; 6710*fcf3ce44SJohn Forte } 6711*fcf3ce44SJohn Forte 6712*fcf3ce44SJohn Forte (void) ddi_log_sysevent(port->fp_port_dip, DDI_VENDOR_SUNW, EC_SUNFC, 6713*fcf3ce44SJohn Forte (type == FC_ULP_DEVICE_ONLINE) ? 6714*fcf3ce44SJohn Forte ESC_SUNFC_DEVICE_ONLINE : ESC_SUNFC_DEVICE_OFFLINE, 6715*fcf3ce44SJohn Forte attr_list, NULL, DDI_SLEEP); 6716*fcf3ce44SJohn Forte nvlist_free(attr_list); 6717*fcf3ce44SJohn Forte return; 6718*fcf3ce44SJohn Forte 6719*fcf3ce44SJohn Forte error: 6720*fcf3ce44SJohn Forte nvlist_free(attr_list); 6721*fcf3ce44SJohn Forte } 6722