xref: /freebsd/sys/dev/ocs_fc/ocs_els.c (revision 95ee2897)
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  * Functions to build and send ELS/CT/BLS commands and responses.
35  */
36 
37 /*!
38 @defgroup els_api ELS/BLS/CT Command and Response Functions
39 */
40 
41 #include "ocs.h"
42 #include "ocs_els.h"
43 #include "ocs_scsi.h"
44 #include "ocs_device.h"
45 
46 #define ELS_IOFMT "[i:%04x t:%04x h:%04x]"
47 #define ELS_IOFMT_ARGS(els) els->init_task_tag, els->tgt_task_tag, els->hw_tag
48 
49 #define node_els_trace()  \
50 	do { \
51 		if (OCS_LOG_ENABLE_ELS_TRACE(ocs)) \
52 			ocs_log_info(ocs, "[%s] %-20s\n", node->display_name, __func__); \
53 	} while (0)
54 
55 #define els_io_printf(els, fmt, ...) \
56 	ocs_log_debug(els->node->ocs, "[%s]" ELS_IOFMT " %-8s " fmt, els->node->display_name, ELS_IOFMT_ARGS(els), els->display_name, ##__VA_ARGS__);
57 
58 static int32_t ocs_els_send(ocs_io_t *els, uint32_t reqlen, uint32_t timeout_sec, ocs_hw_srrs_cb_t cb);
59 static int32_t ocs_els_send_rsp(ocs_io_t *els, uint32_t rsplen);
60 static int32_t ocs_els_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg);
61 static ocs_io_t *ocs_bls_send_acc(ocs_io_t *io, uint32_t s_id, uint16_t ox_id, uint16_t rx_id);
62 static int32_t ocs_bls_send_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length,
63 	int32_t status, uint32_t ext_status, void *app);
64 static void ocs_io_transition(ocs_io_t *els, ocs_sm_function_t state, void *data);
65 static ocs_io_t *ocs_els_abort_io(ocs_io_t *els, int send_abts);
66 static void _ocs_els_io_free(void *arg);
67 static void ocs_els_delay_timer_cb(void *arg);
68 
69 /**
70  * @ingroup els_api
71  * @brief ELS state machine transition wrapper.
72  *
73  * <h3 class="desc">Description</h3>
74  * This function is the transition wrapper for the ELS state machine. It grabs
75  * the node lock prior to making the transition to protect
76  * against multiple threads accessing a particular ELS. For example,
77  * one thread transitioning from __els_init to
78  * __ocs_els_wait_resp and another thread (tasklet) handling the
79  * completion of that ELS request.
80  *
81  * @param els Pointer to the IO context.
82  * @param state State to transition to.
83  * @param data Data to pass in with the transition.
84  *
85  * @return None.
86  */
87 static void
ocs_io_transition(ocs_io_t * els,ocs_sm_function_t state,void * data)88 ocs_io_transition(ocs_io_t *els, ocs_sm_function_t state, void *data)
89 {
90 	/* protect ELS events with node lock */
91 	ocs_node_t *node = els->node;
92 	ocs_node_lock(node);
93 		ocs_sm_transition(&els->els_sm, state, data);
94 	ocs_node_unlock(node);
95 }
96 
97 /**
98  * @ingroup els_api
99  * @brief ELS state machine post event wrapper.
100  *
101  * <h3 class="desc">Description</h3>
102  * Post an event wrapper for the ELS state machine. This function grabs
103  * the node lock prior to posting the event.
104  *
105  * @param els Pointer to the IO context.
106  * @param evt Event to process.
107  * @param data Data to pass in with the transition.
108  *
109  * @return None.
110  */
111 void
ocs_els_post_event(ocs_io_t * els,ocs_sm_event_t evt,void * data)112 ocs_els_post_event(ocs_io_t *els, ocs_sm_event_t evt, void *data)
113 {
114 	/* protect ELS events with node lock */
115 	ocs_node_t *node = els->node;
116 	ocs_node_lock(node);
117 		els->els_evtdepth ++;
118 		ocs_sm_post_event(&els->els_sm, evt, data);
119 		els->els_evtdepth --;
120 	ocs_node_unlock(node);
121 	if (els->els_evtdepth == 0 && els->els_req_free) {
122 		ocs_els_io_free(els);
123 	}
124 }
125 
126 /**
127  * @ingroup els_api
128  * @brief Allocate an IO structure for an ELS IO context.
129  *
130  * <h3 class="desc">Description</h3>
131  * Allocate an IO for an ELS context.  Uses OCS_ELS_RSP_LEN as response size.
132  *
133  * @param node node to associate ELS IO with
134  * @param reqlen Length of ELS request
135  * @param role Role of ELS (originator/responder)
136  *
137  * @return pointer to IO structure allocated
138  */
139 
140 ocs_io_t *
ocs_els_io_alloc(ocs_node_t * node,uint32_t reqlen,ocs_els_role_e role)141 ocs_els_io_alloc(ocs_node_t *node, uint32_t reqlen, ocs_els_role_e role)
142 {
143 	return ocs_els_io_alloc_size(node, reqlen, OCS_ELS_RSP_LEN, role);
144 }
145 
146 /**
147  * @ingroup els_api
148  * @brief Allocate an IO structure for an ELS IO context.
149  *
150  * <h3 class="desc">Description</h3>
151  * Allocate an IO for an ELS context, allowing the caller to specify the size of the response.
152  *
153  * @param node node to associate ELS IO with
154  * @param reqlen Length of ELS request
155  * @param rsplen Length of ELS response
156  * @param role Role of ELS (originator/responder)
157  *
158  * @return pointer to IO structure allocated
159  */
160 
161 ocs_io_t *
ocs_els_io_alloc_size(ocs_node_t * node,uint32_t reqlen,uint32_t rsplen,ocs_els_role_e role)162 ocs_els_io_alloc_size(ocs_node_t *node, uint32_t reqlen, uint32_t rsplen, ocs_els_role_e role)
163 {
164 
165 	ocs_t *ocs;
166 	ocs_xport_t *xport;
167 	ocs_io_t *els;
168 	ocs_assert(node, NULL);
169 	ocs_assert(node->ocs, NULL);
170 	ocs = node->ocs;
171 	ocs_assert(ocs->xport, NULL);
172 	xport = ocs->xport;
173 
174 	ocs_lock(&node->active_ios_lock);
175 		if (!node->io_alloc_enabled) {
176 			ocs_log_debug(ocs, "called with io_alloc_enabled = FALSE\n");
177 			ocs_unlock(&node->active_ios_lock);
178 			return NULL;
179 		}
180 
181 		els = ocs_io_alloc(ocs);
182 		if (els == NULL) {
183 			ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
184 			ocs_unlock(&node->active_ios_lock);
185 			return NULL;
186 		}
187 
188 		/* initialize refcount */
189 		ocs_ref_init(&els->ref, _ocs_els_io_free, els);
190 
191 		switch (role) {
192 		case OCS_ELS_ROLE_ORIGINATOR:
193 			els->cmd_ini = TRUE;
194 			els->cmd_tgt = FALSE;
195 			break;
196 		case OCS_ELS_ROLE_RESPONDER:
197 			els->cmd_ini = FALSE;
198 			els->cmd_tgt = TRUE;
199 			break;
200 		}
201 
202 		/* IO should not have an associated HW IO yet.  Assigned below. */
203 		if (els->hio != NULL) {
204 			ocs_log_err(ocs, "assertion failed.  HIO is not null\n");
205 			ocs_io_free(ocs, els);
206 			ocs_unlock(&node->active_ios_lock);
207 			return NULL;
208 		}
209 
210 		/* populate generic io fields */
211 		els->ocs = ocs;
212 		els->node = node;
213 
214 		/* set type and ELS-specific fields */
215 		els->io_type = OCS_IO_TYPE_ELS;
216 		els->display_name = "pending";
217 
218 		if (reqlen > OCS_ELS_REQ_LEN) {
219 			ocs_log_err(ocs, "ELS command request len greater than allocated\n");
220 			ocs_io_free(ocs, els);
221 			ocs_unlock(&node->active_ios_lock);
222 			return NULL;
223 		}
224 
225 		if (rsplen > OCS_ELS_GID_PT_RSP_LEN) {
226 			ocs_log_err(ocs, "ELS command response len: %d "
227 				"greater than allocated\n", rsplen);
228 			ocs_io_free(ocs, els);
229 			ocs_unlock(&node->active_ios_lock);
230 			return NULL;
231 		}
232 
233 		els->els_req.size = reqlen;
234 		els->els_rsp.size = rsplen;
235 
236 		if (els != NULL) {
237 			ocs_memset(&els->els_sm, 0, sizeof(els->els_sm));
238 			els->els_sm.app = els;
239 
240 			/* initialize fields */
241 			els->els_retries_remaining = OCS_FC_ELS_DEFAULT_RETRIES;
242 			els->els_evtdepth = 0;
243 			els->els_pend = 0;
244 			els->els_active = 0;
245 
246 			/* add els structure to ELS IO list */
247 			ocs_list_add_tail(&node->els_io_pend_list, els);
248 			els->els_pend = 1;
249 		}
250 	ocs_unlock(&node->active_ios_lock);
251 	return els;
252 }
253 
254 /**
255  * @ingroup els_api
256  * @brief Free IO structure for an ELS IO context.
257  *
258  * <h3 class="desc">Description</h3> Free IO for an ELS
259  * IO context
260  *
261  * @param els ELS IO structure for which IO is allocated
262  *
263  * @return None
264  */
265 
266 void
ocs_els_io_free(ocs_io_t * els)267 ocs_els_io_free(ocs_io_t *els)
268 {
269 	ocs_ref_put(&els->ref);
270 }
271 
272 /**
273  * @ingroup els_api
274  * @brief Free IO structure for an ELS IO context.
275  *
276  * <h3 class="desc">Description</h3> Free IO for an ELS
277  * IO context
278  *
279  * @param arg ELS IO structure for which IO is allocated
280  *
281  * @return None
282  */
283 
284 static void
_ocs_els_io_free(void * arg)285 _ocs_els_io_free(void *arg)
286 {
287 	ocs_io_t *els = (ocs_io_t *)arg;
288 	ocs_t *ocs;
289 	ocs_node_t *node;
290 	int send_empty_event = FALSE;
291 
292 	ocs_assert(els);
293 	ocs_assert(els->node);
294 	ocs_assert(els->node->ocs);
295 	ocs = els->node->ocs;
296 
297 	node = els->node;
298 	ocs = node->ocs;
299 
300 	ocs_lock(&node->active_ios_lock);
301 		if (els->els_active) {
302 			/* if active, remove from active list and check empty */
303 			ocs_list_remove(&node->els_io_active_list, els);
304 			/* Send list empty event if the IO allocator is disabled, and the list is empty
305 			 * If node->io_alloc_enabled was not checked, the event would be posted continually
306 			 */
307 			send_empty_event = (!node->io_alloc_enabled) && ocs_list_empty(&node->els_io_active_list);
308 			els->els_active = 0;
309 		} else if (els->els_pend) {
310 			/* if pending, remove from pending list; node shutdown isn't
311 			 * gated off the pending list (only the active list), so no
312 			 * need to check if pending list is empty
313 			 */
314 			ocs_list_remove(&node->els_io_pend_list, els);
315 			els->els_pend = 0;
316 		} else {
317 			ocs_log_err(ocs, "assertion failed: niether els->els_pend nor els->active set\n");
318 			ocs_unlock(&node->active_ios_lock);
319 			return;
320 		}
321 
322 	ocs_unlock(&node->active_ios_lock);
323 
324 	ocs_io_free(ocs, els);
325 
326 	if (send_empty_event) {
327 		ocs_node_post_event(node, OCS_EVT_ALL_CHILD_NODES_FREE, NULL);
328 	}
329 
330 	ocs_scsi_check_pending(ocs);
331 }
332 
333 /**
334  * @ingroup els_api
335  * @brief Make ELS IO active
336  *
337  * @param els Pointer to the IO context to make active.
338  *
339  * @return Returns 0 on success; or a negative error code value on failure.
340  */
341 
342 static void
ocs_els_make_active(ocs_io_t * els)343 ocs_els_make_active(ocs_io_t *els)
344 {
345 	ocs_node_t *node = els->node;
346 
347 	/* move ELS from pending list to active list */
348 	ocs_lock(&node->active_ios_lock);
349 		if (els->els_pend) {
350 			if (els->els_active) {
351 				ocs_log_err(node->ocs, "assertion failed: both els->els_pend and els->active set\n");
352 				ocs_unlock(&node->active_ios_lock);
353 				return;
354 			} else {
355 				/* remove from pending list */
356 				ocs_list_remove(&node->els_io_pend_list, els);
357 				els->els_pend = 0;
358 
359 				/* add els structure to ELS IO list */
360 				ocs_list_add_tail(&node->els_io_active_list, els);
361 				els->els_active = 1;
362 			}
363 		} else {
364 			/* must be retrying; make sure it's already active */
365 			if (!els->els_active) {
366 				ocs_log_err(node->ocs, "assertion failed: niether els->els_pend nor els->active set\n");
367 			}
368 		}
369 	ocs_unlock(&node->active_ios_lock);
370 }
371 
372 /**
373  * @ingroup els_api
374  * @brief Send the ELS command.
375  *
376  * <h3 class="desc">Description</h3>
377  * The command, given by the \c els IO context, is sent to the node that the IO was
378  * configured with, using ocs_hw_srrs_send(). Upon completion,
379  * the \c cb callback is invoked,
380  * with the application-specific argument set to the \c els IO context.
381  *
382  * @param els Pointer to the IO context.
383  * @param reqlen Byte count in the payload to send.
384  * @param timeout_sec Command timeout, in seconds (0 -> 2*R_A_TOV).
385  * @param cb Completion callback.
386  *
387  * @return Returns 0 on success; or a negative error code value on failure.
388  */
389 
390 static int32_t
ocs_els_send(ocs_io_t * els,uint32_t reqlen,uint32_t timeout_sec,ocs_hw_srrs_cb_t cb)391 ocs_els_send(ocs_io_t *els, uint32_t reqlen, uint32_t timeout_sec, ocs_hw_srrs_cb_t cb)
392 {
393 	ocs_node_t *node = els->node;
394 
395 	/* update ELS request counter */
396 	node->els_req_cnt++;
397 
398 	/* move ELS from pending list to active list */
399 	ocs_els_make_active(els);
400 
401 	els->wire_len = reqlen;
402 	return ocs_scsi_io_dispatch(els, cb);
403 }
404 
405 /**
406  * @ingroup els_api
407  * @brief Send the ELS response.
408  *
409  * <h3 class="desc">Description</h3>
410  * The ELS response, given by the \c els IO context, is sent to the node
411  * that the IO was configured with, using ocs_hw_srrs_send().
412  *
413  * @param els Pointer to the IO context.
414  * @param rsplen Byte count in the payload to send.
415  *
416  * @return Returns 0 on success; or a negative error value on failure.
417  */
418 
419 static int32_t
ocs_els_send_rsp(ocs_io_t * els,uint32_t rsplen)420 ocs_els_send_rsp(ocs_io_t *els, uint32_t rsplen)
421 {
422 	ocs_node_t *node = els->node;
423 
424 	/* increment ELS completion counter */
425 	node->els_cmpl_cnt++;
426 
427 	/* move ELS from pending list to active list */
428 	ocs_els_make_active(els);
429 
430 	els->wire_len = rsplen;
431 	return ocs_scsi_io_dispatch(els, ocs_els_acc_cb);
432 }
433 
434 /**
435  * @ingroup els_api
436  * @brief Handle ELS IO request completions.
437  *
438  * <h3 class="desc">Description</h3>
439  * This callback is used for several ELS send operations.
440  *
441  * @param hio Pointer to the HW IO context that completed.
442  * @param rnode Pointer to the remote node.
443  * @param length Length of the returned payload data.
444  * @param status Status of the completion.
445  * @param ext_status Extended status of the completion.
446  * @param arg Application-specific argument (generally a pointer to the ELS IO context).
447  *
448  * @return Returns 0 on success; or a negative error value on failure.
449  */
450 
451 static int32_t
ocs_els_req_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * arg)452 ocs_els_req_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg)
453 {
454 	ocs_io_t *els;
455 	ocs_node_t *node;
456 	ocs_t *ocs;
457 	ocs_node_cb_t cbdata;
458 	ocs_io_t *io;
459 
460 	ocs_assert(arg, -1);
461 	io = arg;
462 	els = io;
463 	ocs_assert(els, -1);
464 	ocs_assert(els->node, -1);
465 	node = els->node;
466 	ocs_assert(node->ocs, -1);
467 	ocs = node->ocs;
468 
469 	ocs_assert(io->hio, -1);
470 	ocs_assert(hio == io->hio, -1);
471 
472 	if (status != 0) {
473 		els_io_printf(els, "status x%x ext x%x\n", status, ext_status);
474 	}
475 
476 	/* set the response len element of els->rsp */
477 	els->els_rsp.len = length;
478 
479 	cbdata.status = status;
480 	cbdata.ext_status = ext_status;
481 	cbdata.header = NULL;
482 	cbdata.els = els;
483 
484 	/* FW returns the number of bytes received on the link in
485 	 * the WCQE, not the amount placed in the buffer; use this info to
486 	 * check if there was an overrun.
487 	 */
488 	if (length > els->els_rsp.size) {
489 		ocs_log_warn(ocs, "ELS response returned len=%d > buflen=%zu\n",
490 				length, els->els_rsp.size);
491 		ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &cbdata);
492 		return 0;
493 	}
494 
495 	/* Post event to ELS IO object */
496 	switch (status) {
497 	case SLI4_FC_WCQE_STATUS_SUCCESS:
498 		ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_OK, &cbdata);
499 		break;
500 
501 	case SLI4_FC_WCQE_STATUS_LS_RJT:
502 		ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_RJT, &cbdata);
503 		break;
504 
505 	case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
506 		switch (ext_status) {
507 		case SLI4_FC_LOCAL_REJECT_SEQUENCE_TIMEOUT:
508 			ocs_els_post_event(els, OCS_EVT_ELS_REQ_TIMEOUT, &cbdata);
509 			break;
510 		case SLI4_FC_LOCAL_REJECT_ABORT_REQUESTED:
511 			ocs_els_post_event(els, OCS_EVT_ELS_REQ_ABORTED, &cbdata);
512 			break;
513 		default:
514 			ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &cbdata);
515 			break;
516 		}
517 		break;
518 	default:
519 		ocs_log_warn(ocs, "els req complete: failed status x%x, ext_status, x%x\n", status, ext_status);
520 		ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &cbdata);
521 		break;
522 	}
523 
524 	return 0;
525 }
526 
527 /**
528  * @ingroup els_api
529  * @brief Handle ELS IO accept/response completions.
530  *
531  * <h3 class="desc">Description</h3>
532  * This callback is used for several ELS send operations.
533  *
534  * @param hio Pointer to the HW IO context that completed.
535  * @param rnode Pointer to the remote node.
536  * @param length Length of the returned payload data.
537  * @param status Status of the completion.
538  * @param ext_status Extended status of the completion.
539  * @param arg Application-specific argument (generally a pointer to the ELS IO context).
540  *
541  * @return Returns 0 on success; or a negative error value on failure.
542  */
543 
544 static int32_t
ocs_els_acc_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * arg)545 ocs_els_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg)
546 {
547 	ocs_io_t *els;
548 	ocs_node_t *node;
549 	ocs_t *ocs;
550 	ocs_node_cb_t cbdata;
551 	ocs_io_t *io;
552 
553 	ocs_assert(arg, -1);
554 	io = arg;
555 	els = io;
556 	ocs_assert(els, -1);
557 	ocs_assert(els->node, -1);
558 	node = els->node;
559 	ocs_assert(node->ocs, -1);
560 	ocs = node->ocs;
561 
562 	ocs_assert(io->hio, -1);
563 	ocs_assert(hio == io->hio, -1);
564 
565 	cbdata.status = status;
566 	cbdata.ext_status = ext_status;
567 	cbdata.header = NULL;
568 	cbdata.els = els;
569 
570 	/* Post node event */
571 	switch (status) {
572 	case SLI4_FC_WCQE_STATUS_SUCCESS:
573 		ocs_node_post_event(node, OCS_EVT_SRRS_ELS_CMPL_OK, &cbdata);
574 		break;
575 
576 	default:
577 		ocs_log_warn(ocs, "[%s] %-8s failed status x%x, ext_status x%x\n",
578 			node->display_name, els->display_name, status, ext_status);
579 		ocs_log_warn(ocs, "els acc complete: failed status x%x, ext_status, x%x\n", status, ext_status);
580 		ocs_node_post_event(node, OCS_EVT_SRRS_ELS_CMPL_FAIL, &cbdata);
581 		break;
582 	}
583 
584 	/* If this IO has a callback, invoke it */
585 	if (els->els_callback) {
586 		(*els->els_callback)(node, &cbdata, els->els_callback_arg);
587 	}
588 
589 	ocs_els_io_free(els);
590 
591 	return 0;
592 }
593 
594 /**
595  * @ingroup els_api
596  * @brief Format and send a PLOGI ELS command.
597  *
598  * <h3 class="desc">Description</h3>
599  * Construct a PLOGI payload using the domain SLI port service parameters,
600  * and send to the \c node.
601  *
602  * @param node Node to which the PLOGI is sent.
603  * @param timeout_sec Command timeout, in seconds.
604  * @param retries Number of times to retry errors before reporting a failure.
605  * @param cb Callback function.
606  * @param cbarg Callback function argument.
607  *
608  * @return Returns pointer to IO object, or NULL if error.
609  */
610 
611 ocs_io_t *
ocs_send_plogi(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,void (* cb)(ocs_node_t * node,ocs_node_cb_t * cbdata,void * arg),void * cbarg)612 ocs_send_plogi(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
613 	void (*cb)(ocs_node_t *node, ocs_node_cb_t *cbdata, void *arg), void *cbarg)
614 {
615 	ocs_io_t *els;
616 	ocs_t *ocs = node->ocs;
617 	fc_plogi_payload_t *plogi;
618 
619 	node_els_trace();
620 
621 	els = ocs_els_io_alloc(node, sizeof(*plogi), OCS_ELS_ROLE_ORIGINATOR);
622 	if (els == NULL) {
623 		ocs_log_err(ocs, "IO alloc failed\n");
624 	} else {
625 		els->els_timeout_sec = timeout_sec;
626 		els->els_retries_remaining = retries;
627 		els->els_callback = cb;
628 		els->els_callback_arg = cbarg;
629 		els->display_name = "plogi";
630 
631 		/* Build PLOGI request */
632 		plogi = els->els_req.virt;
633 
634 		ocs_memcpy(plogi, node->sport->service_params, sizeof(*plogi));
635 
636 		plogi->command_code = FC_ELS_CMD_PLOGI;
637 		plogi->resv1 = 0;
638 
639 		ocs_display_sparams(node->display_name, "plogi send req", 0, NULL, plogi->common_service_parameters);
640 
641 		els->hio_type = OCS_HW_ELS_REQ;
642 		els->iparam.els.timeout = timeout_sec;
643 
644 		ocs_io_transition(els, __ocs_els_init, NULL);
645 	}
646 	return els;
647 }
648 
649 /**
650  * @ingroup els_api
651  * @brief Format and send a FLOGI ELS command.
652  *
653  * <h3 class="desc">Description</h3>
654  * Construct an FLOGI payload, and send to the \c node.
655  *
656  * @param node Node to which the FLOGI is sent.
657  * @param timeout_sec Command timeout, in seconds.
658  * @param retries Number of times to retry errors before reporting a failure.
659  * @param cb Callback function.
660  * @param cbarg Callback function argument.
661  *
662  * @return Returns pointer to IO object, or NULL if error.
663  */
664 
665 ocs_io_t *
ocs_send_flogi(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)666 ocs_send_flogi(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
667 	els_cb_t cb, void *cbarg)
668 {
669 	ocs_io_t *els;
670 	ocs_t *ocs;
671 	fc_plogi_payload_t *flogi;
672 
673 	ocs_assert(node, NULL);
674 	ocs_assert(node->ocs, NULL);
675 	ocs_assert(node->sport, NULL);
676 	ocs = node->ocs;
677 
678 	node_els_trace();
679 
680 	els = ocs_els_io_alloc(node, sizeof(*flogi), OCS_ELS_ROLE_ORIGINATOR);
681 	if (els == NULL) {
682 		ocs_log_err(ocs, "IO alloc failed\n");
683 	} else {
684 		els->els_timeout_sec = timeout_sec;
685 		els->els_retries_remaining = retries;
686 		els->els_callback = cb;
687 		els->els_callback_arg = cbarg;
688 		els->display_name = "flogi";
689 
690 		/* Build FLOGI request */
691 		flogi = els->els_req.virt;
692 
693 		ocs_memcpy(flogi, node->sport->service_params, sizeof(*flogi));
694 		flogi->command_code = FC_ELS_CMD_FLOGI;
695 		flogi->resv1 = 0;
696 
697 		/* Priority tagging support */
698 		flogi->common_service_parameters[1] |= ocs_htobe32(1U << 23);
699 
700 		ocs_display_sparams(node->display_name, "flogi send req", 0, NULL, flogi->common_service_parameters);
701 
702 		els->hio_type = OCS_HW_ELS_REQ;
703 		els->iparam.els.timeout = timeout_sec;
704 		ocs_io_transition(els, __ocs_els_init, NULL);
705 	}
706 	return els;
707 }
708 
709 /**
710  * @ingroup els_api
711  * @brief Format and send a FDISC ELS command.
712  *
713  * <h3 class="desc">Description</h3>
714  * Construct an FDISC payload, and send to the \c node.
715  *
716  * @param node Node to which the FDISC is sent.
717  * @param timeout_sec Command timeout, in seconds.
718  * @param retries Number of times to retry errors before reporting a failure.
719  * @param cb Callback function.
720  * @param cbarg Callback function argument.
721  *
722  * @return Returns pointer to IO object, or NULL if error.
723  */
724 
725 ocs_io_t *
ocs_send_fdisc(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)726 ocs_send_fdisc(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
727 	els_cb_t cb, void *cbarg)
728 {
729 	ocs_io_t *els;
730 	ocs_t *ocs;
731 	fc_plogi_payload_t *fdisc;
732 
733 	ocs_assert(node, NULL);
734 	ocs_assert(node->ocs, NULL);
735 	ocs = node->ocs;
736 
737 	node_els_trace();
738 
739 	els = ocs_els_io_alloc(node, sizeof(*fdisc), OCS_ELS_ROLE_ORIGINATOR);
740 	if (els == NULL) {
741 		ocs_log_err(ocs, "IO alloc failed\n");
742 	} else {
743 		els->els_timeout_sec = timeout_sec;
744 		els->els_retries_remaining = retries;
745 		els->els_callback = cb;
746 		els->els_callback_arg = cbarg;
747 		els->display_name = "fdisc";
748 
749 		/* Build FDISC request */
750 		fdisc = els->els_req.virt;
751 
752 		ocs_memcpy(fdisc, node->sport->service_params, sizeof(*fdisc));
753 		fdisc->command_code = FC_ELS_CMD_FDISC;
754 		fdisc->resv1 = 0;
755 
756 		ocs_display_sparams(node->display_name, "fdisc send req", 0, NULL, fdisc->common_service_parameters);
757 
758 		els->hio_type = OCS_HW_ELS_REQ;
759 		els->iparam.els.timeout = timeout_sec;
760 		ocs_io_transition(els, __ocs_els_init, NULL);
761 	}
762 	return els;
763 }
764 
765 /**
766  * @ingroup els_api
767  * @brief Send a PRLI ELS command.
768  *
769  * <h3 class="desc">Description</h3>
770  * Construct a PRLI ELS command, and send to the \c node.
771  *
772  * @param node Node to which the PRLI is sent.
773  * @param timeout_sec Command timeout, in seconds.
774  * @param retries Number of times to retry errors before reporting a failure.
775  * @param cb Callback function.
776  * @param cbarg Callback function argument.
777  *
778  * @return Returns pointer to IO object, or NULL if error.
779  */
780 
781 ocs_io_t *
ocs_send_prli(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)782 ocs_send_prli(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
783 	els_cb_t cb, void *cbarg)
784 {
785 	ocs_t *ocs = node->ocs;
786 	ocs_io_t *els;
787 	fc_prli_payload_t *prli;
788 
789 	node_els_trace();
790 
791 	els = ocs_els_io_alloc(node, sizeof(*prli), OCS_ELS_ROLE_ORIGINATOR);
792 	if (els == NULL) {
793 		ocs_log_err(ocs, "IO alloc failed\n");
794 	} else {
795 		els->els_timeout_sec = timeout_sec;
796 		els->els_retries_remaining = retries;
797 		els->els_callback = cb;
798 		els->els_callback_arg = cbarg;
799 		els->display_name = "prli";
800 
801 		/* Build PRLI request */
802 		prli = els->els_req.virt;
803 
804 		ocs_memset(prli, 0, sizeof(*prli));
805 
806 		prli->command_code = FC_ELS_CMD_PRLI;
807 		prli->page_length = 16;
808 		prli->payload_length = ocs_htobe16(sizeof(fc_prli_payload_t));
809 		prli->type = FC_TYPE_FCP;
810 		prli->type_ext = 0;
811 		prli->flags = ocs_htobe16(FC_PRLI_ESTABLISH_IMAGE_PAIR);
812 		prli->service_params = ocs_htobe16(FC_PRLI_READ_XRDY_DISABLED |
813 			(node->sport->enable_ini ? FC_PRLI_INITIATOR_FUNCTION : 0) |
814 			(node->sport->enable_tgt ? FC_PRLI_TARGET_FUNCTION : 0));
815 
816 		/* For Tape Drive support */
817 		prli->service_params |= ocs_htobe16(FC_PRLI_CONFIRMED_COMPLETION | FC_PRLI_RETRY |
818 				 FC_PRLI_TASK_RETRY_ID_REQ| FC_PRLI_REC_SUPPORT);
819 
820 		els->hio_type = OCS_HW_ELS_REQ;
821 		els->iparam.els.timeout = timeout_sec;
822 		ocs_io_transition(els, __ocs_els_init, NULL);
823 	}
824 
825 	return els;
826 }
827 
828 /**
829  * @ingroup els_api
830  * @brief Send a PRLO ELS command.
831  *
832  * <h3 class="desc">Description</h3>
833  * Construct a PRLO ELS command, and send to the \c node.
834  *
835  * @param node Node to which the PRLO is sent.
836  * @param timeout_sec Command timeout, in seconds.
837  * @param retries Number of times to retry errors before reporting a failure.
838  * @param cb Callback function.
839  * @param cbarg Callback function argument.
840  *
841  * @return Returns pointer to IO object, or NULL if error.
842  */
843 
844 ocs_io_t *
ocs_send_prlo(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)845 ocs_send_prlo(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
846 	els_cb_t cb, void *cbarg)
847 {
848 	ocs_t *ocs = node->ocs;
849 	ocs_io_t *els;
850 	fc_prlo_payload_t *prlo;
851 
852 	node_els_trace();
853 
854 	els = ocs_els_io_alloc(node, sizeof(*prlo), OCS_ELS_ROLE_ORIGINATOR);
855 	if (els == NULL) {
856 		ocs_log_err(ocs, "IO alloc failed\n");
857 	} else {
858 		els->els_timeout_sec = timeout_sec;
859 		els->els_retries_remaining = retries;
860 		els->els_callback = cb;
861 		els->els_callback_arg = cbarg;
862 		els->display_name = "prlo";
863 
864 		/* Build PRLO request */
865 		prlo = els->els_req.virt;
866 
867 		ocs_memset(prlo, 0, sizeof(*prlo));
868 		prlo->command_code = FC_ELS_CMD_PRLO;
869 		prlo->page_length = 16;
870 		prlo->payload_length = ocs_htobe16(sizeof(fc_prlo_payload_t));
871 		prlo->type = FC_TYPE_FCP;
872 		prlo->type_ext = 0;
873 
874 		els->hio_type = OCS_HW_ELS_REQ;
875 		els->iparam.els.timeout = timeout_sec;
876 		ocs_io_transition(els, __ocs_els_init, NULL);
877 	}
878 	return els;
879 }
880 
881 /**
882  * @ingroup els_api
883  * @brief Send a LOGO ELS command.
884  *
885  * <h3 class="desc">Description</h3>
886  * Format a LOGO, and send to the \c node.
887  *
888  * @param node Node to which the LOGO is sent.
889  * @param timeout_sec Command timeout, in seconds.
890  * @param retries Number of times to retry errors before reporting a failure.
891  * @param cb Callback function.
892  * @param cbarg Callback function argument.
893  *
894  * @return Returns pointer to IO object, or NULL if error.
895  */
896 
897 ocs_io_t *
ocs_send_logo(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)898 ocs_send_logo(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
899 	els_cb_t cb, void *cbarg)
900 {
901 	ocs_io_t *els;
902 	ocs_t *ocs;
903 	fc_logo_payload_t *logo;
904 	fc_plogi_payload_t *sparams;
905 
906 	ocs = node->ocs;
907 
908 	node_els_trace();
909 
910 	sparams = (fc_plogi_payload_t*) node->sport->service_params;
911 
912 	els = ocs_els_io_alloc(node, sizeof(*logo), OCS_ELS_ROLE_ORIGINATOR);
913 	if (els == NULL) {
914 		ocs_log_err(ocs, "IO alloc failed\n");
915 	} else {
916 		els->els_timeout_sec = timeout_sec;
917 		els->els_retries_remaining = retries;
918 		els->els_callback = cb;
919 		els->els_callback_arg = cbarg;
920 		els->display_name = "logo";
921 
922 		/* Build LOGO request */
923 
924 		logo = els->els_req.virt;
925 
926 		ocs_memset(logo, 0, sizeof(*logo));
927 		logo->command_code = FC_ELS_CMD_LOGO;
928 		logo->resv1 = 0;
929 		logo->port_id = fc_htobe24(node->rnode.sport->fc_id);
930 		logo->port_name_hi = sparams->port_name_hi;
931 		logo->port_name_lo = sparams->port_name_lo;
932 
933 		els->hio_type = OCS_HW_ELS_REQ;
934 		els->iparam.els.timeout = timeout_sec;
935 		ocs_io_transition(els, __ocs_els_init, NULL);
936 	}
937 	return els;
938 }
939 
940 /**
941  * @ingroup els_api
942  * @brief Send an ADISC ELS command.
943  *
944  * <h3 class="desc">Description</h3>
945  * Construct an ADISC ELS command, and send to the \c node.
946  *
947  * @param node Node to which the ADISC is sent.
948  * @param timeout_sec Command timeout, in seconds.
949  * @param retries Number of times to retry errors before reporting a failure.
950  * @param cb Callback function.
951  * @param cbarg Callback function argument.
952  *
953  * @return Returns pointer to IO object, or NULL if error.
954  */
955 
956 ocs_io_t *
ocs_send_adisc(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)957 ocs_send_adisc(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
958 	els_cb_t cb, void *cbarg)
959 {
960 	ocs_io_t *els;
961 	ocs_t *ocs;
962 	fc_adisc_payload_t *adisc;
963 	fc_plogi_payload_t *sparams;
964 	ocs_sport_t *sport = node->sport;
965 
966 	ocs = node->ocs;
967 
968 	node_els_trace();
969 
970 	sparams = (fc_plogi_payload_t*) node->sport->service_params;
971 
972 	els = ocs_els_io_alloc(node, sizeof(*adisc), OCS_ELS_ROLE_ORIGINATOR);
973 	if (els == NULL) {
974 		ocs_log_err(ocs, "IO alloc failed\n");
975 	} else {
976 		els->els_timeout_sec = timeout_sec;
977 		els->els_retries_remaining = retries;
978 		els->els_callback = cb;
979 		els->els_callback_arg = cbarg;
980 		els->display_name = "adisc";
981 
982 		/* Build ADISC request */
983 
984 		adisc = els->els_req.virt;
985 		sparams = (fc_plogi_payload_t*) node->sport->service_params;
986 
987 		ocs_memset(adisc, 0, sizeof(*adisc));
988 		adisc->command_code = FC_ELS_CMD_ADISC;
989 		adisc->hard_address = fc_htobe24(sport->fc_id);
990 		adisc->port_name_hi = sparams->port_name_hi;
991 		adisc->port_name_lo = sparams->port_name_lo;
992 		adisc->node_name_hi = sparams->node_name_hi;
993 		adisc->node_name_lo = sparams->node_name_lo;
994 		adisc->port_id = fc_htobe24(node->rnode.sport->fc_id);
995 
996 		els->hio_type = OCS_HW_ELS_REQ;
997 		els->iparam.els.timeout = timeout_sec;
998 		ocs_io_transition(els, __ocs_els_init, NULL);
999 	}
1000 	return els;
1001 }
1002 
1003 /**
1004  * @ingroup els_api
1005  * @brief Send a PDISC ELS command.
1006  *
1007  * <h3 class="desc">Description</h3>
1008  * Construct a PDISC ELS command, and send to the \c node.
1009  *
1010  * @param node Node to which the PDISC is sent.
1011  * @param timeout_sec Command timeout, in seconds.
1012  * @param retries Number of times to retry errors before reporting a failure.
1013  * @param cb Callback function.
1014  * @param cbarg Callback function argument.
1015  *
1016  * @return Returns pointer to IO object, or NULL if error.
1017  */
1018 
1019 ocs_io_t *
ocs_send_pdisc(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)1020 ocs_send_pdisc(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
1021 	els_cb_t cb, void *cbarg)
1022 {
1023 	ocs_io_t *els;
1024 	ocs_t *ocs = node->ocs;
1025 	fc_plogi_payload_t *pdisc;
1026 
1027 	node_els_trace();
1028 
1029 	els = ocs_els_io_alloc(node, sizeof(*pdisc), OCS_ELS_ROLE_ORIGINATOR);
1030 	if (els == NULL) {
1031 		ocs_log_err(ocs, "IO alloc failed\n");
1032 	} else {
1033 		els->els_timeout_sec = timeout_sec;
1034 		els->els_retries_remaining = retries;
1035 		els->els_callback = cb;
1036 		els->els_callback_arg = cbarg;
1037 		els->display_name = "pdisc";
1038 
1039 		pdisc = els->els_req.virt;
1040 
1041 		ocs_memcpy(pdisc, node->sport->service_params, sizeof(*pdisc));
1042 
1043 		pdisc->command_code = FC_ELS_CMD_PDISC;
1044 		pdisc->resv1 = 0;
1045 
1046 		els->hio_type = OCS_HW_ELS_REQ;
1047 		els->iparam.els.timeout = timeout_sec;
1048 		ocs_io_transition(els, __ocs_els_init, NULL);
1049 	}
1050 	return els;
1051 }
1052 
1053 /**
1054  * @ingroup els_api
1055  * @brief Send an SCR ELS command.
1056  *
1057  * <h3 class="desc">Description</h3>
1058  * Format an SCR, and send to the \c node.
1059  *
1060  * @param node Node to which the SCR is sent.
1061  * @param timeout_sec Command timeout, in seconds.
1062  * @param retries Number of times to retry errors before reporting a failure.
1063  * @param cb Callback function
1064  * @param cbarg Callback function arg
1065  *
1066  * @return Returns pointer to IO object, or NULL if error.
1067  */
1068 
1069 ocs_io_t *
ocs_send_scr(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)1070 ocs_send_scr(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
1071 	els_cb_t cb, void *cbarg)
1072 {
1073 	ocs_io_t *els;
1074 	ocs_t *ocs = node->ocs;
1075 	fc_scr_payload_t *req;
1076 
1077 	node_els_trace();
1078 
1079 	els = ocs_els_io_alloc(node, sizeof(*req), OCS_ELS_ROLE_ORIGINATOR);
1080 	if (els == NULL) {
1081 		ocs_log_err(ocs, "IO alloc failed\n");
1082 	} else {
1083 		els->els_timeout_sec = timeout_sec;
1084 		els->els_retries_remaining = retries;
1085 		els->els_callback = cb;
1086 		els->els_callback_arg = cbarg;
1087 		els->display_name = "scr";
1088 
1089 		req = els->els_req.virt;
1090 
1091 		ocs_memset(req, 0, sizeof(*req));
1092 		req->command_code = FC_ELS_CMD_SCR;
1093 		req->function = FC_SCR_REG_FULL;
1094 
1095 		els->hio_type = OCS_HW_ELS_REQ;
1096 		els->iparam.els.timeout = timeout_sec;
1097 		ocs_io_transition(els, __ocs_els_init, NULL);
1098 	}
1099 	return els;
1100 }
1101 
1102 /**
1103  * @ingroup els_api
1104  * @brief Send an RRQ ELS command.
1105  *
1106  * <h3 class="desc">Description</h3>
1107  * Format an RRQ, and send to the \c node.
1108  *
1109  * @param node Node to which the RRQ is sent.
1110  * @param timeout_sec Command timeout, in seconds.
1111  * @param retries Number of times to retry errors before reporting a failure.
1112  * @param cb Callback function
1113  * @param cbarg Callback function arg
1114  *
1115  * @return Returns pointer to IO object, or NULL if error.
1116  */
1117 
1118 ocs_io_t *
ocs_send_rrq(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)1119 ocs_send_rrq(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
1120 	els_cb_t cb, void *cbarg)
1121 {
1122 	ocs_io_t *els;
1123 	ocs_t *ocs = node->ocs;
1124 	fc_scr_payload_t *req;
1125 
1126 	node_els_trace();
1127 
1128 	els = ocs_els_io_alloc(node, sizeof(*req), OCS_ELS_ROLE_ORIGINATOR);
1129 	if (els == NULL) {
1130 		ocs_log_err(ocs, "IO alloc failed\n");
1131 	} else {
1132 		els->els_timeout_sec = timeout_sec;
1133 		els->els_retries_remaining = retries;
1134 		els->els_callback = cb;
1135 		els->els_callback_arg = cbarg;
1136 		els->display_name = "scr";
1137 
1138 		req = els->els_req.virt;
1139 
1140 		ocs_memset(req, 0, sizeof(*req));
1141 		req->command_code = FC_ELS_CMD_RRQ;
1142 		req->function = FC_SCR_REG_FULL;
1143 
1144 		els->hio_type = OCS_HW_ELS_REQ;
1145 		els->iparam.els.timeout = timeout_sec;
1146 		ocs_io_transition(els, __ocs_els_init, NULL);
1147 	}
1148 	return els;
1149 }
1150 
1151 /**
1152  * @ingroup els_api
1153  * @brief Send an RSCN ELS command.
1154  *
1155  * <h3 class="desc">Description</h3>
1156  * Format an RSCN, and send to the \c node.
1157  *
1158  * @param node Node to which the RRQ is sent.
1159  * @param timeout_sec Command timeout, in seconds.
1160  * @param retries Number of times to retry errors before reporting a failure.
1161  * @param port_ids Pointer to port IDs
1162  * @param port_ids_count Count of port IDs
1163  * @param cb Callback function
1164  * @param cbarg Callback function arg
1165  *
1166  * @return Returns pointer to IO object, or NULL if error.
1167  */
1168 ocs_io_t *
ocs_send_rscn(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,void * port_ids,uint32_t port_ids_count,els_cb_t cb,void * cbarg)1169 ocs_send_rscn(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
1170 	void *port_ids, uint32_t port_ids_count, els_cb_t cb, void *cbarg)
1171 {
1172 	ocs_io_t *els;
1173 	ocs_t *ocs = node->ocs;
1174 	fc_rscn_payload_t *req;
1175 	uint32_t payload_length = sizeof(fc_rscn_affected_port_id_page_t)*(port_ids_count - 1) +
1176 		sizeof(fc_rscn_payload_t);
1177 
1178 	node_els_trace();
1179 
1180 	els = ocs_els_io_alloc(node, payload_length, OCS_ELS_ROLE_ORIGINATOR);
1181 	if (els == NULL) {
1182 		ocs_log_err(ocs, "IO alloc failed\n");
1183 	} else {
1184 		els->els_timeout_sec = timeout_sec;
1185 		els->els_retries_remaining = retries;
1186 		els->els_callback = cb;
1187 		els->els_callback_arg = cbarg;
1188 		els->display_name = "rscn";
1189 
1190 		req = els->els_req.virt;
1191 
1192 		req->command_code = FC_ELS_CMD_RSCN;
1193 		req->page_length = sizeof(fc_rscn_affected_port_id_page_t);
1194 		req->payload_length = ocs_htobe16(sizeof(*req) +
1195 			sizeof(fc_rscn_affected_port_id_page_t)*(port_ids_count-1));
1196 
1197 		els->hio_type = OCS_HW_ELS_REQ;
1198 		els->iparam.els.timeout = timeout_sec;
1199 
1200 		/* copy in the payload */
1201 		ocs_memcpy(req->port_list, port_ids, port_ids_count*sizeof(fc_rscn_affected_port_id_page_t));
1202 
1203 		/* Submit the request */
1204 		ocs_io_transition(els, __ocs_els_init, NULL);
1205 	}
1206 	return els;
1207 }
1208 
1209 /**
1210  * @brief Send an LS_RJT ELS response.
1211  *
1212  * <h3 class="desc">Description</h3>
1213  * Send an LS_RJT ELS response.
1214  *
1215  * @param io Pointer to a SCSI IO object.
1216  * @param ox_id Originator exchange ID being responded to.
1217  * @param reason_code Reason code value for LS_RJT.
1218  * @param reason_code_expl Reason code explanation value for LS_RJT.
1219  * @param vendor_unique Vendor-unique value for LS_RJT.
1220  * @param cb Callback function.
1221  * @param cbarg Callback function argument.
1222  *
1223  * @return Returns pointer to IO object, or NULL if error.
1224  */
1225 
1226 ocs_io_t *
ocs_send_ls_rjt(ocs_io_t * io,uint32_t ox_id,uint32_t reason_code,uint32_t reason_code_expl,uint32_t vendor_unique,els_cb_t cb,void * cbarg)1227 ocs_send_ls_rjt(ocs_io_t *io, uint32_t ox_id, uint32_t reason_code, uint32_t reason_code_expl,
1228 		uint32_t vendor_unique, els_cb_t cb, void *cbarg)
1229 {
1230 	ocs_node_t *node = io->node;
1231 	int32_t rc;
1232 	ocs_t *ocs = node->ocs;
1233 	fc_ls_rjt_payload_t *rjt;
1234 
1235 	node_els_trace();
1236 
1237 	io->els_callback = cb;
1238 	io->els_callback_arg = cbarg;
1239 	io->display_name = "ls_rjt";
1240 	io->init_task_tag = ox_id;
1241 
1242 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1243 	io->iparam.els.ox_id = ox_id;
1244 
1245 	rjt = io->els_req.virt;
1246 	ocs_memset(rjt, 0, sizeof(*rjt));
1247 
1248 	rjt->command_code = FC_ELS_CMD_RJT;
1249 	rjt->reason_code = reason_code;
1250 	rjt->reason_code_exp = reason_code_expl;
1251 
1252 	io->hio_type = OCS_HW_ELS_RSP;
1253 	if ((rc = ocs_els_send_rsp(io, sizeof(*rjt)))) {
1254 		ocs_els_io_free(io);
1255 		io = NULL;
1256 	}
1257 
1258 	return io;
1259 }
1260 
1261 /**
1262  * @ingroup els_api
1263  * @brief Send a PLOGI accept response.
1264  *
1265  * <h3 class="desc">Description</h3>
1266  * Construct a PLOGI LS_ACC, and send to the \c node, using the originator exchange ID
1267  * \c ox_id.
1268  *
1269  * @param io Pointer to a SCSI IO object.
1270  * @param ox_id Originator exchange ID being responsed to.
1271  * @param cb Callback function.
1272  * @param cbarg Callback function argument.
1273  *
1274  * @return Returns pointer to IO object, or NULL if error.
1275  */
1276 ocs_io_t *
ocs_send_plogi_acc(ocs_io_t * io,uint32_t ox_id,els_cb_t cb,void * cbarg)1277 ocs_send_plogi_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
1278 {
1279 	ocs_node_t *node = io->node;
1280 	int32_t rc;
1281 	ocs_t *ocs = node->ocs;
1282 	fc_plogi_payload_t *plogi;
1283 	fc_plogi_payload_t *req = (fc_plogi_payload_t *)node->service_params;
1284 
1285 	node_els_trace();
1286 
1287 	io->els_callback = cb;
1288 	io->els_callback_arg = cbarg;
1289 	io->display_name = "plog_acc";
1290 	io->init_task_tag = ox_id;
1291 
1292 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1293 	io->iparam.els.ox_id = ox_id;
1294 
1295 	plogi = io->els_req.virt;
1296 
1297 	/* copy our port's service parameters to payload */
1298 	ocs_memcpy(plogi, node->sport->service_params, sizeof(*plogi));
1299 	plogi->command_code = FC_ELS_CMD_ACC;
1300 	plogi->resv1 = 0;
1301 
1302 	/* Set Application header support bit if requested */
1303 	if (req->common_service_parameters[1] & ocs_htobe32(1U << 24)) {
1304 		plogi->common_service_parameters[1] |= ocs_htobe32(1U << 24);
1305 	}
1306 
1307 	/* Priority tagging support. */
1308 	if (req->common_service_parameters[1] & ocs_htobe32(1U << 23)) {
1309 		plogi->common_service_parameters[1] |= ocs_htobe32(1U << 23);
1310 	}
1311 
1312 	ocs_display_sparams(node->display_name, "plogi send resp", 0, NULL, plogi->common_service_parameters);
1313 
1314 	io->hio_type = OCS_HW_ELS_RSP;
1315 	if ((rc = ocs_els_send_rsp(io, sizeof(*plogi)))) {
1316 		ocs_els_io_free(io);
1317 		io = NULL;
1318 	}
1319 	return io;
1320 }
1321 
1322 /**
1323  * @ingroup els_api
1324  * @brief Send an FLOGI accept response for point-to-point negotiation.
1325  *
1326  * <h3 class="desc">Description</h3>
1327  * Construct an FLOGI accept response, and send to the \c node using the originator
1328  * exchange id \c ox_id. The \c s_id is used for the response frame source FC ID.
1329  *
1330  * @param io Pointer to a SCSI IO object.
1331  * @param ox_id Originator exchange ID for the response.
1332  * @param s_id Source FC ID to be used in the response frame.
1333  * @param cb Callback function.
1334  * @param cbarg Callback function argument.
1335  *
1336  * @return Returns pointer to IO object, or NULL if error.
1337  */
1338 ocs_io_t *
ocs_send_flogi_p2p_acc(ocs_io_t * io,uint32_t ox_id,uint32_t s_id,els_cb_t cb,void * cbarg)1339 ocs_send_flogi_p2p_acc(ocs_io_t *io, uint32_t ox_id, uint32_t s_id, els_cb_t cb, void *cbarg)
1340 {
1341 	ocs_node_t *node = io->node;
1342 	int32_t rc;
1343 	ocs_t *ocs = node->ocs;
1344 	fc_plogi_payload_t *flogi;
1345 
1346 	node_els_trace();
1347 
1348 	io->els_callback = cb;
1349 	io->els_callback_arg = cbarg;
1350 	io->display_name = "flogi_p2p_acc";
1351 	io->init_task_tag = ox_id;
1352 
1353 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1354 	io->iparam.els_sid.ox_id = ox_id;
1355 	io->iparam.els_sid.s_id = s_id;
1356 
1357 	flogi = io->els_req.virt;
1358 
1359 	/* copy our port's service parameters to payload */
1360 	ocs_memcpy(flogi, node->sport->service_params, sizeof(*flogi));
1361 	flogi->command_code = FC_ELS_CMD_ACC;
1362 	flogi->resv1 = 0;
1363 	ocs_memset(flogi->class1_service_parameters, 0, sizeof(flogi->class1_service_parameters));
1364 	ocs_memset(flogi->class2_service_parameters, 0, sizeof(flogi->class1_service_parameters));
1365 	ocs_memset(flogi->class3_service_parameters, 0, sizeof(flogi->class1_service_parameters));
1366 	ocs_memset(flogi->class4_service_parameters, 0, sizeof(flogi->class1_service_parameters));
1367 
1368 	io->hio_type = OCS_HW_ELS_RSP_SID;
1369 	if ((rc = ocs_els_send_rsp(io, sizeof(*flogi)))) {
1370 		ocs_els_io_free(io);
1371 		io = NULL;
1372 	}
1373 
1374 	return io;
1375 }
1376 
1377 ocs_io_t *
ocs_send_flogi_acc(ocs_io_t * io,uint32_t ox_id,uint32_t is_fport,els_cb_t cb,void * cbarg)1378 ocs_send_flogi_acc(ocs_io_t *io, uint32_t ox_id, uint32_t is_fport, els_cb_t cb, void *cbarg)
1379 {
1380 	ocs_node_t *node = io->node;
1381 	int32_t rc;
1382 	ocs_t *ocs = node->ocs;
1383 	fc_plogi_payload_t *flogi;
1384 
1385 	node_els_trace();
1386 
1387 	io->els_callback = cb;
1388 	io->els_callback_arg = cbarg;
1389 	io->display_name = "flogi_acc";
1390 	io->init_task_tag = ox_id;
1391 
1392 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1393 	io->iparam.els_sid.ox_id = ox_id;
1394 	io->iparam.els_sid.s_id = io->node->sport->fc_id;
1395 
1396 	flogi = io->els_req.virt;
1397 
1398 	/* copy our port's service parameters to payload */
1399 	ocs_memcpy(flogi, node->sport->service_params, sizeof(*flogi));
1400 
1401 	/* Set F_port */
1402 	if (is_fport) {
1403 		/* Set F_PORT and Multiple N_PORT_ID Assignment */
1404 		flogi->common_service_parameters[1] |= ocs_be32toh(3U << 28);
1405 	}
1406 
1407 	flogi->command_code = FC_ELS_CMD_ACC;
1408 	flogi->resv1 = 0;
1409 
1410 	ocs_display_sparams(node->display_name, "flogi send resp", 0, NULL, flogi->common_service_parameters);
1411 
1412 	ocs_memset(flogi->class1_service_parameters, 0, sizeof(flogi->class1_service_parameters));
1413 	ocs_memset(flogi->class2_service_parameters, 0, sizeof(flogi->class1_service_parameters));
1414 	ocs_memset(flogi->class3_service_parameters, 0, sizeof(flogi->class1_service_parameters));
1415 	ocs_memset(flogi->class4_service_parameters, 0, sizeof(flogi->class1_service_parameters));
1416 
1417 	io->hio_type = OCS_HW_ELS_RSP_SID;
1418 	if ((rc = ocs_els_send_rsp(io, sizeof(*flogi)))) {
1419 		ocs_els_io_free(io);
1420 		io = NULL;
1421 	}
1422 
1423 	return io;
1424 }
1425 
1426 /**
1427  * @ingroup els_api
1428  * @brief Send a PRLI accept response
1429  *
1430  * <h3 class="desc">Description</h3>
1431  * Construct a PRLI LS_ACC response, and send to the \c node, using the originator
1432  * \c ox_id exchange ID.
1433  *
1434  * @param io Pointer to a SCSI IO object.
1435  * @param ox_id Originator exchange ID.
1436  * @param cb Callback function.
1437  * @param cbarg Callback function argument.
1438  *
1439  * @return Returns pointer to IO object, or NULL if error.
1440  */
1441 
1442 ocs_io_t *
ocs_send_prli_acc(ocs_io_t * io,uint32_t ox_id,uint8_t fc_type,els_cb_t cb,void * cbarg)1443 ocs_send_prli_acc(ocs_io_t *io, uint32_t ox_id, uint8_t fc_type, els_cb_t cb, void *cbarg)
1444 {
1445 	ocs_node_t *node = io->node;
1446 	int32_t rc;
1447 	ocs_t *ocs = node->ocs;
1448 	fc_prli_payload_t *prli;
1449 
1450 	node_els_trace();
1451 
1452 	io->els_callback = cb;
1453 	io->els_callback_arg = cbarg;
1454 	io->display_name = "prli_acc";
1455 	io->init_task_tag = ox_id;
1456 
1457 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1458 	io->iparam.els.ox_id = ox_id;
1459 
1460 	prli = io->els_req.virt;
1461 	ocs_memset(prli, 0, sizeof(*prli));
1462 
1463 	prli->command_code = FC_ELS_CMD_ACC;
1464 	prli->page_length = 16;
1465 	prli->payload_length = ocs_htobe16(sizeof(fc_prli_payload_t));
1466 	prli->type = fc_type;
1467 	prli->type_ext = 0;
1468 	prli->flags = ocs_htobe16(FC_PRLI_ESTABLISH_IMAGE_PAIR | FC_PRLI_REQUEST_EXECUTED);
1469 
1470 	prli->service_params = ocs_htobe16(FC_PRLI_READ_XRDY_DISABLED |
1471 				(node->sport->enable_ini ? FC_PRLI_INITIATOR_FUNCTION : 0) |
1472 				(node->sport->enable_tgt ? FC_PRLI_TARGET_FUNCTION : 0));
1473 
1474 	io->hio_type = OCS_HW_ELS_RSP;
1475 	if ((rc = ocs_els_send_rsp(io, sizeof(*prli)))) {
1476 		ocs_els_io_free(io);
1477 		io = NULL;
1478 	}
1479 
1480 	return io;
1481 }
1482 
1483 /**
1484  * @ingroup els_api
1485  * @brief Send a PRLO accept response.
1486  *
1487  * <h3 class="desc">Description</h3>
1488  * Construct a PRLO LS_ACC response, and send to the \c node, using the originator
1489  * exchange ID \c ox_id.
1490  *
1491  * @param io Pointer to a SCSI IO object.
1492  * @param ox_id Originator exchange ID.
1493  * @param cb Callback function.
1494  * @param cbarg Callback function argument.
1495  *
1496  * @return Returns pointer to IO object, or NULL if error.
1497  */
1498 
1499 ocs_io_t *
ocs_send_prlo_acc(ocs_io_t * io,uint32_t ox_id,uint8_t fc_type,els_cb_t cb,void * cbarg)1500 ocs_send_prlo_acc(ocs_io_t *io, uint32_t ox_id, uint8_t fc_type, els_cb_t cb, void *cbarg)
1501 {
1502 	ocs_node_t *node = io->node;
1503 	int32_t rc;
1504 	ocs_t *ocs = node->ocs;
1505 	fc_prlo_acc_payload_t *prlo_acc;
1506 
1507 	node_els_trace();
1508 
1509 	io->els_callback = cb;
1510 	io->els_callback_arg = cbarg;
1511 	io->display_name = "prlo_acc";
1512 	io->init_task_tag = ox_id;
1513 
1514 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1515 	io->iparam.els.ox_id = ox_id;
1516 
1517 	prlo_acc = io->els_req.virt;
1518 	ocs_memset(prlo_acc, 0, sizeof(*prlo_acc));
1519 
1520 	prlo_acc->command_code = FC_ELS_CMD_ACC;
1521 	prlo_acc->page_length = 16;
1522 	prlo_acc->payload_length = ocs_htobe16(sizeof(fc_prlo_acc_payload_t));
1523 	prlo_acc->type = fc_type;
1524 	prlo_acc->type_ext = 0;
1525 	prlo_acc->response_code = FC_PRLO_REQUEST_EXECUTED;
1526 
1527 	io->hio_type = OCS_HW_ELS_RSP;
1528 	if ((rc = ocs_els_send_rsp(io, sizeof(*prlo_acc)))) {
1529 		ocs_els_io_free(io);
1530 		io = NULL;
1531 	}
1532 
1533 	return io;
1534 }
1535 
1536 /**
1537  * @ingroup els_api
1538  * @brief Send a generic LS_ACC response without a payload.
1539  *
1540  * <h3 class="desc">Description</h3>
1541  * A generic LS_ACC response is sent to the \c node using the originator exchange ID
1542  * \c ox_id.
1543  *
1544  * @param io Pointer to a SCSI IO object.
1545  * @param ox_id Originator exchange id.
1546  * @param cb Callback function.
1547  * @param cbarg Callback function argument.
1548  *
1549  * @return Returns pointer to IO object, or NULL if error.
1550  */
1551 ocs_io_t *
ocs_send_ls_acc(ocs_io_t * io,uint32_t ox_id,els_cb_t cb,void * cbarg)1552 ocs_send_ls_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
1553 {
1554 	ocs_node_t *node = io->node;
1555 	int32_t rc;
1556 	ocs_t *ocs = node->ocs;
1557 	fc_acc_payload_t *acc;
1558 
1559 	node_els_trace();
1560 
1561 	io->els_callback = cb;
1562 	io->els_callback_arg = cbarg;
1563 	io->display_name = "ls_acc";
1564 	io->init_task_tag = ox_id;
1565 
1566 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1567 	io->iparam.els.ox_id = ox_id;
1568 
1569 	acc = io->els_req.virt;
1570 	ocs_memset(acc, 0, sizeof(*acc));
1571 
1572 	acc->command_code = FC_ELS_CMD_ACC;
1573 
1574 	io->hio_type = OCS_HW_ELS_RSP;
1575 	if ((rc = ocs_els_send_rsp(io, sizeof(*acc)))) {
1576 		ocs_els_io_free(io);
1577 		io = NULL;
1578 	}
1579 
1580 	return io;
1581 }
1582 
1583 /**
1584  * @ingroup els_api
1585  * @brief Send a LOGO accept response.
1586  *
1587  * <h3 class="desc">Description</h3>
1588  * Construct a LOGO LS_ACC response, and send to the \c node, using the originator
1589  * exchange ID \c ox_id.
1590  *
1591  * @param io Pointer to a SCSI IO object.
1592  * @param ox_id Originator exchange ID.
1593  * @param cb Callback function.
1594  * @param cbarg Callback function argument.
1595  *
1596  * @return Returns pointer to IO object, or NULL if error.
1597  */
1598 ocs_io_t *
ocs_send_logo_acc(ocs_io_t * io,uint32_t ox_id,els_cb_t cb,void * cbarg)1599 ocs_send_logo_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
1600 {
1601 	ocs_node_t *node = io->node;
1602 	int32_t rc;
1603 	ocs_t *ocs = node->ocs;
1604 	fc_acc_payload_t *logo;
1605 
1606 	node_els_trace();
1607 
1608 	io->els_callback = cb;
1609 	io->els_callback_arg = cbarg;
1610 	io->display_name = "logo_acc";
1611 	io->init_task_tag = ox_id;
1612 
1613 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1614 	io->iparam.els.ox_id = ox_id;
1615 
1616 	logo = io->els_req.virt;
1617 	ocs_memset(logo, 0, sizeof(*logo));
1618 
1619 	logo->command_code = FC_ELS_CMD_ACC;
1620 	logo->resv1 = 0;
1621 
1622 	io->hio_type = OCS_HW_ELS_RSP;
1623 	if ((rc = ocs_els_send_rsp(io, sizeof(*logo)))) {
1624 		ocs_els_io_free(io);
1625 		io = NULL;
1626 	}
1627 
1628 	return io;
1629 }
1630 
1631 /**
1632  * @ingroup els_api
1633  * @brief Send an ADISC accept response.
1634  *
1635  * <h3 class="desc">Description</h3>
1636  * Construct an ADISC LS__ACC, and send to the \c node, using the originator
1637  * exchange id \c ox_id.
1638  *
1639  * @param io Pointer to a SCSI IO object.
1640  * @param ox_id Originator exchange ID.
1641  * @param cb Callback function.
1642  * @param cbarg Callback function argument.
1643  *
1644  * @return Returns pointer to IO object, or NULL if error.
1645  */
1646 
1647 ocs_io_t *
ocs_send_adisc_acc(ocs_io_t * io,uint32_t ox_id,els_cb_t cb,void * cbarg)1648 ocs_send_adisc_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
1649 {
1650 	ocs_node_t *node = io->node;
1651 	int32_t rc;
1652 	fc_adisc_payload_t *adisc;
1653 	fc_plogi_payload_t *sparams;
1654 	ocs_t *ocs;
1655 
1656 	ocs_assert(node, NULL);
1657 	ocs_assert(node->ocs, NULL);
1658 	ocs = node->ocs;
1659 
1660 	node_els_trace();
1661 
1662 	io->els_callback = cb;
1663 	io->els_callback_arg = cbarg;
1664 	io->display_name = "adisc_acc";
1665 	io->init_task_tag = ox_id;
1666 
1667 	/* Go ahead and send the ELS_ACC */
1668 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1669 	io->iparam.els.ox_id = ox_id;
1670 
1671 	sparams = (fc_plogi_payload_t*) node->sport->service_params;
1672 	adisc = io->els_req.virt;
1673 	ocs_memset(adisc, 0, sizeof(fc_adisc_payload_t));
1674 	adisc->command_code = FC_ELS_CMD_ACC;
1675 	adisc->hard_address = 0;
1676 	adisc->port_name_hi = sparams->port_name_hi;
1677 	adisc->port_name_lo = sparams->port_name_lo;
1678 	adisc->node_name_hi = sparams->node_name_hi;
1679 	adisc->node_name_lo = sparams->node_name_lo;
1680 	adisc->port_id = fc_htobe24(node->rnode.sport->fc_id);
1681 
1682 	io->hio_type = OCS_HW_ELS_RSP;
1683 	if ((rc = ocs_els_send_rsp(io, sizeof(*adisc)))) {
1684 		ocs_els_io_free(io);
1685 		io = NULL;
1686 	}
1687 
1688 	return io;
1689 }
1690 
1691 /**
1692  * @ingroup els_api
1693  * @brief Send a RFTID CT request.
1694  *
1695  * <h3 class="desc">Description</h3>
1696  * Construct an RFTID CT request, and send to the \c node.
1697  *
1698  * @param node Node to which the RFTID request is sent.
1699  * @param timeout_sec Time, in seconds, to wait before timing out the ELS.
1700  * @param retries Number of times to retry errors before reporting a failure.
1701  * @param cb Callback function.
1702  * @param cbarg Callback function argument.
1703  *
1704  * @return Returns pointer to IO object, or NULL if error.
1705  */
1706 ocs_io_t *
ocs_ns_send_rftid(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)1707 ocs_ns_send_rftid(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
1708 	els_cb_t cb, void *cbarg)
1709 {
1710 	ocs_io_t *els;
1711 	ocs_t *ocs = node->ocs;
1712 	fcct_rftid_req_t *rftid;
1713 
1714 	node_els_trace();
1715 
1716 	els = ocs_els_io_alloc(node, sizeof(*rftid), OCS_ELS_ROLE_ORIGINATOR);
1717 	if (els == NULL) {
1718 		ocs_log_err(ocs, "IO alloc failed\n");
1719 	} else {
1720 		els->iparam.fc_ct.r_ctl = FC_RCTL_ELS;
1721 		els->iparam.fc_ct.type = FC_TYPE_GS;
1722 		els->iparam.fc_ct.df_ctl = 0;
1723 		els->iparam.fc_ct.timeout = timeout_sec;
1724 
1725 		els->els_callback = cb;
1726 		els->els_callback_arg = cbarg;
1727 		els->display_name = "rftid";
1728 
1729 		rftid = els->els_req.virt;
1730 
1731 		ocs_memset(rftid, 0, sizeof(*rftid));
1732 		fcct_build_req_header(&rftid->hdr, FC_GS_NAMESERVER_RFT_ID, (OCS_ELS_RSP_LEN - sizeof(rftid->hdr)));
1733 		rftid->port_id = ocs_htobe32(node->rnode.sport->fc_id);
1734 		rftid->fc4_types[FC_GS_TYPE_WORD(FC_TYPE_FCP)] = ocs_htobe32(1 << FC_GS_TYPE_BIT(FC_TYPE_FCP));
1735 
1736 		els->hio_type = OCS_HW_FC_CT;
1737 
1738 		ocs_io_transition(els, __ocs_els_init, NULL);
1739 	}
1740 	return els;
1741 }
1742 
1743 /**
1744  * @ingroup els_api
1745  * @brief Send a RFFID CT request.
1746  *
1747  * <h3 class="desc">Description</h3>
1748  * Construct an RFFID CT request, and send to the \c node.
1749  *
1750  * @param node Node to which the RFFID request is sent.
1751  * @param timeout_sec Time, in seconds, to wait before timing out the ELS.
1752  * @param retries Number of times to retry errors before reporting a failure.
1753  * @param cb Callback function
1754  * @param cbarg Callback function argument.
1755  *
1756  * @return Returns pointer to IO object, or NULL if error.
1757  */
1758 ocs_io_t *
ocs_ns_send_rffid(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)1759 ocs_ns_send_rffid(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
1760 	els_cb_t cb, void *cbarg)
1761 {
1762 	ocs_io_t *els;
1763 	ocs_t *ocs = node->ocs;
1764 	fcct_rffid_req_t *rffid;
1765 
1766 	node_els_trace();
1767 
1768 	els = ocs_els_io_alloc(node, sizeof(*rffid), OCS_ELS_ROLE_ORIGINATOR);
1769 	if (els == NULL) {
1770 		ocs_log_err(ocs, "IO alloc failed\n");
1771 	} else {
1772 		els->iparam.fc_ct.r_ctl = FC_RCTL_ELS;
1773 		els->iparam.fc_ct.type = FC_TYPE_GS;
1774 		els->iparam.fc_ct.df_ctl = 0;
1775 		els->iparam.fc_ct.timeout = timeout_sec;
1776 
1777 		els->els_callback = cb;
1778 		els->els_callback_arg = cbarg;
1779 		els->display_name = "rffid";
1780 
1781 		rffid = els->els_req.virt;
1782 
1783 		ocs_memset(rffid, 0, sizeof(*rffid));
1784 
1785 		fcct_build_req_header(&rffid->hdr, FC_GS_NAMESERVER_RFF_ID, (OCS_ELS_RSP_LEN - sizeof(rffid->hdr)));
1786 		rffid->port_id = ocs_htobe32(node->rnode.sport->fc_id);
1787 		if (node->sport->enable_ini) {
1788 			rffid->fc4_feature_bits |= FC4_FEATURE_INITIATOR;
1789 		}
1790 		if (node->sport->enable_tgt) {
1791 			rffid->fc4_feature_bits |= FC4_FEATURE_TARGET;
1792 		}
1793 		rffid->type = FC_TYPE_FCP;
1794 
1795 		els->hio_type = OCS_HW_FC_CT;
1796 
1797 		ocs_io_transition(els, __ocs_els_init, NULL);
1798 	}
1799 	return els;
1800 }
1801 
1802 /**
1803  * @ingroup els_api
1804  * @brief Send a GIDPT CT request.
1805  *
1806  * <h3 class="desc">Description</h3>
1807  * Construct a GIDPT CT request, and send to the \c node.
1808  *
1809  * @param node Node to which the GIDPT request is sent.
1810  * @param timeout_sec Time, in seconds, to wait before timing out the ELS.
1811  * @param retries Number of times to retry errors before reporting a failure.
1812  * @param cb Callback function.
1813  * @param cbarg Callback function argument.
1814  *
1815  * @return Returns pointer to IO object, or NULL if error.
1816  */
1817 
1818 ocs_io_t *
ocs_ns_send_gidpt(ocs_node_t * node,uint32_t timeout_sec,uint32_t retries,els_cb_t cb,void * cbarg)1819 ocs_ns_send_gidpt(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
1820 	els_cb_t cb, void *cbarg)
1821 {
1822 	ocs_io_t *els;
1823 	ocs_t *ocs = node->ocs;
1824 	fcct_gidpt_req_t *gidpt;
1825 
1826 	node_els_trace();
1827 
1828 	els = ocs_els_io_alloc_size(node, sizeof(*gidpt), OCS_ELS_GID_PT_RSP_LEN, OCS_ELS_ROLE_ORIGINATOR);
1829 	if (els == NULL) {
1830 		ocs_log_err(ocs, "IO alloc failed\n");
1831 	} else {
1832 		els->iparam.fc_ct.r_ctl = FC_RCTL_ELS;
1833 		els->iparam.fc_ct.type = FC_TYPE_GS;
1834 		els->iparam.fc_ct.df_ctl = 0;
1835 		els->iparam.fc_ct.timeout = timeout_sec;
1836 
1837 		els->els_callback = cb;
1838 		els->els_callback_arg = cbarg;
1839 		els->display_name = "gidpt";
1840 
1841 		gidpt = els->els_req.virt;
1842 
1843 		ocs_memset(gidpt, 0, sizeof(*gidpt));
1844 		fcct_build_req_header(&gidpt->hdr, FC_GS_NAMESERVER_GID_PT, (OCS_ELS_GID_PT_RSP_LEN - sizeof(gidpt->hdr)) );
1845 		gidpt->domain_id_scope = 0;
1846 		gidpt->area_id_scope = 0;
1847 		gidpt->port_type = 0x7f;
1848 
1849 		els->hio_type = OCS_HW_FC_CT;
1850 
1851 		ocs_io_transition(els, __ocs_els_init, NULL);
1852 	}
1853 	return els;
1854 }
1855 
1856 /**
1857  * @ingroup els_api
1858  * @brief Send a BA_ACC given the request's FC header
1859  *
1860  * <h3 class="desc">Description</h3>
1861  * Using the S_ID/D_ID from the request's FC header, generate a BA_ACC.
1862  *
1863  * @param io Pointer to a SCSI IO object.
1864  * @param hdr Pointer to the FC header.
1865  *
1866  * @return Returns pointer to IO object, or NULL if error.
1867  */
1868 
1869 ocs_io_t *
ocs_bls_send_acc_hdr(ocs_io_t * io,fc_header_t * hdr)1870 ocs_bls_send_acc_hdr(ocs_io_t *io, fc_header_t *hdr)
1871 {
1872 	uint16_t ox_id = ocs_be16toh(hdr->ox_id);
1873 	uint16_t rx_id = ocs_be16toh(hdr->rx_id);
1874 	uint32_t d_id = fc_be24toh(hdr->d_id);
1875 
1876 	return ocs_bls_send_acc(io, d_id, ox_id, rx_id);
1877 }
1878 
1879 /**
1880  * @ingroup els_api
1881  * @brief Send a BLS BA_ACC response.
1882  *
1883  * <h3 class="desc">Description</h3>
1884  * Construct a BLS BA_ACC response, and send to the \c node.
1885  *
1886  * @param io Pointer to a SCSI IO object.
1887  * @param s_id S_ID to use for the response. If UINT32_MAX, then use our SLI port
1888  * (sport) S_ID.
1889  * @param ox_id Originator exchange ID.
1890  * @param rx_id Responder exchange ID.
1891  *
1892  * @return Returns pointer to IO object, or NULL if error.
1893  */
1894 
1895 static ocs_io_t *
ocs_bls_send_acc(ocs_io_t * io,uint32_t s_id,uint16_t ox_id,uint16_t rx_id)1896 ocs_bls_send_acc(ocs_io_t *io, uint32_t s_id, uint16_t ox_id, uint16_t rx_id)
1897 {
1898 	ocs_node_t *node = io->node;
1899 	int32_t rc;
1900 	fc_ba_acc_payload_t *acc;
1901 	ocs_t *ocs;
1902 
1903 	ocs_assert(node, NULL);
1904 	ocs_assert(node->ocs, NULL);
1905 	ocs = node->ocs;
1906 
1907 	if (node->rnode.sport->fc_id == s_id) {
1908 		s_id = UINT32_MAX;
1909 	}
1910 
1911 	/* fill out generic fields */
1912 	io->ocs = ocs;
1913 	io->node = node;
1914 	io->cmd_tgt = TRUE;
1915 
1916 	/* fill out BLS Response-specific fields */
1917 	io->io_type = OCS_IO_TYPE_BLS_RESP;
1918 	io->display_name = "ba_acc";
1919 	io->hio_type = OCS_HW_BLS_ACC_SID;
1920 	io->init_task_tag = ox_id;
1921 
1922 	/* fill out iparam fields */
1923 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
1924 	io->iparam.bls_sid.s_id = s_id;
1925 	io->iparam.bls_sid.ox_id = ox_id;
1926 	io->iparam.bls_sid.rx_id = rx_id;
1927 
1928 	acc = (void *)io->iparam.bls_sid.payload;
1929 
1930 	ocs_memset(io->iparam.bls_sid.payload, 0, sizeof(io->iparam.bls_sid.payload));
1931 	acc->ox_id = io->iparam.bls_sid.ox_id;
1932 	acc->rx_id = io->iparam.bls_sid.rx_id;
1933 	acc->high_seq_cnt = UINT16_MAX;
1934 
1935 	if ((rc = ocs_scsi_io_dispatch(io, ocs_bls_send_acc_cb))) {
1936 		ocs_log_err(ocs, "ocs_scsi_io_dispatch() failed: %d\n", rc);
1937 		ocs_scsi_io_free(io);
1938 		io = NULL;
1939 	}
1940 	return io;
1941 }
1942 
1943 /**
1944  * @brief Handle the BLS accept completion.
1945  *
1946  * <h3 class="desc">Description</h3>
1947  * Upon completion of sending a BA_ACC, this callback is invoked by the HW.
1948  *
1949  * @param hio Pointer to the HW IO object.
1950  * @param rnode Pointer to the HW remote node.
1951  * @param length Length of the response payload, in bytes.
1952  * @param status Completion status.
1953  * @param ext_status Extended completion status.
1954  * @param app Callback private argument.
1955  *
1956  * @return Returns 0 on success; or a negative error value on failure.
1957  */
1958 
1959 static int32_t
ocs_bls_send_acc_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * app)1960 ocs_bls_send_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
1961 {
1962 	ocs_io_t *io = app;
1963 
1964 	ocs_assert(io, -1);
1965 
1966 	ocs_scsi_io_free(io);
1967 	return 0;
1968 }
1969 
1970 /**
1971  * @brief ELS abort callback.
1972  *
1973  * <h3 class="desc">Description</h3>
1974  * This callback is invoked by the HW when an ELS IO is aborted.
1975  *
1976  * @param hio Pointer to the HW IO object.
1977  * @param rnode Pointer to the HW remote node.
1978  * @param length Length of the response payload, in bytes.
1979  * @param status Completion status.
1980  * @param ext_status Extended completion status.
1981  * @param app Callback private argument.
1982  *
1983  * @return Returns 0 on success; or a negative error value on failure.
1984  */
1985 
1986 static int32_t
ocs_els_abort_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * app)1987 ocs_els_abort_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
1988 {
1989 	ocs_io_t *els;
1990 	ocs_io_t *abort_io = NULL; /* IO structure used to abort ELS */
1991 	ocs_t *ocs;
1992 
1993 	ocs_assert(app, -1);
1994 	abort_io = app;
1995 	els = abort_io->io_to_abort;
1996 	ocs_assert(els->node, -1);
1997 	ocs_assert(els->node->ocs, -1);
1998 
1999 	ocs = els->node->ocs;
2000 
2001 	if (status != 0) {
2002 		ocs_log_warn(ocs, "status x%x ext x%x\n", status, ext_status);
2003 	}
2004 
2005 	/* now free the abort IO */
2006 	ocs_io_free(ocs, abort_io);
2007 
2008 	/* send completion event to indicate abort process is complete
2009 	 * Note: The ELS SM will already be receiving ELS_REQ_OK/FAIL/RJT/ABORTED
2010 	 */
2011 	ocs_els_post_event(els, OCS_EVT_ELS_ABORT_CMPL, NULL);
2012 
2013 	/* done with ELS IO to abort */
2014 	ocs_ref_put(&els->ref); /* ocs_ref_get(): ocs_els_abort_io() */
2015 	return 0;
2016 }
2017 
2018 /**
2019  * @brief Abort an ELS IO.
2020  *
2021  * <h3 class="desc">Description</h3>
2022  * The ELS IO is aborted by making a HW abort IO request,
2023  * optionally requesting that an ABTS is sent.
2024  *
2025  * \b Note: This function allocates a HW IO, and associates the HW IO
2026  * with the ELS IO that it is aborting. It does not associate
2027  * the HW IO with the node directly, like for ELS requests. The
2028  * abort completion is propagated up to the node once the
2029  * original WQE and the abort WQE are complete (the original WQE
2030  * completion is not propagated up to node).
2031  *
2032  * @param els Pointer to the ELS IO.
2033  * @param send_abts Boolean to indicate if hardware will automatically generate an ABTS.
2034  *
2035  * @return Returns pointer to Abort IO object, or NULL if error.
2036  */
2037 
2038 static ocs_io_t *
ocs_els_abort_io(ocs_io_t * els,int send_abts)2039 ocs_els_abort_io(ocs_io_t *els, int send_abts)
2040 {
2041 	ocs_t *ocs;
2042 	ocs_xport_t *xport;
2043 	int32_t rc;
2044 	ocs_io_t *abort_io = NULL;
2045 
2046 	ocs_assert(els, NULL);
2047 	ocs_assert(els->node, NULL);
2048 	ocs_assert(els->node->ocs, NULL);
2049 
2050 	ocs = els->node->ocs;
2051 	ocs_assert(ocs->xport, NULL);
2052 	xport = ocs->xport;
2053 
2054 	/* take a reference on IO being aborted */
2055 	if ((ocs_ref_get_unless_zero(&els->ref) == 0)) {
2056 		/* command no longer active */
2057 		ocs_log_debug(ocs, "els no longer active\n");
2058 		return NULL;
2059 	}
2060 
2061 	/* allocate IO structure to send abort */
2062 	abort_io = ocs_io_alloc(ocs);
2063 	if (abort_io == NULL) {
2064 		ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
2065 	} else {
2066 		ocs_assert(abort_io->hio == NULL, NULL);
2067 
2068 		/* set generic fields */
2069 		abort_io->ocs = ocs;
2070 		abort_io->node = els->node;
2071 		abort_io->cmd_ini = TRUE;
2072 
2073 		/* set type and ABORT-specific fields */
2074 		abort_io->io_type = OCS_IO_TYPE_ABORT;
2075 		abort_io->display_name = "abort_els";
2076 		abort_io->io_to_abort = els;
2077 		abort_io->send_abts = send_abts;
2078 
2079 		/* now dispatch IO */
2080 		if ((rc = ocs_scsi_io_dispatch_abort(abort_io, ocs_els_abort_cb))) {
2081 			ocs_log_err(ocs, "ocs_scsi_io_dispatch failed: %d\n", rc);
2082 			ocs_io_free(ocs, abort_io);
2083 			abort_io = NULL;
2084 		}
2085 	}
2086 
2087 	/* if something failed, put reference on ELS to abort */
2088 	if (abort_io == NULL) {
2089 		ocs_ref_put(&els->ref); /* ocs_ref_get(): same function */
2090 	}
2091 	return abort_io;
2092 }
2093 
2094 /*
2095  * ELS IO State Machine
2096  */
2097 
2098 #define std_els_state_decl(...) \
2099 	ocs_io_t *els = NULL; \
2100 	ocs_node_t *node = NULL; \
2101 	ocs_t *ocs = NULL; \
2102 	ocs_assert(ctx != NULL, NULL); \
2103 	els = ctx->app; \
2104 	ocs_assert(els != NULL, NULL); \
2105 	node = els->node; \
2106 	ocs_assert(node != NULL, NULL); \
2107 	ocs = node->ocs; \
2108 	ocs_assert(ocs != NULL, NULL);
2109 
2110 #define els_sm_trace(...) \
2111 	do { \
2112 		if (OCS_LOG_ENABLE_ELS_TRACE(ocs)) \
2113 			ocs_log_info(ocs, "[%s] %-8s %-20s %-20s\n", node->display_name, els->display_name, \
2114 				__func__, ocs_sm_event_name(evt)); \
2115 	} while (0)
2116 
2117 /**
2118  * @brief Cleanup an ELS IO
2119  *
2120  * <h3 class="desc">Description</h3>
2121  * Cleans up an ELS IO by posting the requested event to the owning node object;
2122  * invoking the callback, if one is provided; and then freeing the
2123  * ELS IO object.
2124  *
2125  * @param els Pointer to the ELS IO.
2126  * @param node_evt Node SM event to post.
2127  * @param arg Node SM event argument.
2128  *
2129  * @return None.
2130  */
2131 
2132 void
ocs_els_io_cleanup(ocs_io_t * els,ocs_sm_event_t node_evt,void * arg)2133 ocs_els_io_cleanup(ocs_io_t *els, ocs_sm_event_t node_evt, void *arg)
2134 {
2135 	ocs_assert(els);
2136 
2137 	/* don't want further events that could come; e.g. abort requests
2138 	 * from the node state machine; thus, disable state machine
2139 	 */
2140 	ocs_sm_disable(&els->els_sm);
2141 	ocs_node_post_event(els->node, node_evt, arg);
2142 
2143 	/* If this IO has a callback, invoke it */
2144 	if (els->els_callback) {
2145 		(*els->els_callback)(els->node, arg, els->els_callback_arg);
2146 	}
2147 	els->els_req_free = 1;
2148 }
2149 
2150 /**
2151  * @brief Common event handler for the ELS IO state machine.
2152  *
2153  * <h3 class="desc">Description</h3>
2154  * Provide handler for events for which default actions are desired.
2155  *
2156  * @param funcname Name of the calling function (for logging).
2157  * @param ctx Remote node SM context.
2158  * @param evt Event to process.
2159  * @param arg Per event optional argument.
2160  *
2161  * @return Returns NULL.
2162  */
2163 
2164 void *
__ocs_els_common(const char * funcname,ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2165 __ocs_els_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2166 {
2167 	std_els_state_decl();
2168 
2169 	switch(evt) {
2170 	case OCS_EVT_ENTER:
2171 	case OCS_EVT_REENTER:
2172 	case OCS_EVT_EXIT:
2173 		break;
2174 
2175 	/* If ELS_REQ_FAIL is not handled in state, then we'll terminate this ELS and
2176 	 * pass the event to the node
2177 	 */
2178 	case OCS_EVT_SRRS_ELS_REQ_FAIL:
2179 		ocs_log_warn(els->node->ocs, "[%s] %-20s %-20s not handled - terminating ELS\n", node->display_name, funcname,
2180 			ocs_sm_event_name(evt));
2181 		ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, arg);
2182 		break;
2183 	default:
2184 		ocs_log_warn(els->node->ocs, "[%s] %-20s %-20s not handled\n", node->display_name, funcname,
2185 			ocs_sm_event_name(evt));
2186 		break;
2187 	}
2188 	return NULL;
2189 }
2190 
2191 /**
2192  * @brief Initial ELS IO state
2193  *
2194  * <h3 class="desc">Description</h3>
2195  * This is the initial ELS IO state. Upon entry, the requested ELS/CT is submitted to
2196  * the hardware.
2197  *
2198  * @param ctx Remote node SM context.
2199  * @param evt Event to process.
2200  * @param arg Per event optional argument.
2201  *
2202  * @return Returns NULL.
2203  */
2204 
2205 void *
__ocs_els_init(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2206 __ocs_els_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2207 {
2208 	int32_t rc = 0;
2209 	std_els_state_decl();
2210 
2211 	els_sm_trace();
2212 
2213 	switch(evt) {
2214 	case OCS_EVT_ENTER: {
2215 		rc = ocs_els_send(els, els->els_req.size, els->els_timeout_sec, ocs_els_req_cb);
2216 		if (rc) {
2217 			ocs_node_cb_t cbdata;
2218 			cbdata.status = cbdata.ext_status = (~0);
2219 			cbdata.els = els;
2220 			ocs_log_err(ocs, "ocs_els_send failed: %d\n", rc);
2221 			ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &cbdata);
2222 		} else {
2223 			ocs_io_transition(els, __ocs_els_wait_resp, NULL);
2224 		}
2225 		break;
2226 	}
2227 	default:
2228 		__ocs_els_common(__func__, ctx, evt, arg);
2229 		break;
2230 	}
2231 
2232 	return NULL;
2233 }
2234 
2235 /**
2236  * @brief Wait for the ELS request to complete.
2237  *
2238  * <h3 class="desc">Description</h3>
2239  * This is the ELS IO state that waits for the submitted ELS event to complete.
2240  * If an error completion event is received, the requested ELS is aborted.
2241  *
2242  * @param ctx Remote node SM context.
2243  * @param evt Event to process.
2244  * @param arg Per event optional argument.
2245  *
2246  * @return Returns NULL.
2247  */
2248 
2249 void *
__ocs_els_wait_resp(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2250 __ocs_els_wait_resp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2251 {
2252 	ocs_io_t *io;
2253 	std_els_state_decl();
2254 
2255 	els_sm_trace();
2256 
2257 	switch(evt) {
2258 	case OCS_EVT_SRRS_ELS_REQ_OK: {
2259 		ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_OK, arg);
2260 		break;
2261 	}
2262 
2263 	case OCS_EVT_SRRS_ELS_REQ_FAIL: {
2264 		ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, arg);
2265 		break;
2266 	}
2267 
2268 	case OCS_EVT_ELS_REQ_TIMEOUT: {
2269 		els_io_printf(els, "Timed out, retry (%d tries remaining)\n",
2270 				els->els_retries_remaining-1);
2271 		ocs_io_transition(els, __ocs_els_retry, NULL);
2272 		break;
2273 	}
2274 
2275 	case OCS_EVT_SRRS_ELS_REQ_RJT: {
2276 		ocs_node_cb_t *cbdata = arg;
2277 		uint32_t reason_code = (cbdata->ext_status >> 16) & 0xff;
2278 
2279 		/* delay and retry if reason code is Logical Busy */
2280 		switch (reason_code) {
2281 		case FC_REASON_LOGICAL_BUSY:
2282 			els->node->els_req_cnt--;
2283 			els_io_printf(els, "LS_RJT Logical Busy response, delay and retry\n");
2284 			ocs_io_transition(els, __ocs_els_delay_retry, NULL);
2285 			break;
2286 		default:
2287 			ocs_els_io_cleanup(els, evt, arg);
2288 			break;
2289 		}
2290 		break;
2291 	}
2292 
2293 	case OCS_EVT_ABORT_ELS: {
2294 		/* request to abort this ELS without an ABTS */
2295 		els_io_printf(els, "ELS abort requested\n");
2296 		els->els_retries_remaining = 0;		/* Set retries to zero, we are done */
2297 		io = ocs_els_abort_io(els, FALSE);
2298 		if (io == NULL) {
2299 			ocs_log_err(ocs, "ocs_els_send failed\n");
2300 			ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, arg);
2301 		} else {
2302 			ocs_io_transition(els, __ocs_els_aborting, NULL);
2303 		}
2304 		break;
2305 	}
2306 
2307 	default:
2308 		__ocs_els_common(__func__, ctx, evt, arg);
2309 		break;
2310 	}
2311 	return NULL;
2312 }
2313 
2314 /**
2315  * @brief Wait for the ELS IO abort request to complete, and retry the ELS.
2316  *
2317  * <h3 class="desc">Description</h3>
2318  * This state is entered when waiting for an abort of an ELS
2319  * request to complete so the request can be retried.
2320  *
2321  * @param ctx Remote node SM context.
2322  * @param evt Event to process.
2323  * @param arg Per event optional argument.
2324  *
2325  * @return Returns NULL.
2326  */
2327 
2328 void *
__ocs_els_retry(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2329 __ocs_els_retry(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2330 {
2331 	int32_t rc = 0;
2332 	std_els_state_decl();
2333 
2334 	els_sm_trace();
2335 
2336 	switch(evt) {
2337 	case OCS_EVT_ENTER: {
2338 		/* handle event for ABORT_XRI WQE
2339 		 * once abort is complete, retry if retries left;
2340 		 * don't need to wait for OCS_EVT_SRRS_ELS_REQ_* event because we got
2341 		 * by receiving OCS_EVT_ELS_REQ_TIMEOUT
2342 		 */
2343 		ocs_node_cb_t node_cbdata;
2344 		node_cbdata.status = node_cbdata.ext_status = (~0);
2345 		node_cbdata.els = els;
2346 		if (els->els_retries_remaining && --els->els_retries_remaining) {
2347 			/* Use a different XRI for the retry (would like a new oxid),
2348 			 * so free the HW IO (dispatch will allocate a new one). It's an
2349 			 * optimization to only free the HW IO here and not the ocs_io_t;
2350 			 * Freeing the ocs_io_t object would require copying all the necessary
2351 			 * info from the old ocs_io_t object to the * new one; and allocating
2352 			 * a new ocs_io_t could fail.
2353 			 */
2354 			ocs_assert(els->hio, NULL);
2355 			ocs_hw_io_free(&ocs->hw, els->hio);
2356 			els->hio = NULL;
2357 
2358 			/* result isn't propagated up to node sm, need to decrement req cnt */
2359 			ocs_assert(els->node->els_req_cnt, NULL);
2360 			els->node->els_req_cnt--;
2361 			rc = ocs_els_send(els, els->els_req.size, els->els_timeout_sec, ocs_els_req_cb);
2362 			if (rc) {
2363 				ocs_log_err(ocs, "ocs_els_send failed: %d\n", rc);
2364 				ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &node_cbdata);
2365 			}
2366 			ocs_io_transition(els, __ocs_els_wait_resp, NULL);
2367 		} else {
2368 			els_io_printf(els, "Retries exhausted\n");
2369 			ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &node_cbdata);
2370 		}
2371 		break;
2372 	}
2373 
2374 	default:
2375 		__ocs_els_common(__func__, ctx, evt, arg);
2376 		break;
2377 	}
2378 	return NULL;
2379 }
2380 
2381 /**
2382  * @brief Wait for a retry timer to expire having received an abort request
2383  *
2384  * <h3 class="desc">Description</h3>
2385  * This state is entered when waiting for a timer event, after having received
2386  * an abort request, to avoid a race condition with the timer handler
2387  *
2388  * @param ctx Remote node SM context.
2389  * @param evt Event to process.
2390  * @param arg Per event optional argument.
2391  *
2392  * @return Returns NULL.
2393  */
2394 void *
__ocs_els_aborted_delay_retry(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2395 __ocs_els_aborted_delay_retry(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2396 {
2397 	std_els_state_decl();
2398 
2399 	els_sm_trace();
2400 
2401 	switch(evt) {
2402 	case OCS_EVT_ENTER:
2403 		/* mod/resched the timer for a short duration */
2404 		ocs_mod_timer(&els->delay_timer, 1);
2405 		break;
2406 	case OCS_EVT_TIMER_EXPIRED:
2407 		/* Cancel the timer, skip post node event, and free the io */
2408 		node->els_req_cnt++;
2409 		ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, arg);
2410 		break;
2411 	default:
2412 		__ocs_els_common(__func__, ctx, evt, arg);
2413 		break;
2414 	}
2415 	return NULL;
2416 }
2417 
2418 /**
2419  * @brief Wait for a retry timer to expire
2420  *
2421  * <h3 class="desc">Description</h3>
2422  * This state is entered when waiting for a timer event, so that
2423  * the ELS request can be retried.
2424  *
2425  * @param ctx Remote node SM context.
2426  * @param evt Event to process.
2427  * @param arg Per event optional argument.
2428  *
2429  * @return Returns NULL.
2430  */
2431 void *
__ocs_els_delay_retry(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2432 __ocs_els_delay_retry(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2433 {
2434 	std_els_state_decl();
2435 
2436 	els_sm_trace();
2437 
2438 	switch(evt) {
2439 	case OCS_EVT_ENTER:
2440 		ocs_setup_timer(ocs, &els->delay_timer, ocs_els_delay_timer_cb, els, 5000);
2441 		break;
2442 	case OCS_EVT_TIMER_EXPIRED:
2443 		/* Retry delay timer expired, retry the ELS request, Free the HW IO so
2444 		 * that a new oxid is used.
2445 		 */
2446 		if (els->hio != NULL) {
2447 			ocs_hw_io_free(&ocs->hw, els->hio);
2448 			els->hio = NULL;
2449 		}
2450 		ocs_io_transition(els, __ocs_els_init, NULL);
2451 		break;
2452 	case OCS_EVT_ABORT_ELS:
2453 		ocs_io_transition(els, __ocs_els_aborted_delay_retry, NULL);
2454 		break;
2455 	default:
2456 		__ocs_els_common(__func__, ctx, evt, arg);
2457 		break;
2458 	}
2459 	return NULL;
2460 }
2461 
2462 /**
2463  * @brief Wait for the ELS IO abort request to complete.
2464  *
2465  * <h3 class="desc">Description</h3>
2466  * This state is entered after we abort an ELS WQE and are
2467  * waiting for either the original ELS WQE request or the abort
2468  * to complete.
2469  *
2470  * @param ctx Remote node SM context.
2471  * @param evt Event to process.
2472  * @param arg Per event optional argument.
2473  *
2474  * @return Returns NULL.
2475  */
2476 
2477 void *
__ocs_els_aborting(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2478 __ocs_els_aborting(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2479 {
2480 	std_els_state_decl();
2481 
2482 	els_sm_trace();
2483 
2484 	switch(evt) {
2485 	case OCS_EVT_SRRS_ELS_REQ_OK:
2486 	case OCS_EVT_SRRS_ELS_REQ_FAIL:
2487 	case OCS_EVT_SRRS_ELS_REQ_RJT:
2488 	case OCS_EVT_ELS_REQ_TIMEOUT:
2489 	case OCS_EVT_ELS_REQ_ABORTED: {
2490 		/* completion for ELS received first, transition to wait for abort cmpl */
2491 		els_io_printf(els, "request cmpl evt=%s\n", ocs_sm_event_name(evt));
2492 		ocs_io_transition(els, __ocs_els_aborting_wait_abort_cmpl, NULL);
2493 		break;
2494 	}
2495 	case OCS_EVT_ELS_ABORT_CMPL: {
2496 		/* completion for abort was received first, transition to wait for req cmpl */
2497 		els_io_printf(els, "abort cmpl evt=%s\n", ocs_sm_event_name(evt));
2498 		ocs_io_transition(els, __ocs_els_aborting_wait_req_cmpl, NULL);
2499 		break;
2500 	}
2501 	case OCS_EVT_ABORT_ELS:
2502 		/* nothing we can do but wait */
2503 		break;
2504 
2505 	default:
2506 		__ocs_els_common(__func__, ctx, evt, arg);
2507 		break;
2508 	}
2509 	return NULL;
2510 }
2511 
2512 /**
2513  * @brief cleanup ELS after abort
2514  *
2515  * @param els ELS IO to cleanup
2516  *
2517  * @return Returns None.
2518  */
2519 
2520 static void
ocs_els_abort_cleanup(ocs_io_t * els)2521 ocs_els_abort_cleanup(ocs_io_t *els)
2522 {
2523 	/* handle event for ABORT_WQE
2524 	 * whatever state ELS happened to be in, propagate aborted event up
2525 	 * to node state machine in lieu of OCS_EVT_SRRS_ELS_* event
2526 	 */
2527 	ocs_node_cb_t cbdata;
2528 	cbdata.status = cbdata.ext_status = 0;
2529 	cbdata.els = els;
2530 	els_io_printf(els, "Request aborted\n");
2531 	ocs_els_io_cleanup(els, OCS_EVT_ELS_REQ_ABORTED, &cbdata);
2532 }
2533 
2534 /**
2535  * @brief Wait for the ELS IO abort request to complete.
2536  *
2537  * <h3 class="desc">Description</h3>
2538  * This state is entered after we abort an ELS WQE, we received
2539  * the abort completion first and are waiting for the original
2540  * ELS WQE request to complete.
2541  *
2542  * @param ctx Remote node SM context.
2543  * @param evt Event to process.
2544  * @param arg Per event optional argument.
2545  *
2546  * @return Returns NULL.
2547  */
2548 
2549 void *
__ocs_els_aborting_wait_req_cmpl(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2550 __ocs_els_aborting_wait_req_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2551 {
2552 	std_els_state_decl();
2553 
2554 	els_sm_trace();
2555 
2556 	switch(evt) {
2557 	case OCS_EVT_SRRS_ELS_REQ_OK:
2558 	case OCS_EVT_SRRS_ELS_REQ_FAIL:
2559 	case OCS_EVT_SRRS_ELS_REQ_RJT:
2560 	case OCS_EVT_ELS_REQ_TIMEOUT:
2561 	case OCS_EVT_ELS_REQ_ABORTED: {
2562 		/* completion for ELS that was aborted */
2563 		ocs_els_abort_cleanup(els);
2564 		break;
2565 	}
2566 	case OCS_EVT_ABORT_ELS:
2567 		/* nothing we can do but wait */
2568 		break;
2569 
2570 	default:
2571 		__ocs_els_common(__func__, ctx, evt, arg);
2572 		break;
2573 	}
2574 	return NULL;
2575 }
2576 
2577 /**
2578  * @brief Wait for the ELS IO abort request to complete.
2579  *
2580  * <h3 class="desc">Description</h3>
2581  * This state is entered after we abort an ELS WQE, we received
2582  * the original ELS WQE request completion first and are waiting
2583  * for the abort to complete.
2584  *
2585  * @param ctx Remote node SM context.
2586  * @param evt Event to process.
2587  * @param arg Per event optional argument.
2588  *
2589  * @return Returns NULL.
2590  */
2591 
2592 void *
__ocs_els_aborting_wait_abort_cmpl(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2593 __ocs_els_aborting_wait_abort_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2594 {
2595 	std_els_state_decl();
2596 
2597 	els_sm_trace();
2598 
2599 	switch(evt) {
2600 	case OCS_EVT_ELS_ABORT_CMPL: {
2601 		ocs_els_abort_cleanup(els);
2602 		break;
2603 	}
2604 	case OCS_EVT_ABORT_ELS:
2605 		/* nothing we can do but wait */
2606 		break;
2607 
2608 	default:
2609 		__ocs_els_common(__func__, ctx, evt, arg);
2610 		break;
2611 	}
2612 	return NULL;
2613 }
2614 
2615 /**
2616  * @brief Generate ELS context ddump data.
2617  *
2618  * <h3 class="desc">Description</h3>
2619  * Generate the ddump data for an ELS context.
2620  *
2621  * @param textbuf Pointer to the text buffer.
2622  * @param els Pointer to the ELS context.
2623  *
2624  * @return None.
2625  */
2626 
2627 void
ocs_ddump_els(ocs_textbuf_t * textbuf,ocs_io_t * els)2628 ocs_ddump_els(ocs_textbuf_t *textbuf, ocs_io_t *els)
2629 {
2630 	ocs_ddump_section(textbuf, "els", -1);
2631 	ocs_ddump_value(textbuf, "req_free", "%d", els->els_req_free);
2632 	ocs_ddump_value(textbuf, "evtdepth", "%d", els->els_evtdepth);
2633 	ocs_ddump_value(textbuf, "pend", "%d", els->els_pend);
2634 	ocs_ddump_value(textbuf, "active", "%d", els->els_active);
2635 	ocs_ddump_io(textbuf, els);
2636 	ocs_ddump_endsection(textbuf, "els", -1);
2637 }
2638 
2639 /**
2640  * @brief return TRUE if given ELS list is empty (while taking proper locks)
2641  *
2642  * Test if given ELS list is empty while holding the node->active_ios_lock.
2643  *
2644  * @param node pointer to node object
2645  * @param list pointer to list
2646  *
2647  * @return TRUE if els_io_list is empty
2648  */
2649 
2650 int32_t
ocs_els_io_list_empty(ocs_node_t * node,ocs_list_t * list)2651 ocs_els_io_list_empty(ocs_node_t *node, ocs_list_t *list)
2652 {
2653 	int empty;
2654 	ocs_lock(&node->active_ios_lock);
2655 		empty = ocs_list_empty(list);
2656 	ocs_unlock(&node->active_ios_lock);
2657 	return empty;
2658 }
2659 
2660 /**
2661  * @brief Handle CT send response completion
2662  *
2663  * Called when CT response completes, free IO
2664  *
2665  * @param hio Pointer to the HW IO context that completed.
2666  * @param rnode Pointer to the remote node.
2667  * @param length Length of the returned payload data.
2668  * @param status Status of the completion.
2669  * @param ext_status Extended status of the completion.
2670  * @param arg Application-specific argument (generally a pointer to the ELS IO context).
2671  *
2672  * @return returns 0
2673  */
2674 static int32_t
ocs_ct_acc_cb(ocs_hw_io_t * hio,ocs_remote_node_t * rnode,uint32_t length,int32_t status,uint32_t ext_status,void * arg)2675 ocs_ct_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg)
2676 {
2677 	ocs_io_t *io = arg;
2678 
2679 	ocs_els_io_free(io);
2680 
2681 	return 0;
2682 }
2683 
2684 /**
2685  * @brief Send CT response
2686  *
2687  * Sends a CT response frame with payload
2688  *
2689  * @param io Pointer to the IO context.
2690  * @param ox_id Originator exchange ID
2691  * @param ct_hdr Pointer to the CT IU
2692  * @param cmd_rsp_code CT response code
2693  * @param reason_code Reason code
2694  * @param reason_code_explanation Reason code explanation
2695  *
2696  * @return returns 0 for success, a negative error code value for failure.
2697  */
2698 int32_t
ocs_send_ct_rsp(ocs_io_t * io,uint32_t ox_id,fcct_iu_header_t * ct_hdr,uint32_t cmd_rsp_code,uint32_t reason_code,uint32_t reason_code_explanation)2699 ocs_send_ct_rsp(ocs_io_t *io, uint32_t ox_id, fcct_iu_header_t *ct_hdr, uint32_t cmd_rsp_code, uint32_t reason_code, uint32_t reason_code_explanation)
2700 {
2701 	fcct_iu_header_t *rsp = io->els_rsp.virt;
2702 
2703 	io->io_type = OCS_IO_TYPE_CT_RESP;
2704 
2705 	*rsp = *ct_hdr;
2706 
2707 	fcct_build_req_header(rsp, cmd_rsp_code, 0);
2708 	rsp->reason_code = reason_code;
2709 	rsp->reason_code_explanation = reason_code_explanation;
2710 
2711 	io->display_name = "ct response";
2712 	io->init_task_tag = ox_id;
2713 	io->wire_len += sizeof(*rsp);
2714 
2715 	ocs_memset(&io->iparam, 0, sizeof(io->iparam));
2716 
2717 	io->io_type = OCS_IO_TYPE_CT_RESP;
2718 	io->hio_type = OCS_HW_FC_CT_RSP;
2719 	io->iparam.fc_ct_rsp.ox_id = ocs_htobe16(ox_id);
2720 	io->iparam.fc_ct_rsp.r_ctl = 3;
2721 	io->iparam.fc_ct_rsp.type = FC_TYPE_GS;
2722 	io->iparam.fc_ct_rsp.df_ctl = 0;
2723 	io->iparam.fc_ct_rsp.timeout = 5;
2724 
2725 	if (ocs_scsi_io_dispatch(io, ocs_ct_acc_cb) < 0) {
2726 		ocs_els_io_free(io);
2727 		return -1;
2728 	}
2729 	return 0;
2730 }
2731 
2732 /**
2733  * @brief Handle delay retry timeout
2734  *
2735  * Callback is invoked when the delay retry timer expires.
2736  *
2737  * @param arg pointer to the ELS IO object
2738  *
2739  * @return none
2740  */
2741 static void
ocs_els_delay_timer_cb(void * arg)2742 ocs_els_delay_timer_cb(void *arg)
2743 {
2744 	ocs_io_t *els = arg;
2745 	ocs_node_t *node = els->node;
2746 
2747 	/*
2748 	 * There is a potential deadlock here since is Linux executes timers
2749 	 * in a soft IRQ context. The lock may be aready locked by the interrupt
2750 	 * thread. Handle this case by attempting to take the node lock and reset the
2751 	 * timer if we fail to acquire the lock.
2752 	 *
2753 	 * Note: This code relies on the fact that the node lock is recursive.
2754 	 */
2755 	if (ocs_node_lock_try(node)) {
2756 		ocs_els_post_event(els, OCS_EVT_TIMER_EXPIRED, NULL);
2757 		ocs_node_unlock(node);
2758 	} else {
2759 		ocs_setup_timer(els->ocs, &els->delay_timer, ocs_els_delay_timer_cb, els, 1);
2760 	}
2761 }
2762