4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 *
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <sys/cpuvar.h>
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/stat.h>
31 #include <sys/file.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/modctl.h>
35 #include <sys/sysmacros.h>
36 #include <sys/socket.h>
37 #include <sys/strsubr.h>
38 #include <sys/nvpair.h>
39
40 #include <sys/stmf.h>
41 #include <sys/stmf_ioctl.h>
42 #include <sys/portif.h>
43 #include <sys/idm/idm.h>
44 #include <sys/idm/idm_conn_sm.h>
3108 iscsit_sess_t *ist = ict->ict_sess;
3109 iscsi_scsi_cmd_hdr_t *hdr = (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
3110
3111 mutex_enter(&ist->ist_sn_mutex);
3112 if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
3113 /* do not queue, handle it immediately */
3114 DTRACE_PROBE2(immediate__cmd, iscsit_sess_t *, ist,
3115 idm_pdu_t *, rx_pdu);
3116 mutex_exit(&ist->ist_sn_mutex);
3117 return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3118 }
3119 if (iscsit_sna_lt(ist->ist_expcmdsn, ntohl(hdr->cmdsn))) {
3120 /*
3121 * Out-of-order commands (cmdSN higher than ExpCmdSN)
3122 * are staged on a fixed-size circular buffer until
3123 * the missing command is delivered to the SCSI layer.
3124 * Irrespective of the order of insertion into the
3125 * staging queue, the commands are processed out of the
3126 * queue in cmdSN order only.
3127 */
3128 rx_pdu->isp_queue_time = ddi_get_time();
3129 iscsit_add_pdu_to_queue(ist, rx_pdu);
3130 mutex_exit(&ist->ist_sn_mutex);
3131 return (ISCSIT_CMDSN_GT_EXPCMDSN);
3132 } else if (iscsit_sna_lt(ntohl(hdr->cmdsn), ist->ist_expcmdsn)) {
3133 DTRACE_PROBE3(cmdsn__lt__expcmdsn, iscsit_sess_t *, ist,
3134 iscsit_conn_t *, ict, idm_pdu_t *, rx_pdu);
3135 mutex_exit(&ist->ist_sn_mutex);
3136 return (ISCSIT_CMDSN_LT_EXPCMDSN);
3137 } else {
3138 mutex_exit(&ist->ist_sn_mutex);
3139 return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3140 }
3141 }
3142
3143 /*
3144 * iscsit_add_pdu_to_queue() adds PDUs into the array indexed by
3145 * their cmdsn value. The length of the array is kept above the
3146 * maximum window size. The window keeps the cmdsn within a range
3147 * such that there are no collisons. e.g. the assumption is that
3148 * the windowing checks make it impossible to receive PDUs that
3378 * wait time of 1004 > wait time of 1003, only 1003 will be considered
3379 * by the monitor thread. 1004 will be automatically processed by
3380 * iscsit_process_pdu_in_queue() once the scan is complete and the
3381 * expcmdsn becomes current.
3382 */
3383 mutex_enter(&ist->ist_sn_mutex);
3384 cbuf = ist->ist_rxpdu_queue;
3385 if (cbuf->cb_num_elems == 0) {
3386 mutex_exit(&ist->ist_sn_mutex);
3387 return;
3388 }
3389 for (next_pdu = NULL, i = 0; ; i++) {
3390 next_cmdsn = ist->ist_expcmdsn + i; /* start at expcmdsn */
3391 index = next_cmdsn % ISCSIT_RXPDU_QUEUE_LEN;
3392 if ((next_pdu = cbuf->cb_buffer[index]) != NULL) {
3393 /*
3394 * If the PDU wait time has not exceeded threshold
3395 * stop scanning the staging queue until the timer
3396 * fires again
3397 */
3398 if ((ddi_get_time() - next_pdu->isp_queue_time)
3399 < rxpdu_queue_threshold) {
3400 mutex_exit(&ist->ist_sn_mutex);
3401 return;
3402 }
3403 /*
3404 * Remove the next PDU from the queue and post it
3405 * to the SCSI layer, skipping over the missing
3406 * PDU. Stop scanning the staging queue until
3407 * the monitor timer fires again
3408 */
3409 (void) iscsit_remove_pdu_from_queue(ist, next_cmdsn);
3410 mutex_exit(&ist->ist_sn_mutex);
3411 DTRACE_PROBE3(advanced__to__blocked__cmdsn,
3412 iscsit_sess_t *, ist, idm_pdu_t *, next_pdu,
3413 uint32_t, next_cmdsn);
3414 iscsit_post_staged_pdu(next_pdu);
3415 /* Deliver any subsequent PDUs immediately */
3416 iscsit_process_pdu_in_queue(ist);
3417 return;
3418 }
3419 /*
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 *
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <sys/cpuvar.h>
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/stat.h>
31 #include <sys/file.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/modctl.h>
35 #include <sys/sysmacros.h>
36 #include <sys/socket.h>
37 #include <sys/strsubr.h>
38 #include <sys/nvpair.h>
39
40 #include <sys/stmf.h>
41 #include <sys/stmf_ioctl.h>
42 #include <sys/portif.h>
43 #include <sys/idm/idm.h>
44 #include <sys/idm/idm_conn_sm.h>
3108 iscsit_sess_t *ist = ict->ict_sess;
3109 iscsi_scsi_cmd_hdr_t *hdr = (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
3110
3111 mutex_enter(&ist->ist_sn_mutex);
3112 if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
3113 /* do not queue, handle it immediately */
3114 DTRACE_PROBE2(immediate__cmd, iscsit_sess_t *, ist,
3115 idm_pdu_t *, rx_pdu);
3116 mutex_exit(&ist->ist_sn_mutex);
3117 return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3118 }
3119 if (iscsit_sna_lt(ist->ist_expcmdsn, ntohl(hdr->cmdsn))) {
3120 /*
3121 * Out-of-order commands (cmdSN higher than ExpCmdSN)
3122 * are staged on a fixed-size circular buffer until
3123 * the missing command is delivered to the SCSI layer.
3124 * Irrespective of the order of insertion into the
3125 * staging queue, the commands are processed out of the
3126 * queue in cmdSN order only.
3127 */
3128 rx_pdu->isp_queue_time = gethrtime();
3129 iscsit_add_pdu_to_queue(ist, rx_pdu);
3130 mutex_exit(&ist->ist_sn_mutex);
3131 return (ISCSIT_CMDSN_GT_EXPCMDSN);
3132 } else if (iscsit_sna_lt(ntohl(hdr->cmdsn), ist->ist_expcmdsn)) {
3133 DTRACE_PROBE3(cmdsn__lt__expcmdsn, iscsit_sess_t *, ist,
3134 iscsit_conn_t *, ict, idm_pdu_t *, rx_pdu);
3135 mutex_exit(&ist->ist_sn_mutex);
3136 return (ISCSIT_CMDSN_LT_EXPCMDSN);
3137 } else {
3138 mutex_exit(&ist->ist_sn_mutex);
3139 return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3140 }
3141 }
3142
3143 /*
3144 * iscsit_add_pdu_to_queue() adds PDUs into the array indexed by
3145 * their cmdsn value. The length of the array is kept above the
3146 * maximum window size. The window keeps the cmdsn within a range
3147 * such that there are no collisons. e.g. the assumption is that
3148 * the windowing checks make it impossible to receive PDUs that
3378 * wait time of 1004 > wait time of 1003, only 1003 will be considered
3379 * by the monitor thread. 1004 will be automatically processed by
3380 * iscsit_process_pdu_in_queue() once the scan is complete and the
3381 * expcmdsn becomes current.
3382 */
3383 mutex_enter(&ist->ist_sn_mutex);
3384 cbuf = ist->ist_rxpdu_queue;
3385 if (cbuf->cb_num_elems == 0) {
3386 mutex_exit(&ist->ist_sn_mutex);
3387 return;
3388 }
3389 for (next_pdu = NULL, i = 0; ; i++) {
3390 next_cmdsn = ist->ist_expcmdsn + i; /* start at expcmdsn */
3391 index = next_cmdsn % ISCSIT_RXPDU_QUEUE_LEN;
3392 if ((next_pdu = cbuf->cb_buffer[index]) != NULL) {
3393 /*
3394 * If the PDU wait time has not exceeded threshold
3395 * stop scanning the staging queue until the timer
3396 * fires again
3397 */
3398 if ((gethrtime() - next_pdu->isp_queue_time)
3399 < (rxpdu_queue_threshold * NANOSEC)) {
3400 mutex_exit(&ist->ist_sn_mutex);
3401 return;
3402 }
3403 /*
3404 * Remove the next PDU from the queue and post it
3405 * to the SCSI layer, skipping over the missing
3406 * PDU. Stop scanning the staging queue until
3407 * the monitor timer fires again
3408 */
3409 (void) iscsit_remove_pdu_from_queue(ist, next_cmdsn);
3410 mutex_exit(&ist->ist_sn_mutex);
3411 DTRACE_PROBE3(advanced__to__blocked__cmdsn,
3412 iscsit_sess_t *, ist, idm_pdu_t *, next_pdu,
3413 uint32_t, next_cmdsn);
3414 iscsit_post_staged_pdu(next_pdu);
3415 /* Deliver any subsequent PDUs immediately */
3416 iscsit_process_pdu_in_queue(ist);
3417 return;
3418 }
3419 /*
|