1130f4520SKenneth D. Merry /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3bec9534dSPedro F. Giffuni * 4130f4520SKenneth D. Merry * Copyright (c) 2003 Silicon Graphics International Corp. 5bb8f9017SAlexander Motin * Copyright (c) 2014-2017 Alexander Motin <mav@FreeBSD.org> 6130f4520SKenneth D. Merry * All rights reserved. 7130f4520SKenneth D. Merry * 8130f4520SKenneth D. Merry * Redistribution and use in source and binary forms, with or without 9130f4520SKenneth D. Merry * modification, are permitted provided that the following conditions 10130f4520SKenneth D. Merry * are met: 11130f4520SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright 12130f4520SKenneth D. Merry * notice, this list of conditions, and the following disclaimer, 13130f4520SKenneth D. Merry * without modification. 14130f4520SKenneth D. Merry * 2. Redistributions in binary form must reproduce at minimum a disclaimer 15130f4520SKenneth D. Merry * substantially similar to the "NO WARRANTY" disclaimer below 16130f4520SKenneth D. Merry * ("Disclaimer") and any redistribution must be conditioned upon 17130f4520SKenneth D. Merry * including a substantially similar Disclaimer requirement for further 18130f4520SKenneth D. Merry * binary redistribution. 19130f4520SKenneth D. Merry * 20130f4520SKenneth D. Merry * NO WARRANTY 21130f4520SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22130f4520SKenneth D. Merry * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23130f4520SKenneth D. Merry * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 24130f4520SKenneth D. Merry * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25130f4520SKenneth D. Merry * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26130f4520SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27130f4520SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28130f4520SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29130f4520SKenneth D. Merry * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30130f4520SKenneth D. Merry * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31130f4520SKenneth D. Merry * POSSIBILITY OF SUCH DAMAGES. 32130f4520SKenneth D. Merry * 33130f4520SKenneth D. Merry * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_frontend.c#4 $ 34130f4520SKenneth D. Merry */ 35130f4520SKenneth D. Merry /* 36130f4520SKenneth D. Merry * CAM Target Layer front end interface code 37130f4520SKenneth D. Merry * 38130f4520SKenneth D. Merry * Author: Ken Merry <ken@FreeBSD.org> 39130f4520SKenneth D. Merry */ 40130f4520SKenneth D. Merry 41130f4520SKenneth D. Merry #include <sys/param.h> 42130f4520SKenneth D. Merry #include <sys/systm.h> 43130f4520SKenneth D. Merry #include <sys/kernel.h> 44130f4520SKenneth D. Merry #include <sys/types.h> 45130f4520SKenneth D. Merry #include <sys/malloc.h> 46130f4520SKenneth D. Merry #include <sys/lock.h> 47130f4520SKenneth D. Merry #include <sys/mutex.h> 48130f4520SKenneth D. Merry #include <sys/condvar.h> 49130f4520SKenneth D. Merry #include <sys/endian.h> 50130f4520SKenneth D. Merry #include <sys/queue.h> 51bf8f8f34SKenneth D. Merry #include <sys/sysctl.h> 528951f055SMarcelo Araujo #include <sys/nv.h> 538951f055SMarcelo Araujo #include <sys/dnv.h> 54130f4520SKenneth D. Merry 55130f4520SKenneth D. Merry #include <cam/scsi/scsi_all.h> 56130f4520SKenneth D. Merry #include <cam/scsi/scsi_da.h> 57130f4520SKenneth D. Merry #include <cam/ctl/ctl_io.h> 58130f4520SKenneth D. Merry #include <cam/ctl/ctl.h> 59130f4520SKenneth D. Merry #include <cam/ctl/ctl_frontend.h> 60130f4520SKenneth D. Merry #include <cam/ctl/ctl_backend.h> 61130f4520SKenneth D. Merry /* XXX KDM move defines from ctl_ioctl.h to somewhere else */ 62130f4520SKenneth D. Merry #include <cam/ctl/ctl_ioctl.h> 63130f4520SKenneth D. Merry #include <cam/ctl/ctl_ha.h> 64130f4520SKenneth D. Merry #include <cam/ctl/ctl_private.h> 65130f4520SKenneth D. Merry #include <cam/ctl/ctl_debug.h> 66130f4520SKenneth D. Merry 67130f4520SKenneth D. Merry int 6892168f4cSAlexander Motin ctl_frontend_register(struct ctl_frontend *fe) 6992168f4cSAlexander Motin { 709602f436SAlexander Motin struct ctl_softc *softc = control_softc; 7192168f4cSAlexander Motin struct ctl_frontend *fe_tmp; 720c629e28SAlexander Motin int error; 7392168f4cSAlexander Motin 749602f436SAlexander Motin KASSERT(softc != NULL, ("CTL is not initialized")); 7592168f4cSAlexander Motin 760c629e28SAlexander Motin /* Sanity check, make sure this isn't a duplicate registration. */ 779602f436SAlexander Motin mtx_lock(&softc->ctl_lock); 789602f436SAlexander Motin STAILQ_FOREACH(fe_tmp, &softc->fe_list, links) { 7992168f4cSAlexander Motin if (strcmp(fe_tmp->name, fe->name) == 0) { 809602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 8192168f4cSAlexander Motin return (-1); 8292168f4cSAlexander Motin } 8392168f4cSAlexander Motin } 849602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 8592168f4cSAlexander Motin STAILQ_INIT(&fe->port_list); 8692168f4cSAlexander Motin 870c629e28SAlexander Motin /* Call the frontend's initialization routine. */ 880c629e28SAlexander Motin if (fe->init != NULL) { 890c629e28SAlexander Motin if ((error = fe->init()) != 0) { 900c629e28SAlexander Motin printf("%s frontend init error: %d\n", 910c629e28SAlexander Motin fe->name, error); 920c629e28SAlexander Motin return (error); 930c629e28SAlexander Motin } 940c629e28SAlexander Motin } 9592168f4cSAlexander Motin 969602f436SAlexander Motin mtx_lock(&softc->ctl_lock); 979602f436SAlexander Motin softc->num_frontends++; 989602f436SAlexander Motin STAILQ_INSERT_TAIL(&softc->fe_list, fe, links); 999602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 10092168f4cSAlexander Motin return (0); 10192168f4cSAlexander Motin } 10292168f4cSAlexander Motin 10392168f4cSAlexander Motin int 10492168f4cSAlexander Motin ctl_frontend_deregister(struct ctl_frontend *fe) 10592168f4cSAlexander Motin { 1069602f436SAlexander Motin struct ctl_softc *softc = control_softc; 1070c629e28SAlexander Motin int error; 10892168f4cSAlexander Motin 1090c629e28SAlexander Motin /* Call the frontend's shutdown routine.*/ 1100c629e28SAlexander Motin if (fe->shutdown != NULL) { 1110c629e28SAlexander Motin if ((error = fe->shutdown()) != 0) { 1120c629e28SAlexander Motin printf("%s frontend shutdown error: %d\n", 1130c629e28SAlexander Motin fe->name, error); 1140c629e28SAlexander Motin return (error); 1150c629e28SAlexander Motin } 1160c629e28SAlexander Motin } 11792168f4cSAlexander Motin 1189602f436SAlexander Motin mtx_lock(&softc->ctl_lock); 1199602f436SAlexander Motin STAILQ_REMOVE(&softc->fe_list, fe, ctl_frontend, links); 1209602f436SAlexander Motin softc->num_frontends--; 1219602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 12292168f4cSAlexander Motin return (0); 12392168f4cSAlexander Motin } 12492168f4cSAlexander Motin 125ab2616c5SAlexander Motin struct ctl_frontend * 126ab2616c5SAlexander Motin ctl_frontend_find(char *frontend_name) 127ab2616c5SAlexander Motin { 1289602f436SAlexander Motin struct ctl_softc *softc = control_softc; 129ab2616c5SAlexander Motin struct ctl_frontend *fe; 130ab2616c5SAlexander Motin 1319602f436SAlexander Motin mtx_lock(&softc->ctl_lock); 1329602f436SAlexander Motin STAILQ_FOREACH(fe, &softc->fe_list, links) { 133ab2616c5SAlexander Motin if (strcmp(fe->name, frontend_name) == 0) { 1349602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 135ab2616c5SAlexander Motin return (fe); 136ab2616c5SAlexander Motin } 137ab2616c5SAlexander Motin } 1389602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 139ab2616c5SAlexander Motin return (NULL); 140ab2616c5SAlexander Motin } 141ab2616c5SAlexander Motin 14292168f4cSAlexander Motin int 14323b30f56SAlexander Motin ctl_port_register(struct ctl_port *port) 144130f4520SKenneth D. Merry { 1459602f436SAlexander Motin struct ctl_softc *softc = control_softc; 1467ac58230SAlexander Motin struct ctl_port *tport, *nport; 1471251a76bSAlexander Motin void *pool; 148130f4520SKenneth D. Merry int port_num; 149130f4520SKenneth D. Merry int retval; 150130f4520SKenneth D. Merry 1519602f436SAlexander Motin KASSERT(softc != NULL, ("CTL is not initialized")); 15221d963e5SAlexander Motin port->ctl_softc = softc; 153130f4520SKenneth D. Merry 1549602f436SAlexander Motin mtx_lock(&softc->ctl_lock); 1557ac58230SAlexander Motin if (port->targ_port >= 0) 1567ac58230SAlexander Motin port_num = port->targ_port; 1577ac58230SAlexander Motin else 1587ac58230SAlexander Motin port_num = ctl_ffz(softc->ctl_port_mask, 1597ac58230SAlexander Motin softc->port_min, softc->port_max); 1607ac58230SAlexander Motin if ((port_num < 0) || 1617ac58230SAlexander Motin (ctl_set_mask(softc->ctl_port_mask, port_num) < 0)) { 1629602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 163*e03e77baSJohn Baldwin return (EBUSY); 164130f4520SKenneth D. Merry } 1659602f436SAlexander Motin softc->num_ports++; 1669602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 16792168f4cSAlexander Motin 168130f4520SKenneth D. Merry /* 169604e2579SAlexander Motin * Initialize the initiator and portname mappings 170604e2579SAlexander Motin */ 171604e2579SAlexander Motin port->max_initiators = CTL_MAX_INIT_PER_PORT; 172ac2fffa4SPedro F. Giffuni port->wwpn_iid = malloc(sizeof(*port->wwpn_iid) * port->max_initiators, 173ac2fffa4SPedro F. Giffuni M_CTL, M_NOWAIT | M_ZERO); 174604e2579SAlexander Motin if (port->wwpn_iid == NULL) { 175604e2579SAlexander Motin retval = ENOMEM; 176604e2579SAlexander Motin goto error; 177604e2579SAlexander Motin } 178604e2579SAlexander Motin 179604e2579SAlexander Motin /* 180130f4520SKenneth D. Merry * We add 20 to whatever the caller requests, so he doesn't get 181130f4520SKenneth D. Merry * burned by queueing things back to the pending sense queue. In 182130f4520SKenneth D. Merry * theory, there should probably only be one outstanding item, at 183130f4520SKenneth D. Merry * most, on the pending sense queue for a LUN. We'll clear the 184130f4520SKenneth D. Merry * pending sense queue on the next command, whether or not it is 185130f4520SKenneth D. Merry * a REQUEST SENSE. 186130f4520SKenneth D. Merry */ 1879602f436SAlexander Motin retval = ctl_pool_create(softc, port->port_name, 18892168f4cSAlexander Motin port->num_requested_ctl_io + 20, &pool); 189130f4520SKenneth D. Merry if (retval != 0) { 190604e2579SAlexander Motin free(port->wwpn_iid, M_CTL); 191604e2579SAlexander Motin error: 19292168f4cSAlexander Motin port->targ_port = -1; 1939602f436SAlexander Motin mtx_lock(&softc->ctl_lock); 1949602f436SAlexander Motin ctl_clear_mask(softc->ctl_port_mask, port_num); 1959602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 196130f4520SKenneth D. Merry return (retval); 197130f4520SKenneth D. Merry } 198bb8f9017SAlexander Motin port->targ_port = port_num; 19992168f4cSAlexander Motin port->ctl_pool_ref = pool; 2008951f055SMarcelo Araujo if (port->options == NULL) 2018951f055SMarcelo Araujo port->options = nvlist_create(0); 202bb8f9017SAlexander Motin port->stats.item = port_num; 203bb8f9017SAlexander Motin mtx_init(&port->port_lock, "CTL port", NULL, MTX_DEF); 204917d38fbSAlexander Motin 2059602f436SAlexander Motin mtx_lock(&softc->ctl_lock); 206487ddad5SAlexander Motin STAILQ_INSERT_TAIL(&port->frontend->port_list, port, fe_links); 2077ac58230SAlexander Motin for (tport = NULL, nport = STAILQ_FIRST(&softc->port_list); 2087ac58230SAlexander Motin nport != NULL && nport->targ_port < port_num; 2097ac58230SAlexander Motin tport = nport, nport = STAILQ_NEXT(tport, links)) { 2107ac58230SAlexander Motin } 2117ac58230SAlexander Motin if (tport) 2127ac58230SAlexander Motin STAILQ_INSERT_AFTER(&softc->port_list, tport, port, links); 2137ac58230SAlexander Motin else 2147ac58230SAlexander Motin STAILQ_INSERT_HEAD(&softc->port_list, port, links); 2157ac58230SAlexander Motin softc->ctl_ports[port->targ_port] = port; 2169602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 217130f4520SKenneth D. Merry 218130f4520SKenneth D. Merry return (retval); 219130f4520SKenneth D. Merry } 220130f4520SKenneth D. Merry 221130f4520SKenneth D. Merry int 22292168f4cSAlexander Motin ctl_port_deregister(struct ctl_port *port) 223130f4520SKenneth D. Merry { 22421d963e5SAlexander Motin struct ctl_softc *softc = port->ctl_softc; 225bb8f9017SAlexander Motin struct ctl_io_pool *pool = (struct ctl_io_pool *)port->ctl_pool_ref; 226bb8f9017SAlexander Motin int i; 227130f4520SKenneth D. Merry 228bb8f9017SAlexander Motin if (port->targ_port == -1) 229bb8f9017SAlexander Motin return (1); 230130f4520SKenneth D. Merry 2319602f436SAlexander Motin mtx_lock(&softc->ctl_lock); 2329602f436SAlexander Motin STAILQ_REMOVE(&softc->port_list, port, ctl_port, links); 23392168f4cSAlexander Motin STAILQ_REMOVE(&port->frontend->port_list, port, ctl_port, fe_links); 2349602f436SAlexander Motin softc->num_ports--; 2357ac58230SAlexander Motin ctl_clear_mask(softc->ctl_port_mask, port->targ_port); 2367ac58230SAlexander Motin softc->ctl_ports[port->targ_port] = NULL; 2379602f436SAlexander Motin mtx_unlock(&softc->ctl_lock); 2388c6d5f82SAlexander Motin 2398c6d5f82SAlexander Motin ctl_pool_free(pool); 2408951f055SMarcelo Araujo nvlist_destroy(port->options); 2418c6d5f82SAlexander Motin 242920c6cbaSAlexander Motin ctl_lun_map_deinit(port); 243027e5269SAlexander Motin free(port->port_devid, M_CTL); 244027e5269SAlexander Motin port->port_devid = NULL; 245027e5269SAlexander Motin free(port->target_devid, M_CTL); 246027e5269SAlexander Motin port->target_devid = NULL; 247984a2ea9SAlexander Motin free(port->init_devid, M_CTL); 248984a2ea9SAlexander Motin port->init_devid = NULL; 249604e2579SAlexander Motin for (i = 0; i < port->max_initiators; i++) 250604e2579SAlexander Motin free(port->wwpn_iid[i].name, M_CTL); 251604e2579SAlexander Motin free(port->wwpn_iid, M_CTL); 252bb8f9017SAlexander Motin mtx_destroy(&port->port_lock); 253027e5269SAlexander Motin 254bb8f9017SAlexander Motin return (0); 255130f4520SKenneth D. Merry } 256130f4520SKenneth D. Merry 257130f4520SKenneth D. Merry void 25892168f4cSAlexander Motin ctl_port_set_wwns(struct ctl_port *port, int wwnn_valid, uint64_t wwnn, 259130f4520SKenneth D. Merry int wwpn_valid, uint64_t wwpn) 260130f4520SKenneth D. Merry { 261027e5269SAlexander Motin struct scsi_vpd_id_descriptor *desc; 262027e5269SAlexander Motin int len, proto; 263027e5269SAlexander Motin 264027e5269SAlexander Motin if (port->port_type == CTL_PORT_FC) 265027e5269SAlexander Motin proto = SCSI_PROTO_FC << 4; 266a9d2a193SAlexander Motin else if (port->port_type == CTL_PORT_SAS) 267a9d2a193SAlexander Motin proto = SCSI_PROTO_SAS << 4; 268027e5269SAlexander Motin else if (port->port_type == CTL_PORT_ISCSI) 269027e5269SAlexander Motin proto = SCSI_PROTO_ISCSI << 4; 270027e5269SAlexander Motin else 271027e5269SAlexander Motin proto = SCSI_PROTO_SPI << 4; 272027e5269SAlexander Motin 273027e5269SAlexander Motin if (wwnn_valid) { 27492168f4cSAlexander Motin port->wwnn = wwnn; 275130f4520SKenneth D. Merry 276027e5269SAlexander Motin free(port->target_devid, M_CTL); 277027e5269SAlexander Motin 278027e5269SAlexander Motin len = sizeof(struct scsi_vpd_device_id) + CTL_WWPN_LEN; 279027e5269SAlexander Motin port->target_devid = malloc(sizeof(struct ctl_devid) + len, 280027e5269SAlexander Motin M_CTL, M_WAITOK | M_ZERO); 281027e5269SAlexander Motin port->target_devid->len = len; 282027e5269SAlexander Motin desc = (struct scsi_vpd_id_descriptor *)port->target_devid->data; 283027e5269SAlexander Motin desc->proto_codeset = proto | SVPD_ID_CODESET_BINARY; 284027e5269SAlexander Motin desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_TARGET | 285027e5269SAlexander Motin SVPD_ID_TYPE_NAA; 286027e5269SAlexander Motin desc->length = CTL_WWPN_LEN; 287027e5269SAlexander Motin scsi_u64to8b(port->wwnn, desc->identifier); 288027e5269SAlexander Motin } 289027e5269SAlexander Motin 290027e5269SAlexander Motin if (wwpn_valid) { 29192168f4cSAlexander Motin port->wwpn = wwpn; 292027e5269SAlexander Motin 293027e5269SAlexander Motin free(port->port_devid, M_CTL); 294027e5269SAlexander Motin 295027e5269SAlexander Motin len = sizeof(struct scsi_vpd_device_id) + CTL_WWPN_LEN; 296027e5269SAlexander Motin port->port_devid = malloc(sizeof(struct ctl_devid) + len, 297027e5269SAlexander Motin M_CTL, M_WAITOK | M_ZERO); 298027e5269SAlexander Motin port->port_devid->len = len; 299027e5269SAlexander Motin desc = (struct scsi_vpd_id_descriptor *)port->port_devid->data; 300027e5269SAlexander Motin desc->proto_codeset = proto | SVPD_ID_CODESET_BINARY; 301027e5269SAlexander Motin desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT | 302027e5269SAlexander Motin SVPD_ID_TYPE_NAA; 303027e5269SAlexander Motin desc->length = CTL_WWPN_LEN; 304027e5269SAlexander Motin scsi_u64to8b(port->wwpn, desc->identifier); 305027e5269SAlexander Motin } 306130f4520SKenneth D. Merry } 307130f4520SKenneth D. Merry 308130f4520SKenneth D. Merry void 30992168f4cSAlexander Motin ctl_port_online(struct ctl_port *port) 310130f4520SKenneth D. Merry { 31121d963e5SAlexander Motin struct ctl_softc *softc = port->ctl_softc; 3127834ea88SAlexander Motin struct ctl_lun *lun; 3136bd364b5SAlexander Motin const char *value; 3147834ea88SAlexander Motin uint32_t l; 3157834ea88SAlexander Motin 3161b7849d0SAlexander Motin if (port->lun_enable != NULL) { 3177834ea88SAlexander Motin if (port->lun_map) { 318ee5e44e0SAlexander Motin for (l = 0; l < port->lun_map_size; l++) { 31941243159SAlexander Motin if (ctl_lun_map_from_port(port, l) == 32041243159SAlexander Motin UINT32_MAX) 3217834ea88SAlexander Motin continue; 3227834ea88SAlexander Motin port->lun_enable(port->targ_lun_arg, l); 3237834ea88SAlexander Motin } 3247834ea88SAlexander Motin } else { 3257834ea88SAlexander Motin STAILQ_FOREACH(lun, &softc->lun_list, links) 3267834ea88SAlexander Motin port->lun_enable(port->targ_lun_arg, lun->lun); 3277834ea88SAlexander Motin } 3281b7849d0SAlexander Motin } 3291b7849d0SAlexander Motin if (port->port_online != NULL) 33092168f4cSAlexander Motin port->port_online(port->onoff_arg); 331cfa09873SAlexander Motin mtx_lock(&softc->ctl_lock); 3326bd364b5SAlexander Motin if (softc->is_single == 0) { 3338951f055SMarcelo Araujo value = dnvlist_get_string(port->options, "ha_shared", NULL); 3346bd364b5SAlexander Motin if (value != NULL && strcmp(value, "on") == 0) 3356bd364b5SAlexander Motin port->status |= CTL_PORT_STATUS_HA_SHARED; 3366bd364b5SAlexander Motin else 3376bd364b5SAlexander Motin port->status &= ~CTL_PORT_STATUS_HA_SHARED; 3386bd364b5SAlexander Motin } 33992168f4cSAlexander Motin port->status |= CTL_PORT_STATUS_ONLINE; 340cfa09873SAlexander Motin STAILQ_FOREACH(lun, &softc->lun_list, links) { 34141243159SAlexander Motin if (ctl_lun_map_to_port(port, lun->lun) == UINT32_MAX) 342cfa09873SAlexander Motin continue; 343cfa09873SAlexander Motin mtx_lock(&lun->lun_lock); 344cfa09873SAlexander Motin ctl_est_ua_all(lun, -1, CTL_UA_INQ_CHANGE); 345cfa09873SAlexander Motin mtx_unlock(&lun->lun_lock); 346cfa09873SAlexander Motin } 347cfa09873SAlexander Motin mtx_unlock(&softc->ctl_lock); 3487ac58230SAlexander Motin ctl_isc_announce_port(port); 349130f4520SKenneth D. Merry } 350130f4520SKenneth D. Merry 351130f4520SKenneth D. Merry void 35292168f4cSAlexander Motin ctl_port_offline(struct ctl_port *port) 353130f4520SKenneth D. Merry { 35421d963e5SAlexander Motin struct ctl_softc *softc = port->ctl_softc; 3557834ea88SAlexander Motin struct ctl_lun *lun; 3567834ea88SAlexander Motin uint32_t l; 3577834ea88SAlexander Motin 3581b7849d0SAlexander Motin if (port->port_offline != NULL) 35992168f4cSAlexander Motin port->port_offline(port->onoff_arg); 3601b7849d0SAlexander Motin if (port->lun_disable != NULL) { 3617834ea88SAlexander Motin if (port->lun_map) { 362ee5e44e0SAlexander Motin for (l = 0; l < port->lun_map_size; l++) { 36341243159SAlexander Motin if (ctl_lun_map_from_port(port, l) == 36441243159SAlexander Motin UINT32_MAX) 3657834ea88SAlexander Motin continue; 3667834ea88SAlexander Motin port->lun_disable(port->targ_lun_arg, l); 3677834ea88SAlexander Motin } 3687834ea88SAlexander Motin } else { 3697834ea88SAlexander Motin STAILQ_FOREACH(lun, &softc->lun_list, links) 3707834ea88SAlexander Motin port->lun_disable(port->targ_lun_arg, lun->lun); 3717834ea88SAlexander Motin } 3721b7849d0SAlexander Motin } 373cfa09873SAlexander Motin mtx_lock(&softc->ctl_lock); 37492168f4cSAlexander Motin port->status &= ~CTL_PORT_STATUS_ONLINE; 375cfa09873SAlexander Motin STAILQ_FOREACH(lun, &softc->lun_list, links) { 37641243159SAlexander Motin if (ctl_lun_map_to_port(port, lun->lun) == UINT32_MAX) 377cfa09873SAlexander Motin continue; 378cfa09873SAlexander Motin mtx_lock(&lun->lun_lock); 379cfa09873SAlexander Motin ctl_est_ua_all(lun, -1, CTL_UA_INQ_CHANGE); 380cfa09873SAlexander Motin mtx_unlock(&lun->lun_lock); 381cfa09873SAlexander Motin } 382cfa09873SAlexander Motin mtx_unlock(&softc->ctl_lock); 3837ac58230SAlexander Motin ctl_isc_announce_port(port); 384130f4520SKenneth D. Merry } 385130f4520SKenneth D. Merry 386130f4520SKenneth D. Merry /* 387130f4520SKenneth D. Merry * vim: ts=8 388130f4520SKenneth D. Merry */ 389