Print this page
NEX-3414 CLONE - Port 3339 iscsi/fs:5 causes panic on initiator
NEX-3419 CLONE - Run multi initiator sessions to a single target test can panic the initiator
Reviewed by: Steve Peng <steve.peng@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_io.c
+++ new/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_io.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
23 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 - * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 + * Copyright 2011, 2015 Nexenta Systems, Inc. All rights reserved.
25 25 *
26 26 * iSCSI Pseudo HBA Driver
27 27 */
28 28
29 29 #include <sys/socket.h> /* networking stuff */
30 30 #include <sys/t_kuser.h> /* networking stuff */
31 31 #include <sys/tihdr.h> /* networking stuff */
32 32 #include <sys/strsubr.h> /* networking stuff */
33 33 #include <netinet/tcp.h> /* TCP_NODELAY */
34 34 #include <sys/socketvar.h> /* _ALLOC_SLEEP */
35 35 #include <sys/strsun.h> /* DB_TYPE() */
36 36 #include <sys/scsi/generic/sense.h>
37 37
38 38 #include "iscsi.h" /* iscsi driver */
39 39 #include <sys/iscsi_protocol.h> /* iscsi protocol */
40 40
41 41 #define ISCSI_INI_TASK_TTT 0xffffffff
42 42 #define ISCSI_CONN_TIEMOUT_DETECT 20
43 43
44 44 boolean_t iscsi_io_logging = B_FALSE;
45 45
46 46 #define ISCSI_CHECK_SCSI_READ(ICHK_CMD, ICHK_HDR, ICHK_LEN, ICHK_TYPE) \
47 47 if (idm_pattern_checking) { \
48 48 struct scsi_pkt *pkt = (ICHK_CMD)->cmd_un.scsi.pkt; \
49 49 if (((ICHK_HDR)->response == 0) && \
50 50 ((ICHK_HDR)->cmd_status == 0) && \
51 51 ((pkt->pkt_cdbp[0] == SCMD_READ_G1) || \
52 52 (pkt->pkt_cdbp[0] == SCMD_READ_G4) || \
53 53 (pkt->pkt_cdbp[0] == SCMD_READ) || \
54 54 (pkt->pkt_cdbp[0] == SCMD_READ_G5))) { \
55 55 idm_buf_t *idb = (ICHK_CMD)->cmd_un.scsi.ibp_ibuf; \
56 56 IDM_BUFPAT_CHECK(idb, ICHK_LEN, ICHK_TYPE); \
57 57 } \
58 58 }
59 59
60 60 /* Size of structure scsi_arq_status without sense data. */
61 61 #define ISCSI_ARQ_STATUS_NOSENSE_LEN (sizeof (struct scsi_arq_status) - \
62 62 sizeof (struct scsi_extended_sense))
63 63
64 64 /* generic io helpers */
65 65 static uint32_t n2h24(uchar_t *ptr);
66 66 static int iscsi_sna_lt(uint32_t n1, uint32_t n2);
67 67 void iscsi_update_flow_control(iscsi_sess_t *isp,
68 68 uint32_t max, uint32_t exp);
69 69 static iscsi_status_t iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp,
70 70 idm_conn_t *ic, iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp);
71 71 static iscsi_status_t iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp,
72 72 iscsi_hdr_t *ihp, iscsi_cmd_t **icmdp);
73 73 static void iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
74 74 idm_status_t status);
75 75 static void iscsi_drop_conn_cleanup(iscsi_conn_t *icp);
76 76 static boolean_t iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp);
77 77 /* callbacks from idm */
78 78 static idm_pdu_cb_t iscsi_tx_done;
79 79
80 80 /* receivers */
81 81 static idm_status_t iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu);
82 82 static idm_status_t iscsi_rx_process_data_rsp(idm_conn_t *ic,
83 83 idm_pdu_t *pdu);
84 84 static idm_status_t iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu);
85 85 static idm_status_t iscsi_rx_process_reject_rsp(idm_conn_t *ic,
86 86 idm_pdu_t *pdu);
87 87
88 88 static idm_status_t iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic,
89 89 iscsi_hdr_t *old_ihp);
90 90 static idm_status_t iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic,
91 91 idm_pdu_t *pdu);
92 92 static idm_status_t iscsi_rx_process_logout_rsp(idm_conn_t *ic,
93 93 idm_pdu_t *pdu);
94 94 static idm_status_t iscsi_rx_process_async_rsp(idm_conn_t *ic,
95 95 idm_pdu_t *pdu);
96 96 static idm_status_t iscsi_rx_process_text_rsp(idm_conn_t *ic,
97 97 idm_pdu_t *pdu);
98 98
99 99 /* senders */
100 100 static iscsi_status_t iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
101 101 static iscsi_status_t iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
102 102 static iscsi_status_t iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
103 103 static iscsi_status_t iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
104 104 static iscsi_status_t iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
105 105 static iscsi_status_t iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
106 106
107 107
108 108 /* helpers */
109 109 static void iscsi_logout_start(void *arg);
110 110 static void iscsi_handle_passthru_callback(struct scsi_pkt *pkt);
111 111 static void iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt);
112 112
113 113 static void iscsi_timeout_checks(iscsi_sess_t *isp);
114 114 static void iscsi_nop_checks(iscsi_sess_t *isp);
115 115 static boolean_t iscsi_decode_sense(uint8_t *sense_data, iscsi_cmd_t *icmdp);
116 116 static void iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
117 117 iscsi_conn_t *icp);
118 118
119 119 /*
120 120 * This file contains the main guts of the iSCSI protocol layer.
121 121 * It's broken into 5 sections; Basic helper functions, RX IO path,
122 122 * TX IO path, Completion (IC) IO path, and watchdog (WD) routines.
123 123 *
124 124 * The IO flow model is similiar to the below diagram. The
125 125 * iscsi session, connection and command state machines are used
126 126 * to drive IO through this flow diagram. Reference those files
127 127 * to get a detailed description of their respective state models
128 128 * prior to their xxx_state_machine_function().
129 129 *
130 130 * tran_start() -> CMD_E1 TX_THREAD RX_THREAD
131 131 * | T T
132 132 * V T T
133 133 * PENDING_Q --CMD_E2--> ACTIVE_Q - --CMD_E3--+
134 134 * T \ C T |
135 135 * T \M T |
136 136 * D T |
137 137 * WD_THREAD TT|TT T |
138 138 * /E T |
139 139 * / 6 T |
140 140 * ABORTING_Q<- --CMD_E3--+
141 141 * T |
142 142 * T T |
143 143 * T |
144 144 * callback() <--CMD_E#-- COMPLETION_Q <------------+
145 145 * T
146 146 * T
147 147 * IC_THREAD
148 148 *
149 149 * External and internal command are ran thru this same state
150 150 * machine. All commands enter the state machine by receiving an
151 151 * ISCSI_CMD_EVENT_E1. This event places the command into the
152 152 * PENDING_Q. Next when resources are available the TX_THREAD
153 153 * issues a E2 event on the command. This sends the command
154 154 * to the TCP stack and places the command on the ACTIVE_Q. While
155 155 * on the PENDIING_Q and ACTIVE_Q, the command is monitored via the
156 156 * WD_THREAD to ensure the pkt_time has not elapsed. If elapsed the
157 157 * command is issued an E6(timeout) event which moves either (if pending)
158 158 * completed the command or (if active) moves the command to the
159 159 * aborting queue and issues a SCSI TASK MANAGEMENT ABORT command
160 160 * to cancel the IO request. If the original command is completed
161 161 * or the TASK MANAGEMENT command completes the command is moved
162 162 * to the COMPLETION_Q via a E3 event. The IC_THREAD then processes
163 163 * the COMPLETION_Q and issues the scsi_pkt callback. This
164 164 * callback can not be processed directly from the RX_THREAD
165 165 * because the callback might call back into the iscsi driver
166 166 * causing a deadlock condition.
167 167 *
168 168 * For more details on the complete CMD state machine reference
169 169 * the state machine diagram in iscsi_cmd.c. The connection state
170 170 * machine is driven via IO events in this file. Then session
171 171 * events are driven by the connection events. For complete
172 172 * details on these state machines reference iscsi_sess.c and
173 173 * iscsi_conn.c
174 174 */
175 175
176 176
177 177 /*
178 178 * +--------------------------------------------------------------------+
179 179 * | io helper routines |
180 180 * +--------------------------------------------------------------------+
181 181 */
182 182
183 183 /*
184 184 * n2h24 - native to host 24 bit integer translation.
185 185 */
186 186 static uint32_t
187 187 n2h24(uchar_t *ptr)
188 188 {
189 189 uint32_t idx;
190 190 bcopy(ptr, &idx, 3);
191 191 return (ntohl(idx) >> 8);
192 192 }
193 193
194 194 /*
195 195 * iscsi_sna_lt - Serial Number Arithmetic, 32 bits, less than, RFC1982
196 196 */
197 197 static int
198 198 iscsi_sna_lt(uint32_t n1, uint32_t n2)
199 199 {
200 200 return ((n1 != n2) &&
201 201 (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
202 202 ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
203 203 }
204 204
205 205 /*
206 206 * iscsi_sna_lte - Serial Number Arithmetic, 32 bits, less than or equal,
207 207 * RFC1982
208 208 */
209 209 int
210 210 iscsi_sna_lte(uint32_t n1, uint32_t n2)
211 211 {
212 212 return ((n1 == n2) ||
213 213 (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
214 214 ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
215 215 }
216 216
217 217 /*
218 218 * iscsi_update_flow_control - Update expcmdsn and maxcmdsn iSCSI
219 219 * flow control information for a session
220 220 */
221 221 void
222 222 iscsi_update_flow_control(iscsi_sess_t *isp, uint32_t max, uint32_t exp)
223 223 {
224 224 ASSERT(isp != NULL);
225 225 ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
226 226
227 227 if (!iscsi_sna_lt(max, (exp - 1))) {
228 228
229 229 if (!iscsi_sna_lte(exp, isp->sess_expcmdsn)) {
230 230 isp->sess_expcmdsn = exp;
231 231 }
232 232
233 233 if (!iscsi_sna_lte(max, isp->sess_maxcmdsn)) {
234 234 isp->sess_maxcmdsn = max;
235 235 if (iscsi_sna_lte(isp->sess_cmdsn,
236 236 isp->sess_maxcmdsn)) {
237 237 /*
238 238 * the window is open again - schedule
239 239 * to send any held tasks soon
240 240 */
241 241 iscsi_sess_redrive_io(isp);
242 242 }
243 243 }
244 244 }
245 245 }
246 246
247 247
248 248 /*
249 249 * +--------------------------------------------------------------------+
250 250 * | io receive and processing routines |
251 251 * +--------------------------------------------------------------------+
252 252 */
253 253
254 254 /*
255 255 * iscsi_rx_scsi_rsp - called from idm
256 256 * For each opcode type fan out the processing.
257 257 */
258 258 void
259 259 iscsi_rx_scsi_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
260 260 {
261 261 iscsi_conn_t *icp;
262 262 iscsi_sess_t *isp;
263 263 iscsi_hdr_t *ihp;
264 264 idm_status_t status;
265 265
266 266 ASSERT(ic != NULL);
267 267 ASSERT(pdu != NULL);
268 268 icp = ic->ic_handle;
269 269 ASSERT(icp != NULL);
270 270 ihp = (iscsi_hdr_t *)pdu->isp_hdr;
271 271 ASSERT(ihp != NULL);
272 272 isp = icp->conn_sess;
273 273 ASSERT(isp != NULL);
274 274
275 275 /* reset the session timer when we receive the response */
276 276 isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
277 277
278 278 /* fan out the hdr processing */
279 279 switch (ihp->opcode & ISCSI_OPCODE_MASK) {
280 280 case ISCSI_OP_SCSI_DATA_RSP:
281 281 status = iscsi_rx_process_data_rsp(ic, pdu);
282 282 break;
283 283 case ISCSI_OP_SCSI_RSP:
284 284 status = iscsi_rx_process_cmd_rsp(ic, pdu);
285 285 idm_pdu_complete(pdu, status);
286 286 break;
287 287 default:
288 288 cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
289 289 "received pdu with unsupported opcode 0x%02x",
290 290 icp->conn_oid, ihp->opcode);
291 291 status = IDM_STATUS_PROTOCOL_ERROR;
292 292 }
293 293 iscsi_process_rsp_status(isp, icp, status);
294 294 }
295 295
296 296 void
297 297 iscsi_task_cleanup(int opcode, iscsi_cmd_t *icmdp)
298 298 {
299 299 struct buf *bp;
300 300 idm_buf_t *ibp, *obp;
301 301 idm_task_t *itp;
302 302
303 303 itp = icmdp->cmd_itp;
304 304 ASSERT(itp != NULL);
305 305 ASSERT((opcode == ISCSI_OP_SCSI_DATA_RSP) ||
306 306 (opcode == ISCSI_OP_SCSI_RSP));
307 307
308 308 bp = icmdp->cmd_un.scsi.bp;
309 309 ibp = icmdp->cmd_un.scsi.ibp_ibuf;
310 310 obp = icmdp->cmd_un.scsi.ibp_obuf;
311 311 ISCSI_IO_LOG(CE_NOTE, "DEBUG: task_cleanup: itp: %p opcode: %d "
312 312 "icmdp: %p bp: %p ibp: %p", (void *)itp, opcode,
313 313 (void *)icmdp, (void *)bp, (void *)ibp);
314 314 if (bp && bp->b_bcount) {
315 315 if (ibp != NULL && bp->b_flags & B_READ) {
316 316 idm_buf_unbind_in(itp, ibp);
317 317 idm_buf_free(ibp);
318 318 icmdp->cmd_un.scsi.ibp_ibuf = NULL;
319 319 } else if (obp != NULL && !(bp->b_flags & B_READ)) {
320 320 idm_buf_unbind_out(itp, obp);
321 321 idm_buf_free(obp);
322 322 icmdp->cmd_un.scsi.ibp_obuf = NULL;
323 323 }
324 324 }
325 325
326 326 idm_task_done(itp);
327 327 }
328 328
329 329 idm_status_t
330 330 iscsi_rx_chk(iscsi_conn_t *icp, iscsi_sess_t *isp,
331 331 iscsi_scsi_rsp_hdr_t *irhp, iscsi_cmd_t **icmdp)
332 332 {
333 333 iscsi_status_t rval;
334 334
335 335 mutex_enter(&isp->sess_cmdsn_mutex);
336 336
337 337 if (icp->conn_expstatsn == ntohl(irhp->statsn)) {
338 338 icp->conn_expstatsn++;
339 339 } else {
340 340 cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
341 341 "received status out of order itt:0x%x statsn:0x%x "
342 342 "expstatsn:0x%x", icp->conn_oid, irhp->opcode,
343 343 irhp->itt, ntohl(irhp->statsn), icp->conn_expstatsn);
344 344 mutex_exit(&isp->sess_cmdsn_mutex);
345 345 return (IDM_STATUS_PROTOCOL_ERROR);
346 346 }
347 347
348 348 /* get icmdp so we can cleanup on error */
349 349 if ((irhp->opcode == ISCSI_OP_SCSI_DATA_RSP) ||
350 350 (irhp->opcode == ISCSI_OP_SCSI_RSP)) {
351 351 rval = iscsi_rx_process_scsi_itt_to_icmdp(isp, icp->conn_ic,
352 352 irhp, icmdp);
353 353 } else {
354 354 rval = iscsi_rx_process_itt_to_icmdp(isp,
355 355 (iscsi_hdr_t *)irhp, icmdp);
356 356 }
357 357
358 358 if (!ISCSI_SUCCESS(rval)) {
359 359 mutex_exit(&isp->sess_cmdsn_mutex);
360 360 return (IDM_STATUS_PROTOCOL_ERROR);
361 361 }
362 362
363 363 /* update expcmdsn and maxcmdsn */
364 364 iscsi_update_flow_control(isp, ntohl(irhp->maxcmdsn),
365 365 ntohl(irhp->expcmdsn));
366 366 mutex_exit(&isp->sess_cmdsn_mutex);
367 367 return (IDM_STATUS_SUCCESS);
368 368 }
369 369
370 370 static void
371 371 iscsi_cmd_rsp_chk(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp)
372 372 {
373 373 struct scsi_pkt *pkt;
374 374 size_t data_transferred;
375 375
376 376 pkt = icmdp->cmd_un.scsi.pkt;
377 377 pkt->pkt_resid = 0;
378 378 data_transferred = icmdp->cmd_un.scsi.data_transferred;
379 379 /* Check the residual count */
380 380 if ((icmdp->cmd_un.scsi.bp) &&
381 381 (data_transferred != icmdp->cmd_un.scsi.bp->b_bcount)) {
382 382 /*
383 383 * We didn't xfer the expected amount of data -
384 384 * the residual_count in the header is only
385 385 * valid if the underflow flag is set.
386 386 */
387 387 if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
388 388 pkt->pkt_resid = ntohl(issrhp->residual_count);
389 389 } else {
390 390 if (icmdp->cmd_un.scsi.bp->b_bcount >
391 391 data_transferred) {
392 392 /*
393 393 * Some data fell on the floor
394 394 * somehow - probably a CRC error
395 395 */
396 396 pkt->pkt_resid =
397 397 icmdp->cmd_un.scsi.bp->b_bcount -
398 398 data_transferred;
399 399 }
400 400 }
401 401 ISCSI_IO_LOG(CE_NOTE,
402 402 "DEBUG: iscsi_rx_cmd_rsp_chk: itt: %u"
403 403 "data_trans != b_count data_transferred: %lu "
404 404 "b_count: %lu cmd_status: %d flags: %d resid: %lu",
405 405 issrhp->itt, data_transferred,
406 406 icmdp->cmd_un.scsi.bp->b_bcount,
407 407 issrhp->cmd_status & STATUS_MASK,
408 408 issrhp->flags, pkt->pkt_resid);
409 409 }
410 410 /* set flags that tell SCSA that the command is complete */
411 411 if (icmdp->cmd_crc_error_seen == B_FALSE) {
412 412 /* Set successful completion */
413 413 pkt->pkt_reason = CMD_CMPLT;
414 414 if (icmdp->cmd_un.scsi.bp) {
415 415 pkt->pkt_state |= (STATE_XFERRED_DATA |
416 416 STATE_GOT_STATUS);
417 417 } else {
418 418 pkt->pkt_state |= STATE_GOT_STATUS;
419 419 }
420 420 } else {
421 421 /*
422 422 * Some of the data was found to have an incorrect
423 423 * error at the protocol error.
424 424 */
425 425 pkt->pkt_reason = CMD_PER_FAIL;
426 426 pkt->pkt_statistics |= STAT_PERR;
427 427 if (icmdp->cmd_un.scsi.bp) {
428 428 pkt->pkt_resid =
429 429 icmdp->cmd_un.scsi.bp->b_bcount;
430 430 } else {
431 431 pkt->pkt_resid = 0;
432 432 }
433 433 }
434 434 }
435 435
436 436 static boolean_t
437 437 iscsi_cmd_rsp_cmd_status(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp,
438 438 uint8_t *data)
439 439 {
440 440 int32_t dlength;
441 441 struct scsi_arq_status *arqstat;
442 442 size_t senselen;
443 443 int32_t statuslen;
444 444 int32_t sensebuf_len;
445 445 struct scsi_pkt *pkt;
446 446 boolean_t affect = B_FALSE;
447 447 int32_t senselen_to_copy;
448 448
449 449 pkt = icmdp->cmd_un.scsi.pkt;
450 450 dlength = n2h24(issrhp->dlength);
451 451
452 452 /*
453 453 * Process iSCSI Cmd Response Status
454 454 * RFC 3720 Sectionn 10.4.2.
455 455 */
456 456 switch (issrhp->cmd_status & STATUS_MASK) {
457 457 case STATUS_GOOD:
458 458 /* pass SCSI status up stack */
459 459 if (pkt->pkt_scbp) {
460 460 pkt->pkt_scbp[0] = issrhp->cmd_status;
461 461 }
462 462 break;
463 463 case STATUS_CHECK:
464 464 /*
465 465 * Verify we received a sense buffer and
466 466 * that there is the correct amount of
467 467 * request sense space to copy it to.
468 468 */
469 469 if ((dlength > 1) &&
470 470 (pkt->pkt_scbp != NULL) &&
471 471 (icmdp->cmd_un.scsi.statuslen >=
472 472 sizeof (struct scsi_arq_status))) {
473 473 /*
474 474 * If a bad command status is received we
475 475 * need to reset the pkt_resid to zero.
476 476 * The target driver compares its value
477 477 * before checking other error flags.
478 478 * (ex. check conditions)
479 479 */
480 480 pkt->pkt_resid = 0;
481 481
482 482 /* get sense length from first 2 bytes */
483 483 senselen = ((data[0] << 8) | data[1]) &
484 484 (size_t)0xFFFF;
485 485 ISCSI_IO_LOG(CE_NOTE,
486 486 "DEBUG: iscsi_rx_cmd_rsp_cmd_status status_check: "
487 487 "dlen: %d scbp: %p statuslen: %d arq: %d senselen:"
488 488 " %lu", dlength, (void *)pkt->pkt_scbp,
489 489 icmdp->cmd_un.scsi.statuslen,
490 490 (int)sizeof (struct scsi_arq_status),
491 491 senselen);
492 492
493 493 /* Sanity-check on the sense length */
494 494 if ((senselen + 2) > dlength) {
495 495 senselen = dlength - 2;
496 496 }
497 497
498 498 /*
499 499 * If there was a Data Digest error then
500 500 * the sense data cannot be trusted.
501 501 */
502 502 if (icmdp->cmd_crc_error_seen) {
503 503 senselen = 0;
504 504 }
505 505
506 506 /* automatic request sense */
507 507 arqstat =
508 508 (struct scsi_arq_status *)pkt->pkt_scbp;
509 509
510 510 /* pass SCSI status up stack */
511 511 *((uchar_t *)&arqstat->sts_status) =
512 512 issrhp->cmd_status;
513 513
514 514 /*
515 515 * Set the status for the automatic
516 516 * request sense command
517 517 */
518 518 arqstat->sts_rqpkt_state = (STATE_GOT_BUS |
519 519 STATE_GOT_TARGET | STATE_SENT_CMD |
520 520 STATE_XFERRED_DATA | STATE_GOT_STATUS |
521 521 STATE_ARQ_DONE);
522 522
523 523 *((uchar_t *)&arqstat->sts_rqpkt_status) =
524 524 STATUS_GOOD;
525 525
526 526 arqstat->sts_rqpkt_reason = CMD_CMPLT;
527 527 statuslen = icmdp->cmd_un.scsi.statuslen;
528 528
529 529 if (senselen == 0) {
530 530 /* auto request sense failed */
531 531 arqstat->sts_rqpkt_status.sts_chk = 1;
532 532 arqstat->sts_rqpkt_resid = statuslen;
533 533 } else if (senselen < statuslen) {
534 534 /* auto request sense short */
535 535 arqstat->sts_rqpkt_resid = statuslen - senselen;
536 536 } else {
537 537 /* auto request sense complete */
538 538 arqstat->sts_rqpkt_resid = 0;
539 539 }
540 540 arqstat->sts_rqpkt_statistics = 0;
541 541 pkt->pkt_state |= STATE_ARQ_DONE;
542 542
543 543 if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_XARQ) {
544 544 pkt->pkt_state |= STATE_XARQ_DONE;
545 545 }
546 546
547 547 /*
548 548 * Calculate size of space reserved for sense data in
549 549 * pkt->pkt_scbp.
550 550 */
551 551 sensebuf_len = statuslen - ISCSI_ARQ_STATUS_NOSENSE_LEN;
552 552
553 553 /* copy auto request sense */
554 554 senselen_to_copy = min(senselen, sensebuf_len);
555 555 if (senselen_to_copy > 0) {
556 556 bcopy(&data[2], (uchar_t *)&arqstat->
557 557 sts_sensedata, senselen_to_copy);
558 558
559 559 affect = iscsi_decode_sense(
560 560 (uint8_t *)&arqstat->sts_sensedata, icmdp);
561 561 }
562 562 arqstat->sts_rqpkt_resid = sensebuf_len -
563 563 senselen_to_copy;
564 564 ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_cmd_rsp_cmd_status:"
565 565 " sts_rqpkt_resid: %d pkt_scblen: %d senselen: %lu"
566 566 " sensebuf_len: %d senselen_to_copy: %d affect: %d",
567 567 arqstat->sts_rqpkt_resid, pkt->pkt_scblen, senselen,
568 568 sensebuf_len, senselen_to_copy, affect);
569 569 break;
570 570 }
571 571 /* FALLTHRU */
572 572 case STATUS_BUSY:
573 573 case STATUS_RESERVATION_CONFLICT:
574 574 case STATUS_QFULL:
575 575 case STATUS_ACA_ACTIVE:
576 576 default:
577 577 /*
578 578 * If a bad command status is received we need to
579 579 * reset the pkt_resid to zero. The target driver
580 580 * compares its value before checking other error
581 581 * flags. (ex. check conditions)
582 582 */
583 583 ISCSI_IO_LOG(CE_NOTE,
584 584 "DEBUG: iscsi_rx_cmd_rsp_cmd_status: status: "
585 585 "%d cmd_status: %d dlen: %u scbp: %p statuslen: %d "
586 586 "arg_len: %d", issrhp->cmd_status & STATUS_MASK,
587 587 issrhp->cmd_status, dlength, (void *)pkt->pkt_scbp,
588 588 icmdp->cmd_un.scsi.statuslen,
589 589 (int)sizeof (struct scsi_arq_status));
590 590 pkt->pkt_resid = 0;
591 591 /* pass SCSI status up stack */
592 592 if (pkt->pkt_scbp) {
593 593 pkt->pkt_scbp[0] = issrhp->cmd_status;
594 594 }
595 595 }
596 596
597 597 return (affect);
598 598 }
599 599
600 600 /*
601 601 * iscsi_rx_process_login_pdup - Process login response PDU. This function
602 602 * copies the data into the connection context so that the login code can
603 603 * interpret it.
604 604 */
605 605
606 606 idm_status_t
607 607 iscsi_rx_process_login_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
608 608 {
609 609 iscsi_conn_t *icp;
610 610
611 611 icp = ic->ic_handle;
612 612
613 613 /*
614 614 * Copy header and data into connection structure so iscsi_login()
615 615 * can process it.
616 616 */
617 617 mutex_enter(&icp->conn_login_mutex);
618 618 /*
619 619 * If conn_login_state != LOGIN_TX then we are not ready to handle
620 620 * this login response and we should just drop it.
621 621 */
622 622 if (icp->conn_login_state == LOGIN_TX) {
623 623 icp->conn_login_datalen = pdu->isp_datalen;
624 624 bcopy(pdu->isp_hdr, &icp->conn_login_resp_hdr,
625 625 sizeof (iscsi_hdr_t));
626 626 /*
627 627 * Login code is sloppy with it's NULL handling so make sure
628 628 * we don't leave any stale data in there.
629 629 */
630 630 bzero(icp->conn_login_data, icp->conn_login_max_data_length);
631 631 bcopy(pdu->isp_data, icp->conn_login_data,
632 632 MIN(pdu->isp_datalen, icp->conn_login_max_data_length));
633 633 iscsi_login_update_state_locked(icp, LOGIN_RX);
634 634 }
635 635 mutex_exit(&icp->conn_login_mutex);
636 636
637 637 return (IDM_STATUS_SUCCESS);
638 638 }
639 639
640 640 /*
641 641 * iscsi_rx_process_cmd_rsp - Process received scsi command response. This
642 642 * will contain sense data if the command was not successful. This data needs
643 643 * to be copied into the scsi_pkt. Otherwise we just complete the IO.
644 644 */
645 645 static idm_status_t
646 646 iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
647 647 {
648 648 iscsi_conn_t *icp = ic->ic_handle;
649 649 iscsi_sess_t *isp = icp->conn_sess;
650 650 iscsi_scsi_rsp_hdr_t *issrhp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
651 651 uint8_t *data = pdu->isp_data;
652 652 iscsi_cmd_t *icmdp = NULL;
653 653 struct scsi_pkt *pkt = NULL;
654 654 idm_status_t rval;
655 655 struct buf *bp;
656 656 boolean_t flush = B_FALSE;
657 657 uint32_t cmd_sn = 0;
658 658 uint16_t lun_num = 0;
659 659
660 660 /* make sure we get status in order */
661 661 mutex_enter(&icp->conn_queue_active.mutex);
662 662
663 663 if ((rval = iscsi_rx_chk(icp, isp, issrhp,
664 664 &icmdp)) != IDM_STATUS_SUCCESS) {
665 665 if (icmdp != NULL) {
666 666 iscsi_task_cleanup(issrhp->opcode, icmdp);
667 667 }
668 668 mutex_exit(&icp->conn_queue_active.mutex);
669 669 return (rval);
670 670 }
671 671
672 672 /*
673 673 * If we are in "idm aborting" state then we shouldn't continue
674 674 * to process this command. By definition this command is no longer
675 675 * on the active queue so we shouldn't try to remove it either.
676 676 */
677 677 mutex_enter(&icmdp->cmd_mutex);
678 678 if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
679 679 mutex_exit(&icmdp->cmd_mutex);
680 680 mutex_exit(&icp->conn_queue_active.mutex);
681 681 return (IDM_STATUS_SUCCESS);
682 682 }
683 683 mutex_exit(&icmdp->cmd_mutex);
684 684
685 685 /* Get the IDM buffer and bytes transferred */
686 686 bp = icmdp->cmd_un.scsi.bp;
687 687 if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
688 688 /* Transport tracks bytes transferred so use those counts */
689 689 if (bp && (bp->b_flags & B_READ)) {
690 690 icmdp->cmd_un.scsi.data_transferred +=
691 691 icmdp->cmd_itp->idt_rx_bytes;
692 692 } else {
693 693 icmdp->cmd_un.scsi.data_transferred +=
694 694 icmdp->cmd_itp->idt_tx_bytes;
695 695 }
696 696 } else {
697 697 /*
698 698 * Some transports cannot track the bytes transferred on
699 699 * the initiator side (like iSER) so we have to use the
700 700 * status info. If the response field indicates that
701 701 * the command actually completed then we will assume
702 702 * the data_transferred value represents the entire buffer
703 703 * unless the resid field says otherwise. This is a bit
704 704 * unintuitive but it's really impossible to know what
705 705 * has been transferred without detailed consideration
706 706 * of the SCSI status and sense key and that is outside
707 707 * the scope of the transport. Instead the target/class driver
708 708 * can consider these values along with the resid and figure
709 709 * it out. The data_transferred concept is just belt and
710 710 * suspenders anyway -- RFC 3720 actually explicitly rejects
711 711 * scoreboarding ("Initiators SHOULD NOT keep track of the
712 712 * data transferred to or from the target (scoreboarding)")
713 713 * perhaps for this very reason.
714 714 */
715 715 if (issrhp->response != 0) {
716 716 icmdp->cmd_un.scsi.data_transferred = 0;
717 717 } else {
718 718 icmdp->cmd_un.scsi.data_transferred =
719 719 (bp == NULL) ? 0 : bp->b_bcount;
720 720 if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
721 721 icmdp->cmd_un.scsi.data_transferred -=
722 722 ntohl(issrhp->residual_count);
723 723 }
724 724 }
725 725 }
726 726
727 727 ISCSI_CHECK_SCSI_READ(icmdp, issrhp,
728 728 icmdp->cmd_un.scsi.data_transferred,
729 729 BP_CHECK_THOROUGH);
730 730
731 731 ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu: %p itt:"
732 732 " %x expcmdsn: %x sess_cmd: %x sess_expcmdsn: %x data_transfered:"
733 733 " %lu ibp: %p obp: %p", (void *)ic, (void *)pdu, issrhp->itt,
734 734 issrhp->expcmdsn, isp->sess_cmdsn, isp->sess_expcmdsn,
735 735 icmdp->cmd_un.scsi.data_transferred,
736 736 (void *)icmdp->cmd_un.scsi.ibp_ibuf,
737 737 (void *)icmdp->cmd_un.scsi.ibp_obuf);
738 738
739 739 iscsi_task_cleanup(issrhp->opcode, icmdp);
740 740
741 741 if (issrhp->response) {
742 742 /* The target failed the command. */
743 743 ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu:"
744 744 " %p response: %d bcount: %lu", (void *)ic, (void *)pdu,
745 745 issrhp->response, icmdp->cmd_un.scsi.bp->b_bcount);
746 746 pkt = icmdp->cmd_un.scsi.pkt;
747 747 pkt->pkt_reason = CMD_TRAN_ERR;
748 748 if (icmdp->cmd_un.scsi.bp) {
749 749 pkt->pkt_resid = icmdp->cmd_un.scsi.bp->b_bcount;
750 750 } else {
751 751 pkt->pkt_resid = 0;
752 752 }
753 753 } else {
754 754 /* success */
755 755 iscsi_cmd_rsp_chk(icmdp, issrhp);
756 756 flush = iscsi_cmd_rsp_cmd_status(icmdp, issrhp, data);
757 757
758 758 ASSERT(icmdp->cmd_lun == NULL || icmdp->cmd_lun->lun_num ==
759 759 (icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK));
760 760
761 761 if (flush == B_TRUE) {
762 762 cmd_sn = icmdp->cmd_sn;
763 763 lun_num = icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK;
764 764 }
765 765 }
766 766
767 767 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
768 768 if (flush == B_TRUE) {
769 769 iscsi_flush_cmd_after_reset(cmd_sn, lun_num, icp);
770 770 }
771 771 mutex_exit(&icp->conn_queue_active.mutex);
772 772 return (IDM_STATUS_SUCCESS);
773 773 }
774 774
775 775 static void
776 776 iscsi_data_rsp_pkt(iscsi_cmd_t *icmdp, iscsi_data_rsp_hdr_t *idrhp)
777 777 {
778 778 struct buf *bp = NULL;
779 779 size_t data_transferred;
780 780 struct scsi_pkt *pkt;
781 781
782 782 bp = icmdp->cmd_un.scsi.bp;
783 783 pkt = icmdp->cmd_un.scsi.pkt;
784 784 data_transferred = icmdp->cmd_un.scsi.data_transferred;
785 785 /*
786 786 * The command* must be completed now, since we won't get a command
787 787 * response PDU. The cmd_status and residual_count are
788 788 * not meaningful unless status_present is set.
789 789 */
790 790 pkt->pkt_resid = 0;
791 791 /* Check the residual count */
792 792 if (bp && (data_transferred != bp->b_bcount)) {
793 793 /*
794 794 * We didn't xfer the expected amount of data -
795 795 * the residual_count in the header is only valid
796 796 * if the underflow flag is set.
797 797 */
798 798 if (idrhp->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
799 799 pkt->pkt_resid = ntohl(idrhp->residual_count);
800 800 ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
801 801 "underflow: itt: %d "
802 802 "transferred: %lu count: %lu", idrhp->itt,
803 803 data_transferred, bp->b_bcount);
804 804 } else {
805 805 if (bp->b_bcount > data_transferred) {
806 806 /* Some data fell on the floor somehw */
807 807 ISCSI_IO_LOG(CE_NOTE, "DEBUG: "
808 808 "iscsi_data_rsp_pkt: data fell: itt: %d "
809 809 "transferred: %lu count: %lu", idrhp->itt,
810 810 data_transferred, bp->b_bcount);
811 811 pkt->pkt_resid =
812 812 bp->b_bcount - data_transferred;
813 813 }
814 814 }
815 815 }
816 816
817 817 pkt->pkt_reason = CMD_CMPLT;
818 818 pkt->pkt_state |= (STATE_XFERRED_DATA | STATE_GOT_STATUS);
819 819
820 820 if (((idrhp->cmd_status & STATUS_MASK) != STATUS_GOOD) &&
821 821 (icmdp->cmd_un.scsi.statuslen >=
822 822 sizeof (struct scsi_arq_status)) && pkt->pkt_scbp) {
823 823
824 824 /*
825 825 * Not supposed to get exception status here!
826 826 * We have no request sense data so just do the
827 827 * best we can
828 828 */
829 829 struct scsi_arq_status *arqstat =
830 830 (struct scsi_arq_status *)pkt->pkt_scbp;
831 831
832 832
833 833 bzero(arqstat, sizeof (struct scsi_arq_status));
834 834
835 835 *((uchar_t *)&arqstat->sts_status) =
836 836 idrhp->cmd_status;
837 837
838 838 /* sense residual is set to whole size of sense buffer */
839 839 arqstat->sts_rqpkt_resid = icmdp->cmd_un.scsi.statuslen -
840 840 ISCSI_ARQ_STATUS_NOSENSE_LEN;
841 841 ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
842 842 "exception status: itt: %d resid: %d",
843 843 idrhp->itt, arqstat->sts_rqpkt_resid);
844 844
845 845 } else if (pkt->pkt_scbp) {
846 846 /* just pass along the status we got */
847 847 pkt->pkt_scbp[0] = idrhp->cmd_status;
848 848 }
849 849 }
850 850
851 851 /*
852 852 * iscsi_rx_process_data_rsp -
853 853 * This currently processes the final data sequence denoted by the data response
854 854 * PDU Status bit being set. We will not receive the SCSI response.
855 855 * This bit denotes that the PDU is the successful completion of the
856 856 * command.
857 857 */
858 858 static idm_status_t
859 859 iscsi_rx_process_data_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
860 860 {
861 861 iscsi_sess_t *isp = NULL;
862 862 iscsi_data_rsp_hdr_t *idrhp = (iscsi_data_rsp_hdr_t *)pdu->isp_hdr;
863 863 iscsi_cmd_t *icmdp = NULL;
864 864 struct buf *bp = NULL;
865 865 iscsi_conn_t *icp = ic->ic_handle;
866 866 idm_buf_t *ibp;
867 867 idm_status_t rval;
868 868
869 869
870 870 /* should only call this when the data rsp contains final rsp */
871 871 ASSERT(idrhp->flags & ISCSI_FLAG_DATA_STATUS);
872 872 isp = icp->conn_sess;
873 873
874 874 mutex_enter(&icp->conn_queue_active.mutex);
875 875 if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)idrhp,
876 876 &icmdp)) != IDM_STATUS_SUCCESS) {
877 877 if (icmdp != NULL) {
878 878 iscsi_task_cleanup(idrhp->opcode, icmdp);
879 879 }
880 880 mutex_exit(&icp->conn_queue_active.mutex);
881 881 return (rval);
882 882 }
883 883
884 884 /*
885 885 * If we are in "idm aborting" state then we shouldn't continue
886 886 * to process this command. By definition this command is no longer
887 887 * on the active queue so we shouldn't try to remove it either.
888 888 */
889 889 mutex_enter(&icmdp->cmd_mutex);
890 890 if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
891 891 mutex_exit(&icmdp->cmd_mutex);
892 892 mutex_exit(&icp->conn_queue_active.mutex);
893 893 return (IDM_STATUS_SUCCESS);
894 894 }
895 895 mutex_exit(&icmdp->cmd_mutex);
896 896
897 897 /*
898 898 * Holding the pending/active queue locks across the
899 899 * iscsi_rx_data call later in this function may cause
900 900 * deadlock during fault injections. Instead remove
901 901 * the cmd from the active queue and release the locks.
902 902 * Then before returning or completing the command
903 903 * return the cmd to the active queue and reacquire
904 904 * the locks.
905 905 */
906 906 iscsi_dequeue_active_cmd(icp, icmdp);
907 907
908 908 mutex_exit(&icp->conn_queue_active.mutex);
909 909
910 910 /* shorthand some values */
911 911 bp = icmdp->cmd_un.scsi.bp;
912 912
913 913 /*
914 914 * some poorly behaved targets have been observed
915 915 * sending data-in pdu's during a write operation
916 916 */
917 917 if (bp != NULL) {
918 918 if (!(bp->b_flags & B_READ)) {
919 919 cmn_err(CE_WARN,
920 920 "iscsi connection(%u) protocol error - "
921 921 "received data response during write operation "
922 922 "itt:0x%x",
923 923 icp->conn_oid, idrhp->itt);
924 924 mutex_enter(&icp->conn_queue_active.mutex);
925 925 iscsi_enqueue_active_cmd(icp, icmdp);
926 926 mutex_exit(&icp->conn_queue_active.mutex);
927 927 return (IDM_STATUS_PROTOCOL_ERROR);
928 928 }
929 929 }
930 930
931 931 ibp = icmdp->cmd_un.scsi.ibp_ibuf;
932 932 if (ibp == NULL) {
933 933 /*
934 934 * After the check of bp above we *should* have a corresponding
935 935 * idm_buf_t (ibp). It's possible that the original call
936 936 * to idm_buf_alloc failed due to a pending connection state
937 937 * transition in which case this value can be NULL. It's
938 938 * highly unlikely that the connection would be shutting down
939 939 * *and* we manage to process a data response and get to this
940 940 * point in the code but just in case we should check for it.
941 941 * This isn't really a protocol error -- we are almost certainly
942 942 * closing the connection anyway so just return a generic error.
943 943 */
944 944 mutex_enter(&icp->conn_queue_active.mutex);
945 945 iscsi_enqueue_active_cmd(icp, icmdp);
946 946 mutex_exit(&icp->conn_queue_active.mutex);
947 947 return (IDM_STATUS_FAIL);
948 948 }
949 949
950 950 if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
951 951 icmdp->cmd_un.scsi.data_transferred =
952 952 icmdp->cmd_itp->idt_rx_bytes;
953 953 } else {
954 954 icmdp->cmd_un.scsi.data_transferred = bp->b_bcount;
955 955 if (idrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
956 956 icmdp->cmd_un.scsi.data_transferred -=
957 957 ntohl(idrhp->residual_count);
958 958 }
959 959 }
960 960
961 961 ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_data_rsp: icp: %p pdu: %p "
962 962 "itt: %d ibp: %p icmdp: %p xfer_len: %lu transferred: %lu dlen: %u",
963 963 (void *)icp, (void *)pdu, idrhp->itt, (void *)bp, (void *)icmdp,
964 964 (ibp == NULL) ? 0 : ibp->idb_xfer_len,
965 965 icmdp->cmd_un.scsi.data_transferred,
966 966 n2h24(idrhp->dlength));
967 967
968 968 iscsi_task_cleanup(idrhp->opcode, icmdp);
969 969
970 970 iscsi_data_rsp_pkt(icmdp, idrhp);
971 971
972 972 mutex_enter(&icp->conn_queue_active.mutex);
973 973 iscsi_enqueue_active_cmd(icp, icmdp);
974 974 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
975 975 mutex_exit(&icp->conn_queue_active.mutex);
976 976
977 977 return (IDM_STATUS_SUCCESS);
978 978 }
979 979
980 980 /*
981 981 * iscsi_rx_process_nop - Process a received nop. If nop is in response
982 982 * to a ping we sent update stats. If initiated by the target we need
983 983 * to response back to the target with a nop. Schedule the response.
984 984 */
985 985 /* ARGSUSED */
986 986 static idm_status_t
987 987 iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu)
988 988 {
989 989 iscsi_sess_t *isp = NULL;
990 990 iscsi_nop_in_hdr_t *inihp = (iscsi_nop_in_hdr_t *)pdu->isp_hdr;
991 991 iscsi_cmd_t *icmdp = NULL;
992 992 iscsi_conn_t *icp = ic->ic_handle;
993 993
994 994 if (icp->conn_expstatsn != ntohl(inihp->statsn)) {
995 995 cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
996 996 "received status out of order itt:0x%x statsn:0x%x "
997 997 "expstatsn:0x%x", icp->conn_oid, inihp->opcode, inihp->itt,
998 998 ntohl(inihp->statsn), icp->conn_expstatsn);
999 999 return (IDM_STATUS_PROTOCOL_ERROR);
1000 1000 }
1001 1001 isp = icp->conn_sess;
1002 1002 ASSERT(isp != NULL);
1003 1003 mutex_enter(&isp->sess_queue_pending.mutex);
1004 1004 mutex_enter(&icp->conn_queue_active.mutex);
1005 1005 mutex_enter(&isp->sess_cmdsn_mutex);
1006 1006 if (inihp->itt != ISCSI_RSVD_TASK_TAG) {
1007 1007 if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1008 1008 isp, (iscsi_hdr_t *)inihp, &icmdp))) {
1009 1009 cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
1010 1010 "- can not find cmd for itt:0x%x",
1011 1011 icp->conn_oid, inihp->itt);
1012 1012 mutex_exit(&isp->sess_cmdsn_mutex);
1013 1013 mutex_exit(&icp->conn_queue_active.mutex);
1014 1014 mutex_exit(&isp->sess_queue_pending.mutex);
1015 1015 return (IDM_STATUS_PROTOCOL_ERROR);
1016 1016 }
1017 1017 }
1018 1018
1019 1019 /* update expcmdsn and maxcmdsn */
1020 1020 iscsi_update_flow_control(isp, ntohl(inihp->maxcmdsn),
1021 1021 ntohl(inihp->expcmdsn));
1022 1022 mutex_exit(&isp->sess_cmdsn_mutex);
1023 1023
1024 1024 if ((inihp->itt != ISCSI_RSVD_TASK_TAG) &&
1025 1025 (inihp->ttt == ISCSI_RSVD_TASK_TAG)) {
1026 1026 /* This is the only type of nop that incs. the expstatsn */
1027 1027 icp->conn_expstatsn++;
1028 1028
1029 1029 /*
1030 1030 * This is a targets response to our nop
1031 1031 */
1032 1032 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1033 1033 } else if (inihp->ttt != ISCSI_RSVD_TASK_TAG) {
1034 1034 /*
1035 1035 * Target requested a nop. Send one.
1036 1036 */
1037 1037 iscsi_handle_nop(icp, ISCSI_RSVD_TASK_TAG, inihp->ttt);
1038 1038 } else {
1039 1039 /*
1040 1040 * This is a target-initiated ping that doesn't expect
1041 1041 * a response; nothing to do except update our flow control
1042 1042 * (which we do in all cases above).
1043 1043 */
1044 1044 /* EMPTY */
1045 1045 }
1046 1046 mutex_exit(&icp->conn_queue_active.mutex);
1047 1047 mutex_exit(&isp->sess_queue_pending.mutex);
1048 1048
1049 1049 return (IDM_STATUS_SUCCESS);
1050 1050 }
1051 1051
1052 1052
1053 1053 /*
1054 1054 * iscsi_rx_process_reject_rsp - The server rejected a PDU
1055 1055 */
1056 1056 static idm_status_t
1057 1057 iscsi_rx_process_reject_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1058 1058 {
1059 1059 iscsi_reject_rsp_hdr_t *irrhp = (iscsi_reject_rsp_hdr_t *)pdu->isp_hdr;
1060 1060 iscsi_sess_t *isp = NULL;
1061 1061 uint32_t dlength = 0;
1062 1062 iscsi_hdr_t *old_ihp = NULL;
1063 1063 iscsi_conn_t *icp = ic->ic_handle;
1064 1064 uint8_t *data = pdu->isp_data;
1065 1065 idm_status_t status = IDM_STATUS_SUCCESS;
1066 1066 int i = 0;
1067 1067
1068 1068 ASSERT(data != NULL);
1069 1069 isp = icp->conn_sess;
1070 1070 ASSERT(isp != NULL);
1071 1071
1072 1072 /*
1073 1073 * In RFC3720 section 10.17, this 4 bytes should be all 0xff.
1074 1074 */
1075 1075 for (i = 0; i < 4; i++) {
1076 1076 if (irrhp->must_be_ff[i] != 0xff) {
1077 1077 return (IDM_STATUS_PROTOCOL_ERROR);
1078 1078 }
1079 1079 }
1080 1080 mutex_enter(&isp->sess_cmdsn_mutex);
1081 1081
1082 1082 if (icp->conn_expstatsn == ntohl(irrhp->statsn)) {
1083 1083 icp->conn_expstatsn++;
1084 1084 } else {
1085 1085 cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
1086 1086 "received status out of order statsn:0x%x "
1087 1087 "expstatsn:0x%x", icp->conn_oid, irrhp->opcode,
1088 1088 ntohl(irrhp->statsn), icp->conn_expstatsn);
1089 1089 mutex_exit(&isp->sess_cmdsn_mutex);
1090 1090 return (IDM_STATUS_PROTOCOL_ERROR);
1091 1091 }
1092 1092 /* update expcmdsn and maxcmdsn */
1093 1093 iscsi_update_flow_control(isp, ntohl(irrhp->maxcmdsn),
1094 1094 ntohl(irrhp->expcmdsn));
1095 1095
1096 1096 mutex_exit(&isp->sess_cmdsn_mutex);
1097 1097
1098 1098 /* If we don't have the rejected header we can't do anything */
1099 1099 dlength = n2h24(irrhp->dlength);
1100 1100 if (dlength < sizeof (iscsi_hdr_t)) {
1101 1101 return (IDM_STATUS_PROTOCOL_ERROR);
1102 1102 }
1103 1103
1104 1104 /* map old ihp */
1105 1105 old_ihp = (iscsi_hdr_t *)data;
1106 1106
1107 1107 switch (irrhp->reason) {
1108 1108 /*
1109 1109 * ISCSI_REJECT_IMM_CMD_REJECT - Immediate Command Reject
1110 1110 * too many immediate commands (original cmd can be resent)
1111 1111 */
1112 1112 case ISCSI_REJECT_IMM_CMD_REJECT:
1113 1113 /*
1114 1114 * We have exceeded the server's capacity for outstanding
1115 1115 * immediate commands. This must be a task management
1116 1116 * command so try to find it in the abortingqueue and
1117 1117 * complete it.
1118 1118 */
1119 1119 if (!(old_ihp->opcode & ISCSI_OP_IMMEDIATE)) {
1120 1120 /* Rejecting IMM but old old_hdr wasn't IMM */
1121 1121 return (IDM_STATUS_PROTOCOL_ERROR);
1122 1122 }
1123 1123
1124 1124 /*
1125 1125 * We only send NOP and TASK_MGT as IMM. All other
1126 1126 * cases should be considered as a protocol error.
1127 1127 */
1128 1128 switch (old_ihp->opcode & ISCSI_OPCODE_MASK) {
1129 1129 case ISCSI_OP_NOOP_OUT:
1130 1130 /*
1131 1131 * A ping was rejected - treat this like
1132 1132 * ping response. The down side is we
1133 1133 * didn't get an updated MaxCmdSn.
1134 1134 */
1135 1135 break;
1136 1136 case ISCSI_OP_SCSI_TASK_MGT_MSG:
1137 1137 status =
1138 1138 iscsi_rx_process_rejected_tsk_mgt(ic, old_ihp);
1139 1139 break;
1140 1140 default:
1141 1141 cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
1142 1142 "- received a reject for a command(0x%02x) not "
1143 1143 "sent as an immediate", icp->conn_oid,
1144 1144 old_ihp->opcode);
1145 1145 status = IDM_STATUS_PROTOCOL_ERROR;
1146 1146 break;
1147 1147 }
1148 1148 break;
1149 1149
1150 1150 /*
1151 1151 * For the rest of the reject cases just use the general
1152 1152 * hammer of dis/reconnecting. This will resolve all
1153 1153 * noted issues although could be more graceful.
1154 1154 */
1155 1155 case ISCSI_REJECT_DATA_DIGEST_ERROR:
1156 1156 case ISCSI_REJECT_CMD_BEFORE_LOGIN:
1157 1157 case ISCSI_REJECT_SNACK_REJECT:
1158 1158 case ISCSI_REJECT_PROTOCOL_ERROR:
1159 1159 case ISCSI_REJECT_CMD_NOT_SUPPORTED:
1160 1160 case ISCSI_REJECT_TASK_IN_PROGRESS:
1161 1161 case ISCSI_REJECT_INVALID_DATA_ACK:
1162 1162 case ISCSI_REJECT_INVALID_PDU_FIELD:
1163 1163 case ISCSI_REJECT_LONG_OPERATION_REJECT:
1164 1164 case ISCSI_REJECT_NEGOTIATION_RESET:
1165 1165 default:
1166 1166 cmn_err(CE_WARN, "iscsi connection(%u/%x) closing connection - "
1167 1167 "target requested reason:0x%x",
1168 1168 icp->conn_oid, irrhp->opcode, irrhp->reason);
1169 1169 status = IDM_STATUS_PROTOCOL_ERROR;
1170 1170 break;
1171 1171 }
1172 1172
1173 1173 return (status);
1174 1174 }
1175 1175
1176 1176
1177 1177 /*
1178 1178 * iscsi_rx_process_rejected_tsk_mgt -
1179 1179 */
1180 1180 /* ARGSUSED */
1181 1181 static idm_status_t
1182 1182 iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic, iscsi_hdr_t *old_ihp)
1183 1183 {
1184 1184 iscsi_sess_t *isp = NULL;
1185 1185 iscsi_cmd_t *icmdp = NULL;
1186 1186 iscsi_conn_t *icp = ic->ic_handle;
1187 1187
1188 1188 isp = icp->conn_sess;
1189 1189 ASSERT(old_ihp != NULL);
1190 1190 ASSERT(isp != NULL);
1191 1191
1192 1192 mutex_enter(&icp->conn_queue_active.mutex);
1193 1193 mutex_enter(&isp->sess_cmdsn_mutex);
1194 1194 if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1195 1195 isp, old_ihp, &icmdp))) {
1196 1196 mutex_exit(&isp->sess_cmdsn_mutex);
1197 1197 mutex_exit(&icp->conn_queue_active.mutex);
1198 1198 return (IDM_STATUS_PROTOCOL_ERROR);
1199 1199 }
1200 1200 mutex_exit(&isp->sess_cmdsn_mutex);
1201 1201
1202 1202 switch (icmdp->cmd_type) {
1203 1203 case ISCSI_CMD_TYPE_ABORT:
1204 1204 case ISCSI_CMD_TYPE_RESET:
1205 1205 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E4,
1206 1206 icp->conn_sess);
1207 1207 break;
1208 1208 /* We don't send any other task mgr types */
1209 1209 default:
1210 1210 ASSERT(B_FALSE);
1211 1211 break;
1212 1212 }
1213 1213 mutex_exit(&icp->conn_queue_active.mutex);
1214 1214
1215 1215 return (IDM_STATUS_SUCCESS);
1216 1216 }
1217 1217
1218 1218
1219 1219 /*
1220 1220 * iscsi_rx_process_task_mgt_rsp -
1221 1221 */
1222 1222 /* ARGSUSED */
1223 1223 static idm_status_t
1224 1224 iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1225 1225 {
1226 1226 iscsi_sess_t *isp = NULL;
1227 1227 iscsi_scsi_task_mgt_rsp_hdr_t *istmrhp = NULL;
1228 1228 iscsi_cmd_t *icmdp = NULL;
1229 1229 iscsi_conn_t *icp = ic->ic_handle;
1230 1230 idm_status_t status = IDM_STATUS_SUCCESS;
1231 1231
1232 1232 isp = icp->conn_sess;
1233 1233 istmrhp = (iscsi_scsi_task_mgt_rsp_hdr_t *)pdu->isp_hdr;
1234 1234
1235 1235 mutex_enter(&icp->conn_queue_active.mutex);
1236 1236 if ((status = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)istmrhp,
1237 1237 &icmdp)) != IDM_STATUS_SUCCESS) {
1238 1238 mutex_exit(&icp->conn_queue_active.mutex);
1239 1239 return (status);
1240 1240 }
1241 1241
1242 1242 switch (icmdp->cmd_type) {
1243 1243 case ISCSI_CMD_TYPE_ABORT:
1244 1244 case ISCSI_CMD_TYPE_RESET:
1245 1245 switch (istmrhp->response) {
1246 1246 case SCSI_TCP_TM_RESP_COMPLETE:
1247 1247 /* success */
1248 1248 iscsi_cmd_state_machine(icmdp,
1249 1249 ISCSI_CMD_EVENT_E3, isp);
1250 1250 break;
1251 1251 case SCSI_TCP_TM_RESP_NO_TASK:
1252 1252 /*
1253 1253 * If the array no longer knows about
1254 1254 * an ABORT RTT and we no longer have
1255 1255 * a parent SCSI command it was just
1256 1256 * completed, free this ABORT resource.
1257 1257 * Otherwise FALLTHRU this will flag a
1258 1258 * protocol problem.
1259 1259 */
1260 1260 if ((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) &&
1261 1261 (icmdp->cmd_un.abort.icmdp == NULL)) {
1262 1262 iscsi_cmd_state_machine(icmdp,
1263 1263 ISCSI_CMD_EVENT_E4, isp);
1264 1264 break;
1265 1265 }
1266 1266 /* FALLTHRU */
1267 1267 case SCSI_TCP_TM_RESP_REJECTED:
1268 1268 /*
1269 1269 * If the target rejects our reset task,
1270 1270 * we should record the response and complete
1271 1271 * this command with the result.
1272 1272 */
1273 1273 if (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET) {
1274 1274 icmdp->cmd_un.reset.response =
1275 1275 istmrhp->response;
1276 1276 iscsi_cmd_state_machine(icmdp,
1277 1277 ISCSI_CMD_EVENT_E3, isp);
1278 1278 break;
1279 1279 }
1280 1280 /* FALLTHRU */
1281 1281 case SCSI_TCP_TM_RESP_NO_LUN:
1282 1282 case SCSI_TCP_TM_RESP_TASK_ALLEGIANT:
1283 1283 case SCSI_TCP_TM_RESP_NO_FAILOVER:
1284 1284 case SCSI_TCP_TM_RESP_IN_PRGRESS:
1285 1285 default:
1286 1286 /*
1287 1287 * Something is out of sync. Flush
1288 1288 * active queues and resync the
1289 1289 * the connection to try and recover
1290 1290 * to a known state.
1291 1291 */
1292 1292 status = IDM_STATUS_PROTOCOL_ERROR;
1293 1293 }
1294 1294 break;
1295 1295
1296 1296 default:
1297 1297 cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1298 1298 "received a task mgt response for a non-task mgt "
1299 1299 "cmd itt:0x%x type:%d", icp->conn_oid, istmrhp->itt,
1300 1300 icmdp->cmd_type);
1301 1301 status = IDM_STATUS_PROTOCOL_ERROR;
1302 1302 break;
1303 1303 }
1304 1304
1305 1305 mutex_exit(&icp->conn_queue_active.mutex);
1306 1306 return (status);
1307 1307 }
1308 1308
1309 1309
1310 1310 /*
1311 1311 * iscsi_rx_process_logout_rsp -
1312 1312 *
1313 1313 */
1314 1314 /* ARGSUSED */
1315 1315 idm_status_t
1316 1316 iscsi_rx_process_logout_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1317 1317 {
1318 1318 iscsi_conn_t *icp = ic->ic_handle;
1319 1319 iscsi_logout_rsp_hdr_t *ilrhp =
1320 1320 (iscsi_logout_rsp_hdr_t *)pdu->isp_hdr;
1321 1321 iscsi_cmd_t *icmdp = NULL;
1322 1322 iscsi_sess_t *isp;
1323 1323 idm_status_t status = IDM_STATUS_SUCCESS;
1324 1324
1325 1325 isp = icp->conn_sess;
1326 1326
1327 1327 if (icp->conn_expstatsn != ntohl(ilrhp->statsn)) {
1328 1328 cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
1329 1329 "received status out of order itt:0x%x statsn:0x%x "
1330 1330 "expstatsn:0x%x", icp->conn_oid, ilrhp->opcode, ilrhp->itt,
1331 1331 ntohl(ilrhp->statsn), icp->conn_expstatsn);
1332 1332 return (IDM_STATUS_PROTOCOL_ERROR);
1333 1333 }
1334 1334
1335 1335 mutex_enter(&icp->conn_queue_active.mutex);
1336 1336 mutex_enter(&isp->sess_cmdsn_mutex);
1337 1337 if (ilrhp->itt != ISCSI_RSVD_TASK_TAG) {
1338 1338 if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1339 1339 isp, (iscsi_hdr_t *)ilrhp, &icmdp))) {
1340 1340 mutex_exit(&isp->sess_cmdsn_mutex);
1341 1341 mutex_exit(&icp->conn_queue_active.mutex);
1342 1342 return (IDM_STATUS_PROTOCOL_ERROR);
1343 1343 }
1344 1344 }
1345 1345
1346 1346 /* update expcmdsn and maxcmdsn */
1347 1347 iscsi_update_flow_control(isp, ntohl(ilrhp->maxcmdsn),
1348 1348 ntohl(ilrhp->expcmdsn));
1349 1349 mutex_exit(&isp->sess_cmdsn_mutex);
1350 1350
1351 1351 ISCSI_IO_LOG(CE_NOTE,
1352 1352 "DEBUG: iscsi_rx_process_logout_rsp: response: %d",
1353 1353 ilrhp->response);
1354 1354 switch (ilrhp->response) {
1355 1355 case ISCSI_LOGOUT_CID_NOT_FOUND:
1356 1356 /*
1357 1357 * If the target doesn't know about our connection
1358 1358 * then we can consider our self disconnected.
1359 1359 */
1360 1360 /* FALLTHRU */
1361 1361 case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
1362 1362 /*
1363 1363 * We don't support ErrorRecovery levels above 0
1364 1364 * currently so consider this success.
1365 1365 */
1366 1366 /* FALLTHRU */
1367 1367 case ISCSI_LOGOUT_CLEANUP_FAILED:
1368 1368 /*
1369 1369 * per spec. "cleanup failed for various reasons."
1370 1370 * Although those various reasons are undefined.
1371 1371 * Not sure what to do here. So fake success,
1372 1372 * which will disconnect the connection.
1373 1373 */
1374 1374 /* FALLTHRU */
1375 1375 case ISCSI_LOGOUT_SUCCESS:
1376 1376 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1377 1377 mutex_exit(&icp->conn_queue_active.mutex);
1378 1378 iscsi_drop_conn_cleanup(icp);
1379 1379 break;
1380 1380 default:
1381 1381 mutex_exit(&icp->conn_queue_active.mutex);
1382 1382 status = IDM_STATUS_PROTOCOL_ERROR;
1383 1383 break;
1384 1384
1385 1385 }
1386 1386 return (status);
1387 1387 }
1388 1388
1389 1389 /*
1390 1390 * iscsi_rx_process_async_rsp
1391 1391 *
1392 1392 */
1393 1393 /* ARGSUSED */
1394 1394 static idm_status_t
1395 1395 iscsi_rx_process_async_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1396 1396 {
1397 1397 iscsi_conn_t *icp = ic->ic_handle;
1398 1398 iscsi_sess_t *isp = icp->conn_sess;
1399 1399 idm_status_t rval = IDM_STATUS_SUCCESS;
1400 1400 iscsi_task_t *itp;
1401 1401 iscsi_async_evt_hdr_t *iaehp =
1402 1402 (iscsi_async_evt_hdr_t *)pdu->isp_hdr;
1403 1403
1404 1404 ASSERT(icp != NULL);
1405 1405 ASSERT(pdu != NULL);
1406 1406 ASSERT(isp != NULL);
1407 1407
1408 1408 mutex_enter(&isp->sess_cmdsn_mutex);
1409 1409 if (icp->conn_expstatsn == ntohl(iaehp->statsn)) {
1410 1410 icp->conn_expstatsn++;
1411 1411 } else {
1412 1412 cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1413 1413 "received status out of order statsn:0x%x "
1414 1414 "expstatsn:0x%x", icp->conn_oid,
1415 1415 ntohl(iaehp->statsn), icp->conn_expstatsn);
1416 1416 mutex_exit(&isp->sess_cmdsn_mutex);
1417 1417 return (IDM_STATUS_PROTOCOL_ERROR);
1418 1418 }
1419 1419 mutex_exit(&isp->sess_cmdsn_mutex);
1420 1420
1421 1421 switch (iaehp->async_event) {
1422 1422 case ISCSI_ASYNC_EVENT_SCSI_EVENT:
1423 1423 /*
1424 1424 * SCSI asynchronous event is reported in
1425 1425 * the sense data. Sense data that accompanies
1426 1426 * the report in the data segment identifies the
1427 1427 * condition. If the target supports SCSI
1428 1428 * asynchronous events reporting (see [SAM2])
1429 1429 * as indicated in the stardard INQUIRY data
1430 1430 * (see [SPC3]), its use may be enabled by
1431 1431 * parameters in the SCSI control mode page
1432 1432 * (see [SPC3]).
1433 1433 *
1434 1434 * T-10 has removed SCSI asunchronous events
1435 1435 * from the standard. Although we have seen
1436 1436 * a couple targets still spending these requests.
1437 1437 * Those targets were specifically sending them
1438 1438 * for notification of a LUN/Volume change
1439 1439 * (ex. LUN addition/removal). Fire the enumeration
1440 1440 * to handle the change.
1441 1441 */
1442 1442 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1443 1443 rw_enter(&isp->sess_state_rwlock, RW_READER);
1444 1444 if (isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN) {
1445 1445 (void) iscsi_sess_enum_request(isp, B_FALSE,
1446 1446 isp->sess_state_event_count);
1447 1447 }
1448 1448 rw_exit(&isp->sess_state_rwlock);
1449 1449 }
1450 1450 break;
1451 1451
1452 1452 case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT:
1453 1453 /*
1454 1454 * We've been asked to logout by the target --
1455 1455 * we need to treat this differently from a normal logout
1456 1456 * due to a discovery failure. Normal logouts result in
1457 1457 * an N3 event to the session state machine and an offline
1458 1458 * of the lun. In this case we want to put the connection
1459 1459 * into "failed" state and generate N5 to the session state
1460 1460 * machine since the initiator logged out at the target's
1461 1461 * request. To track this we set a flag indicating we
1462 1462 * received this async logout request from the tharget
1463 1463 */
1464 1464 mutex_enter(&icp->conn_state_mutex);
1465 1465 icp->conn_async_logout = B_TRUE;
1466 1466 mutex_exit(&icp->conn_state_mutex);
1467 1467
1468 1468 /* Hold is released in iscsi_handle_logout. */
1469 1469 idm_conn_hold(ic);
1470 1470
1471 1471 /* Target has requested this connection to logout. */
1472 1472 itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1473 1473 itp->t_arg = icp;
1474 1474 itp->t_blocking = B_FALSE;
1475 1475 if (ddi_taskq_dispatch(isp->sess_login_taskq,
1476 1476 (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
1477 1477 DDI_SUCCESS) {
1478 1478 idm_conn_rele(ic);
1479 1479 /* Disconnect if we couldn't dispatch the task */
1480 1480 idm_ini_conn_disconnect(ic);
1481 1481 }
1482 1482 break;
1483 1483
1484 1484 case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION:
1485 1485 /*
1486 1486 * Target is going to drop our connection.
1487 1487 * param1 - CID which will be dropped.
1488 1488 * param2 - Min time to reconnect.
1489 1489 * param3 - Max time to reconnect.
1490 1490 *
1491 1491 * For now just let fail as another disconnect.
1492 1492 *
1493 1493 * MC/S Once we support > 1 connections then
1494 1494 * we need to check the CID and drop that
1495 1495 * specific connection.
1496 1496 */
1497 1497 iscsi_conn_set_login_min_max(icp, iaehp->param2,
1498 1498 iaehp->param3);
1499 1499 idm_ini_conn_disconnect(ic);
1500 1500 break;
1501 1501
1502 1502 case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS:
1503 1503 /*
1504 1504 * Target is going to drop ALL connections.
1505 1505 * param2 - Min time to reconnect.
1506 1506 * param3 - Max time to reconnect.
1507 1507 *
1508 1508 * For now just let fail as anyother disconnect.
1509 1509 *
1510 1510 * MC/S Once we support more than > 1 connections
1511 1511 * then we need to drop all connections on the
1512 1512 * session.
1513 1513 */
1514 1514 iscsi_conn_set_login_min_max(icp, iaehp->param2,
1515 1515 iaehp->param3);
1516 1516 idm_ini_conn_disconnect(ic);
1517 1517 break;
1518 1518
1519 1519 case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION:
1520 1520 /*
1521 1521 * Target requests parameter negotiation
1522 1522 * on this connection.
1523 1523 *
1524 1524 * The initiator must honor this request. For
1525 1525 * now we will request a logout. We can't
1526 1526 * just ignore this or it might force corruption?
1527 1527 */
1528 1528
1529 1529 /* Hold is released in iscsi_handle_logout */
1530 1530 idm_conn_hold(ic);
1531 1531 itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1532 1532 itp->t_arg = icp;
1533 1533 itp->t_blocking = B_FALSE;
1534 1534 if (ddi_taskq_dispatch(isp->sess_login_taskq,
1535 1535 (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
1536 1536 DDI_SUCCESS) {
1537 1537 /* Disconnect if we couldn't dispatch the task */
1538 1538 idm_conn_rele(ic);
1539 1539 idm_ini_conn_disconnect(ic);
1540 1540 }
1541 1541 break;
1542 1542
1543 1543 case ISCSI_ASYNC_EVENT_VENDOR_SPECIFIC:
1544 1544 /*
1545 1545 * We currently don't handle any vendor
1546 1546 * specific async events. So just ignore
1547 1547 * the request.
1548 1548 */
1549 1549 idm_ini_conn_disconnect(ic);
1550 1550 break;
1551 1551 default:
1552 1552 rval = IDM_STATUS_PROTOCOL_ERROR;
1553 1553 }
1554 1554
1555 1555 return (rval);
1556 1556 }
1557 1557
1558 1558 /*
1559 1559 * iscsi_rx_process_text_rsp - processes iSCSI text response. It sets
1560 1560 * the cmd_result field of the command data structure with the actual
1561 1561 * status value instead of returning the status value. The return value
1562 1562 * is SUCCESS in order to let iscsi_handle_text control the operation of
1563 1563 * a text request.
1564 1564 * Text requests are a handled a little different than other types of
1565 1565 * iSCSI commands because the initiator sends additional empty text requests
1566 1566 * in order to obtain the remaining responses required to complete the
1567 1567 * request. iscsi_handle_text controls the operation of text request, while
1568 1568 * iscsi_rx_process_text_rsp just process the current response.
1569 1569 */
1570 1570 static idm_status_t
1571 1571 iscsi_rx_process_text_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1572 1572 {
1573 1573 iscsi_sess_t *isp = NULL;
1574 1574 iscsi_text_rsp_hdr_t *ithp =
1575 1575 (iscsi_text_rsp_hdr_t *)pdu->isp_hdr;
1576 1576 iscsi_conn_t *icp = ic->ic_handle;
1577 1577 iscsi_cmd_t *icmdp = NULL;
1578 1578 boolean_t final = B_FALSE;
1579 1579 uint32_t data_len;
1580 1580 uint8_t *data = pdu->isp_data;
1581 1581 idm_status_t rval;
1582 1582
1583 1583 isp = icp->conn_sess;
1584 1584
1585 1585 mutex_enter(&icp->conn_queue_active.mutex);
1586 1586 if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)ithp,
1587 1587 &icmdp)) != IDM_STATUS_SUCCESS) {
1588 1588 mutex_exit(&icp->conn_queue_active.mutex);
1589 1589 return (rval);
1590 1590 }
1591 1591
1592 1592 /* update local final response flag */
1593 1593 if (ithp->flags & ISCSI_FLAG_FINAL) {
1594 1594 final = B_TRUE;
1595 1595 }
1596 1596
1597 1597 /*
1598 1598 * validate received TTT value. RFC3720 specifies the following:
1599 1599 * - F bit set to 1 MUST have a reserved TTT value 0xffffffff
1600 1600 * - F bit set to 0 MUST have a non-reserved TTT value !0xffffffff
1601 1601 * In addition, the received TTT value must not change between
1602 1602 * responses of a long text response
1603 1603 */
1604 1604 if (((final == B_TRUE) && (ithp->ttt != ISCSI_RSVD_TASK_TAG)) ||
1605 1605 ((final == B_FALSE) && (ithp->ttt == ISCSI_RSVD_TASK_TAG))) {
1606 1606 icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1607 1607 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1608 1608 mutex_exit(&icp->conn_queue_active.mutex);
1609 1609 cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1610 1610 "received text response with invalid flags:0x%x or "
1611 1611 "ttt:0x%x", icp->conn_oid, ithp->flags, ithp->itt);
1612 1612 return (IDM_STATUS_PROTOCOL_ERROR);
1613 1613 }
1614 1614
1615 1615 if ((icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) &&
1616 1616 (ithp->ttt == ISCSI_RSVD_TASK_TAG) &&
1617 1617 (final == B_FALSE)) {
1618 1618 /* TTT should have matched reserved value */
1619 1619 icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1620 1620 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1621 1621 mutex_exit(&icp->conn_queue_active.mutex);
1622 1622 cmn_err(CE_WARN, "iscsi connection(%u) protocol "
1623 1623 "error - received text response with invalid "
1624 1624 "ttt:0x%x", icp->conn_oid, ithp->ttt);
1625 1625 return (IDM_STATUS_PROTOCOL_ERROR);
1626 1626 }
1627 1627
1628 1628 /*
1629 1629 * If this is first response, save away TTT value for later use
1630 1630 * in a long text request/response sequence
1631 1631 */
1632 1632 if (icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) {
1633 1633 icmdp->cmd_un.text.ttt = ithp->ttt;
1634 1634 }
1635 1635
1636 1636 data_len = ntoh24(ithp->dlength);
1637 1637
1638 1638 /* check whether enough buffer available to copy data */
1639 1639 if ((icmdp->cmd_un.text.total_rx_len + data_len) >
1640 1640 icmdp->cmd_un.text.buf_len) {
1641 1641 icmdp->cmd_un.text.total_rx_len += data_len;
1642 1642 icmdp->cmd_result = ISCSI_STATUS_DATA_OVERFLOW;
1643 1643 /*
1644 1644 * DATA_OVERFLOW will result in a SUCCESS return so that
1645 1645 * iscsi_handle_text can continue to obtain the remaining
1646 1646 * text response if needed.
1647 1647 */
1648 1648 } else {
1649 1649 char *buf_data = (icmdp->cmd_un.text.buf +
1650 1650 icmdp->cmd_un.text.offset);
1651 1651
1652 1652 bcopy(data, buf_data, data_len);
1653 1653 icmdp->cmd_un.text.offset += data_len;
1654 1654 icmdp->cmd_un.text.total_rx_len += data_len;
1655 1655 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
1656 1656 bcopy(ithp->rsvd4, icmdp->cmd_un.text.lun,
1657 1657 sizeof (icmdp->cmd_un.text.lun));
1658 1658 }
1659 1659
1660 1660 /* update stage */
1661 1661 if (final == B_TRUE) {
1662 1662 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1663 1663 } else {
1664 1664 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
1665 1665 }
1666 1666
1667 1667 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1668 1668 mutex_exit(&icp->conn_queue_active.mutex);
1669 1669 return (IDM_STATUS_SUCCESS);
1670 1670 }
1671 1671
1672 1672 /*
1673 1673 * iscsi_rx_process_scsi_itt_to_icmdp - Lookup itt using IDM to find matching
1674 1674 * icmdp. Verify itt in hdr and icmdp are the same.
1675 1675 */
1676 1676 static iscsi_status_t
1677 1677 iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp, idm_conn_t *ic,
1678 1678 iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp)
1679 1679 {
1680 1680 idm_task_t *itp;
1681 1681
1682 1682 ASSERT(isp != NULL);
1683 1683 ASSERT(ihp != NULL);
1684 1684 ASSERT(icmdp != NULL);
1685 1685 ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1686 1686 itp = idm_task_find_and_complete(ic, ihp->itt, ISCSI_INI_TASK_TTT);
1687 1687 if (itp == NULL) {
1688 1688 cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1689 1689 "received unknown itt:0x%x - protocol error",
1690 1690 isp->sess_oid, ihp->itt);
1691 1691 return (ISCSI_STATUS_INTERNAL_ERROR);
1692 1692 }
1693 1693 *icmdp = itp->idt_private;
1694 1694
1695 1695 idm_task_rele(itp);
1696 1696
1697 1697 return (ISCSI_STATUS_SUCCESS);
1698 1698
1699 1699 }
1700 1700
1701 1701 /*
1702 1702 * iscsi_rx_process_itt_to_icmdp - Lookup itt in the session's
1703 1703 * cmd table to find matching icmdp. Verify itt in hdr and
1704 1704 * icmdp are the same.
1705 1705 */
1706 1706 static iscsi_status_t
1707 1707 iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp, iscsi_hdr_t *ihp,
1708 1708 iscsi_cmd_t **icmdp)
1709 1709 {
1710 1710 int cmd_table_idx = 0;
1711 1711
1712 1712 ASSERT(isp != NULL);
1713 1713 ASSERT(ihp != NULL);
1714 1714 ASSERT(icmdp != NULL);
1715 1715 ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1716 1716
1717 1717 /* try to find an associated iscsi_pkt */
1718 1718 cmd_table_idx = (ihp->itt - IDM_TASKIDS_MAX) % ISCSI_CMD_TABLE_SIZE;
1719 1719 if (isp->sess_cmd_table[cmd_table_idx] == NULL) {
1720 1720 cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1721 1721 "received unknown itt:0x%x - protocol error",
1722 1722 isp->sess_oid, ihp->itt);
1723 1723 return (ISCSI_STATUS_INTERNAL_ERROR);
1724 1724 }
1725 1725
1726 1726 /* verify itt */
1727 1727 if (isp->sess_cmd_table[cmd_table_idx]->cmd_itt != ihp->itt) {
1728 1728 cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1729 1729 " which is out of sync with itt:0x%x", isp->sess_oid,
1730 1730 ihp->itt, isp->sess_cmd_table[cmd_table_idx]->cmd_itt);
1731 1731 return (ISCSI_STATUS_INTERNAL_ERROR);
1732 1732 }
1733 1733
1734 1734 /* ensure that icmdp is still in Active state */
1735 1735 if (isp->sess_cmd_table[cmd_table_idx]->cmd_state !=
1736 1736 ISCSI_CMD_STATE_ACTIVE) {
1737 1737 cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1738 1738 "but icmdp (%p) is not in active state",
1739 1739 isp->sess_oid, ihp->itt,
1740 1740 (void *)isp->sess_cmd_table[cmd_table_idx]);
1741 1741 return (ISCSI_STATUS_INTERNAL_ERROR);
1742 1742 }
1743 1743
1744 1744 /* make sure this is a SCSI cmd */
1745 1745 *icmdp = isp->sess_cmd_table[cmd_table_idx];
1746 1746
1747 1747 return (ISCSI_STATUS_SUCCESS);
1748 1748 }
1749 1749
1750 1750 /*
1751 1751 * +--------------------------------------------------------------------+
1752 1752 * | End of protocol receive routines |
1753 1753 * +--------------------------------------------------------------------+
1754 1754 */
1755 1755
1756 1756 /*
1757 1757 * +--------------------------------------------------------------------+
1758 1758 * | Beginning of protocol send routines |
1759 1759 * +--------------------------------------------------------------------+
1760 1760 */
1761 1761
1762 1762
1763 1763 /*
1764 1764 * iscsi_tx_thread - This thread is the driving point for all
1765 1765 * iSCSI PDUs after login. No PDUs should call idm_pdu_tx()
1766 1766 * directly they should be funneled through iscsi_tx_thread.
1767 1767 */
1768 1768 void
1769 1769 iscsi_tx_thread(iscsi_thread_t *thread, void *arg)
1770 1770 {
1771 1771 iscsi_conn_t *icp = (iscsi_conn_t *)arg;
1772 1772 iscsi_sess_t *isp = NULL;
1773 1773 iscsi_cmd_t *icmdp = NULL;
1774 1774 clock_t tout;
1775 1775 int ret = 1;
1776 1776
1777 1777 ASSERT(icp != NULL);
1778 1778 isp = icp->conn_sess;
1779 1779 ASSERT(isp != NULL);
1780 1780 ASSERT(thread != NULL);
1781 1781 ASSERT(thread->signature == SIG_ISCSI_THREAD);
1782 1782
1783 1783 tout = SEC_TO_TICK(1);
1784 1784 /*
1785 1785 * Transfer icmdps until shutdown by owning session.
1786 1786 */
1787 1787 while (ret != 0) {
1788 1788
1789 1789 isp->sess_window_open = B_TRUE;
1790 1790 /*
1791 1791 * While the window is open, there are commands available
1792 1792 * to send and the session state allows those commands to
1793 1793 * be sent try to transfer them.
1794 1794 */
1795 1795 mutex_enter(&isp->sess_queue_pending.mutex);
1796 1796 while ((isp->sess_window_open == B_TRUE) &&
1797 1797 ((icmdp = isp->sess_queue_pending.head) != NULL)) {
1798 1798 if (((icmdp->cmd_type != ISCSI_CMD_TYPE_SCSI) &&
1799 1799 (ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state))) ||
1800 1800 (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN)) {
1801 1801
1802 1802 /* update command with this connection info */
1803 1803 icmdp->cmd_conn = icp;
1804 1804 /* attempt to send this command */
1805 1805 iscsi_cmd_state_machine(icmdp,
1806 1806 ISCSI_CMD_EVENT_E2, isp);
1807 1807
1808 1808 ASSERT(!mutex_owned(
1809 1809 &isp->sess_queue_pending.mutex));
1810 1810 mutex_enter(&isp->sess_queue_pending.mutex);
1811 1811 } else {
1812 1812 while (icmdp != NULL) {
1813 1813 if ((icmdp->cmd_type !=
1814 1814 ISCSI_CMD_TYPE_SCSI) &&
1815 1815 (ISCSI_CONN_STATE_FULL_FEATURE
1816 1816 (icp->conn_state) != B_TRUE)) {
1817 1817 icmdp->cmd_misc_flags |=
1818 1818 ISCSI_CMD_MISCFLAG_STUCK;
1819 1819 } else if (icp->conn_state !=
1820 1820 ISCSI_CONN_STATE_LOGGED_IN) {
1821 1821 icmdp->cmd_misc_flags |=
1822 1822 ISCSI_CMD_MISCFLAG_STUCK;
1823 1823 }
1824 1824 icmdp = icmdp->cmd_next;
1825 1825 }
1826 1826 break;
1827 1827 }
1828 1828 }
1829 1829 mutex_exit(&isp->sess_queue_pending.mutex);
1830 1830
1831 1831 /*
1832 1832 * Go to sleep until there is something new
1833 1833 * to process (awoken via cv_boardcast).
1834 1834 * Or the timer goes off.
1835 1835 */
1836 1836 ret = iscsi_thread_wait(thread, tout);
1837 1837 }
1838 1838
1839 1839 }
1840 1840
1841 1841
1842 1842 /*
1843 1843 * iscsi_tx_cmd - transfers icmdp across wire as iscsi pdu
1844 1844 *
1845 1845 * Just prior to sending the command to the networking layer the
1846 1846 * pending queue lock will be dropped. At this point only local
1847 1847 * resources will be used, not the icmdp. Holding the queue lock
1848 1848 * across the networking call can lead to a hang. (This is due
1849 1849 * to the the target driver and networking layers competing use
1850 1850 * of the timeout() resources and the queue lock being held for
1851 1851 * both sides.) Upon the completion of this command the lock
1852 1852 * will have been re-acquired.
1853 1853 */
1854 1854 iscsi_status_t
1855 1855 iscsi_tx_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
1856 1856 {
1857 1857 iscsi_status_t rval = ISCSI_STATUS_INTERNAL_ERROR;
1858 1858
1859 1859 ASSERT(isp != NULL);
1860 1860 ASSERT(icmdp != NULL);
1861 1861
1862 1862 /* transfer specific command type */
1863 1863 switch (icmdp->cmd_type) {
1864 1864 case ISCSI_CMD_TYPE_SCSI:
1865 1865 rval = iscsi_tx_scsi(isp, icmdp);
1866 1866 break;
1867 1867 case ISCSI_CMD_TYPE_NOP:
1868 1868 rval = iscsi_tx_nop(isp, icmdp);
1869 1869 break;
1870 1870 case ISCSI_CMD_TYPE_ABORT:
1871 1871 rval = iscsi_tx_abort(isp, icmdp);
1872 1872 break;
1873 1873 case ISCSI_CMD_TYPE_RESET:
1874 1874 rval = iscsi_tx_reset(isp, icmdp);
1875 1875 break;
1876 1876 case ISCSI_CMD_TYPE_LOGOUT:
1877 1877 rval = iscsi_tx_logout(isp, icmdp);
1878 1878 break;
1879 1879 case ISCSI_CMD_TYPE_TEXT:
1880 1880 rval = iscsi_tx_text(isp, icmdp);
1881 1881 break;
1882 1882 default:
1883 1883 cmn_err(CE_WARN, "iscsi_tx_cmd: invalid cmdtype: %d",
1884 1884 icmdp->cmd_type);
1885 1885 ASSERT(FALSE);
1886 1886 }
1887 1887
1888 1888 ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
1889 1889 return (rval);
1890 1890 }
1891 1891
1892 1892 /*
1893 1893 * a variable length cdb can be up to 16K, but we obviously don't want
1894 1894 * to put that on the stack; go with 200 bytes; if we get something
1895 1895 * bigger than that we will kmem_alloc a buffer
1896 1896 */
1897 1897 #define DEF_CDB_LEN 200
1898 1898
1899 1899 /*
1900 1900 * given the size of the cdb, return how many bytes the header takes,
1901 1901 * which is the sizeof addl_hdr_t + the CDB size, minus the 16 bytes
1902 1902 * stored in the basic header, minus sizeof (ahs_extscb)
1903 1903 */
1904 1904 #define ADDLHDRSZ(x) (sizeof (iscsi_addl_hdr_t) + (x) - \
1905 1905 16 - 4)
1906 1906
1907 1907 static void
1908 1908 iscsi_tx_init_hdr(iscsi_sess_t *isp, iscsi_conn_t *icp,
1909 1909 iscsi_text_hdr_t *ihp, int opcode, iscsi_cmd_t *icmdp)
1910 1910 {
1911 1911 ihp->opcode = opcode;
1912 1912 ihp->itt = icmdp->cmd_itt;
1913 1913 mutex_enter(&isp->sess_cmdsn_mutex);
1914 1914 icmdp->cmd_sn = isp->sess_cmdsn;
1915 1915 ihp->cmdsn = htonl(isp->sess_cmdsn);
1916 1916 isp->sess_cmdsn++;
1917 1917 mutex_exit(&isp->sess_cmdsn_mutex);
1918 1918 ihp->expstatsn = htonl(icp->conn_expstatsn);
1919 1919 icp->conn_laststatsn = icp->conn_expstatsn;
1920 1920 }
1921 1921
1922 1922
1923 1923 static void
1924 1924 iscsi_tx_scsi_data(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp,
1925 1925 iscsi_conn_t *icp, idm_pdu_t *pdu)
1926 1926 {
1927 1927 struct buf *bp = NULL;
1928 1928 size_t buflen = 0;
1929 1929 uint32_t first_burst_length = 0;
1930 1930 struct scsi_pkt *pkt;
1931 1931
1932 1932 pkt = icmdp->cmd_un.scsi.pkt;
1933 1933 bp = icmdp->cmd_un.scsi.bp;
1934 1934 if ((bp != NULL) && bp->b_bcount) {
1935 1935 buflen = bp->b_bcount;
1936 1936 first_burst_length =
1937 1937 icp->conn_params.first_burst_length;
1938 1938
1939 1939 if (bp->b_flags & B_READ) {
1940 1940 ihp->flags = ISCSI_FLAG_FINAL;
1941 1941 /*
1942 1942 * fix problem where OS sends bp (B_READ &
1943 1943 * b_bcount!=0) for a TUR or START_STOP.
1944 1944 * (comment came from cisco code.)
1945 1945 */
1946 1946 if ((pkt->pkt_cdbp[0] != SCMD_TEST_UNIT_READY) &&
1947 1947 (pkt->pkt_cdbp[0] != SCMD_START_STOP)) {
1948 1948 ihp->flags |= ISCSI_FLAG_CMD_READ;
1949 1949 ihp->data_length = htonl(buflen);
1950 1950 }
1951 1951 } else {
1952 1952 ihp->flags = ISCSI_FLAG_CMD_WRITE;
1953 1953 /*
1954 1954 * FinalBit on the the iSCSI PDU denotes this
1955 1955 * is the last PDU in the sequence.
1956 1956 *
1957 1957 * initial_r2t = true means R2T is required
1958 1958 * for additional PDU, so there will be no more
1959 1959 * unsolicited PDUs following
1960 1960 */
1961 1961 if (icp->conn_params.initial_r2t) {
1962 1962 ihp->flags |= ISCSI_FLAG_FINAL;
1963 1963 }
1964 1964
1965 1965 /* Check if we should send ImmediateData */
1966 1966 if (icp->conn_params.immediate_data) {
1967 1967 pdu->isp_data =
1968 1968 (uint8_t *)icmdp->
1969 1969 cmd_un.scsi.bp->b_un.b_addr;
1970 1970
1971 1971 pdu->isp_datalen = MIN(MIN(buflen,
1972 1972 first_burst_length),
1973 1973 icmdp->cmd_conn->conn_params.
1974 1974 max_xmit_data_seg_len);
1975 1975
1976 1976 /*
1977 1977 * if everything fits immediate, or
1978 1978 * we can send all burst data immediate
1979 1979 * (not unsol), set F
1980 1980 */
1981 1981 /*
1982 1982 * XXX This doesn't look right -- it's not
1983 1983 * clear how we can handle transmitting
1984 1984 * any unsolicited data. It looks like
1985 1985 * we only support immediate data. So what
1986 1986 * happens if we don't set ISCSI_FLAG_FINAL?
1987 1987 *
1988 1988 * Unless there's magic code somewhere that
1989 1989 * is sending the remaining PDU's we should
1990 1990 * simply set ISCSI_FLAG_FINAL and forget
1991 1991 * about sending unsolicited data. The big
1992 1992 * win is the immediate data anyway for small
1993 1993 * PDU's.
1994 1994 */
1995 1995 if ((pdu->isp_datalen == buflen) ||
1996 1996 (pdu->isp_datalen == first_burst_length)) {
1997 1997 ihp->flags |= ISCSI_FLAG_FINAL;
1998 1998 }
1999 1999
2000 2000 hton24(ihp->dlength, pdu->isp_datalen);
2001 2001 }
2002 2002 /* total data transfer length */
2003 2003 ihp->data_length = htonl(buflen);
2004 2004 }
2005 2005 } else {
2006 2006 ihp->flags = ISCSI_FLAG_FINAL;
2007 2007 }
2008 2008 icmdp->cmd_un.scsi.data_transferred += pdu->isp_datalen;
2009 2009 /* XXX How is this different from the code above? */
2010 2010 /* will idm send the next data command up to burst length? */
2011 2011 /* send the burstlen if we haven't sent immediate data */
2012 2012 /* CRM: should idm send difference min(buflen, first_burst) and imm? */
2013 2013 /* (MIN(first_burst_length, buflen) - imdata > 0) */
2014 2014 /* CRM_LATER: change this to generate unsolicited pdu */
2015 2015 if ((buflen > 0) &&
2016 2016 ((bp->b_flags & B_READ) == 0) &&
2017 2017 (icp->conn_params.initial_r2t == 0) &&
2018 2018 pdu->isp_datalen == 0) {
2019 2019
2020 2020 pdu->isp_datalen = MIN(first_burst_length, buflen);
2021 2021 if ((pdu->isp_datalen == buflen) ||
2022 2022 (pdu->isp_datalen == first_burst_length)) {
2023 2023 ihp->flags |= ISCSI_FLAG_FINAL;
2024 2024 }
2025 2025 pdu->isp_data = (uint8_t *)icmdp->cmd_un.scsi.bp->b_un.b_addr;
2026 2026 hton24(ihp->dlength, pdu->isp_datalen);
2027 2027 }
2028 2028 }
2029 2029
2030 2030 static void
2031 2031 iscsi_tx_scsi_init_pkt(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp)
2032 2032 {
2033 2033 struct scsi_pkt *pkt;
2034 2034
2035 2035 pkt = icmdp->cmd_un.scsi.pkt;
2036 2036 pkt->pkt_state = (STATE_GOT_BUS | STATE_GOT_TARGET);
2037 2037 pkt->pkt_reason = CMD_INCOMPLETE;
2038 2038
2039 2039 /* tagged queuing */
2040 2040 if (pkt->pkt_flags & FLAG_HTAG) {
2041 2041 ihp->flags |= ISCSI_ATTR_HEAD_OF_QUEUE;
2042 2042 } else if (pkt->pkt_flags & FLAG_OTAG) {
2043 2043 ihp->flags |= ISCSI_ATTR_ORDERED;
2044 2044 } else if (pkt->pkt_flags & FLAG_STAG) {
2045 2045 ihp->flags |= ISCSI_ATTR_SIMPLE;
2046 2046 } else {
2047 2047 /* ihp->flags |= ISCSI_ATTR_UNTAGGED; */
2048 2048 /* EMPTY */
2049 2049 }
2050 2050
2051 2051 /* iscsi states lun is based on spc.2 */
2052 2052 ISCSI_LUN_BYTE_COPY(ihp->lun, icmdp->cmd_un.scsi.lun);
2053 2053
2054 2054 if (icmdp->cmd_un.scsi.cmdlen <= 16) {
2055 2055 /* copy the SCSI Command Block into the PDU */
2056 2056 bcopy(pkt->pkt_cdbp, ihp->scb,
2057 2057 icmdp->cmd_un.scsi.cmdlen);
2058 2058 } else {
2059 2059 iscsi_addl_hdr_t *iahp;
2060 2060
2061 2061 iahp = (iscsi_addl_hdr_t *)ihp;
2062 2062
2063 2063 ihp->hlength = (ADDLHDRSZ(icmdp->cmd_un.scsi.cmdlen) -
2064 2064 sizeof (iscsi_scsi_cmd_hdr_t) + 3) / 4;
2065 2065 iahp->ahs_hlen_hi = 0;
2066 2066 iahp->ahs_hlen_lo = (icmdp->cmd_un.scsi.cmdlen - 15);
2067 2067 iahp->ahs_key = 0x01;
2068 2068 iahp->ahs_resv = 0;
2069 2069 bcopy(pkt->pkt_cdbp, ihp->scb, 16);
2070 2070 bcopy(((char *)pkt->pkt_cdbp) + 16, &iahp->ahs_extscb[0],
2071 2071 icmdp->cmd_un.scsi.cmdlen);
2072 2072 }
2073 2073
2074 2074 /*
2075 2075 * Update all values before transfering.
2076 2076 * We should never touch the icmdp after
2077 2077 * transfering if there is no more data
2078 2078 * to send. The only case the idm_pdu_tx()
2079 2079 * will fail is a on a connection disconnect
2080 2080 * in that case the command will be flushed.
2081 2081 */
2082 2082 pkt->pkt_state |= STATE_SENT_CMD;
2083 2083 }
2084 2084
2085 2085 static void
2086 2086 iscsi_tx_scsi_init_task(iscsi_cmd_t *icmdp, iscsi_conn_t *icp,
2087 2087 iscsi_scsi_cmd_hdr_t *ihp)
2088 2088 {
2089 2089 idm_task_t *itp;
2090 2090 struct buf *bp = NULL;
2091 2091 uint32_t data_length;
2092 2092
2093 2093 bp = icmdp->cmd_un.scsi.bp;
2094 2094
2095 2095 itp = icmdp->cmd_itp;
2096 2096 ASSERT(itp != NULL);
2097 2097 data_length = ntohl(ihp->data_length);
2098 2098 ISCSI_IO_LOG(CE_NOTE,
2099 2099 "DEBUG: iscsi_tx_init_task: task_start: %p idt_tt: %x cmdsn: %x "
2100 2100 "sess_cmdsn: %x cmd: %p "
2101 2101 "cmdtype: %d datalen: %u",
2102 2102 (void *)itp, itp->idt_tt, ihp->cmdsn, icp->conn_sess->sess_cmdsn,
2103 2103 (void *)icmdp, icmdp->cmd_type, data_length);
2104 2104 if (data_length > 0) {
2105 2105 if (bp->b_flags & B_READ) {
2106 2106 icmdp->cmd_un.scsi.ibp_ibuf =
2107 2107 idm_buf_alloc(icp->conn_ic,
2108 2108 bp->b_un.b_addr, bp->b_bcount);
2109 2109 if (icmdp->cmd_un.scsi.ibp_ibuf)
2110 2110 idm_buf_bind_in(itp,
2111 2111 icmdp->cmd_un.scsi.ibp_ibuf);
2112 2112 } else {
2113 2113 icmdp->cmd_un.scsi.ibp_obuf =
2114 2114 idm_buf_alloc(icp->conn_ic,
2115 2115 bp->b_un.b_addr, bp->b_bcount);
2116 2116 if (icmdp->cmd_un.scsi.ibp_obuf)
2117 2117 idm_buf_bind_out(itp,
2118 2118 icmdp->cmd_un.scsi.ibp_obuf);
2119 2119 }
2120 2120 ISCSI_IO_LOG(CE_NOTE,
2121 2121 "DEBUG: pdu_tx: task_start(%s): %p ic: %p idt_tt: %x "
2122 2122 "cmdsn: %x sess_cmdsn: %x sess_expcmdsn: %x obuf: %p "
2123 2123 "cmdp: %p cmdtype: %d "
2124 2124 "buflen: %lu " "bpaddr: %p datalen: %u ",
2125 2125 bp->b_flags & B_READ ? "B_READ" : "B_WRITE",
2126 2126 (void *)itp, (void *)icp->conn_ic,
2127 2127 itp->idt_tt, ihp->cmdsn,
2128 2128 icp->conn_sess->sess_cmdsn,
2129 2129 icp->conn_sess->sess_expcmdsn,
2130 2130 (void *)icmdp->cmd_un.scsi.ibp_ibuf,
2131 2131 (void *)icmdp, icmdp->cmd_type, bp->b_bcount,
2132 2132 (void *)bp->b_un.b_addr,
2133 2133 data_length);
2134 2134 }
2135 2135
2136 2136 /*
2137 2137 * Task is now active
2138 2138 */
2139 2139 idm_task_start(itp, ISCSI_INI_TASK_TTT);
2140 2140 }
2141 2141
2142 2142 /*
2143 2143 * iscsi_tx_scsi -
2144 2144 *
2145 2145 */
2146 2146 static iscsi_status_t
2147 2147 iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2148 2148 {
2149 2149 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2150 2150 iscsi_conn_t *icp = NULL;
2151 2151 struct scsi_pkt *pkt = NULL;
2152 2152 iscsi_scsi_cmd_hdr_t *ihp = NULL;
2153 2153 int cdblen = 0;
2154 2154 idm_pdu_t *pdu;
2155 2155 int len;
2156 2156
2157 2157 ASSERT(isp != NULL);
2158 2158 ASSERT(icmdp != NULL);
2159 2159
2160 2160 pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
2161 2161
2162 2162 pkt = icmdp->cmd_un.scsi.pkt;
2163 2163 ASSERT(pkt != NULL);
2164 2164 icp = icmdp->cmd_conn;
2165 2165 ASSERT(icp != NULL);
2166 2166
2167 2167 /* Reset counts in case we are on a retry */
2168 2168 icmdp->cmd_un.scsi.data_transferred = 0;
2169 2169
2170 2170 if (icmdp->cmd_un.scsi.cmdlen > DEF_CDB_LEN) {
2171 2171 cdblen = icmdp->cmd_un.scsi.cmdlen;
2172 2172 ihp = kmem_zalloc(ADDLHDRSZ(cdblen), KM_SLEEP);
2173 2173 len = ADDLHDRSZ(cdblen);
2174 2174 } else {
2175 2175 /*
2176 2176 * only bzero the basic header; the additional header
2177 2177 * will be set up correctly later, if needed
2178 2178 */
2179 2179 ihp = kmem_zalloc(sizeof (iscsi_scsi_cmd_hdr_t), KM_SLEEP);
2180 2180 len = sizeof (iscsi_scsi_cmd_hdr_t);
2181 2181 }
2182 2182
2183 2183 iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ihp,
2184 2184 ISCSI_OP_SCSI_CMD, icmdp);
2185 2185
2186 2186 idm_pdu_init(pdu, icp->conn_ic, (void *)icmdp, &iscsi_tx_done);
2187 2187 idm_pdu_init_hdr(pdu, (uint8_t *)ihp, len);
2188 2188 pdu->isp_data = NULL;
2189 2189 pdu->isp_datalen = 0;
2190 2190
2191 2191 /*
2192 2192 * Sestion 12.11 of the iSCSI specification has a good table
2193 2193 * describing when uncolicited data and/or immediate data
2194 2194 * should be sent.
2195 2195 */
2196 2196
2197 2197 iscsi_tx_scsi_data(icmdp, ihp, icp, pdu);
2198 2198
2199 2199 iscsi_tx_scsi_init_pkt(icmdp, ihp);
2200 2200
2201 2201 /* Calls idm_task_start */
2202 2202 iscsi_tx_scsi_init_task(icmdp, icp, ihp);
2203 2203
2204 2204 mutex_exit(&isp->sess_queue_pending.mutex);
2205 2205
2206 2206 idm_pdu_tx(pdu);
2207 2207
2208 2208 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2209 2209
2210 2210 return (rval);
2211 2211 }
2212 2212
2213 2213
2214 2214 /* ARGSUSED */
2215 2215 static void
2216 2216 iscsi_tx_done(idm_pdu_t *pdu, idm_status_t status)
2217 2217 {
2218 2218 kmem_free((iscsi_hdr_t *)pdu->isp_hdr, pdu->isp_hdrlen);
2219 2219 kmem_free(pdu, sizeof (idm_pdu_t));
2220 2220 }
2221 2221
2222 2222
2223 2223 static void
2224 2224 iscsi_tx_pdu(iscsi_conn_t *icp, int opcode, void *hdr, int hdrlen,
2225 2225 iscsi_cmd_t *icmdp)
2226 2226 {
2227 2227 idm_pdu_t *tx_pdu;
2228 2228 iscsi_hdr_t *ihp = (iscsi_hdr_t *)hdr;
2229 2229
2230 2230 tx_pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
2231 2231 ASSERT(tx_pdu != NULL);
2232 2232
2233 2233 idm_pdu_init(tx_pdu, icp->conn_ic, icmdp, &iscsi_tx_done);
2234 2234 idm_pdu_init_hdr(tx_pdu, hdr, hdrlen);
2235 2235 if (opcode == ISCSI_OP_TEXT_CMD) {
2236 2236 idm_pdu_init_data(tx_pdu,
2237 2237 (uint8_t *)icmdp->cmd_un.text.buf,
2238 2238 ntoh24(ihp->dlength));
2239 2239 }
2240 2240
2241 2241 mutex_exit(&icp->conn_sess->sess_queue_pending.mutex);
2242 2242 idm_pdu_tx(tx_pdu);
2243 2243 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2244 2244 }
2245 2245
2246 2246
2247 2247 /*
2248 2248 * iscsi_tx_nop -
2249 2249 *
2250 2250 */
2251 2251 static iscsi_status_t
2252 2252 iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2253 2253 {
2254 2254 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2255 2255 iscsi_conn_t *icp = NULL;
2256 2256 iscsi_nop_out_hdr_t *inohp;
2257 2257
2258 2258 ASSERT(isp != NULL);
2259 2259 ASSERT(icmdp != NULL);
2260 2260 icp = icmdp->cmd_conn;
2261 2261 ASSERT(icp != NULL);
2262 2262
2263 2263 inohp = kmem_zalloc(sizeof (iscsi_nop_out_hdr_t), KM_SLEEP);
2264 2264 ASSERT(inohp != NULL);
2265 2265
2266 2266 inohp->opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
2267 2267 inohp->flags = ISCSI_FLAG_FINAL;
2268 2268 inohp->itt = icmdp->cmd_itt;
2269 2269 inohp->ttt = icmdp->cmd_ttt;
2270 2270 mutex_enter(&isp->sess_cmdsn_mutex);
2271 2271 icmdp->cmd_sn = isp->sess_cmdsn;
2272 2272 inohp->cmdsn = htonl(isp->sess_cmdsn);
2273 2273 mutex_exit(&isp->sess_cmdsn_mutex);
2274 2274 inohp->expstatsn = htonl(icp->conn_expstatsn);
2275 2275 icp->conn_laststatsn = icp->conn_expstatsn;
2276 2276 iscsi_tx_pdu(icp, ISCSI_OP_NOOP_OUT, inohp,
2277 2277 sizeof (iscsi_nop_out_hdr_t), icmdp);
2278 2278 return (rval);
2279 2279 }
2280 2280
2281 2281
2282 2282 /*
2283 2283 * iscsi_tx_abort -
2284 2284 *
2285 2285 */
2286 2286 static iscsi_status_t
2287 2287 iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2288 2288 {
2289 2289 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2290 2290 iscsi_conn_t *icp = NULL;
2291 2291 iscsi_scsi_task_mgt_hdr_t *istmh;
2292 2292
2293 2293 ASSERT(isp != NULL);
2294 2294 ASSERT(icmdp != NULL);
2295 2295 icp = icmdp->cmd_conn;
2296 2296 ASSERT(icp != NULL);
2297 2297
2298 2298 istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
2299 2299 ASSERT(istmh != NULL);
2300 2300 mutex_enter(&isp->sess_cmdsn_mutex);
2301 2301 icmdp->cmd_sn = isp->sess_cmdsn;
2302 2302 istmh->cmdsn = htonl(isp->sess_cmdsn);
2303 2303 mutex_exit(&isp->sess_cmdsn_mutex);
2304 2304 istmh->expstatsn = htonl(icp->conn_expstatsn);
2305 2305 icp->conn_laststatsn = icp->conn_expstatsn;
2306 2306 istmh->itt = icmdp->cmd_itt;
2307 2307 istmh->opcode = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2308 2308 istmh->function = ISCSI_FLAG_FINAL | ISCSI_TM_FUNC_ABORT_TASK;
2309 2309 ISCSI_LUN_BYTE_COPY(istmh->lun,
2310 2310 icmdp->cmd_un.abort.icmdp->cmd_un.scsi.lun);
2311 2311 istmh->rtt = icmdp->cmd_un.abort.icmdp->cmd_itt;
2312 2312 iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
2313 2313 sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
2314 2314
2315 2315 return (rval);
2316 2316 }
2317 2317
2318 2318
2319 2319 /*
2320 2320 * iscsi_tx_reset -
2321 2321 *
2322 2322 */
2323 2323 static iscsi_status_t
2324 2324 iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2325 2325 {
2326 2326 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2327 2327 iscsi_conn_t *icp = NULL;
2328 2328 iscsi_scsi_task_mgt_hdr_t *istmh;
2329 2329
2330 2330 ASSERT(isp != NULL);
2331 2331 ASSERT(icmdp != NULL);
2332 2332 icp = icmdp->cmd_conn;
2333 2333 ASSERT(icp != NULL);
2334 2334
2335 2335 istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
2336 2336 ASSERT(istmh != NULL);
2337 2337 istmh->opcode = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2338 2338 mutex_enter(&isp->sess_cmdsn_mutex);
2339 2339 icmdp->cmd_sn = isp->sess_cmdsn;
2340 2340 istmh->cmdsn = htonl(isp->sess_cmdsn);
2341 2341 mutex_exit(&isp->sess_cmdsn_mutex);
2342 2342 istmh->expstatsn = htonl(icp->conn_expstatsn);
2343 2343 istmh->itt = icmdp->cmd_itt;
2344 2344
2345 2345 switch (icmdp->cmd_un.reset.level) {
2346 2346 case RESET_LUN:
2347 2347 istmh->function = ISCSI_FLAG_FINAL |
2348 2348 ISCSI_TM_FUNC_LOGICAL_UNIT_RESET;
2349 2349 ISCSI_LUN_BYTE_COPY(istmh->lun, icmdp->cmd_lun->lun_num);
2350 2350 break;
2351 2351 case RESET_TARGET:
2352 2352 case RESET_BUS:
2353 2353 istmh->function = ISCSI_FLAG_FINAL |
2354 2354 ISCSI_TM_FUNC_TARGET_WARM_RESET;
2355 2355 break;
2356 2356 default:
2357 2357 /* unsupported / unknown level */
2358 2358 ASSERT(FALSE);
2359 2359 break;
2360 2360 }
2361 2361
2362 2362 iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
2363 2363 sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
2364 2364
2365 2365 return (rval);
2366 2366 }
2367 2367
2368 2368
2369 2369 /*
2370 2370 * iscsi_tx_logout -
2371 2371 *
2372 2372 */
2373 2373 static iscsi_status_t
2374 2374 iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2375 2375 {
2376 2376 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2377 2377 iscsi_conn_t *icp = NULL;
2378 2378 iscsi_logout_hdr_t *ilh;
2379 2379
2380 2380 ASSERT(isp != NULL);
2381 2381 ASSERT(icmdp != NULL);
2382 2382 icp = icmdp->cmd_conn;
2383 2383 ASSERT(icp != NULL);
2384 2384
2385 2385 ilh = kmem_zalloc(sizeof (iscsi_logout_hdr_t), KM_SLEEP);
2386 2386 ilh->opcode = ISCSI_OP_LOGOUT_CMD | ISCSI_OP_IMMEDIATE;
2387 2387 ilh->flags = ISCSI_FLAG_FINAL | ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2388 2388 ilh->itt = icmdp->cmd_itt;
2389 2389 ilh->cid = icp->conn_cid;
2390 2390 mutex_enter(&isp->sess_cmdsn_mutex);
2391 2391 icmdp->cmd_sn = isp->sess_cmdsn;
2392 2392 ilh->cmdsn = htonl(isp->sess_cmdsn);
2393 2393 mutex_exit(&isp->sess_cmdsn_mutex);
2394 2394 ilh->expstatsn = htonl(icp->conn_expstatsn);
2395 2395 iscsi_tx_pdu(icp, ISCSI_OP_LOGOUT_CMD, ilh,
2396 2396 sizeof (iscsi_logout_hdr_t), icmdp);
2397 2397
2398 2398 return (rval);
2399 2399 }
2400 2400
2401 2401 /*
2402 2402 * iscsi_tx_text - setup iSCSI text request header and send PDU with
2403 2403 * data given in the buffer attached to the command. For a single
2404 2404 * text request, the target may need to send its response in multiple
2405 2405 * text response. In this case, empty text requests are sent after
2406 2406 * each received response to notify the target the initiator is ready
2407 2407 * for more response. For the initial request, the data_len field in
2408 2408 * the text specific portion of a command is set to the amount of data
2409 2409 * the initiator wants to send as part of the request. If additional
2410 2410 * empty text requests are required for long responses, the data_len
2411 2411 * field is set to 0 by the iscsi_handle_text function.
2412 2412 */
2413 2413 static iscsi_status_t
2414 2414 iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2415 2415 {
2416 2416 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2417 2417 iscsi_conn_t *icp = NULL;
2418 2418 iscsi_text_hdr_t *ith;
2419 2419
2420 2420 ASSERT(icmdp != NULL);
2421 2421 icp = icmdp->cmd_conn;
2422 2422 ASSERT(icp != NULL);
2423 2423
2424 2424 ith = kmem_zalloc(sizeof (iscsi_text_hdr_t), KM_SLEEP);
2425 2425 ASSERT(ith != NULL);
2426 2426 ith->flags = ISCSI_FLAG_FINAL;
2427 2427 hton24(ith->dlength, icmdp->cmd_un.text.data_len);
2428 2428 ith->ttt = icmdp->cmd_un.text.ttt;
2429 2429 iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ith,
2430 2430 ISCSI_OP_TEXT_CMD, icmdp);
2431 2431 bcopy(icmdp->cmd_un.text.lun, ith->rsvd4, sizeof (ith->rsvd4));
2432 2432
2433 2433 iscsi_tx_pdu(icp, ISCSI_OP_TEXT_CMD, ith, sizeof (iscsi_text_hdr_t),
2434 2434 icmdp);
2435 2435
2436 2436 return (rval);
2437 2437 }
2438 2438
2439 2439 /*
2440 2440 * +--------------------------------------------------------------------+
2441 2441 * | End of protocol send routines |
2442 2442 * +--------------------------------------------------------------------+
2443 2443 */
2444 2444
2445 2445 /*
2446 2446 * iscsi_handle_abort -
2447 2447 *
2448 2448 */
2449 2449 void
2450 2450 iscsi_handle_abort(void *arg)
2451 2451 {
2452 2452 iscsi_sess_t *isp = NULL;
2453 2453 iscsi_cmd_t *icmdp = (iscsi_cmd_t *)arg;
2454 2454 iscsi_cmd_t *new_icmdp;
2455 2455 iscsi_conn_t *icp;
2456 2456
2457 2457 ASSERT(icmdp != NULL);
2458 2458 icp = icmdp->cmd_conn;
2459 2459 ASSERT(icp != NULL);
2460 2460 isp = icp->conn_sess;
2461 2461 ASSERT(isp != NULL);
2462 2462
2463 2463 /* there should only be one abort */
2464 2464 ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
2465 2465
2466 2466 new_icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2467 2467 new_icmdp->cmd_type = ISCSI_CMD_TYPE_ABORT;
2468 2468 new_icmdp->cmd_lun = icmdp->cmd_lun;
2469 2469 new_icmdp->cmd_un.abort.icmdp = icmdp;
2470 2470 new_icmdp->cmd_conn = icmdp->cmd_conn;
2471 2471 icmdp->cmd_un.scsi.abort_icmdp = new_icmdp;
2472 2472
2473 2473 /* pending queue mutex is already held by timeout_checks */
2474 2474 iscsi_cmd_state_machine(new_icmdp, ISCSI_CMD_EVENT_E1, isp);
2475 2475 }
2476 2476
2477 2477 /*
2478 2478 * Callback from IDM indicating that the task has been suspended or aborted.
2479 2479 */
2480 2480 void
2481 2481 iscsi_task_aborted(idm_task_t *idt, idm_status_t status)
2482 2482 {
2483 2483 iscsi_cmd_t *icmdp = idt->idt_private;
2484 2484 iscsi_conn_t *icp = icmdp->cmd_conn;
2485 2485 iscsi_sess_t *isp = icp->conn_sess;
2486 2486
2487 2487 ASSERT(icmdp->cmd_conn != NULL);
2488 2488
2489 2489 switch (status) {
2490 2490 case IDM_STATUS_SUSPENDED:
2491 2491 /*
2492 2492 * If the task is suspended, it may be aborted later,
2493 2493 * so we can ignore this notification.
2494 2494 */
2495 2495 break;
2496 2496
2497 2497 case IDM_STATUS_ABORTED:
2498 2498 mutex_enter(&icp->conn_queue_active.mutex);
2499 2499 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E9, isp);
2500 2500 mutex_exit(&icp->conn_queue_active.mutex);
2501 2501 break;
2502 2502
2503 2503 default:
2504 2504 /*
2505 2505 * Unexpected status.
2506 2506 */
2507 2507 ASSERT(0);
2508 2508 }
2509 2509
2510 2510 }
2511 2511
2512 2512 /*
2513 2513 * iscsi_handle_nop -
2514 2514 *
2515 2515 */
2516 2516 static void
2517 2517 iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt)
2518 2518 {
2519 2519 iscsi_sess_t *isp = NULL;
2520 2520 iscsi_cmd_t *icmdp = NULL;
2521 2521
2522 2522 ASSERT(icp != NULL);
2523 2523 isp = icp->conn_sess;
2524 2524 ASSERT(isp != NULL);
2525 2525
2526 2526 icmdp = iscsi_cmd_alloc(icp, KM_NOSLEEP);
2527 2527 if (icmdp == NULL) {
2528 2528 return;
2529 2529 }
2530 2530
2531 2531 icmdp->cmd_type = ISCSI_CMD_TYPE_NOP;
2532 2532 icmdp->cmd_itt = itt;
2533 2533 icmdp->cmd_ttt = ttt;
2534 2534 icmdp->cmd_lun = NULL;
2535 2535 icp->conn_nop_lbolt = ddi_get_lbolt();
2536 2536
2537 2537 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2538 2538 }
2539 2539
2540 2540 /*
2541 2541 * iscsi_handle_reset - send reset request to the target
2542 2542 *
2543 2543 */
2544 2544 iscsi_status_t
2545 2545 iscsi_handle_reset(iscsi_sess_t *isp, int level, iscsi_lun_t *ilp)
2546 2546 {
2547 2547 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2548 2548 iscsi_conn_t *icp;
2549 2549 iscsi_cmd_t icmd;
2550 2550
2551 2551 ASSERT(isp != NULL);
2552 2552
2553 2553 if (level == RESET_LUN) {
2554 2554 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2555 2555 ASSERT(ilp != NULL);
2556 2556 if (ilp->lun_state & ISCSI_LUN_STATE_BUSY) {
2557 2557 rw_exit(&isp->sess_lun_list_rwlock);
2558 2558 return (ISCSI_STATUS_SUCCESS);
2559 2559 }
2560 2560 ilp->lun_state |= ISCSI_LUN_STATE_BUSY;
2561 2561 rw_exit(&isp->sess_lun_list_rwlock);
2562 2562 } else {
2563 2563 mutex_enter(&isp->sess_reset_mutex);
2564 2564 if (isp->sess_reset_in_progress == B_TRUE) {
2565 2565 /*
2566 2566 * If the reset is in progress, it is unnecessary
2567 2567 * to send reset to the target redunantly.
2568 2568 */
2569 2569 mutex_exit(&isp->sess_reset_mutex);
2570 2570 return (ISCSI_STATUS_SUCCESS);
2571 2571 }
2572 2572 isp->sess_reset_in_progress = B_TRUE;
2573 2573 mutex_exit(&isp->sess_reset_mutex);
2574 2574 }
2575 2575
2576 2576 bzero(&icmd, sizeof (iscsi_cmd_t));
2577 2577 icmd.cmd_sig = ISCSI_SIG_CMD;
2578 2578 icmd.cmd_state = ISCSI_CMD_STATE_FREE;
2579 2579 icmd.cmd_type = ISCSI_CMD_TYPE_RESET;
2580 2580 icmd.cmd_lun = ilp;
2581 2581 icmd.cmd_un.reset.level = level;
2582 2582 icmd.cmd_result = ISCSI_STATUS_SUCCESS;
2583 2583 icmd.cmd_completed = B_FALSE;
2584 2584 icmd.cmd_un.reset.response = SCSI_TCP_TM_RESP_COMPLETE;
2585 2585
2586 2586 mutex_init(&icmd.cmd_mutex, NULL, MUTEX_DRIVER, NULL);
2587 2587 cv_init(&icmd.cmd_completion, NULL, CV_DRIVER, NULL);
2588 2588 /*
2589 2589 * If we received an IO and we are not in the
2590 2590 * LOGGED_IN state we are in the process of
2591 2591 * failing. Just respond that we are BUSY.
2592 2592 */
2593 2593 rw_enter(&isp->sess_state_rwlock, RW_READER);
2594 2594 if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2595 2595 /* We aren't connected to the target fake success */
2596 2596 rw_exit(&isp->sess_state_rwlock);
2597 2597
2598 2598 if (level == RESET_LUN) {
2599 2599 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2600 2600 ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2601 2601 rw_exit(&isp->sess_lun_list_rwlock);
2602 2602 } else {
2603 2603 mutex_enter(&isp->sess_reset_mutex);
2604 2604 isp->sess_reset_in_progress = B_FALSE;
2605 2605 mutex_exit(&isp->sess_reset_mutex);
2606 2606 }
2607 2607
2608 2608 return (ISCSI_STATUS_SUCCESS);
2609 2609 }
2610 2610
2611 2611 mutex_enter(&isp->sess_queue_pending.mutex);
2612 2612 iscsi_cmd_state_machine(&icmd, ISCSI_CMD_EVENT_E1, isp);
2613 2613 mutex_exit(&isp->sess_queue_pending.mutex);
2614 2614 rw_exit(&isp->sess_state_rwlock);
2615 2615
2616 2616 /* stall until completed */
2617 2617 mutex_enter(&icmd.cmd_mutex);
2618 2618 while (icmd.cmd_completed == B_FALSE) {
2619 2619 cv_wait(&icmd.cmd_completion, &icmd.cmd_mutex);
2620 2620 }
2621 2621 mutex_exit(&icmd.cmd_mutex);
2622 2622
2623 2623 /* copy rval */
2624 2624 rval = icmd.cmd_result;
2625 2625
2626 2626 if (rval == ISCSI_STATUS_SUCCESS) {
2627 2627 /*
2628 2628 * Reset was successful. We need to flush
2629 2629 * all active IOs.
2630 2630 */
2631 2631 rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2632 2632 icp = isp->sess_conn_list;
2633 2633 while (icp != NULL) {
2634 2634 iscsi_cmd_t *t_icmdp = NULL;
2635 2635 iscsi_cmd_t *next_icmdp = NULL;
2636 2636
2637 2637 mutex_enter(&icp->conn_queue_active.mutex);
2638 2638 t_icmdp = icp->conn_queue_active.head;
2639 2639 while (t_icmdp != NULL) {
2640 2640 next_icmdp = t_icmdp->cmd_next;
2641 2641 mutex_enter(&t_icmdp->cmd_mutex);
2642 2642 if (!(t_icmdp->cmd_misc_flags &
2643 2643 ISCSI_CMD_MISCFLAG_SENT)) {
2644 2644 /*
2645 2645 * Although this command is in the
2646 2646 * active queue, it has not been sent.
2647 2647 * Skip it.
2648 2648 */
2649 2649 mutex_exit(&t_icmdp->cmd_mutex);
2650 2650 t_icmdp = next_icmdp;
2651 2651 continue;
2652 2652 }
2653 2653 if (level == RESET_LUN) {
2654 2654 if (icmd.cmd_lun == NULL ||
2655 2655 t_icmdp->cmd_lun == NULL ||
2656 2656 (icmd.cmd_lun->lun_num !=
2657 2657 t_icmdp->cmd_lun->lun_num)) {
2658 2658 mutex_exit(&t_icmdp->cmd_mutex);
2659 2659 t_icmdp = next_icmdp;
2660 2660 continue;
2661 2661 }
2662 2662 }
2663 2663
2664 2664 if (icmd.cmd_sn == t_icmdp->cmd_sn) {
2665 2665 /*
2666 2666 * This command may be replied with
2667 2667 * UA sense key later. So currently
2668 2668 * it is not a suitable time to flush
2669 2669 * it. Mark its flag with FLUSH. There
2670 2670 * is no harm to keep it for a while.
2671 2671 */
2672 2672 t_icmdp->cmd_misc_flags |=
2673 2673 ISCSI_CMD_MISCFLAG_FLUSH;
2674 2674 if (t_icmdp->cmd_type ==
2675 2675 ISCSI_CMD_TYPE_SCSI) {
2676 2676 t_icmdp->cmd_un.scsi.pkt_stat |=
2677 2677 STAT_BUS_RESET;
2678 2678 }
2679 2679 mutex_exit(&t_icmdp->cmd_mutex);
2680 2680 } else if ((icmd.cmd_sn > t_icmdp->cmd_sn) ||
2681 2681 ((t_icmdp->cmd_sn - icmd.cmd_sn) >
2682 2682 ISCSI_CMD_SN_WRAP)) {
2683 2683 /*
2684 2684 * This reset request must act on all
2685 2685 * the commnds from the same session
2686 2686 * having a CmdSN lower than the task
2687 2687 * mangement CmdSN. So flush these
2688 2688 * commands here.
2689 2689 */
2690 2690 if (t_icmdp->cmd_type ==
2691 2691 ISCSI_CMD_TYPE_SCSI) {
2692 2692 t_icmdp->cmd_un.scsi.pkt_stat |=
2693 2693 STAT_BUS_RESET;
2694 2694 }
2695 2695 mutex_exit(&t_icmdp->cmd_mutex);
2696 2696 iscsi_cmd_state_machine(t_icmdp,
2697 2697 ISCSI_CMD_EVENT_E7, isp);
2698 2698 } else {
2699 2699 mutex_exit(&t_icmdp->cmd_mutex);
2700 2700 }
2701 2701
2702 2702 t_icmdp = next_icmdp;
2703 2703 }
2704 2704
2705 2705 mutex_exit(&icp->conn_queue_active.mutex);
2706 2706 icp = icp->conn_next;
2707 2707 }
2708 2708 rw_exit(&isp->sess_conn_list_rwlock);
2709 2709 }
2710 2710
2711 2711 /* clean up */
2712 2712 cv_destroy(&icmd.cmd_completion);
2713 2713 mutex_destroy(&icmd.cmd_mutex);
2714 2714
2715 2715 if (level == RESET_LUN) {
2716 2716 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2717 2717 ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2718 2718 rw_exit(&isp->sess_lun_list_rwlock);
2719 2719 } else {
2720 2720 mutex_enter(&isp->sess_reset_mutex);
2721 2721 isp->sess_reset_in_progress = B_FALSE;
2722 2722 mutex_exit(&isp->sess_reset_mutex);
2723 2723 }
2724 2724
2725 2725 return (rval);
2726 2726 }
2727 2727
2728 2728 /*
2729 2729 * iscsi_logout_start - task handler for deferred logout
2730 2730 * Acquire a hold before call, released in iscsi_handle_logout
2731 2731 */
2732 2732 static void
2733 2733 iscsi_logout_start(void *arg)
2734 2734 {
2735 2735 iscsi_task_t *itp = (iscsi_task_t *)arg;
2736 2736 iscsi_conn_t *icp;
2737 2737
2738 2738 icp = (iscsi_conn_t *)itp->t_arg;
2739 2739
2740 2740 mutex_enter(&icp->conn_state_mutex);
2741 2741 (void) iscsi_handle_logout(icp);
2742 2742 mutex_exit(&icp->conn_state_mutex);
2743 2743 }
2744 2744
2745 2745 /*
2746 2746 * iscsi_handle_logout - This function will issue a logout for
2747 2747 * the session from a specific connection.
2748 2748 * Acquire idm_conn_hold before call. Released internally.
2749 2749 */
2750 2750 iscsi_status_t
2751 2751 iscsi_handle_logout(iscsi_conn_t *icp)
2752 2752 {
2753 2753 iscsi_sess_t *isp;
2754 2754 idm_conn_t *ic;
2755 2755 iscsi_cmd_t *icmdp;
2756 2756 int rval;
2757 2757
2758 2758 ASSERT(icp != NULL);
2759 2759 isp = icp->conn_sess;
2760 2760 ic = icp->conn_ic;
2761 2761 ASSERT(isp != NULL);
2762 2762 ASSERT(isp->sess_hba != NULL);
2763 2763 ASSERT(mutex_owned(&icp->conn_state_mutex));
2764 2764
2765 2765 /*
2766 2766 * If the connection has already gone down (e.g. if the transport
2767 2767 * failed between when this LOGOUT was generated and now) then we
2768 2768 * can and must skip sending the LOGOUT. Check the same condition
2769 2769 * we use below to determine that connection has "settled".
2770 2770 */
2771 2771 if ((icp->conn_state == ISCSI_CONN_STATE_FREE) ||
2772 2772 (icp->conn_state == ISCSI_CONN_STATE_FAILED) ||
2773 2773 (icp->conn_state == ISCSI_CONN_STATE_POLLING)) {
2774 2774 idm_conn_rele(ic);
2775 2775 return (0);
2776 2776 }
2777 2777
2778 2778 icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2779 2779 ASSERT(icmdp != NULL);
2780 2780 icmdp->cmd_type = ISCSI_CMD_TYPE_LOGOUT;
2781 2781 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
2782 2782 icmdp->cmd_completed = B_FALSE;
2783 2783
2784 2784 mutex_enter(&isp->sess_queue_pending.mutex);
2785 2785 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2786 2786 mutex_exit(&isp->sess_queue_pending.mutex);
2787 2787
2788 2788 /*
2789 2789 * release connection state mutex to avoid a deadlock. This
2790 2790 * function is called from within the connection state
2791 2791 * machine with the lock held. When the logout response is
2792 2792 * received another call to the connection state machine
2793 2793 * occurs which causes the deadlock
2794 2794 */
2795 2795 mutex_exit(&icp->conn_state_mutex);
2796 2796
2797 2797 /* stall until completed */
2798 2798 mutex_enter(&icmdp->cmd_mutex);
2799 2799 while (icmdp->cmd_completed == B_FALSE) {
2800 2800 cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2801 2801 }
2802 2802 mutex_exit(&icmdp->cmd_mutex);
2803 2803 mutex_enter(&icp->conn_state_mutex);
2804 2804
2805 2805 /* copy rval */
2806 2806 rval = icmdp->cmd_result;
2807 2807
2808 2808 /* clean up */
2809 2809 iscsi_cmd_free(icmdp);
2810 2810
2811 2811 if (rval != 0) {
2812 2812 /* If the logout failed then drop the connection */
2813 2813 idm_ini_conn_disconnect(icp->conn_ic);
2814 2814 }
2815 2815
2816 2816 /* stall until connection settles */
2817 2817 while ((icp->conn_state != ISCSI_CONN_STATE_FREE) &&
2818 2818 (icp->conn_state != ISCSI_CONN_STATE_FAILED) &&
2819 2819 (icp->conn_state != ISCSI_CONN_STATE_POLLING)) {
2820 2820 /* wait for transition */
2821 2821 cv_wait(&icp->conn_state_change, &icp->conn_state_mutex);
2822 2822 }
2823 2823
2824 2824 idm_conn_rele(ic);
2825 2825
2826 2826 /*
2827 2827 * Return value reflects whether the logout command completed --
2828 2828 * regardless of the return value the connection is closed and
2829 2829 * ready for reconnection.
2830 2830 */
2831 2831 return (rval);
2832 2832 }
2833 2833
2834 2834
2835 2835 /*
2836 2836 * iscsi_handle_text - main control function for iSCSI text requests. This
2837 2837 * function handles allocating the command, sending initial text request, and
2838 2838 * handling long response sequence.
2839 2839 * If a data overflow condition occurs, iscsi_handle_text continues to
2840 2840 * receive responses until the all data has been recieved. This allows
2841 2841 * the full data length to be returned to the caller.
2842 2842 */
2843 2843 iscsi_status_t
2844 2844 iscsi_handle_text(iscsi_conn_t *icp, char *buf, uint32_t buf_len,
2845 2845 uint32_t data_len, uint32_t *rx_data_len)
2846 2846 {
2847 2847 iscsi_sess_t *isp;
2848 2848 iscsi_cmd_t *icmdp;
2849 2849 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2850 2850
2851 2851 ASSERT(icp != NULL);
2852 2852 ASSERT(buf != NULL);
2853 2853 ASSERT(rx_data_len != NULL);
2854 2854
2855 2855 isp = icp->conn_sess;
2856 2856 ASSERT(isp != NULL);
2857 2857
2858 2858 /*
2859 2859 * Ensure data for text request command is not greater
2860 2860 * than the negotiated maximum receive data seqment length.
2861 2861 *
2862 2862 * Although iSCSI allows for long text requests (multiple
2863 2863 * pdus), this function places a restriction on text
2864 2864 * requests to ensure it is handled by a single PDU.
2865 2865 */
2866 2866 if (data_len > icp->conn_params.max_xmit_data_seg_len) {
2867 2867 return (ISCSI_STATUS_CMD_FAILED);
2868 2868 }
2869 2869
2870 2870 icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2871 2871 ASSERT(icmdp != NULL);
2872 2872
2873 2873 icmdp->cmd_type = ISCSI_CMD_TYPE_TEXT;
2874 2874 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
2875 2875 icmdp->cmd_misc_flags &= ~ISCSI_CMD_MISCFLAG_FREE;
2876 2876 icmdp->cmd_completed = B_FALSE;
2877 2877
2878 2878 icmdp->cmd_un.text.buf = buf;
2879 2879 icmdp->cmd_un.text.buf_len = buf_len;
2880 2880 icmdp->cmd_un.text.offset = 0;
2881 2881 icmdp->cmd_un.text.data_len = data_len;
2882 2882 icmdp->cmd_un.text.total_rx_len = 0;
2883 2883 icmdp->cmd_un.text.ttt = ISCSI_RSVD_TASK_TAG;
2884 2884 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_INITIAL_REQ;
2885 2885
2886 2886 long_text_response:
2887 2887 rw_enter(&isp->sess_state_rwlock, RW_READER);
2888 2888 if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2889 2889 iscsi_cmd_free(icmdp);
2890 2890 rw_exit(&isp->sess_state_rwlock);
2891 2891 return (ISCSI_STATUS_NO_CONN_LOGGED_IN);
2892 2892 }
2893 2893
2894 2894 mutex_enter(&isp->sess_queue_pending.mutex);
2895 2895 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2896 2896 mutex_exit(&isp->sess_queue_pending.mutex);
2897 2897 rw_exit(&isp->sess_state_rwlock);
2898 2898
2899 2899 /* stall until completed */
2900 2900 mutex_enter(&icmdp->cmd_mutex);
2901 2901 while (icmdp->cmd_completed == B_FALSE) {
2902 2902 cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2903 2903 }
2904 2904 mutex_exit(&icmdp->cmd_mutex);
2905 2905
2906 2906 /*
2907 2907 * check if error occured. If data overflow occured, continue on
2908 2908 * to ensure we get all data so that the full data length can be
2909 2909 * returned to the user
2910 2910 */
2911 2911 if ((icmdp->cmd_result != ISCSI_STATUS_SUCCESS) &&
2912 2912 (icmdp->cmd_result != ISCSI_STATUS_DATA_OVERFLOW)) {
2913 2913 cmn_err(CE_NOTE, "iscsi: SendTarget discovery failed (%d)",
2914 2914 icmdp->cmd_result);
2915 2915 rval = icmdp->cmd_result;
2916 2916 iscsi_cmd_free(icmdp);
2917 2917 return (rval);
2918 2918 }
2919 2919
2920 2920 /* check if this was a partial text PDU */
2921 2921 if (icmdp->cmd_un.text.stage != ISCSI_CMD_TEXT_FINAL_RSP) {
2922 2922 /*
2923 2923 * If a paritial text rexponse received, send an empty
2924 2924 * text request. This follows the behaviour specified
2925 2925 * in RFC3720 regarding long text responses.
2926 2926 */
2927 2927 icmdp->cmd_misc_flags &= ~ISCSI_CMD_MISCFLAG_FREE;
2928 2928 icmdp->cmd_completed = B_FALSE;
2929 2929 icmdp->cmd_un.text.data_len = 0;
2930 2930 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
2931 2931 goto long_text_response;
2932 2932 }
2933 2933
2934 2934 /*
2935 2935 * set total received data length. If data overflow this would be
2936 2936 * amount of data that would have been received if buffer large
2937 2937 * enough.
2938 2938 */
2939 2939 *rx_data_len = icmdp->cmd_un.text.total_rx_len;
2940 2940
2941 2941 /* copy rval */
2942 2942 rval = icmdp->cmd_result;
2943 2943
2944 2944 /* clean up */
2945 2945 iscsi_cmd_free(icmdp);
2946 2946
2947 2947 return (rval);
2948 2948 }
2949 2949
2950 2950 /*
2951 2951 * iscsi_handle_passthru - This function is used to send a uscsi_cmd
2952 2952 * to a specific target lun. This routine is used for internal purposes
2953 2953 * during enumeration and via the ISCSI_USCSICMD IOCTL. We restrict
2954 2954 * the CDBs that can be issued to a target/lun to INQUIRY, REPORT_LUNS,
2955 2955 * and READ_CAPACITY for security purposes.
2956 2956 *
2957 2957 * The logic here is broken into three phases.
2958 2958 * 1) Allocate and initialize a pkt/icmdp
2959 2959 * 2) Send the pkt/icmdp
2960 2960 * 3) cv_wait for completion
2961 2961 */
2962 2962 iscsi_status_t
2963 2963 iscsi_handle_passthru(iscsi_sess_t *isp, uint16_t lun, struct uscsi_cmd *ucmdp)
2964 2964 {
2965 2965 iscsi_status_t rval;
2966 2966 iscsi_cmd_t *icmdp;
2967 2967 struct scsi_pkt *pkt;
2968 2968 struct buf *bp;
2969 2969 struct scsi_arq_status *arqstat;
2970 2970 int statuslen;
2971 2971
2972 2972 ASSERT(isp != NULL);
2973 2973 ASSERT(ucmdp != NULL);
2974 2974
2975 2975 if (ucmdp->uscsi_rqlen > SENSE_LENGTH) {
2976 2976 /*
2977 2977 * The caller provided sense buffer large enough for additional
2978 2978 * sense bytes. We need to allocate pkt_scbp to fit them there
2979 2979 * too.
2980 2980 */
2981 2981 statuslen = ucmdp->uscsi_rqlen + ISCSI_ARQ_STATUS_NOSENSE_LEN;
2982 2982 } else {
2983 2983 /* The default size of pkt_scbp */
2984 2984 statuslen = sizeof (struct scsi_arq_status);
2985 2985 }
2986 2986
2987 2987 /*
2988 2988 * Step 1. Setup structs - KM_SLEEP will always succeed
2989 2989 */
2990 2990 bp = kmem_zalloc(sizeof (struct buf), KM_SLEEP);
2991 2991 ASSERT(bp != NULL);
2992 2992 pkt = kmem_zalloc(sizeof (struct scsi_pkt), KM_SLEEP);
2993 2993 ASSERT(pkt != NULL);
2994 2994 icmdp = iscsi_cmd_alloc(NULL, KM_SLEEP);
2995 2995 ASSERT(icmdp != NULL);
2996 2996
2997 2997 /* setup bp structure */
2998 2998 bp->b_flags = B_READ;
2999 2999 bp->b_bcount = ucmdp->uscsi_buflen;
3000 3000 bp->b_un.b_addr = ucmdp->uscsi_bufaddr;
3001 3001
3002 3002 /* setup scsi_pkt structure */
3003 3003 pkt->pkt_ha_private = icmdp;
3004 3004 pkt->pkt_scbp = kmem_zalloc(statuslen, KM_SLEEP);
3005 3005 pkt->pkt_cdbp = kmem_zalloc(ucmdp->uscsi_cdblen, KM_SLEEP);
3006 3006 /* callback routine for passthru, will wake cv_wait */
3007 3007 pkt->pkt_comp = iscsi_handle_passthru_callback;
3008 3008 pkt->pkt_time = ucmdp->uscsi_timeout;
3009 3009
3010 3010 /* setup iscsi_cmd structure */
3011 3011 icmdp->cmd_lun = NULL;
3012 3012 icmdp->cmd_type = ISCSI_CMD_TYPE_SCSI;
3013 3013 icmdp->cmd_un.scsi.lun = lun;
3014 3014 icmdp->cmd_un.scsi.pkt = pkt;
3015 3015 icmdp->cmd_un.scsi.bp = bp;
3016 3016 bcopy(ucmdp->uscsi_cdb, pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3017 3017 icmdp->cmd_un.scsi.cmdlen = ucmdp->uscsi_cdblen;
3018 3018 icmdp->cmd_un.scsi.statuslen = statuslen;
3019 3019 icmdp->cmd_crc_error_seen = B_FALSE;
3020 3020 icmdp->cmd_completed = B_FALSE;
3021 3021 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
3022 3022
3023 3023 /*
3024 3024 * Step 2. Push IO onto pending queue. If we aren't in
3025 3025 * FULL_FEATURE we need to fail the IO.
3026 3026 */
3027 3027 rw_enter(&isp->sess_state_rwlock, RW_READER);
3028 3028 if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
3029 3029 rw_exit(&isp->sess_state_rwlock);
3030 3030
3031 3031 iscsi_cmd_free(icmdp);
3032 3032 kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3033 3033 kmem_free(pkt->pkt_scbp, statuslen);
3034 3034 kmem_free(pkt, sizeof (struct scsi_pkt));
3035 3035 kmem_free(bp, sizeof (struct buf));
3036 3036
3037 3037 return (ISCSI_STATUS_CMD_FAILED);
3038 3038 }
3039 3039
3040 3040 mutex_enter(&isp->sess_queue_pending.mutex);
3041 3041 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
3042 3042 mutex_exit(&isp->sess_queue_pending.mutex);
3043 3043 rw_exit(&isp->sess_state_rwlock);
3044 3044
3045 3045 /*
3046 3046 * Step 3. Wait on cv_wait for completion routine
3047 3047 */
3048 3048 mutex_enter(&icmdp->cmd_mutex);
3049 3049 while (icmdp->cmd_completed == B_FALSE) {
3050 3050 cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
3051 3051 }
3052 3052 mutex_exit(&icmdp->cmd_mutex);
3053 3053
3054 3054 /* copy rval */
3055 3055 rval = icmdp->cmd_result;
3056 3056
3057 3057 ucmdp->uscsi_resid = pkt->pkt_resid;
3058 3058
3059 3059 /* update scsi status */
3060 3060 arqstat = (struct scsi_arq_status *)pkt->pkt_scbp;
3061 3061 ucmdp->uscsi_status = ((char *)&arqstat->sts_status)[0];
3062 3062
3063 3063 /* copy request sense buffers if caller gave space */
3064 3064 if ((ucmdp->uscsi_rqlen > 0) &&
3065 3065 (ucmdp->uscsi_rqbuf != NULL)) {
3066 3066 ASSERT(ucmdp->uscsi_rqlen >= arqstat->sts_rqpkt_resid);
3067 3067 ucmdp->uscsi_rqresid = arqstat->sts_rqpkt_resid;
3068 3068 bcopy(&arqstat->sts_sensedata, ucmdp->uscsi_rqbuf,
3069 3069 ucmdp->uscsi_rqlen - arqstat->sts_rqpkt_resid);
3070 3070 }
3071 3071
3072 3072 if ((ucmdp->uscsi_status == STATUS_CHECK) &&
3073 3073 ((icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_INTERNAL)) == B_TRUE) {
3074 3074 /*
3075 3075 * Internal SCSI commands received status
3076 3076 */
3077 3077 (void) iscsi_decode_sense(
3078 3078 (uint8_t *)&arqstat->sts_sensedata, icmdp);
3079 3079 }
3080 3080
3081 3081 /* clean up */
3082 3082 iscsi_cmd_free(icmdp);
3083 3083 kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3084 3084 kmem_free(pkt->pkt_scbp, statuslen);
3085 3085 kmem_free(pkt, sizeof (struct scsi_pkt));
3086 3086 kmem_free(bp, sizeof (struct buf));
3087 3087
3088 3088 return (rval);
3089 3089 }
3090 3090
3091 3091
3092 3092 /*
3093 3093 * iscsi_handle_passthru_callback -
3094 3094 *
3095 3095 */
3096 3096 static void
3097 3097 iscsi_handle_passthru_callback(struct scsi_pkt *pkt)
3098 3098 {
3099 3099 iscsi_cmd_t *icmdp = NULL;
3100 3100
3101 3101 ASSERT(pkt != NULL);
3102 3102 icmdp = (iscsi_cmd_t *)pkt->pkt_ha_private;
3103 3103 ASSERT(icmdp != NULL);
3104 3104
3105 3105 mutex_enter(&icmdp->cmd_mutex);
3106 3106 icmdp->cmd_completed = B_TRUE;
3107 3107 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
3108 3108 cv_broadcast(&icmdp->cmd_completion);
3109 3109 mutex_exit(&icmdp->cmd_mutex);
3110 3110
3111 3111 }
3112 3112
3113 3113 /*
3114 3114 * IDM callbacks
3115 3115 */
3116 3116 void
3117 3117 iscsi_build_hdr(idm_task_t *idm_task, idm_pdu_t *pdu, uint8_t opcode)
3118 3118 {
3119 3119 iscsi_cmd_t *icmdp = idm_task->idt_private;
3120 3120 iscsi_conn_t *icp = icmdp->cmd_conn;
3121 3121 iscsi_data_hdr_t *ihp = (iscsi_data_hdr_t *)pdu->isp_hdr;
3122 3122
3123 3123 mutex_enter(&icmdp->cmd_mutex);
3124 3124 if (opcode == ISCSI_OP_SCSI_DATA) {
3125 3125 uint32_t data_sn;
3126 3126 uint32_t lun;
3127 3127 icmdp = idm_task->idt_private;
3128 3128 icp = icmdp->cmd_conn;
3129 3129 ihp->opcode = opcode;
3130 3130 ihp->itt = icmdp->cmd_itt;
3131 3131 ihp->ttt = idm_task->idt_r2t_ttt;
3132 3132 ihp->expstatsn = htonl(icp->conn_expstatsn);
3133 3133 icp->conn_laststatsn = icp->conn_expstatsn;
3134 3134 data_sn = ntohl(ihp->datasn);
3135 3135 data_sn++;
3136 3136 lun = icmdp->cmd_un.scsi.lun;
3137 3137 ISCSI_LUN_BYTE_COPY(ihp->lun, lun);
3138 3138 /* CRM: upate_flow_control */
3139 3139 ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_build_hdr"
3140 3140 "(ISCSI_OP_SCSI_DATA): task: %p icp: %p ic: %p itt: %x "
3141 3141 "exp: %d data_sn: %d", (void *)idm_task, (void *)icp,
3142 3142 (void *)icp->conn_ic, ihp->itt, icp->conn_expstatsn,
3143 3143 data_sn);
3144 3144 } else {
3145 3145 cmn_err(CE_WARN, "iscsi_build_hdr: unprocessed build "
3146 3146 "header opcode: %x", opcode);
3147 3147 }
3148 3148 mutex_exit(&icmdp->cmd_mutex);
3149 3149 }
3150 3150
3151 3151 static void
3152 3152 iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
3153 3153 idm_status_t status)
3154 3154 {
3155 3155 switch (status) {
3156 3156 case IDM_STATUS_SUCCESS:
3157 3157 if ((isp->sess_state == ISCSI_SESS_STATE_IN_FLUSH) &&
3158 3158 (icp->conn_queue_active.count == 0)) {
3159 3159 iscsi_drop_conn_cleanup(icp);
3160 3160 }
3161 3161 break;
3162 3162 case IDM_STATUS_PROTOCOL_ERROR:
3163 3163 KSTAT_INC_CONN_ERR_PROTOCOL(icp);
3164 3164 iscsi_drop_conn_cleanup(icp);
3165 3165 break;
3166 3166 default:
3167 3167 break;
3168 3168 }
3169 3169 }
3170 3170
3171 3171 static void
3172 3172 iscsi_drop_conn_cleanup(iscsi_conn_t *icp) {
3173 3173 mutex_enter(&icp->conn_state_mutex);
3174 3174 idm_ini_conn_disconnect(icp->conn_ic);
3175 3175 mutex_exit(&icp->conn_state_mutex);
3176 3176 }
3177 3177
3178 3178 void
3179 3179 iscsi_rx_error_pdu(idm_conn_t *ic, idm_pdu_t *pdu, idm_status_t status)
3180 3180 {
3181 3181 iscsi_conn_t *icp = (iscsi_conn_t *)ic->ic_handle;
3182 3182 iscsi_sess_t *isp;
3183 3183
3184 3184 ASSERT(icp != NULL);
3185 3185 isp = icp->conn_sess;
3186 3186 ASSERT(isp != NULL);
3187 3187 iscsi_process_rsp_status(isp, icp, status);
3188 3188 idm_pdu_complete(pdu, status);
3189 3189 }
3190 3190
3191 3191 void
3192 3192 iscsi_rx_misc_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
3193 3193 {
3194 3194 iscsi_conn_t *icp;
3195 3195 iscsi_hdr_t *ihp = (iscsi_hdr_t *)pdu->isp_hdr;
3196 3196 iscsi_sess_t *isp;
3197 3197 idm_status_t status;
3198 3198
3199 3199 icp = ic->ic_handle;
3200 3200 isp = icp->conn_sess;
3201 3201 isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
3202 3202 switch (ihp->opcode & ISCSI_OPCODE_MASK) {
3203 3203 case ISCSI_OP_LOGIN_RSP:
3204 3204 status = iscsi_rx_process_login_pdu(ic, pdu);
3205 3205 idm_pdu_complete(pdu, status);
3206 3206 break;
3207 3207 case ISCSI_OP_LOGOUT_RSP:
3208 3208 status = iscsi_rx_process_logout_rsp(ic, pdu);
3209 3209 idm_pdu_complete(pdu, status);
3210 3210 break;
3211 3211 case ISCSI_OP_REJECT_MSG:
3212 3212 status = iscsi_rx_process_reject_rsp(ic, pdu);
3213 3213 break;
3214 3214 case ISCSI_OP_SCSI_TASK_MGT_RSP:
3215 3215 status = iscsi_rx_process_task_mgt_rsp(ic, pdu);
3216 3216 idm_pdu_complete(pdu, status);
3217 3217 break;
3218 3218 case ISCSI_OP_NOOP_IN:
3219 3219 status = iscsi_rx_process_nop(ic, pdu);
3220 3220 idm_pdu_complete(pdu, status);
3221 3221 break;
3222 3222 case ISCSI_OP_ASYNC_EVENT:
3223 3223 status = iscsi_rx_process_async_rsp(ic, pdu);
3224 3224 break;
3225 3225 case ISCSI_OP_TEXT_RSP:
3226 3226 status = iscsi_rx_process_text_rsp(ic, pdu);
3227 3227 idm_pdu_complete(pdu, status);
3228 3228 break;
3229 3229 default:
3230 3230 cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
3231 3231 "- received misc unsupported opcode 0x%02x",
3232 3232 icp->conn_oid, ihp->opcode);
3233 3233 status = IDM_STATUS_PROTOCOL_ERROR;
3234 3234 break;
3235 3235 }
3236 3236 iscsi_process_rsp_status(isp, icp, status);
3237 3237 }
3238 3238
3239 3239 /*
3240 3240 * +--------------------------------------------------------------------+
3241 3241 * | Beginning of completion routines |
3242 3242 * +--------------------------------------------------------------------+
3243 3243 */
3244 3244
3245 3245 /*
3246 3246 * iscsi_ic_thread -
3247 3247 */
3248 3248 void
3249 3249 iscsi_ic_thread(iscsi_thread_t *thread, void *arg)
3250 3250 {
3251 3251 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
3252 3252 int ret;
3253 3253 iscsi_queue_t q;
3254 3254 iscsi_cmd_t *icmdp;
3255 3255 iscsi_cmd_t *next_icmdp;
3256 3256
3257 3257 ASSERT(isp != NULL);
3258 3258 ASSERT(thread != NULL);
3259 3259 ASSERT(thread->signature == SIG_ISCSI_THREAD);
3260 3260
3261 3261 for (;;) {
3262 3262
3263 3263 /*
3264 3264 * We wait till iodone or somebody else wakes us up.
3265 3265 */
3266 3266 ret = iscsi_thread_wait(thread, -1);
3267 3267
3268 3268 /*
3269 3269 * The value should never be negative since we never timeout.
3270 3270 */
3271 3271 ASSERT(ret >= 0);
3272 3272
3273 3273 q.count = 0;
3274 3274 q.head = NULL;
3275 3275 q.tail = NULL;
3276 3276 mutex_enter(&isp->sess_queue_completion.mutex);
3277 3277 icmdp = isp->sess_queue_completion.head;
3278 3278 while (icmdp != NULL) {
3279 3279 next_icmdp = icmdp->cmd_next;
3280 3280 mutex_enter(&icmdp->cmd_mutex);
3281 3281 /*
3282 3282 * check if the associated r2t/abort has finished
3283 3283 * yet. If not, don't complete the command.
3284 3284 */
3285 3285 if ((icmdp->cmd_un.scsi.r2t_icmdp == NULL) &&
3286 3286 (icmdp->cmd_un.scsi.abort_icmdp == NULL)) {
3287 3287 mutex_exit(&icmdp->cmd_mutex);
3288 3288 (void) iscsi_dequeue_cmd(&isp->
3289 3289 sess_queue_completion.head,
3290 3290 &isp->sess_queue_completion.tail,
3291 3291 icmdp);
3292 3292 --isp->sess_queue_completion.count;
3293 3293 iscsi_enqueue_cmd_head(&q.head,
3294 3294 &q.tail, icmdp);
3295 3295 } else {
3296 3296 mutex_exit(&icmdp->cmd_mutex);
3297 3297 }
3298 3298 icmdp = next_icmdp;
3299 3299 }
3300 3300 mutex_exit(&isp->sess_queue_completion.mutex);
3301 3301 icmdp = q.head;
3302 3302 while (icmdp != NULL) {
3303 3303 next_icmdp = icmdp->cmd_next;
3304 3304 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E8, isp);
3305 3305 icmdp = next_icmdp;
3306 3306 }
3307 3307
3308 3308 if (ret > 0)
3309 3309 /* Somebody woke us up to work */
3310 3310 continue;
3311 3311 else
3312 3312 /*
3313 3313 * Somebody woke us up to kill ourselves. We will
3314 3314 * make sure, however that the completion queue is
3315 3315 * empty before leaving. After we've done that it
3316 3316 * is the originator of the signal that has to make
3317 3317 * sure no other SCSI command is posted.
3318 3318 */
3319 3319 break;
3320 3320 }
3321 3321
3322 3322 }
3323 3323
3324 3324 /*
3325 3325 * iscsi_iodone -
3326 3326 *
3327 3327 */
3328 3328 void
3329 3329 iscsi_iodone(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
3330 3330 {
3331 3331 struct scsi_pkt *pkt = NULL;
3332 3332 struct buf *bp = icmdp->cmd_un.scsi.bp;
3333 3333
3334 3334 ASSERT(isp != NULL);
3335 3335 ASSERT(icmdp != NULL);
3336 3336 pkt = icmdp->cmd_un.scsi.pkt;
3337 3337 ASSERT(pkt != NULL);
3338 3338
3339 3339 ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
3340 3340 ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
3341 3341 if (pkt->pkt_reason == CMD_CMPLT) {
3342 3342 if (bp) {
3343 3343 if (bp->b_flags & B_READ) {
3344 3344 KSTAT_SESS_RX_IO_DONE(isp, bp->b_bcount);
3345 3345 } else {
3346 3346 KSTAT_SESS_TX_IO_DONE(isp, bp->b_bcount);
3347 3347 }
3348 3348 }
3349 3349 }
3350 3350
3351 3351 if (pkt->pkt_flags & FLAG_NOINTR) {
3352 3352 cv_broadcast(&icmdp->cmd_completion);
3353 3353 mutex_exit(&icmdp->cmd_mutex);
3354 3354 } else {
3355 3355 /*
3356 3356 * Release mutex. As soon as callback is
3357 3357 * issued the caller may destroy the command.
3358 3358 */
3359 3359 mutex_exit(&icmdp->cmd_mutex);
3360 3360 /*
3361 3361 * We can't just directly call the pk_comp routine. In
3362 3362 * many error cases the target driver will use the calling
3363 3363 * thread to re-drive error handling (reset, retries...)
3364 3364 * back into the hba driver (iscsi). If the target redrives
3365 3365 * a reset back into the iscsi driver off this thead we have
3366 3366 * a chance of deadlocking. So instead use the io completion
3367 3367 * thread.
3368 3368 */
3369 3369 (*icmdp->cmd_un.scsi.pkt->pkt_comp)(icmdp->cmd_un.scsi.pkt);
3370 3370 }
3371 3371 }
3372 3372
3373 3373 /*
3374 3374 * +--------------------------------------------------------------------+
3375 3375 * | End of completion routines |
3376 3376 * +--------------------------------------------------------------------+
3377 3377 */
3378 3378
3379 3379 /*
3380 3380 * +--------------------------------------------------------------------+
3381 3381 * | Beginning of watchdog routines |
3382 3382 * +--------------------------------------------------------------------+
3383 3383 */
3384 3384
3385 3385 /*
3386 3386 * iscsi_watchdog_thread -
3387 3387 *
3388 3388 */
3389 3389 void
3390 3390 iscsi_wd_thread(iscsi_thread_t *thread, void *arg)
3391 3391 {
3392 3392 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
3393 3393 int rc = 1;
3394 3394
3395 3395 ASSERT(isp != NULL);
3396 3396
3397 3397 while (rc != NULL) {
3398 3398
3399 3399 iscsi_timeout_checks(isp);
3400 3400 iscsi_nop_checks(isp);
3401 3401
3402 3402 rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
3403 3403 }
3404 3404 }
3405 3405
3406 3406 /*
3407 3407 * iscsi_timeout_checks -
3408 3408 *
3409 3409 */
3410 3410 static void
3411 3411 iscsi_timeout_checks(iscsi_sess_t *isp)
3412 3412 {
3413 3413 clock_t now = ddi_get_lbolt();
3414 3414 iscsi_conn_t *icp;
3415 3415 iscsi_cmd_t *icmdp, *nicmdp;
3416 3416
3417 3417 ASSERT(isp != NULL);
3418 3418
3419 3419 /* PENDING */
3420 3420 rw_enter(&isp->sess_state_rwlock, RW_READER);
3421 3421 mutex_enter(&isp->sess_queue_pending.mutex);
3422 3422 for (icmdp = isp->sess_queue_pending.head;
3423 3423 icmdp; icmdp = nicmdp) {
3424 3424 nicmdp = icmdp->cmd_next;
3425 3425
3426 3426 /* Skip entries with no timeout */
3427 3427 if (icmdp->cmd_lbolt_timeout == 0)
3428 3428 continue;
3429 3429
3430 3430 /*
3431 3431 * Skip pending queue entries for cmd_type values that depend
3432 3432 * on having an open cmdsn window for successfull transition
3433 3433 * from pending to the active (i.e. ones that depend on
3434 3434 * sess_cmdsn .vs. sess_maxcmdsn). For them, the timer starts
3435 3435 * when they are successfully moved to the active queue by
3436 3436 * iscsi_cmd_state_pending() code.
3437 3437 */
3438 3438 /*
3439 3439 * If the cmd is stuck, at least give it a chance
3440 3440 * to timeout
3441 3441 */
3442 3442 if (((icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) ||
3443 3443 (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT)) &&
3444 3444 !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_STUCK))
3445 3445 continue;
3446 3446
3447 3447 /* Skip if timeout still in the future */
3448 3448 if (now <= icmdp->cmd_lbolt_timeout)
3449 3449 continue;
3450 3450
3451 3451 /* timeout */
3452 3452 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E6, isp);
3453 3453 }
3454 3454 mutex_exit(&isp->sess_queue_pending.mutex);
3455 3455 rw_exit(&isp->sess_state_rwlock);
3456 3456
3457 3457 rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3458 3458 icp = isp->sess_conn_list;
3459 3459 while (icp != NULL) {
3460 3460
3461 3461 icp->conn_timeout = B_FALSE;
3462 3462 /* ACTIVE */
3463 3463 mutex_enter(&icp->conn_state_mutex);
3464 3464 mutex_enter(&isp->sess_queue_pending.mutex);
3465 3465 mutex_enter(&icp->conn_queue_active.mutex);
3466 3466 for (icmdp = icp->conn_queue_active.head;
3467 3467 icmdp; icmdp = nicmdp) {
3468 3468 nicmdp = icmdp->cmd_next;
3469 3469
3470 3470 if (iscsi_nop_timeout_checks(icmdp) == B_TRUE) {
3471 3471 icp->conn_timeout = B_TRUE;
3472 3472 }
3473 3473
3474 3474 /* Skip entries with no timeout */
3475 3475 if (icmdp->cmd_lbolt_timeout == 0)
3476 3476 continue;
3477 3477
3478 3478 /*
3479 3479 * Skip if command is not active or not needed
3480 3480 * to flush.
3481 3481 */
3482 3482 if (icmdp->cmd_state != ISCSI_CMD_STATE_ACTIVE &&
3483 3483 !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH))
3484 3484 continue;
3485 3485
3486 3486 /* Skip if timeout still in the future */
3487 3487 if (now <= icmdp->cmd_lbolt_timeout)
3488 3488 continue;
3489 3489
3490 3490 if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH) {
3491 3491 /*
3492 3492 * This command is left during target reset,
3493 3493 * we can flush it now.
3494 3494 */
3495 3495 iscsi_cmd_state_machine(icmdp,
3496 3496 ISCSI_CMD_EVENT_E7, isp);
3497 3497 } else if (icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE) {
3498 3498 /* timeout */
3499 3499 iscsi_cmd_state_machine(icmdp,
3500 3500 ISCSI_CMD_EVENT_E6, isp);
3501 3501 }
3502 3502
|
↓ open down ↓ |
3468 lines elided |
↑ open up ↑ |
3503 3503 }
3504 3504 mutex_exit(&icp->conn_queue_active.mutex);
3505 3505 mutex_exit(&isp->sess_queue_pending.mutex);
3506 3506 mutex_exit(&icp->conn_state_mutex);
3507 3507
3508 3508 icp = icp->conn_next;
3509 3509 }
3510 3510
3511 3511 icp = isp->sess_conn_list;
3512 3512 while (icp != NULL) {
3513 - if (icp->conn_timeout == B_TRUE) {
3513 + mutex_enter(&icp->conn_state_mutex);
3514 + if ((icp->conn_timeout == B_TRUE) &&
3515 + (icp->conn_state_idm_connected == B_TRUE)) {
3514 3516 /* timeout on this connect detected */
3515 3517 idm_ini_conn_disconnect(icp->conn_ic);
3516 3518 icp->conn_timeout = B_FALSE;
3517 3519 }
3520 + mutex_exit(&icp->conn_state_mutex);
3518 3521 icp = icp->conn_next;
3519 3522 }
3520 3523 rw_exit(&isp->sess_conn_list_rwlock);
3521 3524 }
3522 3525
3523 3526 /*
3524 3527 * iscsi_nop_checks - sends a NOP on idle connections
3525 3528 *
3526 3529 * This function walks the connections on a session and
3527 3530 * issues NOPs on those connections that are in FULL
3528 3531 * FEATURE mode and have not received data for the
3529 3532 * time period specified by iscsi_nop_delay (global).
3530 3533 */
3531 3534 static void
3532 3535 iscsi_nop_checks(iscsi_sess_t *isp)
3533 3536 {
3534 3537 iscsi_conn_t *icp;
3535 3538
3536 3539 ASSERT(isp != NULL);
3537 3540
3538 3541 if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) {
3539 3542 return;
3540 3543 }
3541 3544
3542 3545 rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3543 3546 icp = isp->sess_conn_act;
3544 3547 if (icp != NULL) {
3545 3548
3546 3549 mutex_enter(&icp->conn_state_mutex);
3547 3550 if ((ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state)) &&
3548 3551 (ddi_get_lbolt() > isp->sess_conn_act->conn_rx_lbolt +
3549 3552 SEC_TO_TICK(iscsi_nop_delay)) && (ddi_get_lbolt() >
3550 3553 isp->sess_conn_act->conn_nop_lbolt +
3551 3554 SEC_TO_TICK(iscsi_nop_delay))) {
3552 3555
3553 3556 /*
3554 3557 * We haven't received anything from the
3555 3558 * target is a defined period of time,
3556 3559 * send NOP to see if the target is alive.
3557 3560 */
3558 3561 mutex_enter(&isp->sess_queue_pending.mutex);
3559 3562 iscsi_handle_nop(isp->sess_conn_act,
3560 3563 0, ISCSI_RSVD_TASK_TAG);
3561 3564 mutex_exit(&isp->sess_queue_pending.mutex);
3562 3565 }
3563 3566 mutex_exit(&icp->conn_state_mutex);
3564 3567
3565 3568 icp = icp->conn_next;
3566 3569 }
3567 3570 rw_exit(&isp->sess_conn_list_rwlock);
3568 3571 }
3569 3572
3570 3573 static boolean_t
3571 3574 iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp)
3572 3575 {
3573 3576 if (icmdp->cmd_type == ISCSI_CMD_TYPE_NOP) {
3574 3577 if ((ddi_get_lbolt() - icmdp->cmd_lbolt_active) >
3575 3578 SEC_TO_TICK(ISCSI_CONN_TIEMOUT_DETECT)) {
3576 3579 return (B_TRUE);
3577 3580 } else {
3578 3581 return (B_FALSE);
3579 3582 }
3580 3583 }
3581 3584 return (B_FALSE);
3582 3585 }
3583 3586 /*
3584 3587 * +--------------------------------------------------------------------+
3585 3588 * | End of wd routines |
3586 3589 * +--------------------------------------------------------------------+
3587 3590 */
3588 3591
3589 3592 /*
3590 3593 * iscsi_flush_cmd_after_reset - flush commands after reset
3591 3594 *
3592 3595 * Here we will flush all the commands for a specified LUN whose cmdsn is less
3593 3596 * than the one received with the Unit Attention.
3594 3597 */
3595 3598 static void
3596 3599 iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
3597 3600 iscsi_conn_t *icp)
3598 3601 {
3599 3602 iscsi_cmd_t *t_icmdp = NULL;
3600 3603 iscsi_cmd_t *next_icmdp = NULL;
3601 3604
3602 3605 ASSERT(icp != NULL);
3603 3606
3604 3607 t_icmdp = icp->conn_queue_active.head;
3605 3608 while (t_icmdp != NULL) {
3606 3609 next_icmdp = t_icmdp->cmd_next;
3607 3610 mutex_enter(&t_icmdp->cmd_mutex);
3608 3611 /*
3609 3612 * We will flush the commands whose cmdsn is less than the one
3610 3613 * got Unit Attention.
3611 3614 * Here we will check for wrap by subtracting and compare to
3612 3615 * 1/2 of a 32 bit number, if greater then we wrapped.
3613 3616 */
3614 3617 if ((t_icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_SENT) &&
3615 3618 ((cmd_sn > t_icmdp->cmd_sn) ||
3616 3619 ((t_icmdp->cmd_sn - cmd_sn) >
3617 3620 ISCSI_CMD_SN_WRAP))) {
3618 3621 /*
3619 3622 * Internally generated SCSI commands do not have
3620 3623 * t_icmdp->cmd_lun set, but the LUN can be retrieved
3621 3624 * from t_icmdp->cmd_un.scsi.lun.
3622 3625 */
3623 3626 if ((t_icmdp->cmd_lun != NULL &&
3624 3627 t_icmdp->cmd_lun->lun_num == lun_num) ||
3625 3628 (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI &&
3626 3629 (t_icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK) ==
3627 3630 lun_num)) {
3628 3631 t_icmdp->cmd_misc_flags |=
3629 3632 ISCSI_CMD_MISCFLAG_FLUSH;
3630 3633 if (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
3631 3634 t_icmdp->cmd_un.scsi.pkt_stat |=
3632 3635 STAT_BUS_RESET;
3633 3636 }
3634 3637 }
3635 3638 }
3636 3639 mutex_exit(&t_icmdp->cmd_mutex);
3637 3640 t_icmdp = next_icmdp;
3638 3641 }
3639 3642 }
3640 3643
3641 3644 /*
3642 3645 * iscsi_decode_sense - decode the sense data in the cmd response
3643 3646 * and take proper actions
3644 3647 */
3645 3648 static boolean_t
3646 3649 iscsi_decode_sense(uint8_t *sense_data, iscsi_cmd_t *icmdp)
3647 3650 {
3648 3651 uint8_t sense_key = 0;
3649 3652 uint8_t asc = 0;
3650 3653 uint8_t ascq = 0;
3651 3654 boolean_t flush_io = B_FALSE;
3652 3655 boolean_t reconfig_lun = B_FALSE;
3653 3656 iscsi_sess_t *isp = NULL;
3654 3657
3655 3658 ASSERT(sense_data != NULL);
3656 3659
3657 3660 isp = icmdp->cmd_conn->conn_sess;
3658 3661
3659 3662 sense_key = scsi_sense_key(sense_data);
3660 3663 switch (sense_key) {
3661 3664 case KEY_UNIT_ATTENTION:
3662 3665 asc = scsi_sense_asc(sense_data);
3663 3666 switch (asc) {
3664 3667 case ISCSI_SCSI_RESET_SENSE_CODE:
3665 3668 /*
3666 3669 * POWER ON, RESET, OR BUS_DEVICE RESET
3667 3670 * OCCURRED
3668 3671 */
3669 3672 flush_io = B_TRUE;
3670 3673 break;
3671 3674 case ISCSI_SCSI_LUNCHANGED_CODE:
3672 3675 ascq = scsi_sense_ascq(sense_data);
3673 3676 if (ascq == ISCSI_SCSI_LUNCHANGED_ASCQ)
3674 3677 reconfig_lun = B_TRUE;
3675 3678 default:
3676 3679 break;
3677 3680 }
3678 3681 break;
3679 3682 default:
3680 3683 /*
3681 3684 * Currently we don't care
3682 3685 * about other sense key.
3683 3686 */
3684 3687 break;
3685 3688 }
3686 3689
3687 3690 if (reconfig_lun == B_TRUE) {
3688 3691 rw_enter(&isp->sess_state_rwlock, RW_READER);
3689 3692 if ((isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN) &&
3690 3693 (iscsi_sess_enum_request(isp, B_FALSE,
3691 3694 isp->sess_state_event_count) !=
3692 3695 ISCSI_SESS_ENUM_SUBMITTED)) {
3693 3696 cmn_err(CE_WARN, "Unable to commit re-enumeration for"
3694 3697 " session(%u) %s", isp->sess_oid, isp->sess_name);
3695 3698 }
3696 3699 rw_exit(&isp->sess_state_rwlock);
3697 3700 }
3698 3701
3699 3702 return (flush_io);
3700 3703 }
|
↓ open down ↓ |
173 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX