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