ctl_frontend.c revision 268682
1169689Skan/*- 2169689Skan * Copyright (c) 2003 Silicon Graphics International Corp. 3169689Skan * All rights reserved. 4169689Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6169689Skan * modification, are permitted provided that the following conditions 7169689Skan * are met: 8169689Skan * 1. Redistributions of source code must retain the above copyright 9169689Skan * notice, this list of conditions, and the following disclaimer, 10169689Skan * without modification. 11169689Skan * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12169689Skan * substantially similar to the "NO WARRANTY" disclaimer below 13169689Skan * ("Disclaimer") and any redistribution must be conditioned upon 14169689Skan * including a substantially similar Disclaimer requirement for further 15169689Skan * binary redistribution. 16169689Skan * 17169689Skan * NO WARRANTY 18169689Skan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19169689Skan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20169689Skan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21169689Skan * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22169689Skan * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26169689Skan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27169689Skan * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28169689Skan * POSSIBILITY OF SUCH DAMAGES. 29169689Skan * 30169689Skan * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_frontend.c#4 $ 31169689Skan */ 32169689Skan/* 33169689Skan * CAM Target Layer front end interface code 34169689Skan * 35169689Skan * Author: Ken Merry <ken@FreeBSD.org> 36169689Skan */ 37169689Skan 38169689Skan#include <sys/cdefs.h> 39169689Skan__FBSDID("$FreeBSD: stable/10/sys/cam/ctl/ctl_frontend.c 268682 2014-07-15 17:05:11Z mav $"); 40169689Skan 41169689Skan#include <sys/param.h> 42169689Skan#include <sys/systm.h> 43169689Skan#include <sys/kernel.h> 44169689Skan#include <sys/types.h> 45169689Skan#include <sys/malloc.h> 46169689Skan#include <sys/lock.h> 47169689Skan#include <sys/mutex.h> 48169689Skan#include <sys/condvar.h> 49169689Skan#include <sys/endian.h> 50169689Skan#include <sys/queue.h> 51169689Skan#include <sys/sysctl.h> 52169689Skan 53169689Skan#include <cam/scsi/scsi_all.h> 54169689Skan#include <cam/scsi/scsi_da.h> 55169689Skan#include <cam/ctl/ctl_io.h> 56169689Skan#include <cam/ctl/ctl.h> 57169689Skan#include <cam/ctl/ctl_frontend.h> 58169689Skan#include <cam/ctl/ctl_frontend_internal.h> 59169689Skan#include <cam/ctl/ctl_backend.h> 60169689Skan/* XXX KDM move defines from ctl_ioctl.h to somewhere else */ 61169689Skan#include <cam/ctl/ctl_ioctl.h> 62169689Skan#include <cam/ctl/ctl_ha.h> 63169689Skan#include <cam/ctl/ctl_private.h> 64169689Skan#include <cam/ctl/ctl_debug.h> 65169689Skan 66169689Skanextern struct ctl_softc *control_softc; 67169689Skan 68169689Skanint 69169689Skanctl_frontend_register(struct ctl_frontend *fe) 70169689Skan{ 71169689Skan struct ctl_frontend *fe_tmp; 72169689Skan 73169689Skan KASSERT(control_softc != NULL, ("CTL is not initialized")); 74169689Skan 75169689Skan /* 76169689Skan * Sanity check, make sure this isn't a duplicate registration. 77169689Skan */ 78169689Skan mtx_lock(&control_softc->ctl_lock); 79169689Skan STAILQ_FOREACH(fe_tmp, &control_softc->fe_list, links) { 80169689Skan if (strcmp(fe_tmp->name, fe->name) == 0) { 81169689Skan mtx_unlock(&control_softc->ctl_lock); 82169689Skan return (-1); 83169689Skan } 84169689Skan } 85169689Skan mtx_unlock(&control_softc->ctl_lock); 86169689Skan STAILQ_INIT(&fe->port_list); 87169689Skan 88169689Skan /* 89169689Skan * Call the frontend's initialization routine. 90169689Skan */ 91169689Skan if (fe->init != NULL) 92169689Skan fe->init(); 93169689Skan 94169689Skan mtx_lock(&control_softc->ctl_lock); 95169689Skan control_softc->num_frontends++; 96 STAILQ_INSERT_TAIL(&control_softc->fe_list, fe, links); 97 mtx_unlock(&control_softc->ctl_lock); 98 return (0); 99} 100 101int 102ctl_frontend_deregister(struct ctl_frontend *fe) 103{ 104 105 if (!STAILQ_EMPTY(&fe->port_list)) 106 return (-1); 107 108 mtx_lock(&control_softc->ctl_lock); 109 STAILQ_REMOVE(&control_softc->fe_list, fe, ctl_frontend, links); 110 control_softc->num_frontends--; 111 mtx_unlock(&control_softc->ctl_lock); 112 113 /* 114 * Call the frontend's shutdown routine. 115 */ 116 if (fe->shutdown != NULL) 117 fe->shutdown(); 118 return (0); 119} 120 121struct ctl_frontend * 122ctl_frontend_find(char *frontend_name) 123{ 124 struct ctl_softc *ctl_softc = control_softc; 125 struct ctl_frontend *fe; 126 127 mtx_lock(&ctl_softc->ctl_lock); 128 STAILQ_FOREACH(fe, &ctl_softc->fe_list, links) { 129 if (strcmp(fe->name, frontend_name) == 0) { 130 mtx_unlock(&ctl_softc->ctl_lock); 131 return (fe); 132 } 133 } 134 mtx_unlock(&ctl_softc->ctl_lock); 135 return (NULL); 136} 137 138int 139ctl_port_register(struct ctl_port *port, int master_shelf) 140{ 141 struct ctl_io_pool *pool; 142 int port_num; 143 int retval; 144 145 retval = 0; 146 147 KASSERT(control_softc != NULL, ("CTL is not initialized")); 148 149 mtx_lock(&control_softc->ctl_lock); 150 port_num = ctl_ffz(&control_softc->ctl_port_mask, CTL_MAX_PORTS); 151 if ((port_num == -1) 152 || (ctl_set_mask(&control_softc->ctl_port_mask, port_num) == -1)) { 153 port->targ_port = -1; 154 mtx_unlock(&control_softc->ctl_lock); 155 return (1); 156 } 157 control_softc->num_ports++; 158 mtx_unlock(&control_softc->ctl_lock); 159 160 /* 161 * We add 20 to whatever the caller requests, so he doesn't get 162 * burned by queueing things back to the pending sense queue. In 163 * theory, there should probably only be one outstanding item, at 164 * most, on the pending sense queue for a LUN. We'll clear the 165 * pending sense queue on the next command, whether or not it is 166 * a REQUEST SENSE. 167 */ 168 retval = ctl_pool_create(control_softc, CTL_POOL_FETD, 169 port->num_requested_ctl_io + 20, &pool); 170 if (retval != 0) { 171 port->targ_port = -1; 172 mtx_lock(&control_softc->ctl_lock); 173 ctl_clear_mask(&control_softc->ctl_port_mask, port_num); 174 mtx_unlock(&control_softc->ctl_lock); 175 return (retval); 176 } 177 port->ctl_pool_ref = pool; 178 179 if (port->options.stqh_first == NULL) 180 STAILQ_INIT(&port->options); 181 182 mtx_lock(&control_softc->ctl_lock); 183 port->targ_port = port_num + (master_shelf != 0 ? 0 : CTL_MAX_PORTS); 184 port->max_initiators = CTL_MAX_INIT_PER_PORT; 185 STAILQ_INSERT_TAIL(&port->frontend->port_list, port, fe_links); 186 STAILQ_INSERT_TAIL(&control_softc->port_list, port, links); 187 control_softc->ctl_ports[port_num] = port; 188 mtx_unlock(&control_softc->ctl_lock); 189 190 return (retval); 191} 192 193int 194ctl_port_deregister(struct ctl_port *port) 195{ 196 struct ctl_io_pool *pool; 197 int port_num; 198 int retval; 199 200 retval = 0; 201 202 pool = (struct ctl_io_pool *)port->ctl_pool_ref; 203 204 if (port->targ_port == -1) { 205 retval = 1; 206 goto bailout; 207 } 208 209 mtx_lock(&control_softc->ctl_lock); 210 STAILQ_REMOVE(&control_softc->port_list, port, ctl_port, links); 211 STAILQ_REMOVE(&port->frontend->port_list, port, ctl_port, fe_links); 212 control_softc->num_ports--; 213 port_num = (port->targ_port < CTL_MAX_PORTS) ? port->targ_port : 214 port->targ_port - CTL_MAX_PORTS; 215 ctl_clear_mask(&control_softc->ctl_port_mask, port_num); 216 control_softc->ctl_ports[port_num] = NULL; 217 mtx_unlock(&control_softc->ctl_lock); 218 219 ctl_pool_free(pool); 220 ctl_free_opts(&port->options); 221 222bailout: 223 return (retval); 224} 225 226void 227ctl_port_set_wwns(struct ctl_port *port, int wwnn_valid, uint64_t wwnn, 228 int wwpn_valid, uint64_t wwpn) 229{ 230 if (wwnn_valid) 231 port->wwnn = wwnn; 232 233 if (wwpn_valid) 234 port->wwpn = wwpn; 235} 236 237void 238ctl_port_online(struct ctl_port *port) 239{ 240 port->port_online(port->onoff_arg); 241 /* XXX KDM need a lock here? */ 242 port->status |= CTL_PORT_STATUS_ONLINE; 243} 244 245void 246ctl_port_offline(struct ctl_port *port) 247{ 248 port->port_offline(port->onoff_arg); 249 /* XXX KDM need a lock here? */ 250 port->status &= ~CTL_PORT_STATUS_ONLINE; 251} 252 253/* 254 * vim: ts=8 255 */ 256