1171568Sscottl/*- 2234233Sjpaetzel * Copyright (c) 2005-2011 Daniel Braniss <danny@cs.huji.ac.il> 3171568Sscottl * All rights reserved. 4171568Sscottl * 5171568Sscottl * Redistribution and use in source and binary forms, with or without 6171568Sscottl * modification, are permitted provided that the following conditions 7171568Sscottl * are met: 8171568Sscottl * 1. Redistributions of source code must retain the above copyright 9171568Sscottl * notice, this list of conditions and the following disclaimer. 10171568Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11171568Sscottl * notice, this list of conditions and the following disclaimer in the 12171568Sscottl * documentation and/or other materials provided with the distribution. 13171568Sscottl * 14171568Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15171568Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16171568Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17171568Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18171568Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19171568Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20171568Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21171568Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22171568Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23171568Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24171568Sscottl * SUCH DAMAGE. 25171568Sscottl * 26171568Sscottl * $FreeBSD$ 27171568Sscottl */ 28211095Sdes 29171568Sscottl/* 30211095Sdes | $Id: iscsivar.h 743 2009-08-08 10:54:53Z danny $ 31171568Sscottl */ 32211095Sdes#define ISCSI_MAX_LUNS 128 // don't touch this 33211095Sdes#if ISCSI_MAX_LUNS > 8 34211095Sdes/* 35211095Sdes | for this to work 36211095Sdes | sysctl kern.cam.cam_srch_hi=1 37211095Sdes */ 38211095Sdes#endif 39211095Sdes 40171568Sscottl#ifndef ISCSI_INITIATOR_DEBUG 41171568Sscottl#define ISCSI_INITIATOR_DEBUG 1 42171568Sscottl#endif 43171568Sscottl 44171568Sscottl#ifdef ISCSI_INITIATOR_DEBUG 45171568Sscottlextern int iscsi_debug; 46171568Sscottl#define debug(level, fmt, args...) do {if(level <= iscsi_debug)\ 47171568Sscottl printf("%s: " fmt "\n", __func__ , ##args);} while(0) 48171568Sscottl#define sdebug(level, fmt, args...) do {if(level <= iscsi_debug)\ 49171568Sscottl printf("%d] %s: " fmt "\n", sp->sid, __func__ , ##args);} while(0) 50171568Sscottl#define debug_called(level) do {if(level <= iscsi_debug)\ 51171568Sscottl printf("%s: called\n", __func__);} while(0) 52171568Sscottl#else 53171568Sscottl#define debug(level, fmt, args...) 54171568Sscottl#define debug_called(level) 55171568Sscottl#define sdebug(level, fmt, args...) 56171568Sscottl#endif /* ISCSI_INITIATOR_DEBUG */ 57171568Sscottl 58185289Sscottl#define xdebug(fmt, args...) printf(">>> %s: " fmt "\n", __func__ , ##args) 59171568Sscottl 60211095Sdes#define MAX_SESSIONS ISCSI_MAX_TARGETS 61211095Sdes#define MAX_PDUS (MAX_SESSIONS*256) // XXX: at the moment this is arbitrary 62171568Sscottl 63171568Sscottltypedef uint32_t digest_t(const void *, int len, uint32_t ocrc); 64171568Sscottl 65171568SscottlMALLOC_DECLARE(M_ISCSI); 66211095SdesMALLOC_DECLARE(M_ISCSIBUF); 67171568Sscottl 68211095Sdes#define ISOK2DIG(dig, pp) ((dig != NULL) && ((pp->ipdu.bhs.opcode & 0x1f) != ISCSI_LOGIN_CMD)) 69211095Sdes 70171568Sscottl#ifndef BIT 71171568Sscottl#define BIT(n) (1 <<(n)) 72171568Sscottl#endif 73171568Sscottl 74171568Sscottl#define ISC_SM_RUN BIT(0) 75171568Sscottl#define ISC_SM_RUNNING BIT(1) 76171568Sscottl 77185289Sscottl#define ISC_LINK_UP BIT(2) 78171568Sscottl#define ISC_CON_RUN BIT(3) 79171568Sscottl#define ISC_CON_RUNNING BIT(4) 80171568Sscottl#define ISC_KILL BIT(5) 81185289Sscottl#define ISC_OQNOTEMPTY BIT(6) 82185289Sscottl#define ISC_OWAITING BIT(7) 83171568Sscottl#define ISC_FFPHASE BIT(8) 84171568Sscottl 85211095Sdes#define ISC_CAMDEVS BIT(9) 86211095Sdes#define ISC_SCANWAIT BIT(10) 87171568Sscottl 88211095Sdes#define ISC_MEMWAIT BIT(11) 89211095Sdes#define ISC_SIGNALED BIT(12) 90185289Sscottl 91211095Sdes#define ISC_HOLD BIT(15) 92211095Sdes#define ISC_HOLDED BIT(16) 93211095Sdes 94171568Sscottl#define ISC_SHUTDOWN BIT(31) 95171568Sscottl 96171568Sscottl/* 97171568Sscottl | some stats 98171568Sscottl */ 99171568Sscottlstruct i_stats { 100171568Sscottl int npdu; // number of pdus malloc'ed. 101171568Sscottl int nrecv; // unprocessed received pdus 102171568Sscottl int nsent; // sent pdus 103171568Sscottl 104171568Sscottl int nrsp, max_rsp; 105171568Sscottl int nrsv, max_rsv; 106171568Sscottl int ncsnd, max_csnd; 107171568Sscottl int nisnd, max_isnd; 108171568Sscottl int nwsnd, max_wsnd; 109171568Sscottl int nhld, max_hld; 110171568Sscottl 111171568Sscottl struct bintime t_sent; 112171568Sscottl struct bintime t_recv; 113171568Sscottl}; 114171568Sscottl 115171568Sscottl/* 116171568Sscottl | one per 'session' 117171568Sscottl */ 118185289Sscottl 119185289Sscottltypedef TAILQ_HEAD(, pduq) queue_t; 120185289Sscottl 121171568Sscottltypedef struct isc_session { 122171568Sscottl TAILQ_ENTRY(isc_session) sp_link; 123171568Sscottl int flags; 124171568Sscottl struct cdev *dev; 125171568Sscottl struct socket *soc; 126171568Sscottl struct file *fp; 127171568Sscottl struct thread *td; 128171568Sscottl 129171568Sscottl struct proc *proc; // the userland process 130171568Sscottl int signal; 131171568Sscottl struct proc *soc_proc; 132171568Sscottl struct proc *stp; // the sm thread 133171568Sscottl 134171568Sscottl struct isc_softc *isc; 135171568Sscottl 136171568Sscottl digest_t *hdrDigest; // the digest alg. if any 137171568Sscottl digest_t *dataDigest; // the digest alg. if any 138171568Sscottl 139171568Sscottl int sid; // Session ID 140171568Sscottl sn_t sn; // sequence number stuff; 141171568Sscottl int cws; // current window size 142171568Sscottl 143171568Sscottl int target_nluns; // this and target_lun are 144171568Sscottl // hopefully temporal till I 145171568Sscottl // figure out a better way. 146211095Sdes int target_lun[ISCSI_MAX_LUNS/(sizeof(int)*8) + 1]; 147171568Sscottl 148171568Sscottl struct mtx rsp_mtx; 149171568Sscottl struct mtx rsv_mtx; 150171568Sscottl struct mtx snd_mtx; 151171568Sscottl struct mtx hld_mtx; 152171568Sscottl struct mtx io_mtx; 153185289Sscottl queue_t rsp; 154185289Sscottl queue_t rsv; 155185289Sscottl queue_t csnd; 156185289Sscottl queue_t isnd; 157185289Sscottl queue_t wsnd; 158185289Sscottl queue_t hld; 159171568Sscottl 160211095Sdes isc_opt_t opt; // negotiable values 161171568Sscottl 162171568Sscottl struct i_stats stats; 163171568Sscottl bhs_t bhs; 164171568Sscottl struct uio uio; 165171568Sscottl struct iovec iov; 166171568Sscottl /* 167211095Sdes | cam stuff 168211095Sdes */ 169211095Sdes struct cam_sim *cam_sim; 170211095Sdes struct cam_path *cam_path; 171211095Sdes struct mtx cam_mtx; 172211095Sdes /* 173171568Sscottl | sysctl stuff 174171568Sscottl */ 175171568Sscottl struct sysctl_ctx_list clist; 176171568Sscottl struct sysctl_oid *oid; 177185289Sscottl int douio; //XXX: turn on/off uio on read 178171568Sscottl} isc_session_t; 179171568Sscottl 180171568Sscottltypedef struct pduq { 181171568Sscottl TAILQ_ENTRY(pduq) pq_link; 182171568Sscottl 183171568Sscottl caddr_t buf; 184171568Sscottl u_int len; // the total length of the pdu 185171568Sscottl pdu_t pdu; 186171568Sscottl union ccb *ccb; 187171568Sscottl 188171568Sscottl struct uio uio; 189171568Sscottl struct iovec iov[5]; // XXX: careful ... 190171568Sscottl struct mbuf *mp; 191171568Sscottl struct bintime ts; 192211095Sdes queue_t *pduq; 193171568Sscottl} pduq_t; 194211095Sdes/* 195211095Sdes */ 196171568Sscottlstruct isc_softc { 197211095Sdes struct mtx isc_mtx; 198211095Sdes TAILQ_HEAD(,isc_session) isc_sess; 199211095Sdes int nsess; 200171568Sscottl struct cdev *dev; 201171568Sscottl char isid[6]; // Initiator Session ID (48 bits) 202211095Sdes struct unrhdr *unit; 203211095Sdes struct sx unit_sx; 204171568Sscottl 205211095Sdes uma_zone_t pdu_zone; // pool of free pdu's 206234233Sjpaetzel TAILQ_HEAD(,pduq) freepdu; 207234233Sjpaetzel 208171568Sscottl#ifdef ISCSI_INITIATOR_DEBUG 209211095Sdes int npdu_alloc, npdu_max; // for instrumentation 210171568Sscottl#endif 211211095Sdes#ifdef DO_EVENTHANDLER 212211095Sdes eventhandler_tag eh; 213211095Sdes#endif 214171568Sscottl /* 215171568Sscottl | sysctl stuff 216171568Sscottl */ 217171568Sscottl struct sysctl_ctx_list clist; 218171568Sscottl struct sysctl_oid *oid; 219171568Sscottl}; 220171568Sscottl 221171568Sscottl#ifdef ISCSI_INITIATOR_DEBUG 222171568Sscottlextern struct mtx iscsi_dbg_mtx; 223171568Sscottl#endif 224171568Sscottl 225171568Sscottlvoid isc_start_receiver(isc_session_t *sp); 226171568Sscottlvoid isc_stop_receiver(isc_session_t *sp); 227171568Sscottl 228171568Sscottlint isc_sendPDU(isc_session_t *sp, pduq_t *pq); 229171568Sscottlint isc_qout(isc_session_t *sp, pduq_t *pq); 230171568Sscottlint i_prepPDU(isc_session_t *sp, pduq_t *pq); 231171568Sscottl 232171568Sscottlint ism_fullfeature(struct cdev *dev, int flag); 233171568Sscottl 234171568Sscottlint i_pdu_flush(isc_session_t *sc); 235171568Sscottlint i_setopt(isc_session_t *sp, isc_opt_t *opt); 236171568Sscottlvoid i_freeopt(isc_opt_t *opt); 237171568Sscottl 238211095Sdesint ic_init(isc_session_t *sp); 239211095Sdesvoid ic_destroy(isc_session_t *sp); 240171568Sscottlvoid ic_lost_target(isc_session_t *sp, int target); 241171568Sscottlint ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp); 242171568Sscottl 243171568Sscottlvoid ism_recv(isc_session_t *sp, pduq_t *pq); 244171568Sscottlint ism_start(isc_session_t *sp); 245211095Sdesvoid ism_restart(isc_session_t *sp); 246171568Sscottlvoid ism_stop(isc_session_t *sp); 247171568Sscottl 248171568Sscottlint scsi_encap(struct cam_sim *sim, union ccb *ccb); 249171568Sscottlint scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq); 250171568Sscottlvoid iscsi_r2t(isc_session_t *sp, pduq_t *opq, pduq_t *pq); 251171568Sscottlvoid iscsi_done(isc_session_t *sp, pduq_t *opq, pduq_t *pq); 252171568Sscottlvoid iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq); 253171568Sscottlvoid iscsi_async(isc_session_t *sp, pduq_t *pq); 254171568Sscottlvoid iscsi_cleanup(isc_session_t *sp); 255171568Sscottlint iscsi_requeue(isc_session_t *sp); 256171568Sscottl 257171568Sscottl// Serial Number Arithmetic 258171568Sscottl#define _MAXINCR 0x7FFFFFFF // 2 ^ 31 - 1 259171568Sscottl#define SNA_GT(i1, i2) ((i1 != i2) && (\ 260171568Sscottl (i1 < i2 && i2 - i1 > _MAXINCR) ||\ 261171568Sscottl (i1 > i2 && i1 - i2 < _MAXINCR))?1: 0) 262171568Sscottl 263171568Sscottl/* 264171568Sscottl | inlines 265171568Sscottl */ 266171568Sscottl#ifdef _CAM_CAM_XPT_SIM_H 267171568Sscottl 268171568Sscottl#if __FreeBSD_version < 600000 269171568Sscottl#define CAM_LOCK(arg) 270171568Sscottl#define CAM_ULOCK(arg) 271171568Sscottl 272171568Sscottlstatic __inline void 273211095SdesXPT_DONE(isc_session_t *sp, union ccb *ccb) 274171568Sscottl{ 275171568Sscottl mtx_lock(&Giant); 276171568Sscottl xpt_done(ccb); 277171568Sscottl mtx_unlock(&Giant); 278171568Sscottl} 279171568Sscottl#elif __FreeBSD_version >= 700000 280171568Sscottl#define CAM_LOCK(arg) mtx_lock(&arg->cam_mtx) 281171568Sscottl#define CAM_UNLOCK(arg) mtx_unlock(&arg->cam_mtx) 282171568Sscottl 283171568Sscottlstatic __inline void 284211095SdesXPT_DONE(isc_session_t *sp, union ccb *ccb) 285171568Sscottl{ 286211095Sdes CAM_LOCK(sp); 287171568Sscottl xpt_done(ccb); 288211095Sdes CAM_UNLOCK(sp); 289171568Sscottl} 290171568Sscottl#else 291171568Sscottl//__FreeBSD_version >= 600000 292171568Sscottl#define CAM_LOCK(arg) 293171568Sscottl#define CAM_UNLOCK(arg) 294171568Sscottl#define XPT_DONE(ignore, arg) xpt_done(arg) 295171568Sscottl#endif 296171568Sscottl 297171568Sscottl#endif /* _CAM_CAM_XPT_SIM_H */ 298171568Sscottl 299171568Sscottlstatic __inline pduq_t * 300171568Sscottlpdu_alloc(struct isc_softc *isc, int wait) 301171568Sscottl{ 302171568Sscottl pduq_t *pq; 303171568Sscottl 304212149Sdes pq = (pduq_t *)uma_zalloc(isc->pdu_zone, wait /* M_WAITOK or M_NOWAIT*/); 305171568Sscottl if(pq == NULL) { 306185289Sscottl debug(7, "out of mem"); 307171568Sscottl return NULL; 308171568Sscottl } 309171568Sscottl#ifdef ISCSI_INITIATOR_DEBUG 310234233Sjpaetzel mtx_lock(&iscsi_dbg_mtx); 311171568Sscottl isc->npdu_alloc++; 312171568Sscottl if(isc->npdu_alloc > isc->npdu_max) 313171568Sscottl isc->npdu_max = isc->npdu_alloc; 314234233Sjpaetzel mtx_unlock(&iscsi_dbg_mtx); 315171568Sscottl#endif 316171568Sscottl memset(pq, 0, sizeof(pduq_t)); 317171568Sscottl 318171568Sscottl return pq; 319171568Sscottl} 320171568Sscottl 321171568Sscottlstatic __inline void 322171568Sscottlpdu_free(struct isc_softc *isc, pduq_t *pq) 323171568Sscottl{ 324171568Sscottl if(pq->mp) 325171568Sscottl m_freem(pq->mp); 326185289Sscottl#ifdef NO_USE_MBUF 327171568Sscottl if(pq->buf != NULL) 328211095Sdes free(pq->buf, M_ISCSIBUF); 329185289Sscottl#endif 330234233Sjpaetzel uma_zfree(isc->pdu_zone, pq); 331171568Sscottl#ifdef ISCSI_INITIATOR_DEBUG 332234233Sjpaetzel mtx_lock(&iscsi_dbg_mtx); 333171568Sscottl isc->npdu_alloc--; 334234233Sjpaetzel mtx_unlock(&iscsi_dbg_mtx); 335171568Sscottl#endif 336171568Sscottl} 337171568Sscottl 338171568Sscottlstatic __inline void 339171568Sscottli_nqueue_rsp(isc_session_t *sp, pduq_t *pq) 340171568Sscottl{ 341171568Sscottl mtx_lock(&sp->rsp_mtx); 342171568Sscottl if(++sp->stats.nrsp > sp->stats.max_rsp) 343171568Sscottl sp->stats.max_rsp = sp->stats.nrsp; 344171568Sscottl TAILQ_INSERT_TAIL(&sp->rsp, pq, pq_link); 345171568Sscottl mtx_unlock(&sp->rsp_mtx); 346171568Sscottl} 347171568Sscottl 348171568Sscottlstatic __inline pduq_t * 349171568Sscottli_dqueue_rsp(isc_session_t *sp) 350171568Sscottl{ 351171568Sscottl pduq_t *pq; 352171568Sscottl 353171568Sscottl mtx_lock(&sp->rsp_mtx); 354171568Sscottl if((pq = TAILQ_FIRST(&sp->rsp)) != NULL) { 355171568Sscottl sp->stats.nrsp--; 356171568Sscottl TAILQ_REMOVE(&sp->rsp, pq, pq_link); 357171568Sscottl } 358171568Sscottl mtx_unlock(&sp->rsp_mtx); 359171568Sscottl 360171568Sscottl return pq; 361171568Sscottl} 362171568Sscottl 363171568Sscottlstatic __inline void 364171568Sscottli_nqueue_rsv(isc_session_t *sp, pduq_t *pq) 365171568Sscottl{ 366171568Sscottl mtx_lock(&sp->rsv_mtx); 367171568Sscottl if(++sp->stats.nrsv > sp->stats.max_rsv) 368171568Sscottl sp->stats.max_rsv = sp->stats.nrsv; 369171568Sscottl TAILQ_INSERT_TAIL(&sp->rsv, pq, pq_link); 370171568Sscottl mtx_unlock(&sp->rsv_mtx); 371171568Sscottl} 372171568Sscottl 373171568Sscottlstatic __inline pduq_t * 374171568Sscottli_dqueue_rsv(isc_session_t *sp) 375171568Sscottl{ 376171568Sscottl pduq_t *pq; 377171568Sscottl 378171568Sscottl mtx_lock(&sp->rsv_mtx); 379171568Sscottl if((pq = TAILQ_FIRST(&sp->rsv)) != NULL) { 380171568Sscottl sp->stats.nrsv--; 381171568Sscottl TAILQ_REMOVE(&sp->rsv, pq, pq_link); 382171568Sscottl } 383171568Sscottl mtx_unlock(&sp->rsv_mtx); 384171568Sscottl 385171568Sscottl return pq; 386171568Sscottl} 387171568Sscottl 388171568Sscottlstatic __inline void 389171568Sscottli_nqueue_csnd(isc_session_t *sp, pduq_t *pq) 390171568Sscottl{ 391171568Sscottl mtx_lock(&sp->snd_mtx); 392171568Sscottl if(++sp->stats.ncsnd > sp->stats.max_csnd) 393171568Sscottl sp->stats.max_csnd = sp->stats.ncsnd; 394171568Sscottl TAILQ_INSERT_TAIL(&sp->csnd, pq, pq_link); 395171568Sscottl mtx_unlock(&sp->snd_mtx); 396171568Sscottl} 397171568Sscottl 398171568Sscottlstatic __inline pduq_t * 399171568Sscottli_dqueue_csnd(isc_session_t *sp) 400171568Sscottl{ 401171568Sscottl pduq_t *pq; 402171568Sscottl 403171568Sscottl mtx_lock(&sp->snd_mtx); 404171568Sscottl if((pq = TAILQ_FIRST(&sp->csnd)) != NULL) { 405171568Sscottl sp->stats.ncsnd--; 406171568Sscottl TAILQ_REMOVE(&sp->csnd, pq, pq_link); 407171568Sscottl } 408171568Sscottl mtx_unlock(&sp->snd_mtx); 409171568Sscottl 410171568Sscottl return pq; 411171568Sscottl} 412171568Sscottl 413171568Sscottlstatic __inline void 414171568Sscottli_nqueue_isnd(isc_session_t *sp, pduq_t *pq) 415171568Sscottl{ 416171568Sscottl mtx_lock(&sp->snd_mtx); 417171568Sscottl if(++sp->stats.nisnd > sp->stats.max_isnd) 418171568Sscottl sp->stats.max_isnd = sp->stats.nisnd; 419171568Sscottl TAILQ_INSERT_TAIL(&sp->isnd, pq, pq_link); 420171568Sscottl mtx_unlock(&sp->snd_mtx); 421171568Sscottl} 422171568Sscottl 423171568Sscottlstatic __inline pduq_t * 424171568Sscottli_dqueue_isnd(isc_session_t *sp) 425171568Sscottl{ 426171568Sscottl pduq_t *pq; 427171568Sscottl 428171568Sscottl mtx_lock(&sp->snd_mtx); 429171568Sscottl if((pq = TAILQ_FIRST(&sp->isnd)) != NULL) { 430171568Sscottl sp->stats.nisnd--; 431171568Sscottl TAILQ_REMOVE(&sp->isnd, pq, pq_link); 432171568Sscottl } 433171568Sscottl mtx_unlock(&sp->snd_mtx); 434171568Sscottl 435171568Sscottl return pq; 436171568Sscottl} 437171568Sscottl 438171568Sscottlstatic __inline void 439171568Sscottli_nqueue_wsnd(isc_session_t *sp, pduq_t *pq) 440171568Sscottl{ 441171568Sscottl mtx_lock(&sp->snd_mtx); 442171568Sscottl if(++sp->stats.nwsnd > sp->stats.max_wsnd) 443171568Sscottl sp->stats.max_wsnd = sp->stats.nwsnd; 444171568Sscottl TAILQ_INSERT_TAIL(&sp->wsnd, pq, pq_link); 445171568Sscottl mtx_unlock(&sp->snd_mtx); 446171568Sscottl} 447171568Sscottl 448171568Sscottlstatic __inline pduq_t * 449171568Sscottli_dqueue_wsnd(isc_session_t *sp) 450171568Sscottl{ 451171568Sscottl pduq_t *pq; 452171568Sscottl 453171568Sscottl mtx_lock(&sp->snd_mtx); 454171568Sscottl if((pq = TAILQ_FIRST(&sp->wsnd)) != NULL) { 455171568Sscottl sp->stats.nwsnd--; 456171568Sscottl TAILQ_REMOVE(&sp->wsnd, pq, pq_link); 457171568Sscottl } 458171568Sscottl mtx_unlock(&sp->snd_mtx); 459171568Sscottl 460171568Sscottl return pq; 461171568Sscottl} 462171568Sscottl 463171568Sscottlstatic __inline pduq_t * 464171568Sscottli_dqueue_snd(isc_session_t *sp, int which) 465171568Sscottl{ 466171568Sscottl pduq_t *pq; 467171568Sscottl 468171568Sscottl pq = NULL; 469171568Sscottl mtx_lock(&sp->snd_mtx); 470171568Sscottl if((which & BIT(0)) && (pq = TAILQ_FIRST(&sp->isnd)) != NULL) { 471171568Sscottl sp->stats.nisnd--; 472171568Sscottl TAILQ_REMOVE(&sp->isnd, pq, pq_link); 473185289Sscottl pq->pduq = &sp->isnd; // remember where you came from 474171568Sscottl } else 475171568Sscottl if((which & BIT(1)) && (pq = TAILQ_FIRST(&sp->wsnd)) != NULL) { 476171568Sscottl sp->stats.nwsnd--; 477171568Sscottl TAILQ_REMOVE(&sp->wsnd, pq, pq_link); 478185289Sscottl pq->pduq = &sp->wsnd; // remember where you came from 479171568Sscottl } else 480171568Sscottl if((which & BIT(2)) && (pq = TAILQ_FIRST(&sp->csnd)) != NULL) { 481171568Sscottl sp->stats.ncsnd--; 482171568Sscottl TAILQ_REMOVE(&sp->csnd, pq, pq_link); 483185289Sscottl pq->pduq = &sp->csnd; // remember where you came from 484171568Sscottl } 485171568Sscottl mtx_unlock(&sp->snd_mtx); 486171568Sscottl 487171568Sscottl return pq; 488171568Sscottl} 489171568Sscottl 490185289Sscottlstatic __inline void 491185289Sscottli_rqueue_pdu(isc_session_t *sp, pduq_t *pq) 492185289Sscottl{ 493185289Sscottl mtx_lock(&sp->snd_mtx); 494185289Sscottl KASSERT(pq->pduq != NULL, ("pq->pduq is NULL")); 495185289Sscottl TAILQ_INSERT_TAIL(pq->pduq, pq, pq_link); 496185289Sscottl mtx_unlock(&sp->snd_mtx); 497185289Sscottl} 498185289Sscottl 499171568Sscottl/* 500171568Sscottl | Waiting for ACK (or something :-) 501171568Sscottl */ 502171568Sscottlstatic __inline void 503171568Sscottli_nqueue_hld(isc_session_t *sp, pduq_t *pq) 504171568Sscottl{ 505171568Sscottl getbintime(&pq->ts); 506171568Sscottl mtx_lock(&sp->hld_mtx); 507171568Sscottl if(++sp->stats.nhld > sp->stats.max_hld) 508171568Sscottl sp->stats.max_hld = sp->stats.nhld; 509171568Sscottl TAILQ_INSERT_TAIL(&sp->hld, pq, pq_link); 510171568Sscottl mtx_unlock(&sp->hld_mtx); 511171568Sscottl return; 512171568Sscottl} 513171568Sscottl 514171568Sscottlstatic __inline void 515171568Sscottli_remove_hld(isc_session_t *sp, pduq_t *pq) 516171568Sscottl{ 517171568Sscottl mtx_lock(&sp->hld_mtx); 518171568Sscottl sp->stats.nhld--; 519171568Sscottl TAILQ_REMOVE(&sp->hld, pq, pq_link); 520171568Sscottl mtx_unlock(&sp->hld_mtx); 521171568Sscottl} 522171568Sscottl 523171568Sscottlstatic __inline pduq_t * 524171568Sscottli_dqueue_hld(isc_session_t *sp) 525171568Sscottl{ 526171568Sscottl pduq_t *pq; 527171568Sscottl 528171568Sscottl mtx_lock(&sp->hld_mtx); 529171568Sscottl if((pq = TAILQ_FIRST(&sp->hld)) != NULL) { 530171568Sscottl sp->stats.nhld--; 531171568Sscottl TAILQ_REMOVE(&sp->hld, pq, pq_link); 532171568Sscottl } 533171568Sscottl mtx_unlock(&sp->hld_mtx); 534171568Sscottl 535171568Sscottl return pq; 536171568Sscottl} 537171568Sscottl 538171568Sscottlstatic __inline pduq_t * 539171568Sscottli_search_hld(isc_session_t *sp, int itt, int keep) 540171568Sscottl{ 541171568Sscottl pduq_t *pq, *tmp; 542171568Sscottl 543171568Sscottl pq = NULL; 544171568Sscottl 545171568Sscottl mtx_lock(&sp->hld_mtx); 546171568Sscottl TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) { 547171568Sscottl if(pq->pdu.ipdu.bhs.itt == itt) { 548171568Sscottl if(!keep) { 549171568Sscottl sp->stats.nhld--; 550171568Sscottl TAILQ_REMOVE(&sp->hld, pq, pq_link); 551171568Sscottl } 552171568Sscottl break; 553171568Sscottl } 554171568Sscottl } 555171568Sscottl mtx_unlock(&sp->hld_mtx); 556171568Sscottl 557171568Sscottl return pq; 558171568Sscottl} 559171568Sscottl 560171568Sscottlstatic __inline void 561211095Sdesi_acked_hld(isc_session_t *sp, pdu_t *op) 562211095Sdes{ 563211095Sdes pduq_t *pq, *tmp; 564211095Sdes u_int exp = sp->sn.expCmd; 565211095Sdes 566211095Sdes pq = NULL; 567211095Sdes mtx_lock(&sp->hld_mtx); 568211095Sdes TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) { 569211095Sdes if((op && op->ipdu.bhs.itt == pq->pdu.ipdu.bhs.itt) 570211095Sdes || (pq->ccb == NULL 571211095Sdes && (pq->pdu.ipdu.bhs.opcode != ISCSI_WRITE_DATA) 572211095Sdes && SNA_GT(exp, ntohl(pq->pdu.ipdu.bhs.ExpStSN)))) { 573211095Sdes sp->stats.nhld--; 574211095Sdes TAILQ_REMOVE(&sp->hld, pq, pq_link); 575211095Sdes pdu_free(sp->isc, pq); 576211095Sdes } 577211095Sdes } 578211095Sdes mtx_unlock(&sp->hld_mtx); 579211095Sdes} 580211095Sdes 581211095Sdesstatic __inline void 582171568Sscottli_mbufcopy(struct mbuf *mp, caddr_t dp, int len) 583171568Sscottl{ 584171568Sscottl struct mbuf *m; 585171568Sscottl caddr_t bp; 586171568Sscottl 587171568Sscottl for(m = mp; m != NULL; m = m->m_next) { 588171568Sscottl bp = mtod(m, caddr_t); 589171568Sscottl /* 590171568Sscottl | the pdu is word (4 octed) aligned 591171568Sscottl | so len <= packet 592171568Sscottl */ 593171568Sscottl memcpy(dp, bp, MIN(len, m->m_len)); 594171568Sscottl dp += m->m_len; 595171568Sscottl len -= m->m_len; 596171568Sscottl if(len <= 0) 597171568Sscottl break; 598171568Sscottl } 599171568Sscottl} 600