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