cam_sim.c revision 248800
155682Smarkm/*- 2233294Sstas * Common functions for SCSI Interface Modules (SIMs). 3233294Sstas * 4233294Sstas * Copyright (c) 1997 Justin T. Gibbs. 555682Smarkm * All rights reserved. 6233294Sstas * 755682Smarkm * Redistribution and use in source and binary forms, with or without 8233294Sstas * modification, are permitted provided that the following conditions 9233294Sstas * are met: 10233294Sstas * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions, and the following disclaimer, 12233294Sstas * without modification, immediately at the beginning of the file. 13233294Sstas * 2. The name of the author may not be used to endorse or promote products 1455682Smarkm * derived from this software without specific prior written permission. 15233294Sstas * 16233294Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1855682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20233294Sstas * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26233294Sstas * SUCH DAMAGE. 27233294Sstas */ 28233294Sstas 29233294Sstas#include <sys/cdefs.h> 30233294Sstas__FBSDID("$FreeBSD: head/sys/cam/cam_sim.c 248800 2013-03-27 18:55:01Z mav $"); 31233294Sstas 32233294Sstas#include <sys/param.h> 33233294Sstas#include <sys/systm.h> 3455682Smarkm#include <sys/malloc.h> 3555682Smarkm#include <sys/kernel.h> 3655682Smarkm#include <sys/lock.h> 3755682Smarkm#include <sys/mutex.h> 38233294Sstas 3955682Smarkm#include <cam/cam.h> 4055682Smarkm#include <cam/cam_ccb.h> 4155682Smarkm#include <cam/cam_sim.h> 4255682Smarkm#include <cam/cam_queue.h> 4355682Smarkm#include <cam/cam_xpt.h> 44233294Sstas 45233294Sstas#define CAM_PATH_ANY (u_int32_t)-1 46233294Sstas 47233294Sstasstatic MALLOC_DEFINE(M_CAMSIM, "CAM SIM", "CAM SIM buffers"); 4855682Smarkm 4955682Smarkmstruct cam_devq * 5055682Smarkmcam_simq_alloc(u_int32_t max_sim_transactions) 51102644Snectar{ 5255682Smarkm return (cam_devq_alloc(/*size*/0, max_sim_transactions)); 5355682Smarkm} 5455682Smarkm 55233294Sstasvoid 5655682Smarkmcam_simq_free(struct cam_devq *devq) 5755682Smarkm{ 5855682Smarkm cam_devq_free(devq); 5955682Smarkm} 6055682Smarkm 6155682Smarkmstruct cam_sim * 6255682Smarkmcam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll, 6355682Smarkm const char *sim_name, void *softc, u_int32_t unit, 6455682Smarkm struct mtx *mtx, int max_dev_transactions, 6555682Smarkm int max_tagged_dev_transactions, struct cam_devq *queue) 6672445Sassar{ 6772445Sassar struct cam_sim *sim; 6872445Sassar 6972445Sassar if (mtx == NULL) 7055682Smarkm return (NULL); 7172445Sassar 7272445Sassar sim = (struct cam_sim *)malloc(sizeof(struct cam_sim), 7372445Sassar M_CAMSIM, M_ZERO | M_NOWAIT); 7472445Sassar 7572445Sassar if (sim == NULL) 7672445Sassar return (NULL); 7772445Sassar 7872445Sassar sim->sim_action = sim_action; 7972445Sassar sim->sim_poll = sim_poll; 8055682Smarkm sim->sim_name = sim_name; 8155682Smarkm sim->softc = softc; 8255682Smarkm sim->path_id = CAM_PATH_ANY; 8355682Smarkm sim->unit_number = unit; 8455682Smarkm sim->bus_id = 0; /* set in xpt_bus_register */ 8555682Smarkm sim->max_tagged_dev_openings = max_tagged_dev_transactions; 8655682Smarkm sim->max_dev_openings = max_dev_transactions; 8755682Smarkm sim->flags = 0; 8855682Smarkm sim->refcount = 1; 8955682Smarkm sim->devq = queue; 9055682Smarkm sim->max_ccbs = 8; /* Reserve for management purposes. */ 9155682Smarkm sim->mtx = mtx; 9255682Smarkm if (mtx == &Giant) { 9355682Smarkm sim->flags |= 0; 9455682Smarkm callout_init(&sim->callout, 0); 9555682Smarkm } else { 9655682Smarkm sim->flags |= CAM_SIM_MPSAFE; 9755682Smarkm callout_init(&sim->callout, 1); 9855682Smarkm } 9955682Smarkm 10055682Smarkm SLIST_INIT(&sim->ccb_freeq); 10155682Smarkm TAILQ_INIT(&sim->sim_doneq); 10255682Smarkm 10355682Smarkm return (sim); 10455682Smarkm} 10555682Smarkm 10655682Smarkmvoid 10755682Smarkmcam_sim_free(struct cam_sim *sim, int free_devq) 10855682Smarkm{ 10955682Smarkm union ccb *ccb; 11055682Smarkm int error; 11155682Smarkm 11255682Smarkm sim->refcount--; 11355682Smarkm if (sim->refcount > 0) { 11455682Smarkm error = msleep(sim, sim->mtx, PRIBIO, "simfree", 0); 11555682Smarkm KASSERT(error == 0, ("invalid error value for msleep(9)")); 11655682Smarkm } 11755682Smarkm 11855682Smarkm KASSERT(sim->refcount == 0, ("sim->refcount == 0")); 11955682Smarkm 12055682Smarkm while ((ccb = (union ccb *)SLIST_FIRST(&sim->ccb_freeq)) != NULL) { 121178825Sdfr SLIST_REMOVE_HEAD(&sim->ccb_freeq, xpt_links.sle); 122233294Sstas xpt_free_ccb(ccb); 123178825Sdfr } 124178825Sdfr if (free_devq) 125178825Sdfr cam_simq_free(sim->devq); 126178825Sdfr free(sim, M_CAMSIM); 127178825Sdfr} 12855682Smarkm 12955682Smarkmvoid 13055682Smarkmcam_sim_release(struct cam_sim *sim) 13155682Smarkm{ 13255682Smarkm KASSERT(sim->refcount >= 1, ("sim->refcount >= 1")); 13355682Smarkm mtx_assert(sim->mtx, MA_OWNED); 13455682Smarkm 135178825Sdfr sim->refcount--; 136178825Sdfr if (sim->refcount == 0) 137178825Sdfr wakeup(sim); 138178825Sdfr} 13955682Smarkm 14055682Smarkmvoid 14155682Smarkmcam_sim_hold(struct cam_sim *sim) 14255682Smarkm{ 14355682Smarkm KASSERT(sim->refcount >= 1, ("sim->refcount >= 1")); 14455682Smarkm mtx_assert(sim->mtx, MA_OWNED); 145233294Sstas 146233294Sstas sim->refcount++; 14755682Smarkm} 14855682Smarkm 14955682Smarkmvoid 150102644Snectarcam_sim_set_path(struct cam_sim *sim, u_int32_t path_id) 151102644Snectar{ 152102644Snectar sim->path_id = path_id; 15355682Smarkm} 15455682Smarkm