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