1 /*-
2  * Copyright (c) 2017 Broadcom. All rights reserved.
3  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions and the following disclaimer in the documentation
13  *    and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD: stable/12/sys/dev/ocs_fc/ocs_scsi.c 371383 2021-12-24 09:03:50Z ram $
32  */
33 
34 /**
35  * @file
36  * OCS Linux SCSI API base driver implementation.
37  */
38 
39 /**
40  * @defgroup scsi_api_base SCSI Base Target/Initiator
41  */
42 
43 
44 #include "ocs.h"
45 #include "ocs_els.h"
46 #include "ocs_scsi.h"
47 #include "ocs_vpd.h"
48 #include "ocs_utils.h"
49 #include "ocs_device.h"
50 
51 #define SCSI_IOFMT "[%04x][i:%0*x t:%0*x h:%04x]"
52 #define SCSI_ITT_SIZE(ocs)	((ocs->ocs_xport == OCS_XPORT_FC) ? 4 : 8)
53 
54 #define SCSI_IOFMT_ARGS(io) io->instance_index, SCSI_ITT_SIZE(io->ocs), io->init_task_tag, SCSI_ITT_SIZE(io->ocs), io->tgt_task_tag, io->hw_tag
55 
56 #define enable_tsend_auto_resp(ocs)		((ocs->ctrlmask & OCS_CTRLMASK_XPORT_DISABLE_AUTORSP_TSEND) == 0)
57 #define enable_treceive_auto_resp(ocs)	((ocs->ctrlmask & OCS_CTRLMASK_XPORT_DISABLE_AUTORSP_TRECEIVE) == 0)
58 
59 #define scsi_io_printf(io, fmt, ...) ocs_log_info(io->ocs, "[%s]" SCSI_IOFMT fmt, \
60 	io->node->display_name, SCSI_IOFMT_ARGS(io), ##__VA_ARGS__)
61 
62 #define scsi_io_trace(io, fmt, ...) \
63 	do { \
64 		if (OCS_LOG_ENABLE_SCSI_TRACE(io->ocs)) \
65 			scsi_io_printf(io, fmt, ##__VA_ARGS__); \
66 	} while (0)
67 
68 #define scsi_log(ocs, fmt, ...) \
69 	do { \
70 		if (OCS_LOG_ENABLE_SCSI_TRACE(ocs)) \
71 			ocs_log_info(ocs, fmt, ##__VA_ARGS__); \
72 	} while (0)
73 
74 static int32_t ocs_target_send_bls_resp(ocs_io_t *io, ocs_scsi_io_cb_t cb, void *arg);
75 static int32_t ocs_scsi_abort_io_cb(struct ocs_hw_io_s *hio, ocs_remote_node_t *rnode, uint32_t len, int32_t status,
76 	uint32_t ext, void *arg);
77 
78 static void ocs_scsi_io_free_ovfl(ocs_io_t *io);
79 static uint32_t ocs_scsi_count_sgls(ocs_hw_dif_info_t *hw_dif, ocs_scsi_sgl_t *sgl, uint32_t sgl_count);
80 static int ocs_scsi_dif_guard_is_crc(uint8_t direction, ocs_hw_dif_info_t *dif_info);
81 static ocs_scsi_io_status_e ocs_scsi_dif_check_unknown(ocs_io_t *io, uint32_t length, uint32_t check_length, int is_crc);
82 static uint32_t ocs_scsi_dif_check_guard(ocs_hw_dif_info_t *dif_info, ocs_scsi_vaddr_len_t addrlen[],
83 	uint32_t addrlen_count, ocs_dif_t *dif, int is_crc);
84 static uint32_t ocs_scsi_dif_check_app_tag(ocs_t *ocs, ocs_hw_dif_info_t *dif_info, uint16_t exp_app_tag, ocs_dif_t *dif);
85 static uint32_t ocs_scsi_dif_check_ref_tag(ocs_t *ocs, ocs_hw_dif_info_t *dif_info, uint32_t exp_ref_tag, ocs_dif_t *dif);
86 static int32_t ocs_scsi_convert_dif_info(ocs_t *ocs, ocs_scsi_dif_info_t *scsi_dif_info,
87 	ocs_hw_dif_info_t *hw_dif_info);
88 static int32_t ocs_scsi_io_dispatch_hw_io(ocs_io_t *io, ocs_hw_io_t *hio);
89 static int32_t ocs_scsi_io_dispatch_no_hw_io(ocs_io_t *io);
90 static void _ocs_scsi_io_free(void *arg);
91 
92 
93 /**
94  * @ingroup scsi_api_base
95  * @brief Returns a big-endian 32-bit value given a pointer.
96  *
97  * @param p Pointer to the 32-bit big-endian location.
98  *
99  * @return Returns the byte-swapped 32-bit value.
100  */
101 
102 static inline uint32_t
ocs_fc_getbe32(void * p)103 ocs_fc_getbe32(void *p)
104 {
105 	return ocs_be32toh(*((uint32_t*)p));
106 }
107 
108 /**
109  * @ingroup scsi_api_base
110  * @brief Enable IO allocation.
111  *
112  * @par Description
113  * The SCSI and Transport IO allocation functions are enabled. If the allocation functions
114  * are not enabled, then calls to ocs_scsi_io_alloc() (and ocs_els_io_alloc() for FC) will
115  * fail.
116  *
117  * @param node Pointer to node object.
118  *
119  * @return None.
120  */
121 void
ocs_scsi_io_alloc_enable(ocs_node_t * node)122 ocs_scsi_io_alloc_enable(ocs_node_t *node)
123 {
124 	ocs_assert(node != NULL);
125 	ocs_lock(&node->active_ios_lock);
126 		node->io_alloc_enabled = TRUE;
127 	ocs_unlock(&node->active_ios_lock);
128 }
129 
130 /**
131  * @ingroup scsi_api_base
132  * @brief Disable IO allocation
133  *
134  * @par Description
135  * The SCSI and Transport IO allocation functions are disabled. If the allocation functions
136  * are not enabled, then calls to ocs_scsi_io_alloc() (and ocs_els_io_alloc() for FC) will
137  * fail.
138  *
139  * @param node Pointer to node object
140  *
141  * @return None.
142  */
143 void
ocs_scsi_io_alloc_disable(ocs_node_t * node)144 ocs_scsi_io_alloc_disable(ocs_node_t *node)
145 {
146 	ocs_assert(node != NULL);
147 	ocs_lock(&node->active_ios_lock);
148 		node->io_alloc_enabled = FALSE;
149 	ocs_unlock(&node->active_ios_lock);
150 }
151 
152 /**
153  * @ingroup scsi_api_base
154  * @brief Allocate a SCSI IO context.
155  *
156  * @par Description
157  * A SCSI IO context is allocated and associated with a @c node. This function
158  * is called by an initiator-client when issuing SCSI commands to remote
159  * target devices. On completion, ocs_scsi_io_free() is called.
160  * @n @n
161  * The returned ocs_io_t structure has an element of type ocs_scsi_ini_io_t named
162  * "ini_io" that is declared and used by an initiator-client for private information.
163  *
164  * @param node Pointer to the associated node structure.
165  * @param role Role for IO (originator/responder).
166  *
167  * @return Returns the pointer to the IO context, or NULL.
168  *
169  */
170 
171 ocs_io_t *
ocs_scsi_io_alloc(ocs_node_t * node,ocs_scsi_io_role_e role)172 ocs_scsi_io_alloc(ocs_node_t *node, ocs_scsi_io_role_e role)
173 {
174 	ocs_t *ocs;
175 	ocs_xport_t *xport;
176 	ocs_io_t *io;
177 
178 	ocs_assert(node, NULL);
179 	ocs_assert(node->ocs, NULL);
180 
181 	ocs = node->ocs;
182 	ocs_assert(ocs->xport, NULL);
183 	xport = ocs->xport;
184 
185 	ocs_lock(&node->active_ios_lock);
186 
187 		if (!node->io_alloc_enabled) {
188 			ocs_unlock(&node->active_ios_lock);
189 			return NULL;
190 		}
191 
192 		io = ocs_io_alloc(ocs);
193 		if (io == NULL) {
194 			ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
195 			ocs_unlock(&node->active_ios_lock);
196 			return NULL;
197 		}
198 
199 		/* initialize refcount */
200 		ocs_ref_init(&io->ref, _ocs_scsi_io_free, io);
201 
202 		if (io->hio != NULL) {
203 			ocs_log_err(node->ocs, "assertion failed: io->hio is not NULL\n");
204 			ocs_io_free(ocs, io);
205 			ocs_unlock(&node->active_ios_lock);
206 			return NULL;
207 		}
208 
209 		/* set generic fields */
210 		io->ocs = ocs;
211 		io->node = node;
212 
213 		/* set type and name */
214 		io->io_type = OCS_IO_TYPE_IO;
215 		io->display_name = "scsi_io";
216 
217 		switch (role) {
218 		case OCS_SCSI_IO_ROLE_ORIGINATOR:
219 			io->cmd_ini = TRUE;
220 			io->cmd_tgt = FALSE;
221 			break;
222 		case OCS_SCSI_IO_ROLE_RESPONDER:
223 			io->cmd_ini = FALSE;
224 			io->cmd_tgt = TRUE;
225 			break;
226 		}
227 
228 		/* Add to node's active_ios list */
229 		ocs_list_add_tail(&node->active_ios, io);
230 
231 	ocs_unlock(&node->active_ios_lock);
232 
233 	return io;
234 }
235 
236 /**
237  * @ingroup scsi_api_base
238  * @brief Free a SCSI IO context (internal).
239  *
240  * @par Description
241  * The IO context previously allocated using ocs_scsi_io_alloc()
242  * is freed. This is called from within the transport layer,
243  * when the reference count goes to zero.
244  *
245  * @param arg Pointer to the IO context.
246  *
247  * @return None.
248  */
249 static void
_ocs_scsi_io_free(void * arg)250 _ocs_scsi_io_free(void *arg)
251 {
252 	ocs_io_t *io = (ocs_io_t *)arg;
253 	ocs_t *ocs = io->ocs;
254 	ocs_node_t *node = io->node;
255 	int send_empty_event;
256 
257 	ocs_assert(io != NULL);
258 
259 	scsi_io_trace(io, "freeing io 0x%p %s\n", io, io->display_name);
260 
261 	ocs_assert(ocs_io_busy(io));
262 
263 	ocs_lock(&node->active_ios_lock);
264 		ocs_list_remove(&node->active_ios, io);
265 		send_empty_event = (!node->io_alloc_enabled) && ocs_list_empty(&node->active_ios);
266 	ocs_unlock(&node->active_ios_lock);
267 
268 	if (send_empty_event) {
269 		ocs_node_post_event(node, OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY, NULL);
270 	}
271 
272 	io->node = NULL;
273 	ocs_io_free(ocs, io);
274 
275 }
276 
277 /**
278  * @ingroup scsi_api_base
279  * @brief Free a SCSI IO context.
280  *
281  * @par Description
282  * The IO context previously allocated using ocs_scsi_io_alloc() is freed.
283  *
284  * @param io Pointer to the IO context.
285  *
286  * @return None.
287  */
288 void
ocs_scsi_io_free(ocs_io_t * io)289 ocs_scsi_io_free(ocs_io_t *io)
290 {
291 	scsi_io_trace(io, "freeing io 0x%p %s\n", io, io->display_name);
292 	ocs_assert(ocs_ref_read_count(&io->ref) > 0);
293 	ocs_ref_put(&io->ref); /* ocs_ref_get(): ocs_scsi_io_alloc() */
294 }
295 
296 
297 
298 static int32_t
299 ocs_scsi_send_io(ocs_hw_io_type_e type, ocs_node_t *node, ocs_io_t *io, uint64_t lun,
300 	ocs_scsi_tmf_cmd_e tmf, uint8_t *cdb, uint32_t cdb_len,
301 	ocs_scsi_dif_info_t *dif_info,
302 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst,
303 	ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags);
304 
305 /**
306  * @brief Target response completion callback.
307  *
308  * @par Description
309  * Function is called upon the completion of a target IO request.
310  *
311  * @param hio Pointer to the HW IO structure.
312  * @param rnode Remote node associated with the IO that is completing.
313  * @param length Length of the response payload.
314  * @param status Completion status.
315  * @param ext_status Extended completion status.
316  * @param app Application-specific data (generally a pointer to the IO context).
317  *
318  * @return None.
319  */
320 
321 static void
ocs_target_io_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * app)322 ocs_target_io_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length,
323 	int32_t status, uint32_t ext_status, void *app)
324 {
325 	ocs_io_t *io = app;
326 	ocs_t *ocs;
327 	ocs_scsi_io_status_e scsi_status = OCS_SCSI_STATUS_GOOD;
328 	uint16_t additional_length;
329 	uint8_t edir;
330 	uint8_t tdpv;
331 	ocs_hw_dif_info_t *dif_info = &io->hw_dif;
332 	int is_crc;
333 
334 	ocs_assert(io);
335 
336 	scsi_io_trace(io, "status x%x ext_status x%x\n", status, ext_status);
337 
338 	ocs = io->ocs;
339 	ocs_assert(ocs);
340 
341 	ocs_scsi_io_free_ovfl(io);
342 
343 	io->transferred += length;
344 
345 	/* Call target server completion */
346 	if (io->scsi_tgt_cb) {
347 		ocs_scsi_io_cb_t cb = io->scsi_tgt_cb;
348 		uint32_t flags = 0;
349 
350 		/* Clear the callback before invoking the callback */
351 		io->scsi_tgt_cb = NULL;
352 
353 		/* if status was good, and auto-good-response was set, then callback
354 		 * target-server with IO_CMPL_RSP_SENT, otherwise send IO_CMPL
355 		 */
356 		if ((status == 0) && (io->auto_resp))
357 			flags |= OCS_SCSI_IO_CMPL_RSP_SENT;
358 		else
359 			flags |= OCS_SCSI_IO_CMPL;
360 
361 		switch (status) {
362 		case SLI4_FC_WCQE_STATUS_SUCCESS:
363 			scsi_status = OCS_SCSI_STATUS_GOOD;
364 			break;
365 		case SLI4_FC_WCQE_STATUS_DI_ERROR:
366 			if (ext_status & SLI4_FC_DI_ERROR_GE) {
367 				scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR;
368 			} else if (ext_status & SLI4_FC_DI_ERROR_AE) {
369 				scsi_status = OCS_SCSI_STATUS_DIF_APP_TAG_ERROR;
370 			} else if (ext_status & SLI4_FC_DI_ERROR_RE) {
371 				scsi_status = OCS_SCSI_STATUS_DIF_REF_TAG_ERROR;
372 			} else {
373 				additional_length = ((ext_status >> 16) & 0xFFFF);
374 
375 				/* Capture the EDIR and TDPV bits as 0 or 1 for easier printing. */
376 				edir = !!(ext_status & SLI4_FC_DI_ERROR_EDIR);
377 				tdpv = !!(ext_status & SLI4_FC_DI_ERROR_TDPV);
378 
379 				is_crc = ocs_scsi_dif_guard_is_crc(edir, dif_info);
380 
381 				if (edir == 0) {
382 					/* For reads, we have everything in memory.  Start checking from beginning. */
383 					scsi_status = ocs_scsi_dif_check_unknown(io, 0, io->wire_len, is_crc);
384 				} else {
385 					/* For writes, use the additional length to determine where to look for the error.
386 					 * The additional_length field is set to 0 if it is not supported.
387 					 * The additional length field is valid if:
388 					 *    . additional_length is not zero
389 					 *    . Total Data Placed is valid
390 					 *    . Error Direction is RX (1)
391 					 *    . Operation is a pass thru (CRC or CKSUM on IN, and CRC or CHKSUM on OUT) (all pass-thru cases except raw)
392 					 */
393 					if ((additional_length != 0) && (tdpv != 0) &&
394 					    (dif_info->dif == SLI4_DIF_PASS_THROUGH) && (dif_info->dif_oper != OCS_HW_SGE_DIF_OP_IN_RAW_OUT_RAW) ) {
395 						scsi_status = ocs_scsi_dif_check_unknown(io, length, additional_length, is_crc);
396 					} else {
397 						/* If we can't do additional checking, then fall-back to guard error */
398 						scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR;
399 					}
400 				}
401 			}
402 			break;
403 		case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
404 			switch (ext_status) {
405 			case SLI4_FC_LOCAL_REJECT_INVALID_RELOFFSET:
406 			case SLI4_FC_LOCAL_REJECT_ABORT_REQUESTED:
407 				scsi_status = OCS_SCSI_STATUS_ABORTED;
408 				break;
409 			case SLI4_FC_LOCAL_REJECT_INVALID_RPI:
410 				scsi_status = OCS_SCSI_STATUS_NEXUS_LOST;
411 				break;
412 			case SLI4_FC_LOCAL_REJECT_NO_XRI:
413 				scsi_status = OCS_SCSI_STATUS_NO_IO;
414 				break;
415 			default:
416 				/* TODO: we have seen 0x0d (TX_DMA_FAILED error) */
417 				scsi_status = OCS_SCSI_STATUS_ERROR;
418 				break;
419 			}
420 			break;
421 
422 		case SLI4_FC_WCQE_STATUS_TARGET_WQE_TIMEOUT:
423 			/* target IO timed out */
424 			scsi_status = OCS_SCSI_STATUS_TIMEDOUT_AND_ABORTED;
425 			break;
426 
427 		case SLI4_FC_WCQE_STATUS_SHUTDOWN:
428 			/* Target IO cancelled by HW */
429 			scsi_status = OCS_SCSI_STATUS_SHUTDOWN;
430 			break;
431 
432 		default:
433 			scsi_status = OCS_SCSI_STATUS_ERROR;
434 			break;
435 		}
436 
437 		cb(io, scsi_status, flags, io->scsi_tgt_cb_arg);
438 
439 	}
440 	ocs_scsi_check_pending(ocs);
441 }
442 
443 /**
444  * @brief Determine if an IO is using CRC for DIF guard format.
445  *
446  * @param direction IO direction: 1 for write, 0 for read.
447  * @param dif_info Pointer to HW DIF info data.
448  *
449  * @return Returns TRUE if using CRC, FALSE if not.
450  */
451 static int
ocs_scsi_dif_guard_is_crc(uint8_t direction,ocs_hw_dif_info_t * dif_info)452 ocs_scsi_dif_guard_is_crc(uint8_t direction, ocs_hw_dif_info_t *dif_info)
453 {
454 	int is_crc;
455 
456 	if (direction) {
457 		/* For writes, check if operation is "OUT_CRC" or not */
458 		switch(dif_info->dif_oper) {
459 			case OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CRC:
460 			case OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC:
461 			case OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CRC:
462 				is_crc = TRUE;
463 				break;
464 			default:
465 				is_crc = FALSE;
466 				break;
467 		}
468 	} else {
469 		/* For reads, check if operation is "IN_CRC" or not */
470 		switch(dif_info->dif_oper) {
471 			case OCS_HW_SGE_DIF_OP_IN_CRC_OUT_NODIF:
472 			case OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC:
473 			case OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CHKSUM:
474 				is_crc = TRUE;
475 				break;
476 			default:
477 				is_crc = FALSE;
478 				break;
479 		}
480 	}
481 
482 	return is_crc;
483 }
484 
485 /**
486  * @brief Check a block and DIF data, computing the appropriate SCSI status
487  *
488  * @par Description
489  * This function is used to check blocks and DIF when given an unknown DIF
490  * status using the following logic:
491  *
492  * Given the address of the last good block, and a length of bytes that includes
493  * the block with the DIF error, find the bad block. If a block is found with an
494  * app_tag or ref_tag error, then return the appropriate error. No block is expected
495  * to have a block guard error since hardware "fixes" the crc. So if no block in the
496  * range of blocks has an error, then it is presumed to be a BLOCK GUARD error.
497  *
498  * @param io Pointer to the IO object.
499  * @param length Length of bytes covering the good blocks.
500  * @param check_length Length of bytes that covers the bad block.
501  * @param is_crc True if guard is using CRC format.
502  *
503  * @return Returns SCSI status.
504  */
505 
506 static ocs_scsi_io_status_e
ocs_scsi_dif_check_unknown(ocs_io_t * io,uint32_t length,uint32_t check_length,int is_crc)507 ocs_scsi_dif_check_unknown(ocs_io_t *io, uint32_t length, uint32_t check_length, int is_crc)
508 {
509 	uint32_t i;
510 	ocs_t *ocs = io->ocs;
511 	ocs_hw_dif_info_t *dif_info = &io->hw_dif;
512 	ocs_scsi_io_status_e scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR;
513 	uint32_t blocksize;			/* data block size */
514 	uint64_t first_check_block;		/* first block following total data placed */
515 	uint64_t last_check_block;		/* last block to check */
516 	uint32_t check_count;			/* count of blocks to check */
517 	ocs_scsi_vaddr_len_t addrlen[4];	/* address-length pairs returned from target */
518 	int32_t addrlen_count;			/* count of address-length pairs */
519 	ocs_dif_t *dif;				/* pointer to DIF block returned from target */
520 	ocs_scsi_dif_info_t scsi_dif_info = io->scsi_dif_info;
521 
522 	blocksize = ocs_hw_dif_mem_blocksize(&io->hw_dif, TRUE);
523 	first_check_block = length / blocksize;
524 	last_check_block = ((length + check_length) / blocksize);
525 	check_count = last_check_block - first_check_block;
526 
527 	ocs_log_debug(ocs, "blocksize %d first check_block %" PRId64 " last_check_block %" PRId64 " check_count %d\n",
528 		blocksize, first_check_block, last_check_block, check_count);
529 
530 	for (i = first_check_block; i < last_check_block; i++) {
531 		addrlen_count = ocs_scsi_get_block_vaddr(io, (scsi_dif_info.lba + i), addrlen, ARRAY_SIZE(addrlen), (void**) &dif);
532 		if (addrlen_count < 0) {
533 			ocs_log_test(ocs, "ocs_scsi_get_block_vaddr() failed: %d\n", addrlen_count);
534 			scsi_status = OCS_SCSI_STATUS_DIF_UNKNOWN_ERROR;
535 			break;
536 		}
537 
538 		if (! ocs_scsi_dif_check_guard(dif_info, addrlen, addrlen_count, dif, is_crc)) {
539 			ocs_log_debug(ocs, "block guard check error, lba %" PRId64 "\n", scsi_dif_info.lba + i);
540 			scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR;
541 			break;
542 		}
543 		if (! ocs_scsi_dif_check_app_tag(ocs, dif_info, scsi_dif_info.app_tag, dif)) {
544 			ocs_log_debug(ocs, "app tag check error, lba %" PRId64 "\n", scsi_dif_info.lba + i);
545 			scsi_status = OCS_SCSI_STATUS_DIF_APP_TAG_ERROR;
546 			break;
547 		}
548 		if (! ocs_scsi_dif_check_ref_tag(ocs, dif_info, (scsi_dif_info.ref_tag + i), dif)) {
549 			ocs_log_debug(ocs, "ref tag check error, lba %" PRId64 "\n", scsi_dif_info.lba + i);
550 			scsi_status = OCS_SCSI_STATUS_DIF_REF_TAG_ERROR;
551 			break;
552 		}
553 
554 	}
555 	return scsi_status;
556 }
557 
558 /**
559  * @brief Check the block guard of block data
560  *
561  * @par Description
562  * Using the dif_info for the transfer, check the block guard value.
563  *
564  * @param dif_info Pointer to HW DIF info data.
565  * @param addrlen Array of address length pairs.
566  * @param addrlen_count Number of entries in the addrlen[] array.
567  * @param dif Pointer to the DIF data block being checked.
568  * @param is_crc True if guard is using CRC format.
569  *
570  * @return Returns TRUE if block guard check is ok.
571  */
572 static uint32_t
ocs_scsi_dif_check_guard(ocs_hw_dif_info_t * dif_info,ocs_scsi_vaddr_len_t addrlen[],uint32_t addrlen_count,ocs_dif_t * dif,int is_crc)573 ocs_scsi_dif_check_guard(ocs_hw_dif_info_t *dif_info, ocs_scsi_vaddr_len_t addrlen[], uint32_t addrlen_count,
574 	ocs_dif_t *dif, int is_crc)
575 {
576 	uint16_t crc = dif_info->dif_seed;
577 	uint32_t i;
578 	uint16_t checksum;
579 
580 	if ((dif == NULL)  || !dif_info->check_guard) {
581 		return TRUE;
582 	}
583 
584 	if (is_crc) {
585 		for (i = 0; i < addrlen_count; i++) {
586 			crc = ocs_scsi_dif_calc_crc(addrlen[i].vaddr, addrlen[i].length, crc);
587 		}
588 		return (crc == ocs_be16toh(dif->crc));
589 	} else {
590 		checksum = ocs_scsi_dif_calc_checksum(addrlen, addrlen_count);
591 
592 		return (checksum == dif->crc);
593 	}
594 }
595 
596 /**
597  * @brief Check the app tag of dif data
598  *
599  * @par Description
600  * Using the dif_info for the transfer, check the app tag.
601  *
602  * @param ocs Pointer to the ocs structure for logging.
603  * @param dif_info Pointer to HW DIF info data.
604  * @param exp_app_tag The value the app tag is expected to be.
605  * @param dif Pointer to the DIF data block being checked.
606  *
607  * @return Returns TRUE if app tag check is ok.
608  */
609 static uint32_t
ocs_scsi_dif_check_app_tag(ocs_t * ocs,ocs_hw_dif_info_t * dif_info,uint16_t exp_app_tag,ocs_dif_t * dif)610 ocs_scsi_dif_check_app_tag(ocs_t *ocs, ocs_hw_dif_info_t *dif_info, uint16_t exp_app_tag, ocs_dif_t *dif)
611 {
612 	if ((dif == NULL)  || !dif_info->check_app_tag) {
613 		return TRUE;
614 	}
615 
616 	ocs_log_debug(ocs, "expected app tag 0x%x,  actual 0x%x\n",
617 		exp_app_tag, ocs_be16toh(dif->app_tag));
618 
619 	return (exp_app_tag == ocs_be16toh(dif->app_tag));
620 }
621 
622 /**
623  * @brief Check the ref tag of dif data
624  *
625  * @par Description
626  * Using the dif_info for the transfer, check the app tag.
627  *
628  * @param ocs Pointer to the ocs structure for logging.
629  * @param dif_info Pointer to HW DIF info data.
630  * @param exp_ref_tag The value the ref tag is expected to be.
631  * @param dif Pointer to the DIF data block being checked.
632  *
633  * @return Returns TRUE if ref tag check is ok.
634  */
635 static uint32_t
ocs_scsi_dif_check_ref_tag(ocs_t * ocs,ocs_hw_dif_info_t * dif_info,uint32_t exp_ref_tag,ocs_dif_t * dif)636 ocs_scsi_dif_check_ref_tag(ocs_t *ocs, ocs_hw_dif_info_t *dif_info, uint32_t exp_ref_tag, ocs_dif_t *dif)
637 {
638 	if ((dif == NULL)  || !dif_info->check_ref_tag) {
639 		return TRUE;
640 	}
641 
642 	if (exp_ref_tag != ocs_be32toh(dif->ref_tag)) {
643 		ocs_log_debug(ocs, "expected ref tag 0x%x, actual 0x%x\n",
644 			exp_ref_tag, ocs_be32toh(dif->ref_tag));
645 		return FALSE;
646 	} else {
647 		return TRUE;
648 	}
649 }
650 
651 /**
652  * @brief Return count of SGE's required for request
653  *
654  * @par Description
655  * An accurate count of SGEs is computed and returned.
656  *
657  * @param hw_dif Pointer to HW dif information.
658  * @param sgl Pointer to SGL from back end.
659  * @param sgl_count Count of SGEs in SGL.
660  *
661  * @return Count of SGEs.
662  */
663 static uint32_t
ocs_scsi_count_sgls(ocs_hw_dif_info_t * hw_dif,ocs_scsi_sgl_t * sgl,uint32_t sgl_count)664 ocs_scsi_count_sgls(ocs_hw_dif_info_t *hw_dif, ocs_scsi_sgl_t *sgl, uint32_t sgl_count)
665 {
666 	uint32_t count = 0;
667 	uint32_t i;
668 
669 	/* Convert DIF Information */
670 	if (hw_dif->dif_oper != OCS_HW_DIF_OPER_DISABLED) {
671 
672 		/* If we're not DIF separate, then emit a seed SGE */
673 		if (!hw_dif->dif_separate) {
674 			count++;
675 		}
676 
677 		for (i = 0; i < sgl_count; i++) {
678 			/* If DIF is enabled, and DIF is separate, then append a SEED then DIF SGE */
679 			if (hw_dif->dif_separate) {
680 				count += 2;
681 			}
682 
683 			count++;
684 		}
685 	} else {
686 		count = sgl_count;
687 	}
688 	return count;
689 }
690 
691 static int32_t
ocs_scsi_build_sgls(ocs_hw_t * hw,ocs_hw_io_t * hio,ocs_hw_dif_info_t * hw_dif,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,ocs_hw_io_type_e type)692 ocs_scsi_build_sgls(ocs_hw_t *hw, ocs_hw_io_t *hio, ocs_hw_dif_info_t *hw_dif, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, ocs_hw_io_type_e type)
693 {
694 	int32_t rc;
695 	uint32_t i;
696 	ocs_t *ocs = hw->os;
697 	uint32_t blocksize = 0;
698 	uint32_t blockcount;
699 
700 	ocs_assert(hio, -1);
701 
702 	/* Initialize HW SGL */
703 	rc = ocs_hw_io_init_sges(hw, hio, type);
704 	if (rc) {
705 		ocs_log_err(ocs, "ocs_hw_io_init_sges failed: %d\n", rc);
706 		return -1;
707 	}
708 
709 	/* Convert DIF Information */
710 	if (hw_dif->dif_oper != OCS_HW_DIF_OPER_DISABLED) {
711 
712 		/* If we're not DIF separate, then emit a seed SGE */
713 		if (!hw_dif->dif_separate) {
714 			rc = ocs_hw_io_add_seed_sge(hw, hio, hw_dif);
715 			if (rc) {
716 				return rc;
717 			}
718 		}
719 
720 		/* if we are doing DIF separate, then figure out the block size so that we
721 		 * can update the ref tag in the DIF seed SGE.   Also verify that the
722 		 * the sgl lengths are all multiples of the blocksize
723 		 */
724 		if (hw_dif->dif_separate) {
725 			switch(hw_dif->blk_size) {
726 			case OCS_HW_DIF_BK_SIZE_512:	blocksize = 512; break;
727 			case OCS_HW_DIF_BK_SIZE_1024:	blocksize = 1024; break;
728 			case OCS_HW_DIF_BK_SIZE_2048:	blocksize = 2048; break;
729 			case OCS_HW_DIF_BK_SIZE_4096:	blocksize = 4096; break;
730 			case OCS_HW_DIF_BK_SIZE_520:	blocksize = 520; break;
731 			case OCS_HW_DIF_BK_SIZE_4104:	blocksize = 4104; break;
732 			default:
733 				ocs_log_test(hw->os, "Inavlid hw_dif blocksize %d\n", hw_dif->blk_size);
734 				return -1;
735 			}
736 			for (i = 0; i < sgl_count; i++) {
737 				if ((sgl[i].len % blocksize) != 0) {
738 					ocs_log_test(hw->os, "sgl[%d] len of %ld is not multiple of blocksize\n",
739 						     i, sgl[i].len);
740 					return -1;
741 				}
742 			}
743 		}
744 
745 		for (i = 0; i < sgl_count; i++) {
746 			ocs_assert(sgl[i].addr, -1);
747 			ocs_assert(sgl[i].len, -1);
748 
749 			/* If DIF is enabled, and DIF is separate, then append a SEED then DIF SGE */
750 			if (hw_dif->dif_separate) {
751 				rc = ocs_hw_io_add_seed_sge(hw, hio, hw_dif);
752 				if (rc) {
753 					return rc;
754 				}
755 				rc = ocs_hw_io_add_dif_sge(hw, hio, sgl[i].dif_addr);
756 				if (rc) {
757 					return rc;
758 				}
759 				/* Update the ref_tag for the next DIF seed SGE */
760 				blockcount = sgl[i].len / blocksize;
761 				if (hw_dif->dif_oper == OCS_HW_DIF_OPER_INSERT) {
762 					hw_dif->ref_tag_repl += blockcount;
763 				} else {
764 					hw_dif->ref_tag_cmp += blockcount;
765 				}
766 			}
767 
768 			/* Add data SGE */
769 			rc = ocs_hw_io_add_sge(hw, hio, sgl[i].addr, sgl[i].len);
770 			if (rc) {
771 				ocs_log_err(ocs, "ocs_hw_io_add_sge failed: count=%d rc=%d\n",
772 						sgl_count, rc);
773 				return rc;
774 			}
775 		}
776 	} else {
777 		for (i = 0; i < sgl_count; i++) {
778 			ocs_assert(sgl[i].addr, -1);
779 			ocs_assert(sgl[i].len, -1);
780 
781 			/* Add data SGE */
782 			rc = ocs_hw_io_add_sge(hw, hio, sgl[i].addr, sgl[i].len);
783 			if (rc) {
784 				ocs_log_err(ocs, "ocs_hw_io_add_sge failed: count=%d rc=%d\n",
785 						sgl_count, rc);
786 				return rc;
787 			}
788 
789 		}
790 	}
791 	return 0;
792 }
793 
794 /**
795  * @ingroup scsi_api_base
796  * @brief Convert SCSI API T10 DIF information into the FC HW format.
797  *
798  * @param ocs Pointer to the ocs structure for logging.
799  * @param scsi_dif_info Pointer to the SCSI API T10 DIF fields.
800  * @param hw_dif_info Pointer to the FC HW API T10 DIF fields.
801  *
802  * @return Returns 0 on success, or a negative error code value on failure.
803  */
804 
805 static int32_t
ocs_scsi_convert_dif_info(ocs_t * ocs,ocs_scsi_dif_info_t * scsi_dif_info,ocs_hw_dif_info_t * hw_dif_info)806 ocs_scsi_convert_dif_info(ocs_t *ocs, ocs_scsi_dif_info_t *scsi_dif_info, ocs_hw_dif_info_t *hw_dif_info)
807 {
808 	uint32_t dif_seed;
809 	ocs_memset(hw_dif_info, 0, sizeof(ocs_hw_dif_info_t));
810 
811 	if (scsi_dif_info == NULL) {
812 		hw_dif_info->dif_oper = OCS_HW_DIF_OPER_DISABLED;
813 		hw_dif_info->blk_size =  OCS_HW_DIF_BK_SIZE_NA;
814 		return 0;
815 	}
816 
817 	/* Convert the DIF operation */
818 	switch(scsi_dif_info->dif_oper) {
819 	case OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CRC:
820 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CRC;
821 		hw_dif_info->dif = SLI4_DIF_INSERT;
822 		break;
823 	case OCS_SCSI_DIF_OPER_IN_CRC_OUT_NODIF:
824 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CRC_OUT_NODIF;
825 		hw_dif_info->dif = SLI4_DIF_STRIP;
826 		break;
827 	case OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CHKSUM:
828 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CHKSUM;
829 		hw_dif_info->dif = SLI4_DIF_INSERT;
830 		break;
831 	case OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_NODIF:
832 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_NODIF;
833 		hw_dif_info->dif = SLI4_DIF_STRIP;
834 		break;
835 	case OCS_SCSI_DIF_OPER_IN_CRC_OUT_CRC:
836 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC;
837 		hw_dif_info->dif = SLI4_DIF_PASS_THROUGH;
838 		break;
839 	case OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CHKSUM:
840 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CHKSUM;
841 		hw_dif_info->dif = SLI4_DIF_PASS_THROUGH;
842 		break;
843 	case OCS_SCSI_DIF_OPER_IN_CRC_OUT_CHKSUM:
844 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CHKSUM;
845 		hw_dif_info->dif = SLI4_DIF_PASS_THROUGH;
846 		break;
847 	case OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CRC:
848 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CRC;
849 		hw_dif_info->dif = SLI4_DIF_PASS_THROUGH;
850 		break;
851 	case OCS_SCSI_DIF_OPER_IN_RAW_OUT_RAW:
852 		hw_dif_info->dif_oper = OCS_HW_SGE_DIF_OP_IN_RAW_OUT_RAW;
853 		hw_dif_info->dif = SLI4_DIF_PASS_THROUGH;
854 		break;
855 	default:
856 		ocs_log_test(ocs, "unhandled SCSI DIF operation %d\n",
857 			     scsi_dif_info->dif_oper);
858 		return -1;
859 	}
860 
861 	switch(scsi_dif_info->blk_size) {
862 	case OCS_SCSI_DIF_BK_SIZE_512:
863 		hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_512;
864 		break;
865 	case OCS_SCSI_DIF_BK_SIZE_1024:
866 		hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_1024;
867 		break;
868 	case OCS_SCSI_DIF_BK_SIZE_2048:
869 		hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_2048;
870 		break;
871 	case OCS_SCSI_DIF_BK_SIZE_4096:
872 		hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_4096;
873 		break;
874 	case OCS_SCSI_DIF_BK_SIZE_520:
875 		hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_520;
876 		break;
877 	case OCS_SCSI_DIF_BK_SIZE_4104:
878 		hw_dif_info->blk_size = OCS_HW_DIF_BK_SIZE_4104;
879 		break;
880 	default:
881 		ocs_log_test(ocs, "unhandled SCSI DIF block size %d\n",
882 			     scsi_dif_info->blk_size);
883 		return -1;
884 	}
885 
886 	/* If the operation is an INSERT the tags provided are the ones that should be
887 	 * inserted, otherwise they're the ones to be checked against. */
888 	if (hw_dif_info->dif == SLI4_DIF_INSERT ) {
889 		hw_dif_info->ref_tag_repl = scsi_dif_info->ref_tag;
890 		hw_dif_info->app_tag_repl = scsi_dif_info->app_tag;
891 	} else {
892 		hw_dif_info->ref_tag_cmp = scsi_dif_info->ref_tag;
893 		hw_dif_info->app_tag_cmp = scsi_dif_info->app_tag;
894 	}
895 
896 	hw_dif_info->check_ref_tag = scsi_dif_info->check_ref_tag;
897 	hw_dif_info->check_app_tag = scsi_dif_info->check_app_tag;
898 	hw_dif_info->check_guard = scsi_dif_info->check_guard;
899 	hw_dif_info->auto_incr_ref_tag = 1;
900 	hw_dif_info->dif_separate = scsi_dif_info->dif_separate;
901 	hw_dif_info->disable_app_ffff = scsi_dif_info->disable_app_ffff;
902 	hw_dif_info->disable_app_ref_ffff = scsi_dif_info->disable_app_ref_ffff;
903 
904 	ocs_hw_get(&ocs->hw, OCS_HW_DIF_SEED, &dif_seed);
905 	hw_dif_info->dif_seed = dif_seed;
906 
907 	return 0;
908 }
909 
910 /**
911  * @ingroup scsi_api_base
912  * @brief This function logs the SGLs for an IO.
913  *
914  * @param io Pointer to the IO context.
915  */
ocs_log_sgl(ocs_io_t * io)916 static void ocs_log_sgl(ocs_io_t *io)
917 {
918 	ocs_hw_io_t *hio = io->hio;
919 	sli4_sge_t *data = NULL;
920 	uint32_t *dword = NULL;
921 	uint32_t i;
922 	uint32_t n_sge;
923 
924 	scsi_io_trace(io, "def_sgl at 0x%x 0x%08x\n",
925 		      ocs_addr32_hi(hio->def_sgl.phys),
926 		      ocs_addr32_lo(hio->def_sgl.phys));
927 	n_sge = (hio->sgl == &hio->def_sgl ? hio->n_sge : hio->def_sgl_count);
928 	for (i = 0, data = hio->def_sgl.virt; i < n_sge; i++, data++) {
929 		dword = (uint32_t*)data;
930 
931 		scsi_io_trace(io, "SGL %2d 0x%08x 0x%08x 0x%08x 0x%08x\n",
932 			 i, dword[0], dword[1], dword[2], dword[3]);
933 
934 		if (dword[2] & (1U << 31)) {
935 			break;
936 		}
937 	}
938 
939 	if (hio->ovfl_sgl != NULL &&
940 		hio->sgl == hio->ovfl_sgl) {
941 		scsi_io_trace(io, "Overflow at 0x%x 0x%08x\n",
942 			      ocs_addr32_hi(hio->ovfl_sgl->phys),
943 			      ocs_addr32_lo(hio->ovfl_sgl->phys));
944 		for (i = 0, data = hio->ovfl_sgl->virt; i < hio->n_sge; i++, data++) {
945 			dword = (uint32_t*)data;
946 
947 			scsi_io_trace(io, "SGL %2d 0x%08x 0x%08x 0x%08x 0x%08x\n",
948 				 i, dword[0], dword[1], dword[2], dword[3]);
949 			if (dword[2] & (1U << 31)) {
950 				break;
951 			}
952 		}
953 	}
954 
955 }
956 
957 
958 /**
959  * @brief Check pending error asynchronous callback function.
960  *
961  * @par Description
962  * Invoke the HW callback function for a given IO. This function is called
963  * from the NOP mailbox completion context.
964  *
965  * @param hw Pointer to HW object.
966  * @param status Completion status.
967  * @param mqe Mailbox completion queue entry.
968  * @param arg General purpose argument.
969  *
970  * @return Returns 0.
971  */
972 static int32_t
ocs_scsi_check_pending_async_cb(ocs_hw_t * hw,int32_t status,uint8_t * mqe,void * arg)973 ocs_scsi_check_pending_async_cb(ocs_hw_t *hw, int32_t status, uint8_t *mqe, void *arg)
974 {
975 	ocs_io_t *io = arg;
976 
977 	if (io != NULL) {
978 		if (io->hw_cb != NULL) {
979 			ocs_hw_done_t cb = io->hw_cb;
980 
981 			io->hw_cb = NULL;
982 			cb(io->hio, NULL, 0, SLI4_FC_WCQE_STATUS_DISPATCH_ERROR, 0, io);
983 		}
984 	}
985 	return 0;
986 }
987 
988 /**
989  * @brief Check for pending IOs to dispatch.
990  *
991  * @par Description
992  * If there are IOs on the pending list, and a HW IO is available, then
993  * dispatch the IOs.
994  *
995  * @param ocs Pointer to the OCS structure.
996  *
997  * @return None.
998  */
999 
1000 void
ocs_scsi_check_pending(ocs_t * ocs)1001 ocs_scsi_check_pending(ocs_t *ocs)
1002 {
1003 	ocs_xport_t *xport = ocs->xport;
1004 	ocs_io_t *io;
1005 	ocs_hw_io_t *hio;
1006 	int32_t status;
1007 	int count = 0;
1008 	int dispatch;
1009 
1010 	/* Guard against recursion */
1011 	if (ocs_atomic_add_return(&xport->io_pending_recursing, 1)) {
1012 		/* This function is already running.  Decrement and return. */
1013 		ocs_atomic_sub_return(&xport->io_pending_recursing, 1);
1014 		return;
1015 	}
1016 
1017 	do {
1018 		ocs_lock(&xport->io_pending_lock);
1019 			status = 0;
1020 			hio = NULL;
1021 			io = ocs_list_remove_head(&xport->io_pending_list);
1022 			if (io != NULL) {
1023 				if (io->io_type == OCS_IO_TYPE_ABORT) {
1024 					hio = NULL;
1025 				} else {
1026 					hio = ocs_hw_io_alloc(&ocs->hw);
1027 					if (hio == NULL) {
1028 						/*
1029 						 * No HW IO available.
1030 						 * Put IO back on the front of pending list
1031 						 */
1032 						ocs_list_add_head(&xport->io_pending_list, io);
1033 						io = NULL;
1034 					} else {
1035 						hio->eq = io->hw_priv;
1036 					}
1037 				}
1038 			}
1039 		/* Must drop the lock before dispatching the IO */
1040 		ocs_unlock(&xport->io_pending_lock);
1041 
1042 		if (io != NULL) {
1043 			count++;
1044 
1045 			/*
1046 			 * We pulled an IO off the pending list,
1047 			 * and either got an HW IO or don't need one
1048 			 */
1049 			ocs_atomic_sub_return(&xport->io_pending_count, 1);
1050 			if (hio == NULL) {
1051 				status = ocs_scsi_io_dispatch_no_hw_io(io);
1052 			} else {
1053 				status = ocs_scsi_io_dispatch_hw_io(io, hio);
1054 			}
1055 			if (status) {
1056 				/*
1057 				 * Invoke the HW callback, but do so in the separate execution context,
1058 				 * provided by the NOP mailbox completion processing context by using
1059 				 * ocs_hw_async_call()
1060 				 */
1061 				if (ocs_hw_async_call(&ocs->hw, ocs_scsi_check_pending_async_cb, io)) {
1062 					ocs_log_test(ocs, "call to ocs_hw_async_call() failed\n");
1063 				}
1064 			}
1065 		}
1066 	} while (io != NULL);
1067 
1068 
1069 	/*
1070 	 * If nothing was removed from the list,
1071 	 * we might be in a case where we need to abort an
1072 	 * active IO and the abort is on the pending list.
1073 	 * Look for an abort we can dispatch.
1074 	 */
1075 	if (count == 0 ) {
1076 		dispatch = 0;
1077 
1078 		ocs_lock(&xport->io_pending_lock);
1079 			ocs_list_foreach(&xport->io_pending_list, io) {
1080 				if (io->io_type == OCS_IO_TYPE_ABORT) {
1081 					if (io->io_to_abort->hio != NULL) {
1082 						/* This IO has a HW IO, so it is active.  Dispatch the abort. */
1083 						dispatch = 1;
1084 					} else {
1085 						/* Leave this abort on the pending list and keep looking */
1086 						dispatch = 0;
1087 					}
1088 				}
1089 				if (dispatch) {
1090 					ocs_list_remove(&xport->io_pending_list, io);
1091 					ocs_atomic_sub_return(&xport->io_pending_count, 1);
1092 					break;
1093 				}
1094 			}
1095 		ocs_unlock(&xport->io_pending_lock);
1096 
1097 		if (dispatch) {
1098 			status = ocs_scsi_io_dispatch_no_hw_io(io);
1099 			if (status) {
1100 				if (ocs_hw_async_call(&ocs->hw, ocs_scsi_check_pending_async_cb, io)) {
1101 					ocs_log_test(ocs, "call to ocs_hw_async_call() failed\n");
1102 				}
1103 			}
1104 		}
1105 	}
1106 
1107 	ocs_atomic_sub_return(&xport->io_pending_recursing, 1);
1108 	return;
1109 }
1110 
1111 /**
1112  * @brief Attempt to dispatch a non-abort IO
1113  *
1114  * @par Description
1115  * An IO is dispatched:
1116  * - if the pending list is not empty, add IO to pending list
1117  *   and call a function to process the pending list.
1118  * - if pending list is empty, try to allocate a HW IO. If none
1119  *   is available, place this IO at the tail of the pending IO
1120  *   list.
1121  * - if HW IO is available, attach this IO to the HW IO and
1122  *   submit it.
1123  *
1124  * @param io Pointer to IO structure.
1125  * @param cb Callback function.
1126  *
1127  * @return Returns 0 on success, a negative error code value on failure.
1128  */
1129 
1130 int32_t
ocs_scsi_io_dispatch(ocs_io_t * io,void * cb)1131 ocs_scsi_io_dispatch(ocs_io_t *io, void *cb)
1132 {
1133 	ocs_hw_io_t *hio;
1134 	ocs_t *ocs = io->ocs;
1135 	ocs_xport_t *xport = ocs->xport;
1136 
1137 	ocs_assert(io->cmd_tgt || io->cmd_ini, -1);
1138 	ocs_assert((io->io_type != OCS_IO_TYPE_ABORT), -1);
1139 	io->hw_cb = cb;
1140 
1141 	/*
1142 	 * if this IO already has a HW IO, then this is either not the first phase of
1143 	 * the IO. Send it to the HW.
1144 	 */
1145 	if (io->hio != NULL) {
1146 		return ocs_scsi_io_dispatch_hw_io(io, io->hio);
1147 	}
1148 
1149 	/*
1150 	 * We don't already have a HW IO associated with the IO. First check
1151 	 * the pending list. If not empty, add IO to the tail and process the
1152 	 * pending list.
1153 	 */
1154 	ocs_lock(&xport->io_pending_lock);
1155 		if (!ocs_list_empty(&xport->io_pending_list)) {
1156 			/*
1157 			 * If this is a low latency request, the put at the front of the IO pending
1158 			 * queue, otherwise put it at the end of the queue.
1159 			 */
1160 			if (io->low_latency) {
1161 				ocs_list_add_head(&xport->io_pending_list, io);
1162 			} else {
1163 				ocs_list_add_tail(&xport->io_pending_list, io);
1164 			}
1165 			ocs_unlock(&xport->io_pending_lock);
1166 			ocs_atomic_add_return(&xport->io_pending_count, 1);
1167 			ocs_atomic_add_return(&xport->io_total_pending, 1);
1168 
1169 			/* process pending list */
1170 			ocs_scsi_check_pending(ocs);
1171 			return 0;
1172 		}
1173 	ocs_unlock(&xport->io_pending_lock);
1174 
1175 	/*
1176 	 * We don't have a HW IO associated with the IO and there's nothing
1177 	 * on the pending list. Attempt to allocate a HW IO and dispatch it.
1178 	 */
1179 	hio = ocs_hw_io_alloc(&io->ocs->hw);
1180 	if (hio == NULL) {
1181 
1182 		/* Couldn't get a HW IO. Save this IO on the pending list */
1183 		ocs_lock(&xport->io_pending_lock);
1184 			ocs_list_add_tail(&xport->io_pending_list, io);
1185 		ocs_unlock(&xport->io_pending_lock);
1186 
1187 		ocs_atomic_add_return(&xport->io_total_pending, 1);
1188 		ocs_atomic_add_return(&xport->io_pending_count, 1);
1189 		return 0;
1190 	}
1191 
1192 	/* We successfully allocated a HW IO; dispatch to HW */
1193 	return ocs_scsi_io_dispatch_hw_io(io, hio);
1194 }
1195 
1196 /**
1197  * @brief Attempt to dispatch an Abort IO.
1198  *
1199  * @par Description
1200  * An Abort IO is dispatched:
1201  * - if the pending list is not empty, add IO to pending list
1202  *   and call a function to process the pending list.
1203  * - if pending list is empty, send abort to the HW.
1204  *
1205  * @param io Pointer to IO structure.
1206  * @param cb Callback function.
1207  *
1208  * @return Returns 0 on success, a negative error code value on failure.
1209  */
1210 
1211 int32_t
ocs_scsi_io_dispatch_abort(ocs_io_t * io,void * cb)1212 ocs_scsi_io_dispatch_abort(ocs_io_t *io, void *cb)
1213 {
1214 	ocs_t *ocs = io->ocs;
1215 	ocs_xport_t *xport = ocs->xport;
1216 
1217 	ocs_assert((io->io_type == OCS_IO_TYPE_ABORT), -1);
1218 	io->hw_cb = cb;
1219 
1220 	/*
1221 	 * For aborts, we don't need a HW IO, but we still want to pass through
1222 	 * the pending list to preserve ordering. Thus, if the pending list is
1223 	 * not empty, add this abort to the pending list and process the pending list.
1224 	 */
1225 	ocs_lock(&xport->io_pending_lock);
1226 		if (!ocs_list_empty(&xport->io_pending_list)) {
1227 			ocs_list_add_tail(&xport->io_pending_list, io);
1228 			ocs_unlock(&xport->io_pending_lock);
1229 			ocs_atomic_add_return(&xport->io_pending_count, 1);
1230 			ocs_atomic_add_return(&xport->io_total_pending, 1);
1231 
1232 			/* process pending list */
1233 			ocs_scsi_check_pending(ocs);
1234 			return 0;
1235 		}
1236 	ocs_unlock(&xport->io_pending_lock);
1237 
1238 	/* nothing on pending list, dispatch abort */
1239 	return ocs_scsi_io_dispatch_no_hw_io(io);
1240 
1241 }
1242 
1243 /**
1244  * @brief Dispatch IO
1245  *
1246  * @par Description
1247  * An IO and its associated HW IO is dispatched to the HW.
1248  *
1249  * @param io Pointer to IO structure.
1250  * @param hio Pointer to HW IO structure from which IO will be
1251  * dispatched.
1252  *
1253  * @return Returns 0 on success, a negative error code value on failure.
1254  */
1255 
1256 static int32_t
ocs_scsi_io_dispatch_hw_io(ocs_io_t * io,ocs_hw_io_t * hio)1257 ocs_scsi_io_dispatch_hw_io(ocs_io_t *io, ocs_hw_io_t *hio)
1258 {
1259 	int32_t rc;
1260 	ocs_t *ocs = io->ocs;
1261 
1262 	/* Got a HW IO; update ini/tgt_task_tag with HW IO info and dispatch */
1263 	io->hio = hio;
1264 	if (io->cmd_tgt) {
1265 		io->tgt_task_tag = hio->indicator;
1266 	} else if (io->cmd_ini) {
1267 		io->init_task_tag = hio->indicator;
1268 	}
1269 	io->hw_tag = hio->reqtag;
1270 
1271 	hio->eq = io->hw_priv;
1272 
1273 	/* Copy WQ steering */
1274 	switch(io->wq_steering) {
1275 	case OCS_SCSI_WQ_STEERING_CLASS >> OCS_SCSI_WQ_STEERING_SHIFT:
1276 		hio->wq_steering = OCS_HW_WQ_STEERING_CLASS;
1277 		break;
1278 	case OCS_SCSI_WQ_STEERING_REQUEST >> OCS_SCSI_WQ_STEERING_SHIFT:
1279 		hio->wq_steering = OCS_HW_WQ_STEERING_REQUEST;
1280 		break;
1281 	case OCS_SCSI_WQ_STEERING_CPU >> OCS_SCSI_WQ_STEERING_SHIFT:
1282 		hio->wq_steering = OCS_HW_WQ_STEERING_CPU;
1283 		break;
1284 	}
1285 
1286 
1287 	switch (io->io_type) {
1288 	case OCS_IO_TYPE_IO: {
1289 		uint32_t max_sgl;
1290 		uint32_t total_count;
1291 		uint32_t host_allocated;
1292 
1293 		ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &max_sgl);
1294 		ocs_hw_get(&ocs->hw, OCS_HW_SGL_CHAINING_HOST_ALLOCATED, &host_allocated);
1295 
1296 		/*
1297 		 * If the requested SGL is larger than the default size, then we can allocate
1298 		 * an overflow SGL.
1299 		 */
1300 		total_count = ocs_scsi_count_sgls(&io->hw_dif, io->sgl, io->sgl_count);
1301 
1302 		/*
1303 		 * Lancer requires us to allocate the chained memory area, but
1304 		 * Skyhawk must use the SGL list associated with another XRI.
1305 		 */
1306 		if (host_allocated && total_count > max_sgl) {
1307 			/* Compute count needed, the number extra plus 1 for the link sge */
1308 			uint32_t count = total_count - max_sgl + 1;
1309 			rc = ocs_dma_alloc(ocs, &io->ovfl_sgl, count*sizeof(sli4_sge_t), 64);
1310 			if (rc) {
1311 				ocs_log_err(ocs, "ocs_dma_alloc overflow sgl failed\n");
1312 				break;
1313 			}
1314 			rc = ocs_hw_io_register_sgl(&ocs->hw, io->hio, &io->ovfl_sgl, count);
1315 			if (rc) {
1316 				ocs_scsi_io_free_ovfl(io);
1317 				ocs_log_err(ocs, "ocs_hw_io_register_sgl() failed\n");
1318 				break;
1319 			}
1320 			/* EVT: update chained_io_count */
1321 			io->node->chained_io_count++;
1322 		}
1323 
1324 		rc = ocs_scsi_build_sgls(&ocs->hw, io->hio, &io->hw_dif, io->sgl, io->sgl_count, io->hio_type);
1325 		if (rc) {
1326 			ocs_scsi_io_free_ovfl(io);
1327 			break;
1328 		}
1329 
1330 		if (OCS_LOG_ENABLE_SCSI_TRACE(ocs)) {
1331 			ocs_log_sgl(io);
1332 		}
1333 
1334 		if (io->app_id) {
1335 			io->iparam.fcp_tgt.app_id = io->app_id;
1336 		}
1337 
1338 		rc = ocs_hw_io_send(&io->ocs->hw, io->hio_type, io->hio, io->wire_len, &io->iparam, &io->node->rnode,
1339 			io->hw_cb, io);
1340 		break;
1341 	}
1342 	case OCS_IO_TYPE_ELS:
1343 	case OCS_IO_TYPE_CT: {
1344 		rc = ocs_hw_srrs_send(&ocs->hw, io->hio_type, io->hio,
1345 			&io->els_req, io->wire_len,
1346 			&io->els_rsp, &io->node->rnode, &io->iparam,
1347 			io->hw_cb, io);
1348 		break;
1349 	}
1350 	case OCS_IO_TYPE_CT_RESP: {
1351 		rc = ocs_hw_srrs_send(&ocs->hw, io->hio_type, io->hio,
1352 			&io->els_rsp, io->wire_len,
1353 			NULL, &io->node->rnode, &io->iparam,
1354 			io->hw_cb, io);
1355 		break;
1356 	}
1357 	case OCS_IO_TYPE_BLS_RESP: {
1358 		/* no need to update tgt_task_tag for BLS response since the RX_ID
1359 		 * will be specified by the payload, not the XRI */
1360 		rc = ocs_hw_srrs_send(&ocs->hw, io->hio_type, io->hio,
1361 			NULL, 0, NULL, &io->node->rnode, &io->iparam, io->hw_cb, io);
1362 		break;
1363 	}
1364 	default:
1365 		scsi_io_printf(io, "Unknown IO type=%d\n", io->io_type);
1366 		rc = -1;
1367 		break;
1368 	}
1369 	return rc;
1370 }
1371 
1372 /**
1373  * @brief Dispatch IO
1374  *
1375  * @par Description
1376  * An IO that does require a HW IO is dispatched to the HW.
1377  *
1378  * @param io Pointer to IO structure.
1379  *
1380  * @return Returns 0 on success, or a negative error code value on failure.
1381  */
1382 
1383 static int32_t
ocs_scsi_io_dispatch_no_hw_io(ocs_io_t * io)1384 ocs_scsi_io_dispatch_no_hw_io(ocs_io_t *io)
1385 {
1386 	int32_t rc;
1387 
1388 	switch (io->io_type) {
1389 	case OCS_IO_TYPE_ABORT: {
1390 		ocs_hw_io_t *hio_to_abort = NULL;
1391 		ocs_assert(io->io_to_abort, -1);
1392 		hio_to_abort = io->io_to_abort->hio;
1393 
1394 		if (hio_to_abort == NULL) {
1395 			/*
1396 			 * If "IO to abort" does not have an associated HW IO, immediately
1397 			 * make callback with success. The command must have been sent to
1398 			 * the backend, but the data phase has not yet started, so we don't
1399 			 * have a HW IO.
1400 			 *
1401 			 * Note: since the backend shims should be taking a reference
1402 			 * on io_to_abort, it should not be possible to have been completed
1403 			 * and freed by the backend before the abort got here.
1404 			 */
1405 			scsi_io_printf(io, "IO: " SCSI_IOFMT " not active\n",
1406 				       SCSI_IOFMT_ARGS(io->io_to_abort));
1407 			((ocs_hw_done_t)io->hw_cb)(io->hio, NULL, 0, SLI4_FC_WCQE_STATUS_SUCCESS, 0, io);
1408 			rc = 0;
1409 		} else {
1410 			/* HW IO is valid, abort it */
1411 			scsi_io_printf(io, "aborting " SCSI_IOFMT "\n", SCSI_IOFMT_ARGS(io->io_to_abort));
1412 			rc = ocs_hw_io_abort(&io->ocs->hw, hio_to_abort, io->send_abts,
1413 					      io->hw_cb, io);
1414 			if (rc) {
1415 				int status = SLI4_FC_WCQE_STATUS_SUCCESS;
1416 				if ((rc != OCS_HW_RTN_IO_NOT_ACTIVE) &&
1417 				    (rc != OCS_HW_RTN_IO_ABORT_IN_PROGRESS)) {
1418 					status = -1;
1419 					scsi_io_printf(io, "Failed to abort IO: " SCSI_IOFMT " status=%d\n",
1420 						       SCSI_IOFMT_ARGS(io->io_to_abort), rc);
1421 				}
1422 				((ocs_hw_done_t)io->hw_cb)(io->hio, NULL, 0, status, 0, io);
1423 				rc = 0;
1424 			}
1425 		}
1426 
1427 		break;
1428 	}
1429 	default:
1430 		scsi_io_printf(io, "Unknown IO type=%d\n", io->io_type);
1431 		rc = -1;
1432 		break;
1433 	}
1434 	return rc;
1435 }
1436 
1437 /**
1438  * @ingroup scsi_api_base
1439  * @brief Send read/write data.
1440  *
1441  * @par Description
1442  * This call is made by a target-server to initiate a SCSI read or write data phase, transferring
1443  * data between the target to the remote initiator. The payload is specified by the
1444  * scatter-gather list @c sgl of length @c sgl_count. The @c wire_len argument
1445  * specifies the payload length (independent of the scatter-gather list cumulative length).
1446  * @n @n
1447  * The @c flags argument has one bit, OCS_SCSI_LAST_DATAPHASE, which is a hint to the base
1448  * driver that it may use auto SCSI response features if the hardware supports it.
1449  * @n @n
1450  * Upon completion, the callback function @b cb is called with flags indicating that the
1451  * IO has completed (OCS_SCSI_IO_COMPL) and another data phase or response may be sent;
1452  * that the IO has completed and no response needs to be sent (OCS_SCSI_IO_COMPL_NO_RSP);
1453  * or that the IO was aborted (OCS_SCSI_IO_ABORTED).
1454  *
1455  * @param io Pointer to the IO context.
1456  * @param flags Flags controlling the sending of data.
1457  * @param dif_info Pointer to T10 DIF fields, or NULL if no DIF.
1458  * @param sgl Pointer to the payload scatter-gather list.
1459  * @param sgl_count Count of the scatter-gather list elements.
1460  * @param xwire_len Length of the payload on wire, in bytes.
1461  * @param type HW IO type.
1462  * @param enable_ar Enable auto-response if true.
1463  * @param cb Completion callback.
1464  * @param arg Application-supplied callback data.
1465  *
1466  * @return Returns 0 on success, or a negative error code value on failure.
1467  */
1468 
1469 static inline int32_t
ocs_scsi_xfer_data(ocs_io_t * io,uint32_t flags,ocs_scsi_dif_info_t * dif_info,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,uint32_t xwire_len,ocs_hw_io_type_e type,int enable_ar,ocs_scsi_io_cb_t cb,void * arg)1470 ocs_scsi_xfer_data(ocs_io_t *io, uint32_t flags,
1471 	ocs_scsi_dif_info_t *dif_info,
1472 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t xwire_len,
1473 	ocs_hw_io_type_e type, int enable_ar,
1474 	ocs_scsi_io_cb_t cb, void *arg)
1475 {
1476 	int32_t rc;
1477 	ocs_t *ocs;
1478 	uint32_t disable_ar_tgt_dif = FALSE;
1479 	size_t residual = 0;
1480 
1481 	if ((dif_info != NULL) && (dif_info->dif_oper == OCS_SCSI_DIF_OPER_DISABLED)) {
1482 		dif_info = NULL;
1483 	}
1484 
1485 	ocs_assert(io, -1);
1486 
1487 	if (dif_info != NULL) {
1488 		ocs_hw_get(&io->ocs->hw, OCS_HW_DISABLE_AR_TGT_DIF, &disable_ar_tgt_dif);
1489 		if (disable_ar_tgt_dif) {
1490 			enable_ar = FALSE;
1491 		}
1492 	}
1493 
1494 	io->sgl_count = sgl_count;
1495 
1496 	/* If needed, copy SGL */
1497 	if (sgl && (sgl != io->sgl)) {
1498 		ocs_assert(sgl_count <= io->sgl_allocated, -1);
1499 		ocs_memcpy(io->sgl, sgl, sgl_count*sizeof(*io->sgl));
1500 	}
1501 
1502 	ocs = io->ocs;
1503 	ocs_assert(ocs, -1);
1504 	ocs_assert(io->node, -1);
1505 
1506 	scsi_io_trace(io, "%s wire_len %d\n", (type == OCS_HW_IO_TARGET_READ) ? "send" : "recv", xwire_len);
1507 
1508 	ocs_assert(sgl, -1);
1509 	ocs_assert(sgl_count > 0, -1);
1510 	ocs_assert(io->exp_xfer_len > io->transferred, -1);
1511 
1512 	io->hio_type = type;
1513 
1514 	io->scsi_tgt_cb = cb;
1515 	io->scsi_tgt_cb_arg = arg;
1516 
1517 	rc = ocs_scsi_convert_dif_info(ocs, dif_info, &io->hw_dif);
1518 	if (rc) {
1519 		return rc;
1520 	}
1521 
1522 	/* If DIF is used, then save lba for error recovery */
1523 	if (dif_info) {
1524 		io->scsi_dif_info = *dif_info;
1525 	}
1526 
1527 	io->wire_len = MIN(xwire_len, io->exp_xfer_len - io->transferred);
1528 	residual = (xwire_len - io->wire_len);
1529 
1530 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1531 	io->iparam.fcp_tgt.ox_id = io->init_task_tag;
1532 	io->iparam.fcp_tgt.offset = io->transferred;
1533 	io->iparam.fcp_tgt.dif_oper = io->hw_dif.dif;
1534 	io->iparam.fcp_tgt.blk_size = io->hw_dif.blk_size;
1535 	io->iparam.fcp_tgt.cs_ctl = io->cs_ctl;
1536 	io->iparam.fcp_tgt.timeout = io->timeout;
1537 
1538 	/* if this is the last data phase and there is no residual, enable
1539 	 * auto-good-response
1540 	 */
1541 	if (enable_ar && (flags & OCS_SCSI_LAST_DATAPHASE) &&
1542 		(residual == 0) && ((io->transferred + io->wire_len) == io->exp_xfer_len) && (!(flags & OCS_SCSI_NO_AUTO_RESPONSE))) {
1543 		io->iparam.fcp_tgt.flags |= SLI4_IO_AUTO_GOOD_RESPONSE;
1544 		io->auto_resp = TRUE;
1545 	} else {
1546 		io->auto_resp = FALSE;
1547 	}
1548 
1549 	/* save this transfer length */
1550 	io->xfer_req = io->wire_len;
1551 
1552 	/* Adjust the transferred count to account for overrun
1553 	 * when the residual is calculated in ocs_scsi_send_resp
1554 	 */
1555 	io->transferred += residual;
1556 
1557 	/* Adjust the SGL size if there is overrun */
1558 
1559 	if (residual) {
1560 		ocs_scsi_sgl_t  *sgl_ptr = &io->sgl[sgl_count-1];
1561 
1562 		while (residual) {
1563 			size_t len = sgl_ptr->len;
1564 			if ( len > residual) {
1565 				sgl_ptr->len = len - residual;
1566 				residual = 0;
1567 			} else {
1568 				sgl_ptr->len = 0;
1569 				residual -= len;
1570 				io->sgl_count--;
1571 			}
1572 			sgl_ptr--;
1573 		}
1574 	}
1575 
1576 	/* Set latency and WQ steering */
1577 	io->low_latency = (flags & OCS_SCSI_LOW_LATENCY) != 0;
1578 	io->wq_steering = (flags & OCS_SCSI_WQ_STEERING_MASK) >> OCS_SCSI_WQ_STEERING_SHIFT;
1579 	io->wq_class = (flags & OCS_SCSI_WQ_CLASS_MASK) >> OCS_SCSI_WQ_CLASS_SHIFT;
1580 
1581 	return ocs_scsi_io_dispatch(io, ocs_target_io_cb);
1582 }
1583 
1584 
1585 int32_t
ocs_scsi_send_rd_data(ocs_io_t * io,uint32_t flags,ocs_scsi_dif_info_t * dif_info,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,uint32_t len,ocs_scsi_io_cb_t cb,void * arg)1586 ocs_scsi_send_rd_data(ocs_io_t *io, uint32_t flags,
1587 	ocs_scsi_dif_info_t *dif_info,
1588 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t len,
1589 	ocs_scsi_io_cb_t cb, void *arg)
1590 {
1591 	return ocs_scsi_xfer_data(io, flags, dif_info, sgl, sgl_count, len, OCS_HW_IO_TARGET_READ,
1592 				  enable_tsend_auto_resp(io->ocs), cb, arg);
1593 }
1594 
1595 int32_t
ocs_scsi_recv_wr_data(ocs_io_t * io,uint32_t flags,ocs_scsi_dif_info_t * dif_info,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,uint32_t len,ocs_scsi_io_cb_t cb,void * arg)1596 ocs_scsi_recv_wr_data(ocs_io_t *io, uint32_t flags,
1597 	ocs_scsi_dif_info_t *dif_info,
1598 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t len,
1599 	ocs_scsi_io_cb_t cb, void *arg)
1600 {
1601 	return ocs_scsi_xfer_data(io, flags, dif_info, sgl, sgl_count, len, OCS_HW_IO_TARGET_WRITE,
1602 				  enable_treceive_auto_resp(io->ocs), cb, arg);
1603 }
1604 
1605 /**
1606  * @ingroup scsi_api_base
1607  * @brief Free overflow SGL.
1608  *
1609  * @par Description
1610  * Free the overflow SGL if it is present.
1611  *
1612  * @param io Pointer to IO object.
1613  *
1614  * @return None.
1615  */
1616 static void
ocs_scsi_io_free_ovfl(ocs_io_t * io)1617 ocs_scsi_io_free_ovfl(ocs_io_t *io) {
1618 	if (io->ovfl_sgl.size) {
1619 		ocs_dma_free(io->ocs, &io->ovfl_sgl);
1620 	}
1621 }
1622 
1623 /**
1624  * @ingroup scsi_api_base
1625  * @brief Send response data.
1626  *
1627  * @par Description
1628  * This function is used by a target-server to send the SCSI response data to a remote
1629  * initiator node. The target-server populates the @c ocs_scsi_cmd_resp_t
1630  * argument with scsi status, status qualifier, sense data, and response data, as
1631  * needed.
1632  * @n @n
1633  * Upon completion, the callback function @c cb is invoked. The target-server will generally
1634  * clean up its IO context resources and call ocs_scsi_io_complete().
1635  *
1636  * @param io Pointer to the IO context.
1637  * @param flags Flags to control sending of the SCSI response.
1638  * @param rsp Pointer to the response data populated by the caller.
1639  * @param cb Completion callback.
1640  * @param arg Application-specified completion callback argument.
1641 
1642  * @return Returns 0 on success, or a negative error code value on failure.
1643  */
1644 int32_t
ocs_scsi_send_resp(ocs_io_t * io,uint32_t flags,ocs_scsi_cmd_resp_t * rsp,ocs_scsi_io_cb_t cb,void * arg)1645 ocs_scsi_send_resp(ocs_io_t *io, uint32_t flags, ocs_scsi_cmd_resp_t *rsp, ocs_scsi_io_cb_t cb, void *arg)
1646 {
1647 	ocs_t *ocs;
1648 	int32_t residual;
1649 	int auto_resp = TRUE;		/* Always try auto resp */
1650 	uint8_t scsi_status = 0;
1651 	uint16_t scsi_status_qualifier = 0;
1652 	uint8_t *sense_data = NULL;
1653 	uint32_t sense_data_length = 0;
1654 
1655 	ocs_assert(io, -1);
1656 
1657 	ocs = io->ocs;
1658 	ocs_assert(ocs, -1);
1659 
1660 	ocs_assert(io->node, -1);
1661 
1662 	ocs_scsi_convert_dif_info(ocs, NULL, &io->hw_dif);
1663 
1664 	if (rsp) {
1665 		scsi_status = rsp->scsi_status;
1666 		scsi_status_qualifier = rsp->scsi_status_qualifier;
1667 		sense_data = rsp->sense_data;
1668 		sense_data_length = rsp->sense_data_length;
1669 		residual = rsp->residual;
1670 	} else {
1671 		residual = io->exp_xfer_len - io->transferred;
1672 	}
1673 
1674 	io->wire_len = 0;
1675 	io->hio_type = OCS_HW_IO_TARGET_RSP;
1676 
1677 	io->scsi_tgt_cb = cb;
1678 	io->scsi_tgt_cb_arg = arg;
1679 
1680 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1681 	io->iparam.fcp_tgt.ox_id = io->init_task_tag;
1682 	io->iparam.fcp_tgt.offset = 0;
1683 	io->iparam.fcp_tgt.cs_ctl = io->cs_ctl;
1684 	io->iparam.fcp_tgt.timeout = io->timeout;
1685 
1686 	/* Set low latency queueing request */
1687 	io->low_latency = (flags & OCS_SCSI_LOW_LATENCY) != 0;
1688 	io->wq_steering = (flags & OCS_SCSI_WQ_STEERING_MASK) >> OCS_SCSI_WQ_STEERING_SHIFT;
1689 	io->wq_class = (flags & OCS_SCSI_WQ_CLASS_MASK) >> OCS_SCSI_WQ_CLASS_SHIFT;
1690 
1691 	if ((scsi_status != 0) || residual || sense_data_length) {
1692 		fcp_rsp_iu_t *fcprsp = io->rspbuf.virt;
1693 
1694 		if (!fcprsp) {
1695 			ocs_log_err(ocs, "NULL response buffer\n");
1696 			return -1;
1697 		}
1698 
1699 		auto_resp = FALSE;
1700 
1701 		ocs_memset(fcprsp, 0, sizeof(*fcprsp));
1702 
1703 		io->wire_len += (sizeof(*fcprsp) - sizeof(fcprsp->data));
1704 
1705 		fcprsp->scsi_status = scsi_status;
1706 		*((uint16_t*)fcprsp->status_qualifier) = ocs_htobe16(scsi_status_qualifier);
1707 
1708 		/* set residual status if necessary */
1709 		if (residual != 0) {
1710 			/* FCP: if data transferred is less than the amount expected, then this is an
1711 			 * underflow.  If data transferred would have been greater than the amount expected
1712 			 * then this is an overflow
1713 			 */
1714 			if (residual > 0) {
1715 				fcprsp->flags |= FCP_RESID_UNDER;
1716 				*((uint32_t *)fcprsp->fcp_resid) = ocs_htobe32(residual);
1717 			} else {
1718 				fcprsp->flags |= FCP_RESID_OVER;
1719 				*((uint32_t *)fcprsp->fcp_resid) = ocs_htobe32(-residual);
1720 			}
1721 		}
1722 
1723 		if (sense_data && sense_data_length) {
1724 			ocs_assert(sense_data_length <= sizeof(fcprsp->data), -1);
1725 			fcprsp->flags |= FCP_SNS_LEN_VALID;
1726 			ocs_memcpy(fcprsp->data, sense_data, sense_data_length);
1727 			*((uint32_t*)fcprsp->fcp_sns_len) = ocs_htobe32(sense_data_length);
1728 			io->wire_len += sense_data_length;
1729 		}
1730 
1731 		io->sgl[0].addr = io->rspbuf.phys;
1732 		io->sgl[0].dif_addr = 0;
1733 		io->sgl[0].len = io->wire_len;
1734 		io->sgl_count = 1;
1735 	}
1736 
1737 	if (auto_resp) {
1738 		io->iparam.fcp_tgt.flags |= SLI4_IO_AUTO_GOOD_RESPONSE;
1739 	}
1740 
1741 	return ocs_scsi_io_dispatch(io, ocs_target_io_cb);
1742 }
1743 
1744 /**
1745  * @ingroup scsi_api_base
1746  * @brief Send TMF response data.
1747  *
1748  * @par Description
1749  * This function is used by a target-server to send SCSI TMF response data to a remote
1750  * initiator node.
1751  * Upon completion, the callback function @c cb is invoked. The target-server will generally
1752  * clean up its IO context resources and call ocs_scsi_io_complete().
1753  *
1754  * @param io Pointer to the IO context.
1755  * @param rspcode TMF response code.
1756  * @param addl_rsp_info Additional TMF response information (may be NULL for zero data).
1757  * @param cb Completion callback.
1758  * @param arg Application-specified completion callback argument.
1759  *
1760  * @return Returns 0 on success, or a negative error code value on failure.
1761  */
1762 int32_t
ocs_scsi_send_tmf_resp(ocs_io_t * io,ocs_scsi_tmf_resp_e rspcode,uint8_t addl_rsp_info[3],ocs_scsi_io_cb_t cb,void * arg)1763 ocs_scsi_send_tmf_resp(ocs_io_t *io, ocs_scsi_tmf_resp_e rspcode, uint8_t addl_rsp_info[3],
1764 		ocs_scsi_io_cb_t cb, void *arg)
1765 {
1766 	int32_t rc = -1;
1767 	ocs_t *ocs = NULL;
1768 	fcp_rsp_iu_t *fcprsp = NULL;
1769 	fcp_rsp_info_t *rspinfo = NULL;
1770 	uint8_t fcp_rspcode;
1771 
1772 	ocs_assert(io, -1);
1773 	ocs_assert(io->ocs, -1);
1774 	ocs_assert(io->node, -1);
1775 
1776 	ocs = io->ocs;
1777 
1778 	io->wire_len = 0;
1779 	ocs_scsi_convert_dif_info(ocs, NULL, &io->hw_dif);
1780 
1781 	switch(rspcode) {
1782 	case OCS_SCSI_TMF_FUNCTION_COMPLETE:
1783 		fcp_rspcode = FCP_TMF_COMPLETE;
1784 		break;
1785 	case OCS_SCSI_TMF_FUNCTION_SUCCEEDED:
1786 	case OCS_SCSI_TMF_FUNCTION_IO_NOT_FOUND:
1787 		fcp_rspcode = FCP_TMF_SUCCEEDED;
1788 		break;
1789 	case OCS_SCSI_TMF_FUNCTION_REJECTED:
1790 		fcp_rspcode = FCP_TMF_REJECTED;
1791 		break;
1792 	case OCS_SCSI_TMF_INCORRECT_LOGICAL_UNIT_NUMBER:
1793 		fcp_rspcode = FCP_TMF_INCORRECT_LUN;
1794 		break;
1795 	case OCS_SCSI_TMF_SERVICE_DELIVERY:
1796 		fcp_rspcode = FCP_TMF_FAILED;
1797 		break;
1798 	default:
1799 		fcp_rspcode = FCP_TMF_REJECTED;
1800 		break;
1801 	}
1802 
1803 	io->hio_type = OCS_HW_IO_TARGET_RSP;
1804 
1805 	io->scsi_tgt_cb = cb;
1806 	io->scsi_tgt_cb_arg = arg;
1807 
1808 	if (io->tmf_cmd == OCS_SCSI_TMF_ABORT_TASK) {
1809 		rc = ocs_target_send_bls_resp(io, cb, arg);
1810 		return rc;
1811 	}
1812 
1813 	/* populate the FCP TMF response */
1814 	fcprsp = io->rspbuf.virt;
1815 	ocs_memset(fcprsp, 0, sizeof(*fcprsp));
1816 
1817 	fcprsp->flags |= FCP_RSP_LEN_VALID;
1818 
1819 	rspinfo = (fcp_rsp_info_t*) fcprsp->data;
1820 	if (addl_rsp_info != NULL) {
1821 		ocs_memcpy(rspinfo->addl_rsp_info, addl_rsp_info, sizeof(rspinfo->addl_rsp_info));
1822 	}
1823 	rspinfo->rsp_code = fcp_rspcode;
1824 
1825 	io->wire_len = sizeof(*fcprsp) - sizeof(fcprsp->data) + sizeof(*rspinfo);
1826 
1827 	*((uint32_t*)fcprsp->fcp_rsp_len) = ocs_htobe32(sizeof(*rspinfo));
1828 
1829 	io->sgl[0].addr = io->rspbuf.phys;
1830 	io->sgl[0].dif_addr = 0;
1831 	io->sgl[0].len = io->wire_len;
1832 	io->sgl_count = 1;
1833 
1834 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1835 	io->iparam.fcp_tgt.ox_id = io->init_task_tag;
1836 	io->iparam.fcp_tgt.offset = 0;
1837 	io->iparam.fcp_tgt.cs_ctl = io->cs_ctl;
1838 	io->iparam.fcp_tgt.timeout = io->timeout;
1839 
1840 	rc = ocs_scsi_io_dispatch(io, ocs_target_io_cb);
1841 
1842 	return rc;
1843 }
1844 
1845 
1846 /**
1847  * @brief Process target abort callback.
1848  *
1849  * @par Description
1850  * Accepts HW abort requests.
1851  *
1852  * @param hio HW IO context.
1853  * @param rnode Remote node.
1854  * @param length Length of response data.
1855  * @param status Completion status.
1856  * @param ext_status Extended completion status.
1857  * @param app Application-specified callback data.
1858  *
1859  * @return Returns 0 on success, or a negative error code value on failure.
1860  */
1861 
1862 static int32_t
ocs_target_abort_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * app)1863 ocs_target_abort_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
1864 {
1865 	ocs_io_t *io = app;
1866 	ocs_t *ocs;
1867 	ocs_scsi_io_status_e scsi_status;
1868 
1869 	ocs_assert(io, -1);
1870 	ocs_assert(io->ocs, -1);
1871 
1872 	ocs = io->ocs;
1873 
1874 	if (io->abort_cb) {
1875 		ocs_scsi_io_cb_t abort_cb = io->abort_cb;
1876 		void *abort_cb_arg = io->abort_cb_arg;
1877 
1878 		io->abort_cb = NULL;
1879 		io->abort_cb_arg = NULL;
1880 
1881 		switch (status) {
1882 		case SLI4_FC_WCQE_STATUS_SUCCESS:
1883 			scsi_status = OCS_SCSI_STATUS_GOOD;
1884 			break;
1885 		case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
1886 			switch (ext_status) {
1887 			case SLI4_FC_LOCAL_REJECT_NO_XRI:
1888 				scsi_status = OCS_SCSI_STATUS_NO_IO;
1889 				break;
1890 			case SLI4_FC_LOCAL_REJECT_ABORT_IN_PROGRESS:
1891 				scsi_status = OCS_SCSI_STATUS_ABORT_IN_PROGRESS;
1892 				break;
1893 			default:
1894 				/* TODO: we have seen 0x15 (abort in progress) */
1895 				scsi_status = OCS_SCSI_STATUS_ERROR;
1896 				break;
1897 			}
1898 			break;
1899 		case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE:
1900 			scsi_status = OCS_SCSI_STATUS_CHECK_RESPONSE;
1901 			break;
1902 		default:
1903 			scsi_status = OCS_SCSI_STATUS_ERROR;
1904 			break;
1905 		}
1906 		/* invoke callback */
1907 		abort_cb(io->io_to_abort, scsi_status, 0, abort_cb_arg);
1908 	}
1909 
1910 	ocs_assert(io != io->io_to_abort, -1);
1911 
1912 	/* done with IO to abort */
1913 	ocs_ref_put(&io->io_to_abort->ref); /* ocs_ref_get(): ocs_scsi_tgt_abort_io() */
1914 
1915 	ocs_io_free(ocs, io);
1916 
1917 	ocs_scsi_check_pending(ocs);
1918 	return 0;
1919 }
1920 
1921 /**
1922  * @ingroup scsi_api_base
1923  * @brief Abort a target IO.
1924  *
1925  * @par Description
1926  * This routine is called from a SCSI target-server. It initiates an abort of a
1927  * previously-issued target data phase or response request.
1928  *
1929  * @param io IO context.
1930  * @param cb SCSI target server callback.
1931  * @param arg SCSI target server supplied callback argument.
1932  *
1933  * @return Returns 0 on success, or a non-zero value on failure.
1934  */
1935 int32_t
ocs_scsi_tgt_abort_io(ocs_io_t * io,ocs_scsi_io_cb_t cb,void * arg)1936 ocs_scsi_tgt_abort_io(ocs_io_t *io, ocs_scsi_io_cb_t cb, void *arg)
1937 {
1938 	ocs_t *ocs;
1939 	ocs_xport_t *xport;
1940 	int32_t rc;
1941 
1942 	ocs_io_t *abort_io = NULL;
1943 	ocs_assert(io, -1);
1944 	ocs_assert(io->node, -1);
1945 	ocs_assert(io->ocs, -1);
1946 
1947 	ocs = io->ocs;
1948 	xport = ocs->xport;
1949 
1950 	/* take a reference on IO being aborted */
1951 	if ((ocs_ref_get_unless_zero(&io->ref) == 0)) {
1952 		/* command no longer active */
1953 		scsi_io_printf(io, "command no longer active\n");
1954 		return -1;
1955 	}
1956 
1957 	/*
1958 	 * allocate a new IO to send the abort request. Use ocs_io_alloc() directly, as
1959 	 * we need an IO object that will not fail allocation due to allocations being
1960 	 * disabled (in ocs_scsi_io_alloc())
1961 	 */
1962 	abort_io = ocs_io_alloc(ocs);
1963 	if (abort_io == NULL) {
1964 		ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
1965 		ocs_ref_put(&io->ref); /* ocs_ref_get(): same function */
1966 		return -1;
1967 	}
1968 
1969 	/* Save the target server callback and argument */
1970 	ocs_assert(abort_io->hio == NULL, -1);
1971 
1972 	/* set generic fields */
1973 	abort_io->cmd_tgt = TRUE;
1974 	abort_io->node = io->node;
1975 
1976 	/* set type and abort-specific fields */
1977 	abort_io->io_type = OCS_IO_TYPE_ABORT;
1978 	abort_io->display_name = "tgt_abort";
1979 	abort_io->io_to_abort = io;
1980 	abort_io->send_abts = FALSE;
1981 	abort_io->abort_cb = cb;
1982 	abort_io->abort_cb_arg = arg;
1983 
1984 	/* now dispatch IO */
1985 	rc = ocs_scsi_io_dispatch_abort(abort_io, ocs_target_abort_cb);
1986 	if (rc) {
1987 		ocs_ref_put(&io->ref); /* ocs_ref_get(): same function */
1988 	}
1989 	return rc;
1990 }
1991 
1992 /**
1993  * @brief Process target BLS response callback.
1994  *
1995  * @par Description
1996  * Accepts HW abort requests.
1997  *
1998  * @param hio HW IO context.
1999  * @param rnode Remote node.
2000  * @param length Length of response data.
2001  * @param status Completion status.
2002  * @param ext_status Extended completion status.
2003  * @param app Application-specified callback data.
2004  *
2005  * @return Returns 0 on success, or a negative error code value on failure.
2006  */
2007 
2008 static int32_t
ocs_target_bls_resp_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * app)2009 ocs_target_bls_resp_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
2010 {
2011 	ocs_io_t *io = app;
2012 	ocs_t *ocs;
2013 	ocs_scsi_io_status_e bls_status;
2014 
2015 	ocs_assert(io, -1);
2016 	ocs_assert(io->ocs, -1);
2017 
2018 	ocs = io->ocs;
2019 
2020 	/* BLS isn't really a "SCSI" concept, but use SCSI status */
2021 	if (status) {
2022 		io_error_log(io, "s=%#x x=%#x\n", status, ext_status);
2023 		bls_status = OCS_SCSI_STATUS_ERROR;
2024 	} else {
2025 		bls_status = OCS_SCSI_STATUS_GOOD;
2026 	}
2027 
2028 	if (io->bls_cb) {
2029 		ocs_scsi_io_cb_t bls_cb = io->bls_cb;
2030 		void *bls_cb_arg = io->bls_cb_arg;
2031 
2032 		io->bls_cb = NULL;
2033 		io->bls_cb_arg = NULL;
2034 
2035 		/* invoke callback */
2036 		bls_cb(io, bls_status, 0, bls_cb_arg);
2037 	}
2038 
2039 	ocs_scsi_check_pending(ocs);
2040 	return 0;
2041 }
2042 
2043 /**
2044  * @brief Complete abort request.
2045  *
2046  * @par Description
2047  * An abort request is completed by posting a BA_ACC for the IO that requested the abort.
2048  *
2049  * @param io Pointer to the IO context.
2050  * @param cb Callback function to invoke upon completion.
2051  * @param arg Application-specified completion callback argument.
2052  *
2053  * @return Returns 0 on success, or a negative error code value on failure.
2054  */
2055 
2056 static int32_t
ocs_target_send_bls_resp(ocs_io_t * io,ocs_scsi_io_cb_t cb,void * arg)2057 ocs_target_send_bls_resp(ocs_io_t *io, ocs_scsi_io_cb_t cb, void *arg)
2058 {
2059 	int32_t rc;
2060 	fc_ba_acc_payload_t *acc;
2061 
2062 	ocs_assert(io, -1);
2063 
2064 	/* fill out IO structure with everything needed to send BA_ACC */
2065 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
2066 	io->iparam.bls.ox_id = io->init_task_tag;
2067 	io->iparam.bls.rx_id = io->abort_rx_id;
2068 
2069 	acc = (void *)io->iparam.bls.payload;
2070 
2071 	ocs_memset(io->iparam.bls.payload, 0, sizeof(io->iparam.bls.payload));
2072 	acc->ox_id = io->iparam.bls.ox_id;
2073 	acc->rx_id = io->iparam.bls.rx_id;
2074 	acc->high_seq_cnt = UINT16_MAX;
2075 
2076 	/* generic io fields have already been populated */
2077 
2078 	/* set type and BLS-specific fields */
2079 	io->io_type = OCS_IO_TYPE_BLS_RESP;
2080 	io->display_name = "bls_rsp";
2081 	io->hio_type = OCS_HW_BLS_ACC;
2082 	io->bls_cb = cb;
2083 	io->bls_cb_arg = arg;
2084 
2085 	/* dispatch IO */
2086 	rc = ocs_scsi_io_dispatch(io, ocs_target_bls_resp_cb);
2087 	return rc;
2088 }
2089 
2090 /**
2091  * @ingroup scsi_api_base
2092  * @brief Notify the base driver that the IO is complete.
2093  *
2094  * @par Description
2095  * This function is called by a target-server to notify the base driver that an IO
2096  * has completed, allowing for the base driver to free resources.
2097  * @n
2098  * @n @b Note: This function is not called by initiator-clients.
2099  *
2100  * @param io Pointer to IO context.
2101  *
2102  * @return None.
2103  */
2104 void
ocs_scsi_io_complete(ocs_io_t * io)2105 ocs_scsi_io_complete(ocs_io_t *io)
2106 {
2107 	ocs_assert(io);
2108 
2109 	if (!ocs_io_busy(io)) {
2110 		ocs_log_test(io->ocs, "Got completion for non-busy io with tag 0x%x\n", io->tag);
2111 		return;
2112 	}
2113 
2114 	scsi_io_trace(io, "freeing io 0x%p %s\n", io, io->display_name);
2115 	ocs_assert(ocs_ref_read_count(&io->ref) > 0);
2116 	ocs_ref_put(&io->ref); /* ocs_ref_get(): ocs_scsi_io_alloc() */
2117 }
2118 
2119 
2120 /**
2121  * @brief Handle initiator IO completion.
2122  *
2123  * @par Description
2124  * This callback is made upon completion of an initiator operation (initiator read/write command).
2125  *
2126  * @param hio HW IO context.
2127  * @param rnode Remote node.
2128  * @param length Length of completion data.
2129  * @param status Completion status.
2130  * @param ext_status Extended completion status.
2131  * @param app Application-specified callback data.
2132  *
2133  * @return None.
2134  */
2135 
2136 static void
ocs_initiator_io_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * app)2137 ocs_initiator_io_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length,
2138 	int32_t status, uint32_t ext_status, void *app)
2139 {
2140 	ocs_io_t *io = app;
2141 	ocs_t *ocs;
2142 	ocs_scsi_io_status_e scsi_status;
2143 
2144 	ocs_assert(io);
2145 	ocs_assert(io->scsi_ini_cb);
2146 
2147 	scsi_io_trace(io, "status x%x ext_status x%x\n", status, ext_status);
2148 
2149 	ocs = io->ocs;
2150 	ocs_assert(ocs);
2151 
2152 	ocs_scsi_io_free_ovfl(io);
2153 
2154 	/* Call target server completion */
2155 	if (io->scsi_ini_cb) {
2156 		fcp_rsp_iu_t *fcprsp = io->rspbuf.virt;
2157 		ocs_scsi_cmd_resp_t rsp;
2158 		ocs_scsi_rsp_io_cb_t cb = io->scsi_ini_cb;
2159 		uint32_t flags = 0;
2160 		uint8_t *pd = fcprsp->data;
2161 
2162 		/* Clear the callback before invoking the callback */
2163 		io->scsi_ini_cb = NULL;
2164 
2165 		ocs_memset(&rsp, 0, sizeof(rsp));
2166 
2167 		/* Unless status is FCP_RSP_FAILURE, fcprsp is not filled in */
2168 		switch (status) {
2169 		case SLI4_FC_WCQE_STATUS_SUCCESS:
2170 			scsi_status = OCS_SCSI_STATUS_GOOD;
2171 			break;
2172 		case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE:
2173 			scsi_status = OCS_SCSI_STATUS_CHECK_RESPONSE;
2174 			rsp.scsi_status = fcprsp->scsi_status;
2175 			rsp.scsi_status_qualifier = ocs_be16toh(*((uint16_t*)fcprsp->status_qualifier));
2176 
2177 			if (fcprsp->flags & FCP_RSP_LEN_VALID) {
2178 				rsp.response_data = pd;
2179 				rsp.response_data_length = ocs_fc_getbe32(fcprsp->fcp_rsp_len);
2180 				pd += rsp.response_data_length;
2181 			}
2182 			if (fcprsp->flags & FCP_SNS_LEN_VALID) {
2183 				uint32_t sns_len = ocs_fc_getbe32(fcprsp->fcp_sns_len);
2184 				rsp.sense_data = pd;
2185 				rsp.sense_data_length = sns_len;
2186 				pd += sns_len;
2187 			}
2188 			/* Set residual */
2189 			if (fcprsp->flags & FCP_RESID_OVER) {
2190 				rsp.residual = -ocs_fc_getbe32(fcprsp->fcp_resid);
2191 				rsp.response_wire_length = length;
2192 			} else	if (fcprsp->flags & FCP_RESID_UNDER) {
2193 				rsp.residual = ocs_fc_getbe32(fcprsp->fcp_resid);
2194 				rsp.response_wire_length = length;
2195 			}
2196 
2197 			/*
2198 			 * Note: The FCP_RSP_FAILURE can be returned for initiator IOs when the total data
2199 			 * placed does not match the requested length even if the status is good. If
2200 			 * the status is all zeroes, then we have to assume that a frame(s) were
2201 			 * dropped and change the status to LOCAL_REJECT/OUT_OF_ORDER_DATA
2202 			 */
2203 			if (length != io->wire_len) {
2204 				uint32_t rsp_len = ext_status;
2205 				uint8_t *rsp_bytes = io->rspbuf.virt;
2206 				uint32_t i;
2207 				uint8_t all_zeroes = (rsp_len > 0);
2208 				/* Check if the rsp is zero */
2209 				for (i = 0; i < rsp_len; i++) {
2210 					if (rsp_bytes[i] != 0) {
2211 						all_zeroes = FALSE;
2212 						break;
2213 					}
2214 				}
2215 				if (all_zeroes) {
2216 					scsi_status = OCS_SCSI_STATUS_ERROR;
2217 					ocs_log_test(io->ocs, "[%s]" SCSI_IOFMT "local reject=0x%02x\n",
2218 						     io->node->display_name, SCSI_IOFMT_ARGS(io),
2219 						     SLI4_FC_LOCAL_REJECT_OUT_OF_ORDER_DATA);
2220 				}
2221 			}
2222 			break;
2223 		case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
2224 			if (ext_status == SLI4_FC_LOCAL_REJECT_SEQUENCE_TIMEOUT) {
2225 				scsi_status = OCS_SCSI_STATUS_COMMAND_TIMEOUT;
2226 			} else {
2227 				scsi_status = OCS_SCSI_STATUS_ERROR;
2228 			}
2229 			break;
2230 		case SLI4_FC_WCQE_STATUS_DI_ERROR:
2231 			if (ext_status & 0x01) {
2232 				scsi_status = OCS_SCSI_STATUS_DIF_GUARD_ERROR;
2233 			} else if (ext_status & 0x02) {
2234 				scsi_status = OCS_SCSI_STATUS_DIF_APP_TAG_ERROR;
2235 			} else if (ext_status & 0x04) {
2236 				scsi_status = OCS_SCSI_STATUS_DIF_REF_TAG_ERROR;
2237 			} else {
2238 				scsi_status = OCS_SCSI_STATUS_DIF_UNKNOWN_ERROR;
2239 			}
2240 			break;
2241 		default:
2242 			scsi_status = OCS_SCSI_STATUS_ERROR;
2243 			break;
2244 		}
2245 
2246 		cb(io, scsi_status, &rsp, flags, io->scsi_ini_cb_arg);
2247 
2248 	}
2249 	ocs_scsi_check_pending(ocs);
2250 }
2251 
2252 /**
2253  * @ingroup scsi_api_base
2254  * @brief Initiate initiator read IO.
2255  *
2256  * @par Description
2257  * This call is made by an initiator-client to send a SCSI read command. The payload
2258  * for the command is given by a scatter-gather list @c sgl for @c sgl_count
2259  * entries.
2260  * @n @n
2261  * Upon completion, the callback @b cb is invoked and passed request status.
2262  * If the command completed successfully, the callback is given SCSI response data.
2263  *
2264  * @param node Pointer to the node.
2265  * @param io Pointer to the IO context.
2266  * @param lun LUN value.
2267  * @param cdb Pointer to the CDB.
2268  * @param cdb_len Length of the CDB.
2269  * @param dif_info Pointer to the T10 DIF fields, or NULL if no DIF.
2270  * @param sgl Pointer to the scatter-gather list.
2271  * @param sgl_count Count of the scatter-gather list elements.
2272  * @param wire_len Length of the payload.
2273  * @param cb Completion callback.
2274  * @param arg Application-specified completion callback argument.
2275  *
2276  * @return Returns 0 on success, or a negative error code value on failure.
2277  */
2278 int32_t
ocs_scsi_send_rd_io(ocs_node_t * node,ocs_io_t * io,uint64_t lun,void * cdb,uint32_t cdb_len,ocs_scsi_dif_info_t * dif_info,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,uint32_t wire_len,ocs_scsi_rsp_io_cb_t cb,void * arg,uint32_t flags)2279 ocs_scsi_send_rd_io(ocs_node_t *node, ocs_io_t *io, uint64_t lun, void *cdb, uint32_t cdb_len,
2280 	ocs_scsi_dif_info_t *dif_info,
2281 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len,
2282 	ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags)
2283 {
2284 	int32_t rc;
2285 
2286 	rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_READ, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count,
2287 			      wire_len, 0, cb, arg, flags);
2288 
2289 	return rc;
2290 }
2291 
2292 /**
2293  * @ingroup scsi_api_base
2294  * @brief Initiate initiator write IO.
2295  *
2296  * @par Description
2297  * This call is made by an initiator-client to send a SCSI write command. The payload
2298  * for the command is given by a scatter-gather list @c sgl for @c sgl_count
2299  * entries.
2300  * @n @n
2301  * Upon completion, the callback @c cb is invoked and passed request status. If the command
2302  * completed successfully, the callback is given SCSI response data.
2303  *
2304  * @param node Pointer to the node.
2305  * @param io Pointer to IO context.
2306  * @param lun LUN value.
2307  * @param cdb Pointer to the CDB.
2308  * @param cdb_len Length of the CDB.
2309  * @param dif_info Pointer to the T10 DIF fields, or NULL if no DIF.
2310  * @param sgl Pointer to the scatter-gather list.
2311  * @param sgl_count Count of the scatter-gather list elements.
2312  * @param wire_len Length of the payload.
2313  * @param cb Completion callback.
2314  * @param arg Application-specified completion callback argument.
2315  *
2316  * @return Returns 0 on success, or a negative error code value on failure.
2317  */
ocs_scsi_send_wr_io(ocs_node_t * node,ocs_io_t * io,uint64_t lun,void * cdb,uint32_t cdb_len,ocs_scsi_dif_info_t * dif_info,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,uint32_t wire_len,ocs_scsi_rsp_io_cb_t cb,void * arg,uint32_t flags)2318 int32_t ocs_scsi_send_wr_io(ocs_node_t *node, ocs_io_t *io, uint64_t lun, void *cdb, uint32_t cdb_len,
2319 	ocs_scsi_dif_info_t *dif_info,
2320 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len,
2321 	ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags)
2322 {
2323 	int32_t rc;
2324 
2325 	rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_WRITE, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count,
2326 			      wire_len, 0, cb, arg, flags);
2327 
2328 	return rc;
2329 }
2330 
2331 /**
2332  * @ingroup scsi_api_base
2333  * @brief Initiate initiator write IO.
2334  *
2335  * @par Description
2336  * This call is made by an initiator-client to send a SCSI write command. The payload
2337  * for the command is given by a scatter-gather list @c sgl for @c sgl_count
2338  * entries.
2339  * @n @n
2340  * Upon completion, the callback @c cb is invoked and passed request status. If the command
2341  * completed successfully, the callback is given SCSI response data.
2342  *
2343  * @param node Pointer to the node.
2344  * @param io Pointer to IO context.
2345  * @param lun LUN value.
2346  * @param cdb Pointer to the CDB.
2347  * @param cdb_len Length of the CDB.
2348  * @param dif_info Pointer to the T10 DIF fields, or NULL if no DIF.
2349  * @param sgl Pointer to the scatter-gather list.
2350  * @param sgl_count Count of the scatter-gather list elements.
2351  * @param wire_len Length of the payload.
2352  * @param first_burst Number of first burst bytes to send.
2353  * @param cb Completion callback.
2354  * @param arg Application-specified completion callback argument.
2355  *
2356  * @return Returns 0 on success, or a negative error code value on failure.
2357  */
2358 int32_t
ocs_scsi_send_wr_io_first_burst(ocs_node_t * node,ocs_io_t * io,uint64_t lun,void * cdb,uint32_t cdb_len,ocs_scsi_dif_info_t * dif_info,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,uint32_t wire_len,uint32_t first_burst,ocs_scsi_rsp_io_cb_t cb,void * arg,uint32_t flags)2359 ocs_scsi_send_wr_io_first_burst(ocs_node_t *node, ocs_io_t *io, uint64_t lun, void *cdb, uint32_t cdb_len,
2360 	ocs_scsi_dif_info_t *dif_info,
2361 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst,
2362 	ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags)
2363 {
2364 	int32_t rc;
2365 
2366 	rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_WRITE, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count,
2367 			      wire_len, 0, cb, arg, flags);
2368 
2369 	return rc;
2370 }
2371 
2372 /**
2373  * @ingroup scsi_api_base
2374  * @brief Initiate initiator SCSI command with no data.
2375  *
2376  * @par Description
2377  * This call is made by an initiator-client to send a SCSI command with no data.
2378  * @n @n
2379  * Upon completion, the callback @c cb is invoked and passed request status. If the command
2380  * completed successfully, the callback is given SCSI response data.
2381  *
2382  * @param node Pointer to the node.
2383  * @param io Pointer to the IO context.
2384  * @param lun LUN value.
2385  * @param cdb Pointer to the CDB.
2386  * @param cdb_len Length of the CDB.
2387  * @param cb Completion callback.
2388  * @param arg Application-specified completion callback argument.
2389  *
2390  * @return Returns 0 on success, or a negative error code value on failure.
2391  */
ocs_scsi_send_nodata_io(ocs_node_t * node,ocs_io_t * io,uint64_t lun,void * cdb,uint32_t cdb_len,ocs_scsi_rsp_io_cb_t cb,void * arg,uint32_t flags)2392 int32_t ocs_scsi_send_nodata_io(ocs_node_t *node, ocs_io_t *io, uint64_t lun, void *cdb, uint32_t cdb_len,
2393 	ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags)
2394 {
2395 	int32_t rc;
2396 
2397 	rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_NODATA, node, io, lun, 0, cdb, cdb_len, NULL, NULL, 0, 0, 0, cb, arg, flags);
2398 
2399 	return rc;
2400 }
2401 /**
2402  * @ingroup scsi_api_base
2403  * @brief Initiate initiator task management operation.
2404  *
2405  * @par Description
2406  * This command is used to send a SCSI task management function command. If the command
2407  * requires it (QUERY_TASK_SET for example), a payload may be associated with the command.
2408  * If no payload is required, then @c sgl_count may be zero and @c sgl is ignored.
2409  * @n @n
2410  * Upon completion @c cb is invoked with status and SCSI response data.
2411  *
2412  * @param node Pointer to the node.
2413  * @param io Pointer to the IO context.
2414  * @param io_to_abort Pointer to the IO context to abort in the
2415  * case of OCS_SCSI_TMF_ABORT_TASK. Note: this can point to the
2416  * same the same ocs_io_t as @c io, provided that @c io does not
2417  * have any outstanding work requests.
2418  * @param lun LUN value.
2419  * @param tmf Task management command.
2420  * @param sgl Pointer to the scatter-gather list.
2421  * @param sgl_count Count of the scatter-gather list elements.
2422  * @param len Length of the payload.
2423  * @param cb Completion callback.
2424  * @param arg Application-specified completion callback argument.
2425  *
2426  * @return Returns 0 on success, or a negative error code value on failure.
2427  */
2428 int32_t
ocs_scsi_send_tmf(ocs_node_t * node,ocs_io_t * io,ocs_io_t * io_to_abort,uint64_t lun,ocs_scsi_tmf_cmd_e tmf,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,uint32_t len,ocs_scsi_rsp_io_cb_t cb,void * arg)2429 ocs_scsi_send_tmf(ocs_node_t *node, ocs_io_t *io, ocs_io_t *io_to_abort, uint64_t lun, ocs_scsi_tmf_cmd_e tmf,
2430 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t len, ocs_scsi_rsp_io_cb_t cb, void *arg)
2431 {
2432 	int32_t rc;
2433 	ocs_assert(io, -1);
2434 
2435 	if (tmf == OCS_SCSI_TMF_ABORT_TASK) {
2436 		ocs_assert(io_to_abort, -1);
2437 
2438 		/* take a reference on IO being aborted */
2439 		if ((ocs_ref_get_unless_zero(&io_to_abort->ref) == 0)) {
2440 			/* command no longer active */
2441 			scsi_io_printf(io, "command no longer active\n");
2442 			return -1;
2443 		}
2444 		/* generic io fields have already been populated */
2445 
2446 		/* abort-specific fields */
2447 		io->io_type = OCS_IO_TYPE_ABORT;
2448 		io->display_name = "abort_task";
2449 		io->io_to_abort = io_to_abort;
2450 		io->send_abts = TRUE;
2451 		io->scsi_ini_cb = cb;
2452 		io->scsi_ini_cb_arg = arg;
2453 
2454 		/* now dispatch IO */
2455 		rc = ocs_scsi_io_dispatch_abort(io, ocs_scsi_abort_io_cb);
2456 		if (rc) {
2457 			scsi_io_printf(io, "Failed to dispatch abort\n");
2458 			ocs_ref_put(&io->ref); /* ocs_ref_get(): same function */
2459 		}
2460 	} else {
2461 		io->display_name = "tmf";
2462 		rc = ocs_scsi_send_io(OCS_HW_IO_INITIATOR_READ, node, io, lun, tmf, NULL, 0, NULL,
2463 				      sgl, sgl_count, len, 0, cb, arg, 0);
2464 	}
2465 
2466 	return rc;
2467 }
2468 
2469 /**
2470  * @ingroup scsi_api_base
2471  * @brief Send an FCP IO.
2472  *
2473  * @par Description
2474  * An FCP read/write IO command, with optional task management flags, is sent to @c node.
2475  *
2476  * @param type HW IO type to send.
2477  * @param node Pointer to the node destination of the IO.
2478  * @param io Pointer to the IO context.
2479  * @param lun LUN value.
2480  * @param tmf Task management command.
2481  * @param cdb Pointer to the SCSI CDB.
2482  * @param cdb_len Length of the CDB, in bytes.
2483  * @param dif_info Pointer to the T10 DIF fields, or NULL if no DIF.
2484  * @param sgl Pointer to the scatter-gather list.
2485  * @param sgl_count Number of SGL entries in SGL.
2486  * @param wire_len Payload length, in bytes, of data on wire.
2487  * @param first_burst Number of first burst bytes to send.
2488  * @param cb Completion callback.
2489  * @param arg Application-specified completion callback argument.
2490  *
2491  * @return Returns 0 on success, or a negative error code value on failure.
2492  */
2493 
2494 /* tc: could elminiate LUN, as it's part of the IO structure */
2495 
ocs_scsi_send_io(ocs_hw_io_type_e type,ocs_node_t * node,ocs_io_t * io,uint64_t lun,ocs_scsi_tmf_cmd_e tmf,uint8_t * cdb,uint32_t cdb_len,ocs_scsi_dif_info_t * dif_info,ocs_scsi_sgl_t * sgl,uint32_t sgl_count,uint32_t wire_len,uint32_t first_burst,ocs_scsi_rsp_io_cb_t cb,void * arg,uint32_t flags)2496 static int32_t ocs_scsi_send_io(ocs_hw_io_type_e type, ocs_node_t *node, ocs_io_t *io, uint64_t lun,
2497 	ocs_scsi_tmf_cmd_e tmf, uint8_t *cdb, uint32_t cdb_len,
2498 	ocs_scsi_dif_info_t *dif_info,
2499 	ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst,
2500 	ocs_scsi_rsp_io_cb_t cb, void *arg, uint32_t flags)
2501 {
2502 	int32_t rc;
2503 	ocs_t *ocs;
2504 	fcp_cmnd_iu_t *cmnd;
2505 	uint32_t cmnd_bytes = 0;
2506 	uint32_t *fcp_dl;
2507 	uint8_t tmf_flags = 0;
2508 
2509 	ocs_assert(io->node, -1);
2510 	ocs_assert(io->node == node, -1);
2511 	ocs_assert(io, -1);
2512 	ocs = io->ocs;
2513 	ocs_assert(cb, -1);
2514 
2515 	io->sgl_count = sgl_count;
2516 
2517 	/* Copy SGL if needed */
2518 	if (sgl != io->sgl) {
2519 		ocs_assert(sgl_count <= io->sgl_allocated, -1);
2520 		ocs_memcpy(io->sgl, sgl, sizeof(*io->sgl) * sgl_count);
2521 	}
2522 
2523 	/* save initiator and target task tags for debugging */
2524 	io->tgt_task_tag = 0xffff;
2525 
2526 	io->wire_len = wire_len;
2527 	io->hio_type = type;
2528 
2529 	if (OCS_LOG_ENABLE_SCSI_TRACE(ocs)) {
2530 		char buf[80];
2531 		ocs_textbuf_t txtbuf;
2532 		uint32_t i;
2533 
2534 		ocs_textbuf_init(ocs, &txtbuf, buf, sizeof(buf));
2535 
2536 		ocs_textbuf_printf(&txtbuf, "cdb%d: ", cdb_len);
2537 		for (i = 0; i < cdb_len; i ++) {
2538 			ocs_textbuf_printf(&txtbuf, "%02X%s", cdb[i], (i == (cdb_len-1)) ? "" : " ");
2539 		}
2540 		scsi_io_printf(io, "%s len %d, %s\n", (io->hio_type == OCS_HW_IO_INITIATOR_READ) ? "read" :
2541 			(io->hio_type == OCS_HW_IO_INITIATOR_WRITE) ? "write" : "",  io->wire_len,
2542 			ocs_textbuf_get_buffer(&txtbuf));
2543 	}
2544 
2545 
2546 	ocs_assert(io->cmdbuf.virt, -1);
2547 
2548 	cmnd = io->cmdbuf.virt;
2549 
2550 	ocs_assert(sizeof(*cmnd) <= io->cmdbuf.size, -1);
2551 
2552 	ocs_memset(cmnd, 0, sizeof(*cmnd));
2553 
2554 	/* Default FCP_CMND IU doesn't include additional CDB bytes but does include FCP_DL */
2555 	cmnd_bytes = sizeof(fcp_cmnd_iu_t) - sizeof(cmnd->fcp_cdb_and_dl) + sizeof(uint32_t);
2556 
2557 	fcp_dl = (uint32_t*)(&(cmnd->fcp_cdb_and_dl));
2558 
2559 	if (cdb) {
2560 		if (cdb_len <= 16) {
2561 			ocs_memcpy(cmnd->fcp_cdb, cdb, cdb_len);
2562 		} else {
2563 			uint32_t addl_cdb_bytes;
2564 
2565 			ocs_memcpy(cmnd->fcp_cdb, cdb, 16);
2566 			addl_cdb_bytes = cdb_len - 16;
2567 			ocs_memcpy(cmnd->fcp_cdb_and_dl, &(cdb[16]), addl_cdb_bytes);
2568 			/* additional_fcp_cdb_length is in words, not bytes */
2569 			cmnd->additional_fcp_cdb_length = (addl_cdb_bytes + 3) / 4;
2570 			fcp_dl += cmnd->additional_fcp_cdb_length;
2571 
2572 			/* Round up additional CDB bytes */
2573 			cmnd_bytes += (addl_cdb_bytes + 3) & ~0x3;
2574 		}
2575 	}
2576 
2577 	be64enc(cmnd->fcp_lun, CAM_EXTLUN_BYTE_SWIZZLE(lun));
2578 
2579 	if (node->fcp2device) {
2580 		if(ocs_get_crn(node, &cmnd->command_reference_number,
2581 					lun)) {
2582 			return -1;
2583 		}
2584 	}
2585 	if (flags & OCS_SCSI_CMD_HEAD_OF_QUEUE)
2586 		cmnd->task_attribute = FCP_TASK_ATTR_HEAD_OF_QUEUE;
2587 	else if (flags & OCS_SCSI_CMD_ORDERED)
2588 		cmnd->task_attribute = FCP_TASK_ATTR_ORDERED;
2589 	else if (flags & OCS_SCSI_CMD_UNTAGGED)
2590 		cmnd->task_attribute = FCP_TASK_ATTR_UNTAGGED;
2591 	else if (flags & OCS_SCSI_CMD_ACA)
2592 		cmnd->task_attribute = FCP_TASK_ATTR_ACA;
2593 	else
2594 		cmnd->task_attribute = FCP_TASK_ATTR_SIMPLE;
2595 	cmnd->command_priority = (flags & OCS_SCSI_PRIORITY_MASK) >>
2596 	    OCS_SCSI_PRIORITY_SHIFT;
2597 
2598 	switch (tmf) {
2599 	case OCS_SCSI_TMF_QUERY_TASK_SET:
2600 		tmf_flags = FCP_QUERY_TASK_SET;
2601 		break;
2602 	case OCS_SCSI_TMF_ABORT_TASK_SET:
2603 		tmf_flags = FCP_ABORT_TASK_SET;
2604 		break;
2605 	case OCS_SCSI_TMF_CLEAR_TASK_SET:
2606 		tmf_flags = FCP_CLEAR_TASK_SET;
2607 		break;
2608 	case OCS_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT:
2609 		tmf_flags = FCP_QUERY_ASYNCHRONOUS_EVENT;
2610 		break;
2611 	case OCS_SCSI_TMF_LOGICAL_UNIT_RESET:
2612 		tmf_flags = FCP_LOGICAL_UNIT_RESET;
2613 		break;
2614 	case OCS_SCSI_TMF_CLEAR_ACA:
2615 		tmf_flags = FCP_CLEAR_ACA;
2616 		break;
2617 	case OCS_SCSI_TMF_TARGET_RESET:
2618 		tmf_flags = FCP_TARGET_RESET;
2619 		break;
2620 	default:
2621 		tmf_flags = 0;
2622 	}
2623 	cmnd->task_management_flags = tmf_flags;
2624 
2625 	*fcp_dl = ocs_htobe32(io->wire_len);
2626 
2627 	switch (io->hio_type) {
2628 	case OCS_HW_IO_INITIATOR_READ:
2629 		cmnd->rddata = 1;
2630 		break;
2631 	case OCS_HW_IO_INITIATOR_WRITE:
2632 		cmnd->wrdata = 1;
2633 		break;
2634 	case  OCS_HW_IO_INITIATOR_NODATA:
2635 		/* sets neither */
2636 		break;
2637 	default:
2638 		ocs_log_test(ocs, "bad IO type %d\n", io->hio_type);
2639 		return -1;
2640 	}
2641 
2642 	rc = ocs_scsi_convert_dif_info(ocs, dif_info, &io->hw_dif);
2643 	if (rc) {
2644 		return rc;
2645 	}
2646 
2647 	io->scsi_ini_cb = cb;
2648 	io->scsi_ini_cb_arg = arg;
2649 
2650 	/* set command and response buffers in the iparam */
2651 	io->iparam.fcp_ini.cmnd = &io->cmdbuf;
2652 	io->iparam.fcp_ini.cmnd_size = cmnd_bytes;
2653 	io->iparam.fcp_ini.rsp = &io->rspbuf;
2654 	io->iparam.fcp_ini.flags = 0;
2655 	io->iparam.fcp_ini.dif_oper = io->hw_dif.dif;
2656 	io->iparam.fcp_ini.blk_size = io->hw_dif.blk_size;
2657 	io->iparam.fcp_ini.timeout = io->timeout;
2658 	io->iparam.fcp_ini.first_burst = first_burst;
2659 
2660 	return ocs_scsi_io_dispatch(io, ocs_initiator_io_cb);
2661 }
2662 
2663 /**
2664  * @ingroup scsi_api_base
2665  * @brief Callback for an aborted IO.
2666  *
2667  * @par Description
2668  * Callback function invoked upon completion of an IO abort request.
2669  *
2670  * @param hio HW IO context.
2671  * @param rnode Remote node.
2672  * @param len Response length.
2673  * @param status Completion status.
2674  * @param ext_status Extended completion status.
2675  * @param arg Application-specific callback, usually IO context.
2676 
2677  * @return Returns 0 on success, or a negative error code value on failure.
2678  */
2679 
2680 static int32_t
ocs_scsi_abort_io_cb(struct ocs_hw_io_s * hio,ocs_remote_node_t * rnode,uint32_t len,int32_t status,uint32_t ext_status,void * arg)2681 ocs_scsi_abort_io_cb(struct ocs_hw_io_s *hio, ocs_remote_node_t *rnode, uint32_t len, int32_t status,
2682 	uint32_t ext_status, void *arg)
2683 {
2684 	ocs_io_t *io = arg;
2685 	ocs_t *ocs;
2686 	ocs_scsi_io_status_e scsi_status = OCS_SCSI_STATUS_GOOD;
2687 
2688 	ocs_assert(io, -1);
2689 	ocs_assert(ocs_io_busy(io), -1);
2690 	ocs_assert(io->ocs, -1);
2691 	ocs_assert(io->io_to_abort, -1);
2692 	ocs = io->ocs;
2693 
2694 	ocs_log_debug(ocs, "status %d ext %d\n", status, ext_status);
2695 
2696 	/* done with IO to abort */
2697 	ocs_ref_put(&io->io_to_abort->ref); /* ocs_ref_get(): ocs_scsi_send_tmf() */
2698 
2699 	ocs_scsi_io_free_ovfl(io);
2700 
2701 	switch (status) {
2702 	case SLI4_FC_WCQE_STATUS_SUCCESS:
2703 		scsi_status = OCS_SCSI_STATUS_GOOD;
2704 		break;
2705 	case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
2706 		if (ext_status == SLI4_FC_LOCAL_REJECT_ABORT_REQUESTED) {
2707 			scsi_status = OCS_SCSI_STATUS_ABORTED;
2708 		} else if (ext_status == SLI4_FC_LOCAL_REJECT_NO_XRI) {
2709 			scsi_status = OCS_SCSI_STATUS_NO_IO;
2710 		} else if (ext_status == SLI4_FC_LOCAL_REJECT_ABORT_IN_PROGRESS) {
2711 			scsi_status = OCS_SCSI_STATUS_ABORT_IN_PROGRESS;
2712 		} else {
2713 			ocs_log_test(ocs, "Unhandled local reject 0x%x/0x%x\n", status, ext_status);
2714 			scsi_status = OCS_SCSI_STATUS_ERROR;
2715 		}
2716 		break;
2717 	default:
2718 		scsi_status = OCS_SCSI_STATUS_ERROR;
2719 		break;
2720 	}
2721 
2722 	if (io->scsi_ini_cb) {
2723 		(*io->scsi_ini_cb)(io, scsi_status, NULL, 0, io->scsi_ini_cb_arg);
2724 	} else {
2725 		ocs_scsi_io_free(io);
2726 	}
2727 
2728 	ocs_scsi_check_pending(ocs);
2729 	return 0;
2730 }
2731 
2732 /**
2733  * @ingroup scsi_api_base
2734  * @brief Return SCSI API integer valued property.
2735  *
2736  * @par Description
2737  * This function is called by a target-server or initiator-client to
2738  * retrieve an integer valued property.
2739  *
2740  * @param ocs Pointer to the ocs.
2741  * @param prop Property value to return.
2742  *
2743  * @return Returns a value, or 0 if invalid property was requested.
2744  */
2745 uint32_t
ocs_scsi_get_property(ocs_t * ocs,ocs_scsi_property_e prop)2746 ocs_scsi_get_property(ocs_t *ocs, ocs_scsi_property_e prop)
2747 {
2748 	ocs_xport_t *xport = ocs->xport;
2749 	uint32_t	val;
2750 
2751 	switch (prop) {
2752 	case OCS_SCSI_MAX_SGE:
2753 		if (0 == ocs_hw_get(&ocs->hw, OCS_HW_MAX_SGE, &val)) {
2754 			return val;
2755 		}
2756 		break;
2757 	case OCS_SCSI_MAX_SGL:
2758 		if (ocs->ctrlmask & OCS_CTRLMASK_TEST_CHAINED_SGLS) {
2759 			/*
2760 			 * If chain SGL test-mode is enabled, the number of HW SGEs
2761 			 * has been limited; report back original max.
2762 			 */
2763 			return (OCS_FC_MAX_SGL);
2764 		}
2765 		if (0 == ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &val)) {
2766 			return val;
2767 		}
2768 		break;
2769 	case OCS_SCSI_MAX_IOS:
2770 		return ocs_io_pool_allocated(xport->io_pool);
2771 	case OCS_SCSI_DIF_CAPABLE:
2772 	        if (0 == ocs_hw_get(&ocs->hw, OCS_HW_DIF_CAPABLE, &val)) {
2773 	                return val;
2774 	        }
2775 		break;
2776 	case OCS_SCSI_MAX_FIRST_BURST:
2777 		return 0;
2778 	case OCS_SCSI_DIF_MULTI_SEPARATE:
2779 	        if (ocs_hw_get(&ocs->hw, OCS_HW_DIF_MULTI_SEPARATE, &val) == 0) {
2780 	                return val;
2781 	        }
2782 		break;
2783 	case OCS_SCSI_ENABLE_TASK_SET_FULL:
2784 		/* Return FALSE if we are send frame capable */
2785 		if (ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &val) == 0) {
2786 			return ! val;
2787 		}
2788 		break;
2789 	default:
2790 		break;
2791 	}
2792 
2793 	ocs_log_debug(ocs, "invalid property request %d\n", prop);
2794 	return 0;
2795 }
2796 
2797 /**
2798  * @ingroup scsi_api_base
2799  * @brief Return a property pointer.
2800  *
2801  * @par Description
2802  * This function is called by a target-server or initiator-client to
2803  * retrieve a pointer to the requested property.
2804  *
2805  * @param ocs Pointer to the ocs.
2806  * @param prop Property value to return.
2807  *
2808  * @return Returns pointer to the requested property, or NULL otherwise.
2809  */
ocs_scsi_get_property_ptr(ocs_t * ocs,ocs_scsi_property_e prop)2810 void *ocs_scsi_get_property_ptr(ocs_t *ocs, ocs_scsi_property_e prop)
2811 {
2812 	void *rc = NULL;
2813 
2814 	switch (prop) {
2815 	case OCS_SCSI_WWNN:
2816 		rc = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_NODE);
2817 		break;
2818 	case OCS_SCSI_WWPN:
2819 		rc = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_PORT);
2820 		break;
2821 	case OCS_SCSI_PORTNUM:
2822 		rc = ocs_hw_get_ptr(&ocs->hw, OCS_HW_PORTNUM);
2823 		break;
2824 	case OCS_SCSI_BIOS_VERSION_STRING:
2825 		rc = ocs_hw_get_ptr(&ocs->hw, OCS_HW_BIOS_VERSION_STRING);
2826 		break;
2827 	case OCS_SCSI_SERIALNUMBER:
2828 	{
2829 		uint8_t *pvpd;
2830 		uint32_t vpd_len;
2831 
2832 		if (ocs_hw_get(&ocs->hw, OCS_HW_VPD_LEN, &vpd_len)) {
2833 			ocs_log_test(ocs, "Can't get VPD length\n");
2834 			rc = "\012sn-unknown";
2835 			break;
2836 		}
2837 
2838 		pvpd = ocs_hw_get_ptr(&ocs->hw, OCS_HW_VPD);
2839 		if (pvpd) {
2840 			rc = ocs_find_vpd(pvpd, vpd_len, "SN");
2841 		}
2842 
2843 		if (rc == NULL ||
2844 		    ocs_strlen(rc) == 0) {
2845 			/* Note: VPD is missing, using wwnn for serial number */
2846 			scsi_log(ocs, "Note: VPD is missing, using wwnn for serial number\n");
2847 			/* Use the last 32 bits of the WWN */
2848 			if ((ocs == NULL) || (ocs->domain == NULL) || (ocs->domain->sport == NULL)) {
2849 				rc = "\011(Unknown)";
2850 			} else {
2851 				rc = &ocs->domain->sport->wwnn_str[8];
2852 			}
2853 		}
2854 		break;
2855 	}
2856 	case OCS_SCSI_PARTNUMBER:
2857 	{
2858 		uint8_t *pvpd;
2859 		uint32_t vpd_len;
2860 
2861 		if (ocs_hw_get(&ocs->hw, OCS_HW_VPD_LEN, &vpd_len)) {
2862 			ocs_log_test(ocs, "Can't get VPD length\n");
2863 			rc = "\012pn-unknown";
2864 			break;
2865 		}
2866 		pvpd = ocs_hw_get_ptr(&ocs->hw, OCS_HW_VPD);
2867 		if (pvpd) {
2868 			rc = ocs_find_vpd(pvpd, vpd_len, "PN");
2869 			if (rc == NULL) {
2870 				rc = "\012pn-unknown";
2871 			}
2872 		} else {
2873 			rc = "\012pn-unknown";
2874 		}
2875 		break;
2876 	}
2877 	default:
2878 		break;
2879 	}
2880 
2881 	if (rc == NULL) {
2882 		ocs_log_debug(ocs, "invalid property request %d\n", prop);
2883 	}
2884 	return rc;
2885 }
2886 
2887 /**
2888  * @ingroup scsi_api_base
2889  * @brief Notify that delete initiator is complete.
2890  *
2891  * @par Description
2892  * Sent by the target-server to notify the base driver that the work started from
2893  * ocs_scsi_del_initiator() is now complete and that it is safe for the node to
2894  * release the rest of its resources.
2895  *
2896  * @param node Pointer to the node.
2897  *
2898  * @return None.
2899  */
2900 void
ocs_scsi_del_initiator_complete(ocs_node_t * node)2901 ocs_scsi_del_initiator_complete(ocs_node_t *node)
2902 {
2903 	/* Notify the node to resume */
2904 	ocs_node_post_event(node, OCS_EVT_NODE_DEL_INI_COMPLETE, NULL);
2905 }
2906 
2907 
2908 /**
2909  * @ingroup scsi_api_base
2910  * @brief Notify that delete target is complete.
2911  *
2912  * @par Description
2913  * Sent by the initiator-client to notify the base driver that the work started from
2914  * ocs_scsi_del_target() is now complete and that it is safe for the node to
2915  * release the rest of its resources.
2916  *
2917  * @param node Pointer to the node.
2918  *
2919  * @return None.
2920  */
2921 void
ocs_scsi_del_target_complete(ocs_node_t * node)2922 ocs_scsi_del_target_complete(ocs_node_t *node)
2923 {
2924 	/* Notify the node to resume */
2925 	ocs_node_post_event(node, OCS_EVT_NODE_DEL_TGT_COMPLETE, NULL);
2926 }
2927 
2928 
2929 /**
2930  * @brief Update transferred count
2931  *
2932  * @par Description
2933  * Updates io->transferred, as required when using first burst, when the amount
2934  * of first burst data processed differs from the amount of first burst
2935  * data received.
2936  *
2937  * @param io Pointer to the io object.
2938  * @param transferred Number of bytes transferred out of first burst buffers.
2939  *
2940  * @return None.
2941  */
2942 void
ocs_scsi_update_first_burst_transferred(ocs_io_t * io,uint32_t transferred)2943 ocs_scsi_update_first_burst_transferred(ocs_io_t *io, uint32_t transferred)
2944 {
2945 	io->transferred = transferred;
2946 }
2947 
2948 /**
2949  * @brief Register bounce callback for multi-threading.
2950  *
2951  * @par Description
2952  * Register the back end bounce function.
2953  *
2954  * @param ocs Pointer to device object.
2955  * @param fctn Function pointer of bounce function.
2956  *
2957  * @return None.
2958  */
2959 void
ocs_scsi_register_bounce(ocs_t * ocs,void (* fctn)(void (* fctn)(void * arg),void * arg,uint32_t s_id,uint32_t d_id,uint32_t ox_id))2960 ocs_scsi_register_bounce(ocs_t *ocs, void(*fctn)(void(*fctn)(void *arg), void *arg, uint32_t s_id, uint32_t d_id,
2961 						 uint32_t ox_id))
2962 {
2963 	ocs_hw_rtn_e rc;
2964 
2965 	rc = ocs_hw_callback(&ocs->hw, OCS_HW_CB_BOUNCE, fctn, NULL);
2966 	if (rc) {
2967 		ocs_log_test(ocs, "ocs_hw_callback(OCS_HW_CB_BOUNCE) failed: %d\n", rc);
2968 	}
2969 }
2970