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