NFE - Change default RX ring size from 128 -> 256, Adjust moderation timer.
[dragonfly.git] / sys / dev / disk / iscsi / initiator / isc_sm.c
blob4ab7bebfa1f11dfc63e93dabd5572d12a8d87782
1 /*-
2 * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
26 * $FreeBSD: src/sys/dev/iscsi/initiator/isc_sm.c,v 1.3 2008/11/25 07:17:11 scottl Exp $
29 | iSCSI - Session Manager
30 | $Id: isc_sm.c,v 1.30 2007/04/22 09:53:09 danny Exp danny $
33 #include "opt_iscsi_initiator.h"
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/conf.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/ctype.h>
41 #include <sys/errno.h>
42 #include <sys/sysctl.h>
43 #include <sys/file.h>
44 #include <sys/uio.h>
45 #include <sys/socketvar.h>
46 #include <sys/socket.h>
47 #include <sys/protosw.h>
48 #include <sys/proc.h>
49 #include <sys/ioccom.h>
50 #include <sys/queue.h>
51 #include <sys/kthread.h>
52 #include <sys/syslog.h>
53 #include <sys/mbuf.h>
54 #include <sys/bus.h>
55 #include <sys/eventhandler.h>
56 #include <sys/mutex.h>
57 #include <sys/mutex2.h>
59 #include <bus/cam/cam.h>
60 #include <bus/cam/cam_ccb.h>
61 #include <bus/cam/cam_sim.h>
62 #include <bus/cam/cam_xpt_sim.h>
63 #include <bus/cam/cam_periph.h>
65 #include <dev/disk/iscsi/initiator/iscsi.h>
66 #include <dev/disk/iscsi/initiator/iscsivar.h>
68 static void
69 _async(isc_session_t *sp, pduq_t *pq)
71 debug_called(8);
73 iscsi_async(sp, pq);
75 pdu_free(sp->isc, pq);
78 static void
79 _reject(isc_session_t *sp, pduq_t *pq)
81 pduq_t *opq;
82 pdu_t *pdu;
83 reject_t *reject;
84 int itt;
86 debug_called(8);
87 pdu = mtod(pq->mp, pdu_t *);
88 itt = pdu->ipdu.bhs.itt;
89 reject = &pq->pdu.ipdu.reject;
90 sdebug(2, "itt=%x reason=0x%x", ntohl(itt), reject->reason);
91 opq = i_search_hld(sp, itt, 0);
92 if(opq != NULL)
93 iscsi_reject(sp, opq, pq);
94 else {
95 switch(pq->pdu.ipdu.bhs.opcode) {
96 case ISCSI_LOGOUT_CMD: // XXX: wasabi does this - can't figure out why
97 sdebug(2, "ISCSI_LOGOUT_CMD ...");
98 break;
99 default:
100 xdebug("%d] we lost something itt=%x",
101 sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
104 pdu_free(sp->isc, pq);
107 static void
108 _r2t(isc_session_t *sp, pduq_t *pq)
110 pduq_t *opq;
112 debug_called(8);
113 opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1);
114 if(opq != NULL) {
115 iscsi_r2t(sp, opq, pq);
117 else {
118 r2t_t *r2t = &pq->pdu.ipdu.r2t;
120 xdebug("%d] we lost something itt=%x r2tSN=%d bo=%x ddtl=%x",
121 sp->sid, ntohl(pq->pdu.ipdu.bhs.itt),
122 ntohl(r2t->r2tSN), ntohl(r2t->bo), ntohl(r2t->ddtl));
124 pdu_free(sp->isc, pq);
127 static void
128 _scsi_rsp(isc_session_t *sp, pduq_t *pq)
130 pduq_t *opq;
132 debug_called(8);
133 opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 0);
134 debug(5, "itt=%x pq=%p opq=%p", ntohl(pq->pdu.ipdu.bhs.itt), pq, opq);
135 if(opq != NULL)
136 iscsi_done(sp, opq, pq);
137 else
138 xdebug("%d] we lost something itt=%x",
139 sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
140 pdu_free(sp->isc, pq);
143 static void
144 _read_data(isc_session_t *sp, pduq_t *pq)
146 pduq_t *opq;
148 debug_called(8);
149 opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1);
150 if(opq != NULL) {
151 if(scsi_decap(sp, opq, pq) != 1) {
152 i_remove_hld(sp, opq); // done
153 pdu_free(sp->isc, opq);
156 else
157 xdebug("%d] we lost something itt=%x",
158 sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
159 pdu_free(sp->isc, pq);
162 | this is a kludge,
163 | the jury is not back with a veredict, user or kernel
165 static void
166 _nop_out(isc_session_t *sp)
168 pduq_t *pq;
169 nop_out_t *nop_out;
171 debug_called(8);
173 sdebug(4, "cws=%d", sp->cws);
174 if(sp->cws == 0) {
176 | only send a nop if window is closed.
178 if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL)
179 // I guess we ran out of resources
180 return;
181 nop_out = &pq->pdu.ipdu.nop_out;
182 nop_out->opcode = ISCSI_NOP_OUT;
183 nop_out->itt = htonl(sp->sn.itt);
184 nop_out->ttt = -1;
185 nop_out->I = 1;
186 nop_out->F = 1;
187 if(isc_qout(sp, pq) != 0) {
188 sdebug(1, "failed");
189 pdu_free(sp->isc, pq);
194 static void
195 _nop_in(isc_session_t *sp, pduq_t *pq)
197 pdu_t *pp = &pq->pdu;
198 nop_in_t *nop_in = &pp->ipdu.nop_in;
199 bhs_t *bhs = &pp->ipdu.bhs;
201 debug_called(8);
203 sdebug(5, "itt=%x ttt=%x", htonl(nop_in->itt), htonl(nop_in->ttt));
204 if(nop_in->itt == -1) {
205 if(pp->ds_len != 0) {
207 | according to RFC 3720 this should be zero
208 | what to do if not?
210 xdebug("%d] dslen not zero", sp->sid);
212 if(nop_in->ttt != -1) {
213 nop_out_t *nop_out;
215 | target wants a nop_out
217 bhs->opcode = ISCSI_NOP_OUT;
218 bhs->I = 1;
219 bhs->F = 1;
221 | we are reusing the pdu, so bhs->ttt == nop_in->ttt;
222 | and need to zero out 'Reserved'
223 | small cludge here.
225 nop_out = &pp->ipdu.nop_out;
226 nop_out->sn.maxcmd = 0;
227 memset(nop_out->mbz, 0, sizeof(nop_out->mbz));
228 (void)isc_qout(sp, pq); //XXX: should check return?
229 return;
231 //else {
232 // just making noise?
233 // see 10.9.1: target does not want and answer.
236 } else
237 if(nop_in->ttt == -1) {
239 | it is an answer to a nop_in from us
241 if(nop_in->itt != -1) {
242 #ifdef ISC_WAIT4PING
243 // XXX: MUTEX please
244 if(sp->flags & ISC_WAIT4PING) {
245 i_nqueue_rsp(sp, pq);
246 wakeup(&sp->rsp);
247 return;
249 #endif
253 | drop it
255 pdu_free(sp->isc, pq);
256 return;
260 i_prepPDU(isc_session_t *sp, pduq_t *pq)
262 size_t len, n;
263 pdu_t *pp = &pq->pdu;
264 bhs_t *bhp = &pp->ipdu.bhs;
266 len = sizeof(bhs_t);
267 if(pp->ahs_len) {
268 len += pp->ahs_len;
269 bhp->AHSLength = pp->ahs_len / 4;
271 if(sp->hdrDigest)
272 len += 4;
273 if(pp->ds_len) {
274 n = pp->ds_len;
275 len += n;
276 #if BYTE_ORDER == LITTLE_ENDIAN
277 bhp->DSLength = ((n & 0x00ff0000) >> 16)
278 | (n & 0x0000ff00)
279 | ((n & 0x000000ff) << 16);
280 #else
281 bhp->DSLength = n;
282 #endif
283 if(len & 03) {
284 n = 4 - (len & 03);
285 len += n;
287 if(sp->dataDigest)
288 len += 4;
291 pq->len = len;
292 len -= sizeof(bhs_t);
293 if(sp->opt.maxBurstLength && (len > sp->opt.maxBurstLength)) {
294 xdebug("%d] pdu len=%zd > %d",
295 sp->sid, len, sp->opt.maxBurstLength);
296 // XXX: when this happens it used to hang ...
297 return E2BIG;
299 return 0;
303 isc_qout(isc_session_t *sp, pduq_t *pq)
305 int error = 0;
307 debug_called(8);
309 if(pq->len == 0 && (error = i_prepPDU(sp, pq)))
310 return error;
312 if(pq->pdu.ipdu.bhs.I)
313 i_nqueue_isnd(sp, pq);
314 else
315 if(pq->pdu.ipdu.data_out.opcode == ISCSI_WRITE_DATA)
316 i_nqueue_wsnd(sp, pq);
317 else
318 i_nqueue_csnd(sp, pq);
320 sdebug(5, "enqued: pq=%p", pq);
322 iscsi_lock_ex(&sp->io_mtx);
323 sp->flags |= ISC_OQNOTEMPTY;
324 if(sp->flags & ISC_OWAITING)
325 wakeup(&sp->flags);
326 iscsi_unlock_ex(&sp->io_mtx);
328 return error;
331 | called when a fullPhase is restarted
333 static void
334 ism_restart(isc_session_t *sp)
336 int lastcmd;
338 sdebug(2, "restart ...");
339 lastcmd = iscsi_requeue(sp);
340 #if 0
341 if(lastcmd != sp->sn.cmd) {
342 sdebug(1, "resetting CmdSN to=%d (from %d)", lastcmd, sp->sn.cmd);
343 sp->sn.cmd = lastcmd;
345 #endif
346 iscsi_lock_ex(&sp->io_mtx);
347 if(sp->flags & ISC_OWAITING) {
348 wakeup(&sp->flags);
350 iscsi_unlock_ex(&sp->io_mtx);
352 sdebug(2, "restarted lastcmd=0x%x", lastcmd);
356 ism_fullfeature(struct cdev *dev, int flag)
358 isc_session_t *sp = (isc_session_t *)dev->si_drv2;
359 int error;
361 sdebug(2, "flag=%d", flag);
363 error = 0;
364 switch(flag) {
365 case 0: // stop
366 sp->flags &= ~ISC_FFPHASE;
367 break;
368 case 1: // start
369 error = ic_fullfeature(dev);
370 break;
371 case 2: // restart
372 ism_restart(sp);
373 break;
375 return error;
378 void
379 ism_recv(isc_session_t *sp, pduq_t *pq)
381 bhs_t *bhs;
382 int statSN;
384 debug_called(8);
386 bhs = &pq->pdu.ipdu.bhs;
387 statSN = ntohl(bhs->OpcodeSpecificFields[1]);
388 #if 0
391 | this code is only for debugging.
393 sn_t *sn = &sp->sn;
394 if(sp->cws == 0) {
395 if((sp->flags & ISC_STALLED) == 0) {
396 sdebug(4, "window closed: max=0x%x exp=0x%x opcode=0x%x cmd=0x%x cws=%d.",
397 sn->maxCmd, sn->expCmd, bhs->opcode, sn->cmd, sp->cws);
398 sp->flags |= ISC_STALLED;
399 } else
400 if(sp->flags & ISC_STALLED) {
401 sdebug(4, "window opened: max=0x%x exp=0x%x opcode=0x%x cmd=0x%x cws=%d.",
402 sn->maxCmd, sn->expCmd, bhs->opcode, sn->cmd, sp->cws);
403 sp->flags &= ~ISC_STALLED;;
407 #endif
409 #ifdef notyet
410 if(sp->sn.expCmd != sn->cmd) {
411 sdebug(1, "we lost something ... exp=0x%x cmd=0x%x",
412 sn->expCmd, sn->cmd);
414 #endif
415 sdebug(5, "opcode=0x%x itt=0x%x stat#0x%x maxcmd=0x%0x",
416 bhs->opcode, ntohl(bhs->itt), statSN, sp->sn.maxCmd);
418 switch(bhs->opcode) {
419 case ISCSI_READ_DATA: {
420 data_in_t *cmd = &pq->pdu.ipdu.data_in;
422 if(cmd->S == 0)
423 break;
426 default:
427 if(statSN > (sp->sn.stat + 1)) {
428 sdebug(1, "we lost some rec=0x%x exp=0x%x",
429 statSN, sp->sn.stat);
430 // XXX: must do some error recovery here.
432 sp->sn.stat = statSN;
435 switch(bhs->opcode) {
436 case ISCSI_LOGIN_RSP:
437 case ISCSI_TEXT_RSP:
438 case ISCSI_LOGOUT_RSP:
439 i_nqueue_rsp(sp, pq);
440 wakeup(&sp->rsp);
441 sdebug(3, "wakeup rsp");
442 break;
444 case ISCSI_NOP_IN: _nop_in(sp, pq); break;
445 case ISCSI_SCSI_RSP: _scsi_rsp(sp, pq); break;
446 case ISCSI_READ_DATA: _read_data(sp, pq); break;
447 case ISCSI_R2T: _r2t(sp, pq); break;
448 case ISCSI_REJECT: _reject(sp, pq); break;
449 case ISCSI_ASYNC: _async(sp, pq); break;
451 case ISCSI_TASK_RSP:
452 default:
453 sdebug(1, "opcode=0x%x itt=0x%x not implemented yet",
454 bhs->opcode, ntohl(bhs->itt));
455 break;
460 | go through the out queues looking for work
461 | if either nothing to do, or window is closed
462 | return.
464 static int
465 proc_out(isc_session_t *sp)
467 sn_t *sn = &sp->sn;
468 pduq_t *pq;
469 int error, ndone;
470 int which;
472 debug_called(8);
473 error = ndone = 0;
475 while(sp->flags & ISC_LINK_UP) {
476 pdu_t *pp;
477 bhs_t *bhs;
479 | check if there is outstanding work in:
480 | 1- the Immediate queue
481 | 2- the R2T queue
482 | 3- the cmd queue, only if the command window allows it.
484 which = BIT(0) | BIT(1);
485 if(SNA_GT(sn->cmd, sn->maxCmd) == 0) // if(sn->maxCmd - sn->smc + 1) > 0
486 which |= BIT(2);
488 sdebug(4, "which=%d sn->maxCmd=%d sn->cmd=%d", which, sn->maxCmd, sn->cmd);
490 if((pq = i_dqueue_snd(sp, which)) == NULL)
491 break;
492 sdebug(4, "pq=%p", pq);
494 pp = &pq->pdu;
495 bhs = &pp->ipdu.bhs;
496 switch(bhs->opcode) {
497 case ISCSI_SCSI_CMD:
498 sn->itt++;
499 bhs->itt = htonl(sn->itt);
501 case ISCSI_LOGIN_CMD:
502 case ISCSI_TEXT_CMD:
503 case ISCSI_LOGOUT_CMD:
504 case ISCSI_SNACK:
505 case ISCSI_NOP_OUT:
506 case ISCSI_TASK_CMD:
507 bhs->CmdSN = htonl(sn->cmd);
508 if(bhs->I == 0)
509 sn->cmd++;
511 case ISCSI_WRITE_DATA:
512 bhs->ExpStSN = htonl(sn->stat);
513 break;
515 default:
516 // XXX: can this happen?
517 xdebug("bad opcode=0x%x sn(cmd=0x%x expCmd=0x%x maxCmd=0x%x expStat=0x%x itt=0x%x)",
518 bhs->opcode,
519 sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt);
520 // XXX: and now?
523 sdebug(4, "opcode=0x%x sn(cmd=0x%x expCmd=0x%x maxCmd=0x%x expStat=0x%x itt=0x%x)",
524 bhs->opcode,
525 sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt);
527 if(pq->ccb)
528 i_nqueue_hld(sp, pq);
530 if((error = isc_sendPDU(sp, pq)) == 0) {
531 ndone++;
532 if(pq->ccb == NULL)
533 pdu_free(sp->isc, pq);
535 else {
536 xdebug("error=%d ndone=%d opcode=0x%x ccb=%p itt=%x",
537 error, ndone, bhs->opcode, pq->ccb, ntohl(bhs->itt));
538 if(pq->ccb)
539 i_remove_hld(sp, pq);
540 switch(error) {
541 case EPIPE:
542 sp->flags &= ~ISC_LINK_UP;
544 case EAGAIN:
545 xdebug("requed");
546 i_rqueue_pdu(sp, pq);
547 break;
549 default:
550 if(pq->ccb) {
551 xdebug("back to cam");
552 pq->ccb->ccb_h.status |= CAM_REQUEUE_REQ; // some better error?
553 XPT_DONE(sp->isc, pq->ccb);
554 pdu_free(sp->isc, pq);
556 else
557 xdebug("we lost it!");
561 return error;
565 | survives link breakdowns.
567 static void
568 ism_proc(void *vp)
570 isc_session_t *sp = (isc_session_t *)vp;
571 int error;
573 debug_called(8);
575 sdebug(3, "started sp->flags=%x", sp->flags);
576 do {
577 if((sp->flags & ISC_HOLD) == 0) {
578 error = proc_out(sp);
579 if(error) {
580 sdebug(3, "error=%d", error);
583 iscsi_lock_ex(&sp->io_mtx);
584 if((sp->flags & ISC_LINK_UP) == 0) {
585 wakeup(&sp->soc);
588 if((sp->flags & (ISC_OQNOTEMPTY | ISC_SM_RUN)) == ISC_SM_RUN) {
589 sp->flags |= ISC_OWAITING;
590 if(issleep(&sp->flags, &sp->io_mtx, 0, "iscproc", hz*30) == EWOULDBLOCK) {
591 if(sp->flags & ISC_CON_RUNNING)
592 _nop_out(sp);
594 sp->flags &= ~ISC_OWAITING;
596 sp->flags &= ~ISC_OQNOTEMPTY;
597 iscsi_unlock_ex(&sp->io_mtx);
598 } while(sp->flags & ISC_SM_RUN);
600 sp->flags &= ~ISC_SM_RUNNING;
601 sdebug(3, "dropped ISC_SM_RUNNING");
603 wakeup(sp);
605 debug(3, "terminated sp=%p sp->sid=%d", sp, sp->sid);
607 kthread_exit();
610 #if 0
611 static int
612 isc_dump_options(SYSCTL_HANDLER_ARGS)
614 int error;
615 isc_session_t *sp;
616 char buf[1024], *bp;
618 sp = (isc_session_t *)arg1;
619 bp = buf;
620 ksprintf(bp, "targetname='%s'", sp->opt.targetName);
621 bp += strlen(bp);
622 ksprintf(bp, " targetname='%s'", sp->opt.targetAddress);
623 error = SYSCTL_OUT(req, buf, strlen(buf));
624 return error;
626 #endif
628 static int
629 isc_dump_stats(SYSCTL_HANDLER_ARGS)
631 isc_session_t *sp;
632 struct isc_softc *sc;
633 char buf[1024], *bp;
634 int error, n;
636 sp = (isc_session_t *)arg1;
637 sc = sp->isc;
639 bp = buf;
640 n = sizeof(buf);
641 ksnprintf(bp, n, "recv=%d sent=%d", sp->stats.nrecv, sp->stats.nsent);
642 bp += strlen(bp);
643 n -= strlen(bp);
644 ksnprintf(bp, n, " flags=0x%08x pdus-alloc=%d pdus-max=%d",
645 sp->flags, sc->npdu_alloc, sc->npdu_max);
646 bp += strlen(bp);
647 n -= strlen(bp);
648 ksnprintf(bp, n, " cws=%d cmd=%x exp=%x max=%x stat=%x itt=%x",
649 sp->cws, sp->sn.cmd, sp->sn.expCmd, sp->sn.maxCmd, sp->sn.stat, sp->sn.itt);
650 error = SYSCTL_OUT(req, buf, strlen(buf));
651 return error;
654 static int
655 isc_sysctl_targetName(SYSCTL_HANDLER_ARGS)
657 char buf[128], **cp;
658 int error;
660 cp = (char **)arg1;
661 ksnprintf(buf, sizeof(buf), "%s", *cp);
662 error = SYSCTL_OUT(req, buf, strlen(buf));
663 return error;
665 static int
666 isc_sysctl_targetAddress(SYSCTL_HANDLER_ARGS)
668 char buf[128], **cp;
669 int error;
671 cp = (char **)arg1;
672 ksnprintf(buf, sizeof(buf), "%s", *cp);
673 error = SYSCTL_OUT(req, buf, strlen(buf));
674 return error;
676 static void
677 isc_add_sysctls(isc_session_t *sp)
679 debug_called(8);
680 sdebug(6, "sid=%d %s", sp->sid, sp->dev->si_name);
682 sysctl_ctx_init(&sp->clist);
683 sp->oid = SYSCTL_ADD_NODE(&sp->clist,
684 SYSCTL_CHILDREN(sp->isc->oid),
685 OID_AUTO,
686 sp->dev->si_name+5, // iscsi0
687 CTLFLAG_RD,
689 "initiator");
690 SYSCTL_ADD_PROC(&sp->clist,
691 SYSCTL_CHILDREN(sp->oid),
692 OID_AUTO,
693 "targetname",
694 CTLFLAG_RD,
695 (void *)&sp->opt.targetName, 0,
696 isc_sysctl_targetName, "A", "target name");
698 SYSCTL_ADD_PROC(&sp->clist,
699 SYSCTL_CHILDREN(sp->oid),
700 OID_AUTO,
701 "targeaddress",
702 CTLFLAG_RD,
703 (void *)&sp->opt.targetAddress, 0,
704 isc_sysctl_targetAddress, "A", "target address");
706 SYSCTL_ADD_PROC(&sp->clist,
707 SYSCTL_CHILDREN(sp->oid),
708 OID_AUTO,
709 "stats",
710 CTLFLAG_RD,
711 (void *)sp, 0,
712 isc_dump_stats, "A", "statistics");
714 SYSCTL_ADD_INT(&sp->clist,
715 SYSCTL_CHILDREN(sp->oid),
716 OID_AUTO,
717 "douio",
718 CTLFLAG_RW,
719 &sp->douio, 0, "enable uio on read");
722 void
723 ism_stop(isc_session_t *sp)
725 struct isc_softc *sc = sp->isc;
726 cdev_t dev;
728 debug_called(8);
729 sdebug(2, "terminating");
731 | first stop the receiver
733 isc_stop_receiver(sp);
736 | now stop the xmitter
738 sp->flags &= ~ISC_SM_RUN;
739 while(sp->flags & ISC_SM_RUNNING) {
740 sdebug(2, "waiting for ism to stop");
741 wakeup(&sp->flags);
742 tsleep(sp, 0, "-", hz);
744 sdebug(2, "ism stopped");
745 sp->flags &= ~ISC_FFPHASE;
747 iscsi_cleanup(sp);
749 (void)i_pdu_flush(sp);
751 ic_lost_target(sp, sp->sid);
753 lockmgr(&sc->lock, LK_EXCLUSIVE);
754 TAILQ_REMOVE(&sc->isc_sess, sp, sp_link);
755 sc->nsess--;
756 lockmgr(&sc->lock, LK_RELEASE);
758 dev = sp->dev;
759 sp->dev = NULL;
761 release_dev(dev);
762 destroy_dev(dev);
764 mtx_uninit(&sp->rsp_mtx);
765 mtx_uninit(&sp->rsv_mtx);
766 mtx_uninit(&sp->hld_mtx);
767 mtx_uninit(&sp->snd_mtx);
768 mtx_uninit(&sp->io_mtx);
770 i_freeopt(&sp->opt);
771 sc->sessions[sp->sid] = NULL;
773 if(sysctl_ctx_free(&sp->clist))
774 xdebug("sysctl_ctx_free failed");
776 kfree(sp, M_ISCSI);
780 ism_start(isc_session_t *sp)
782 debug_called(8);
784 | now is a good time to do some initialization
786 TAILQ_INIT(&sp->rsp);
787 TAILQ_INIT(&sp->rsv);
788 TAILQ_INIT(&sp->csnd);
789 TAILQ_INIT(&sp->isnd);
790 TAILQ_INIT(&sp->wsnd);
791 TAILQ_INIT(&sp->hld);
793 mtx_init(&sp->rsv_mtx);
794 mtx_init(&sp->rsp_mtx);
795 mtx_init(&sp->snd_mtx);
796 mtx_init(&sp->hld_mtx);
798 mtx_init(&sp->io_mtx);
800 isc_add_sysctls(sp);
802 sp->flags |= ISC_SM_RUN;
803 sp->flags |= ISC_SM_RUNNING;
805 debug(4, "starting ism_proc: sp->sid=%d", sp->sid);
806 return kthread_create(ism_proc, sp, &sp->stp, "ism_%d", sp->sid);