xref: /freebsd/sys/dev/ocs_fc/ocs_node.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1 /*-
2  * Copyright (c) 2017 Broadcom. All rights reserved.
3  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions and the following disclaimer in the documentation
13  *    and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /**
33  * @file
34  * OCS driver remote node handler.  This file contains code that is shared
35  * between fabric (ocs_fabric.c) and device (ocs_device.c) nodes.
36  */
37 
38 /*!
39  * @defgroup node_common Node common support
40  * @defgroup node_alloc Node allocation
41  */
42 
43 #include "ocs.h"
44 #include "ocs_els.h"
45 #include "ocs_device.h"
46 
47 #define SCSI_IOFMT "[%04x][i:%0*x t:%0*x h:%04x]"
48 #define SCSI_ITT_SIZE(ocs)	((ocs->ocs_xport == OCS_XPORT_FC) ? 4 : 8)
49 
50 #define SCSI_IOFMT_ARGS(io) io->instance_index, SCSI_ITT_SIZE(io->ocs), io->init_task_tag, SCSI_ITT_SIZE(io->ocs), io->tgt_task_tag, io->hw_tag
51 
52 #define scsi_io_printf(io, fmt, ...) ocs_log_debug(io->ocs, "[%s]" SCSI_IOFMT fmt, \
53 	io->node->display_name, SCSI_IOFMT_ARGS(io), ##__VA_ARGS__)
54 
55 void ocs_mgmt_node_list(ocs_textbuf_t *textbuf, void *node);
56 void ocs_mgmt_node_get_all(ocs_textbuf_t *textbuf, void *node);
57 int ocs_mgmt_node_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *node);
58 int ocs_mgmt_node_set(char *parent, char *name, char *value, void *node);
59 int ocs_mgmt_node_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length,
60 		void *arg_out, uint32_t arg_out_length, void *node);
61 static ocs_mgmt_functions_t node_mgmt_functions = {
62 	.get_list_handler	=	ocs_mgmt_node_list,
63 	.get_handler		=	ocs_mgmt_node_get,
64 	.get_all_handler	=	ocs_mgmt_node_get_all,
65 	.set_handler		=	ocs_mgmt_node_set,
66 	.exec_handler		=	ocs_mgmt_node_exec,
67 };
68 
69 /**
70  * @ingroup node_common
71  * @brief Device node state machine wait for all ELS's to
72  *        complete
73  *
74  * Abort all ELS's for given node.
75  *
76  * @param node node for which ELS's will be aborted
77  */
78 
79 void
ocs_node_abort_all_els(ocs_node_t * node)80 ocs_node_abort_all_els(ocs_node_t *node)
81 {
82 	ocs_io_t *els;
83 	ocs_io_t *els_next;
84 	ocs_node_cb_t cbdata = {0};
85 
86 	ocs_node_hold_frames(node);
87 	ocs_lock(&node->active_ios_lock);
88 		ocs_list_foreach_safe(&node->els_io_active_list, els, els_next) {
89 			ocs_log_debug(node->ocs, "[%s] initiate ELS abort %s\n", node->display_name, els->display_name);
90 			ocs_unlock(&node->active_ios_lock);
91 			cbdata.els = els;
92 			ocs_els_post_event(els, OCS_EVT_ABORT_ELS, &cbdata);
93 			ocs_lock(&node->active_ios_lock);
94 		}
95 	ocs_unlock(&node->active_ios_lock);
96 }
97 
98 /**
99  * @ingroup node_common
100  * @brief Handle remote node events from HW
101  *
102  * Handle remote node events from HW.   Essentially the HW event is translated into
103  * a node state machine event that is posted to the affected node.
104  *
105  * @param arg pointer to ocs
106  * @param event HW event to proceoss
107  * @param data application specific data (pointer to the affected node)
108  *
109  * @return returns 0 for success, a negative error code value for failure.
110  */
111 int32_t
ocs_remote_node_cb(void * arg,ocs_hw_remote_node_event_e event,void * data)112 ocs_remote_node_cb(void *arg, ocs_hw_remote_node_event_e event, void *data)
113 {
114 	ocs_t *ocs = arg;
115 	ocs_sm_event_t	sm_event = OCS_EVT_LAST;
116 	ocs_remote_node_t *rnode = data;
117 	ocs_node_t *node = rnode->node;
118 
119 	switch (event) {
120 	case OCS_HW_NODE_ATTACH_OK:
121 		sm_event = OCS_EVT_NODE_ATTACH_OK;
122 		break;
123 
124 	case OCS_HW_NODE_ATTACH_FAIL:
125 		sm_event = OCS_EVT_NODE_ATTACH_FAIL;
126 		break;
127 
128 	case OCS_HW_NODE_FREE_OK:
129 		sm_event = OCS_EVT_NODE_FREE_OK;
130 		break;
131 
132 	case OCS_HW_NODE_FREE_FAIL:
133 		sm_event = OCS_EVT_NODE_FREE_FAIL;
134 		break;
135 
136 	default:
137 		ocs_log_test(ocs, "unhandled event %#x\n", event);
138 		return -1;
139 	}
140 
141 	/* If we're using HLM, forward the NODE_ATTACH_OK/FAIL event to all nodes in the node group */
142 	if ((node->node_group != NULL) &&
143 			((sm_event == OCS_EVT_NODE_ATTACH_OK) || (sm_event == OCS_EVT_NODE_ATTACH_FAIL))) {
144 		ocs_node_t *n = NULL;
145 		uint8_t		attach_ok = sm_event == OCS_EVT_NODE_ATTACH_OK;
146 
147 		ocs_sport_lock(node->sport);
148 		{
149 			ocs_list_foreach(&node->sport->node_list, n) {
150 				if (node == n) {
151 					continue;
152 				}
153 				ocs_node_lock(n);
154 					if ((!n->rnode.attached) && (node->node_group == n->node_group)) {
155 						n->rnode.attached = attach_ok;
156 						node_printf(n, "rpi[%d] deferred HLM node attach %s posted\n",
157 								n->rnode.index, attach_ok ? "ok" : "fail");
158 						ocs_node_post_event(n, sm_event, NULL);
159 					}
160 				ocs_node_unlock(n);
161 			}
162 		}
163 
164 		ocs_sport_unlock(node->sport);
165 	}
166 
167 	ocs_node_post_event(node, sm_event, NULL);
168 
169 	return 0;
170 }
171 
172 /**
173  * @ingroup node_alloc
174  * @brief Find an FC node structure given the FC port ID
175  *
176  * @param sport the SPORT to search
177  * @param port_id FC port ID
178  *
179  * @return pointer to the object or NULL if not found
180  */
181 ocs_node_t *
ocs_node_find(ocs_sport_t * sport,uint32_t port_id)182 ocs_node_find(ocs_sport_t *sport, uint32_t port_id)
183 {
184 	ocs_node_t *node;
185 
186 	ocs_assert(sport->lookup, NULL);
187 	ocs_sport_lock(sport);
188 		node = spv_get(sport->lookup, port_id);
189 	ocs_sport_unlock(sport);
190 	return node;
191 }
192 
193 /**
194  * @ingroup node_alloc
195  * @brief Find an FC node structure given the WWPN
196  *
197  * @param sport the SPORT to search
198  * @param wwpn the WWPN to search for (host endian)
199  *
200  * @return pointer to the object or NULL if not found
201  */
202 ocs_node_t *
ocs_node_find_wwpn(ocs_sport_t * sport,uint64_t wwpn)203 ocs_node_find_wwpn(ocs_sport_t *sport, uint64_t wwpn)
204 {
205 	ocs_node_t *node = NULL;
206 
207 	ocs_assert(sport, NULL);
208 
209 	ocs_sport_lock(sport);
210 		ocs_list_foreach(&sport->node_list, node) {
211 			if (ocs_node_get_wwpn(node) == wwpn) {
212 				ocs_sport_unlock(sport);
213 				return node;
214 			}
215 		}
216 	ocs_sport_unlock(sport);
217 	return NULL;
218 }
219 
220 /**
221  * @ingroup node_alloc
222  * @brief allocate node object pool
223  *
224  * A pool of ocs_node_t objects is allocated.
225  *
226  * @param ocs pointer to driver instance context
227  * @param node_count count of nodes to allocate
228  *
229  * @return returns 0 for success, a negative error code value for failure.
230  */
231 
232 int32_t
ocs_node_create_pool(ocs_t * ocs,uint32_t node_count)233 ocs_node_create_pool(ocs_t *ocs, uint32_t node_count)
234 {
235 	ocs_xport_t *xport = ocs->xport;
236 	uint32_t i;
237 	ocs_node_t *node;
238 	uint32_t max_sge;
239 	uint32_t num_sgl;
240 	uint64_t max_xfer_size;
241 	int32_t rc;
242 
243 	xport->nodes_count = node_count;
244 
245 	xport->nodes = ocs_malloc(ocs, node_count * sizeof(ocs_node_t *), OCS_M_ZERO | OCS_M_NOWAIT);
246 	if (xport->nodes == NULL) {
247 		ocs_log_err(ocs, "node ptrs allocation failed");
248 		return -1;
249 	}
250 
251 	if (0 == ocs_hw_get(&ocs->hw, OCS_HW_MAX_SGE, &max_sge) &&
252 	    0 == ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &num_sgl)) {
253 		max_xfer_size = (max_sge * (uint64_t)num_sgl);
254 	} else {
255 		max_xfer_size = 65536;
256 	}
257 
258 	if (max_xfer_size > 65536)
259 		max_xfer_size = 65536;
260 
261 	ocs_list_init(&xport->nodes_free_list, ocs_node_t, link);
262 
263 	for (i = 0; i < node_count; i ++) {
264 		node = ocs_malloc(ocs, sizeof(ocs_node_t), OCS_M_ZERO | OCS_M_NOWAIT);
265 		if (node == NULL) {
266 			ocs_log_err(ocs, "node allocation failed");
267 			goto error;
268 		}
269 
270 		/* Assign any persistent field values */
271 		node->instance_index = i;
272 		node->max_wr_xfer_size = max_xfer_size;
273 		node->rnode.indicator = UINT32_MAX;
274 
275 		rc = ocs_dma_alloc(ocs, &node->sparm_dma_buf, 256, 16);
276 		if (rc) {
277 			ocs_free(ocs, node, sizeof(ocs_node_t));
278 			ocs_log_err(ocs, "ocs_dma_alloc failed: %d\n", rc);
279 			goto error;
280 		}
281 
282 		xport->nodes[i] = node;
283 		ocs_list_add_tail(&xport->nodes_free_list, node);
284 	}
285 	return 0;
286 
287 error:
288 	ocs_node_free_pool(ocs);
289 	return -1;
290 }
291 
292 /**
293  * @ingroup node_alloc
294  * @brief free node object pool
295  *
296  * The pool of previously allocated node objects is freed
297  *
298  * @param ocs pointer to driver instance context
299  *
300  * @return none
301  */
302 
303 void
ocs_node_free_pool(ocs_t * ocs)304 ocs_node_free_pool(ocs_t *ocs)
305 {
306 	ocs_xport_t *xport = ocs->xport;
307 	ocs_node_t *node;
308 	uint32_t i;
309 
310 	if (!xport->nodes)
311 		return;
312 
313 	ocs_device_lock(ocs);
314 
315 	for (i = 0; i < xport->nodes_count; i ++) {
316 		node = xport->nodes[i];
317 		if (node) {
318 			/* free sparam_dma_buf */
319 			ocs_dma_free(ocs, &node->sparm_dma_buf);
320 			ocs_free(ocs, node, sizeof(ocs_node_t));
321 		}
322 		xport->nodes[i] = NULL;
323 	}
324 
325 	ocs_free(ocs, xport->nodes, (xport->nodes_count * sizeof(ocs_node_t *)));
326 
327 	ocs_device_unlock(ocs);
328 }
329 
330 /**
331  * @ingroup node_alloc
332  * @brief return pointer to node object given instance index
333  *
334  * A pointer to the node object given by an instance index is returned.
335  *
336  * @param ocs pointer to driver instance context
337  * @param index instance index
338  *
339  * @return returns pointer to node object, or NULL
340  */
341 
342 ocs_node_t *
ocs_node_get_instance(ocs_t * ocs,uint32_t index)343 ocs_node_get_instance(ocs_t *ocs, uint32_t index)
344 {
345 	ocs_xport_t *xport = ocs->xport;
346 	ocs_node_t *node = NULL;
347 
348 	if (index >= (xport->nodes_count)) {
349 		ocs_log_test(ocs, "invalid index: %d\n", index);
350 		return NULL;
351 	}
352 	node = xport->nodes[index];
353 	return node->attached ? node : NULL;
354 }
355 
356 /**
357  * @ingroup node_alloc
358  * @brief Allocate an fc node structure and add to node list
359  *
360  * @param sport pointer to the SPORT from which this node is allocated
361  * @param port_id FC port ID of new node
362  * @param init Port is an inititiator (sent a plogi)
363  * @param targ Port is potentially a target
364  *
365  * @return pointer to the object or NULL if none available
366  */
367 
368 ocs_node_t *
ocs_node_alloc(ocs_sport_t * sport,uint32_t port_id,uint8_t init,uint8_t targ)369 ocs_node_alloc(ocs_sport_t *sport, uint32_t port_id, uint8_t init, uint8_t targ)
370 {
371 	int32_t rc;
372 	ocs_node_t *node = NULL;
373 	uint32_t instance_index;
374 	uint32_t max_wr_xfer_size;
375 	ocs_t *ocs = sport->ocs;
376 	ocs_xport_t *xport = ocs->xport;
377 	ocs_dma_t sparm_dma_buf;
378 
379 	ocs_assert(sport, NULL);
380 
381 	if (sport->shutting_down) {
382 		ocs_log_debug(ocs, "node allocation when shutting down %06x", port_id);
383 		return NULL;
384 	}
385 
386 	ocs_device_lock(ocs);
387 		node = ocs_list_remove_head(&xport->nodes_free_list);
388 	ocs_device_unlock(ocs);
389 	if (node == NULL) {
390 		ocs_log_err(ocs, "node allocation failed %06x", port_id);
391 		return NULL;
392 	}
393 
394 	/* Save persistent values across memset zero */
395 	instance_index = node->instance_index;
396 	max_wr_xfer_size = node->max_wr_xfer_size;
397 	sparm_dma_buf = node->sparm_dma_buf;
398 
399 	ocs_memset(node, 0, sizeof(*node));
400 	node->instance_index = instance_index;
401 	node->max_wr_xfer_size = max_wr_xfer_size;
402 	node->sparm_dma_buf = sparm_dma_buf;
403 	node->rnode.indicator = UINT32_MAX;
404 
405 	node->sport = sport;
406 	ocs_sport_lock(sport);
407 
408 		node->ocs = ocs;
409 		node->init = init;
410 		node->targ = targ;
411 
412 		rc = ocs_hw_node_alloc(&ocs->hw, &node->rnode, port_id, sport);
413 		if (rc) {
414 			ocs_log_err(ocs, "ocs_hw_node_alloc failed: %d\n", rc);
415 			ocs_sport_unlock(sport);
416 
417 			/* Return back to pool. */
418 			ocs_device_lock(ocs);
419 			ocs_list_add_tail(&xport->nodes_free_list, node);
420 			ocs_device_unlock(ocs);
421 
422 			return NULL;
423 		}
424 		ocs_list_add_tail(&sport->node_list, node);
425 
426 		ocs_node_lock_init(node);
427 		ocs_lock_init(ocs, &node->pend_frames_lock, "pend_frames_lock[%d]", node->instance_index);
428 		ocs_list_init(&node->pend_frames, ocs_hw_sequence_t, link);
429 		ocs_lock_init(ocs, &node->active_ios_lock, "active_ios[%d]", node->instance_index);
430 		ocs_list_init(&node->active_ios, ocs_io_t, link);
431 		ocs_list_init(&node->els_io_pend_list, ocs_io_t, link);
432 		ocs_list_init(&node->els_io_active_list, ocs_io_t, link);
433 		ocs_scsi_io_alloc_enable(node);
434 
435 		/* zero the service parameters */
436 		ocs_memset(node->sparm_dma_buf.virt, 0, node->sparm_dma_buf.size);
437 
438 		node->rnode.node = node;
439 		node->sm.app = node;
440 		node->evtdepth = 0;
441 
442 		ocs_node_update_display_name(node);
443 
444 		spv_set(sport->lookup, port_id, node);
445 	ocs_sport_unlock(sport);
446 	node->mgmt_functions = &node_mgmt_functions;
447 
448 	return node;
449 }
450 
451 /**
452  * @ingroup node_alloc
453  * @brief free a node structure
454  *
455  * The node structure given by 'node' is free'd
456  *
457  * @param node the node to free
458  *
459  * @return returns 0 for success, a negative error code value for failure.
460  */
461 
462 int32_t
ocs_node_free(ocs_node_t * node)463 ocs_node_free(ocs_node_t *node)
464 {
465 	ocs_sport_t *sport;
466 	ocs_t *ocs;
467 	ocs_xport_t *xport;
468 	ocs_hw_rtn_e rc = 0;
469 	ocs_node_t *ns = NULL;
470 	int post_all_free = FALSE;
471 
472 	ocs_assert(node, -1);
473 	ocs_assert(node->sport, -1);
474 	ocs_assert(node->ocs, -1);
475 	sport = node->sport;
476 	ocs_assert(sport, -1);
477 	ocs = node->ocs;
478 	ocs_assert(ocs->xport, -1);
479 	xport = ocs->xport;
480 
481 	node_printf(node, "Free'd\n");
482 
483 	if(node->refound) {
484 		/*
485 		 * Save the name server node. We will send fake RSCN event at
486 		 * the end to handle ignored RSCN event during node deletion
487 		 */
488 		ns = ocs_node_find(node->sport, FC_ADDR_NAMESERVER);
489 	}
490 
491 	/* Remove from node list */
492 	ocs_sport_lock(sport);
493 		ocs_list_remove(&sport->node_list, node);
494 
495 		/* Free HW resources */
496 		if (OCS_HW_RTN_IS_ERROR((rc = ocs_hw_node_free_resources(&ocs->hw, &node->rnode)))) {
497 			ocs_log_test(ocs, "ocs_hw_node_free failed: %d\n", rc);
498 			rc = -1;
499 		}
500 
501 		/* if the gidpt_delay_timer is still running, then delete it */
502 		if (ocs_timer_pending(&node->gidpt_delay_timer)) {
503 			ocs_del_timer(&node->gidpt_delay_timer);
504 		}
505 
506 		if (node->fcp2device) {
507 			ocs_del_crn(node);
508 		}
509 
510 		/* remove entry from sparse vector list */
511 		if (sport->lookup == NULL) {
512 			ocs_log_test(node->ocs, "assertion failed: sport lookup is NULL\n");
513 			ocs_sport_unlock(sport);
514 			return -1;
515 		}
516 
517 		spv_set(sport->lookup, node->rnode.fc_id, NULL);
518 
519 		/*
520 		 * If the node_list is empty, then post a ALL_CHILD_NODES_FREE event to the sport,
521 		 * after the lock is released.  The sport may be free'd as a result of the event.
522 		 */
523 		if (ocs_list_empty(&sport->node_list)) {
524 			post_all_free = TRUE;
525 		}
526 
527 	ocs_sport_unlock(sport);
528 
529 	if (post_all_free) {
530 		ocs_sm_post_event(&sport->sm, OCS_EVT_ALL_CHILD_NODES_FREE, NULL);
531 	}
532 
533 	node->sport = NULL;
534 	node->sm.current_state = NULL;
535 
536 	ocs_node_lock_free(node);
537 	ocs_lock_free(&node->pend_frames_lock);
538 	ocs_lock_free(&node->active_ios_lock);
539 
540 	/* return to free list */
541 	ocs_device_lock(ocs);
542 		ocs_list_add_tail(&xport->nodes_free_list, node);
543 	ocs_device_unlock(ocs);
544 
545 	if(ns != NULL) {
546 		/* sending fake RSCN event to name server node */
547 		ocs_node_post_event(ns, OCS_EVT_RSCN_RCVD, NULL);
548 	}
549 
550 	return rc;
551 }
552 
553 /**
554  * @brief free memory resources of a node object
555  *
556  * The node object's child objects are freed after which the
557  * node object is freed.
558  *
559  * @param node pointer to a node object
560  *
561  * @return none
562  */
563 
564 void
ocs_node_force_free(ocs_node_t * node)565 ocs_node_force_free(ocs_node_t *node)
566 {
567 	ocs_io_t *io;
568 	ocs_io_t *next;
569 	ocs_io_t *els;
570 	ocs_io_t *els_next;
571 
572 	/* shutdown sm processing */
573 	ocs_sm_disable(&node->sm);
574 	ocs_strncpy(node->prev_state_name, node->current_state_name, sizeof(node->prev_state_name));
575 	ocs_strncpy(node->current_state_name, "disabled", sizeof(node->current_state_name));
576 
577 	/* Let the backend cleanup if needed */
578 	ocs_scsi_notify_node_force_free(node);
579 
580 	ocs_lock(&node->active_ios_lock);
581 		ocs_list_foreach_safe(&node->active_ios, io, next) {
582 			ocs_list_remove(&io->node->active_ios, io);
583 			ocs_io_free(node->ocs, io);
584 		}
585 	ocs_unlock(&node->active_ios_lock);
586 
587 	/* free all pending ELS IOs */
588 	ocs_lock(&node->active_ios_lock);
589 		ocs_list_foreach_safe(&node->els_io_pend_list, els, els_next) {
590 			/* can't call ocs_els_io_free() because lock is held; cleanup manually */
591 			ocs_list_remove(&node->els_io_pend_list, els);
592 
593 			ocs_io_free(node->ocs, els);
594 		}
595 	ocs_unlock(&node->active_ios_lock);
596 
597 	/* free all active ELS IOs */
598 	ocs_lock(&node->active_ios_lock);
599 		ocs_list_foreach_safe(&node->els_io_active_list, els, els_next) {
600 			/* can't call ocs_els_io_free() because lock is held; cleanup manually */
601 			ocs_list_remove(&node->els_io_active_list, els);
602 
603 			ocs_io_free(node->ocs, els);
604 		}
605 	ocs_unlock(&node->active_ios_lock);
606 
607 	/* manually purge pending frames (if any) */
608 	ocs_node_purge_pending(node);
609 
610 	ocs_node_free(node);
611 }
612 
613 /**
614  * @ingroup node_common
615  * @brief Perform HW call to attach a remote node
616  *
617  * @param node pointer to node object
618  *
619  * @return 0 on success, non-zero otherwise
620  */
621 int32_t
ocs_node_attach(ocs_node_t * node)622 ocs_node_attach(ocs_node_t *node)
623 {
624 	int32_t rc = 0;
625 	ocs_sport_t *sport = node->sport;
626 	ocs_domain_t *domain = sport->domain;
627 	ocs_t *ocs = node->ocs;
628 
629 	if (!domain->attached) {
630 		ocs_log_test(ocs, "Warning: ocs_node_attach with unattached domain\n");
631 		return -1;
632 	}
633 	/* Update node->wwpn/wwnn */
634 
635 	ocs_node_build_eui_name(node->wwpn, sizeof(node->wwpn), ocs_node_get_wwpn(node));
636 	ocs_node_build_eui_name(node->wwnn, sizeof(node->wwnn), ocs_node_get_wwnn(node));
637 
638 	if (ocs->enable_hlm) {
639 		ocs_node_group_init(node);
640 	}
641 
642 	ocs_dma_copy_in(&node->sparm_dma_buf, node->service_params+4, sizeof(node->service_params)-4);
643 
644 	/* take lock to protect node->rnode.attached */
645 	ocs_node_lock(node);
646 		rc = ocs_hw_node_attach(&ocs->hw, &node->rnode, &node->sparm_dma_buf);
647 		if (OCS_HW_RTN_IS_ERROR(rc)) {
648 			ocs_log_test(ocs, "ocs_hw_node_attach failed: %d\n", rc);
649 		}
650 	ocs_node_unlock(node);
651 
652 	return rc;
653 }
654 
655 /**
656  * @ingroup node_common
657  * @brief Generate text for a node's fc_id
658  *
659  * The text for a nodes fc_id is generated, either as a well known name, or a 6 digit
660  * hex value.
661  *
662  * @param fc_id fc_id
663  * @param buffer text buffer
664  * @param buffer_length text buffer length in bytes
665  *
666  * @return none
667  */
668 
669 void
ocs_node_fcid_display(uint32_t fc_id,char * buffer,uint32_t buffer_length)670 ocs_node_fcid_display(uint32_t fc_id, char *buffer, uint32_t buffer_length)
671 {
672 	switch (fc_id) {
673 	case FC_ADDR_FABRIC:
674 		ocs_snprintf(buffer, buffer_length, "fabric");
675 		break;
676 	case FC_ADDR_CONTROLLER:
677 		ocs_snprintf(buffer, buffer_length, "fabctl");
678 		break;
679 	case FC_ADDR_NAMESERVER:
680 		ocs_snprintf(buffer, buffer_length, "nserve");
681 		break;
682 	default:
683 		if (FC_ADDR_IS_DOMAIN_CTRL(fc_id)) {
684 			ocs_snprintf(buffer, buffer_length, "dctl%02x",
685 				FC_ADDR_GET_DOMAIN_CTRL(fc_id));
686 		} else {
687 			ocs_snprintf(buffer, buffer_length, "%06x", fc_id);
688 		}
689 		break;
690 	}
691 
692 }
693 
694 /**
695  * @brief update the node's display name
696  *
697  * The node's display name is updated, sometimes needed because the sport part
698  * is updated after the node is allocated.
699  *
700  * @param node pointer to the node object
701  *
702  * @return none
703  */
704 
705 void
ocs_node_update_display_name(ocs_node_t * node)706 ocs_node_update_display_name(ocs_node_t *node)
707 {
708 	uint32_t port_id = node->rnode.fc_id;
709 	ocs_sport_t *sport = node->sport;
710 	char portid_display[16];
711 
712 	ocs_assert(sport);
713 
714 	ocs_node_fcid_display(port_id, portid_display, sizeof(portid_display));
715 
716 	ocs_snprintf(node->display_name, sizeof(node->display_name), "%s.%s", sport->display_name, portid_display);
717 }
718 
719 /**
720  * @brief cleans up an XRI for the pending link services accept by aborting the
721  *         XRI if required.
722  *
723  * <h3 class="desc">Description</h3>
724  * This function is called when the LS accept is not sent.
725  *
726  * @param node Node for which should be cleaned up
727  */
728 
729 void
ocs_node_send_ls_io_cleanup(ocs_node_t * node)730 ocs_node_send_ls_io_cleanup(ocs_node_t *node)
731 {
732 	ocs_t *ocs = node->ocs;
733 
734 	if (node->send_ls_acc != OCS_NODE_SEND_LS_ACC_NONE) {
735 		ocs_assert(node->ls_acc_io);
736 		ocs_log_debug(ocs, "[%s] cleaning up LS_ACC oxid=0x%x\n",
737 			node->display_name, node->ls_acc_oxid);
738 
739 		node->ls_acc_io->hio = NULL;
740 		ocs_els_io_free(node->ls_acc_io);
741 		node->send_ls_acc = OCS_NODE_SEND_LS_ACC_NONE;
742 		node->ls_acc_io = NULL;
743 	}
744 }
745 
746 /**
747  * @ingroup node_common
748  * @brief state: shutdown a node
749  *
750  * A node is shutdown,
751  *
752  * @param ctx remote node sm context
753  * @param evt event to process
754  * @param arg per event optional argument
755  *
756  * @return returns NULL
757  *
758  * @note
759  */
760 
761 void *
__ocs_node_shutdown(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)762 __ocs_node_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
763 {
764 	int32_t rc;
765 	std_node_state_decl();
766 
767 	node_sm_trace();
768 
769 	switch(evt) {
770 	case OCS_EVT_ENTER: {
771 		ocs_node_hold_frames(node);
772 		ocs_assert(ocs_node_active_ios_empty(node), NULL);
773 		ocs_assert(ocs_els_io_list_empty(node, &node->els_io_active_list), NULL);
774 
775 		/* by default, we will be freeing node after we unwind */
776 		node->req_free = 1;
777 
778 		switch (node->shutdown_reason) {
779 		case OCS_NODE_SHUTDOWN_IMPLICIT_LOGO:
780 			/* sm: if shutdown reason is implicit logout / ocs_node_attach
781 			 * Node shutdown b/c of PLOGI received when node already
782 			 * logged in. We have PLOGI service parameters, so submit
783 			 * node attach; we won't be freeing this node
784 			 */
785 
786 			/* currently, only case for implicit logo is PLOGI recvd. Thus,
787 			 * node's ELS IO pending list won't be empty (PLOGI will be on it)
788 			 */
789 			ocs_assert(node->send_ls_acc == OCS_NODE_SEND_LS_ACC_PLOGI, NULL);
790 			node_printf(node, "Shutdown reason: implicit logout, re-authenticate\n");
791 
792 			ocs_scsi_io_alloc_enable(node);
793 
794 			/* Re-attach node with the same HW node resources */
795 			node->req_free = 0;
796 			rc = ocs_node_attach(node);
797 			ocs_node_transition(node, __ocs_d_wait_node_attach, NULL);
798 			if (rc == OCS_HW_RTN_SUCCESS_SYNC) {
799 				ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL);
800 			}
801 			break;
802 		case OCS_NODE_SHUTDOWN_EXPLICIT_LOGO: {
803 			int8_t pend_frames_empty;
804 
805 			/* cleanup any pending LS_ACC ELSs */
806 			ocs_node_send_ls_io_cleanup(node);
807 			ocs_assert(ocs_els_io_list_empty(node, &node->els_io_pend_list), NULL);
808 
809 			ocs_lock(&node->pend_frames_lock);
810 				pend_frames_empty = ocs_list_empty(&node->pend_frames);
811 			ocs_unlock(&node->pend_frames_lock);
812 
813 			/* there are two scenarios where we want to keep this node alive:
814 			 * 1. there are pending frames that need to be processed or
815 			 * 2. we're an initiator and the remote node is a target and we
816 			 *    need to re-authenticate
817 			 */
818 			node_printf(node, "Shutdown: explicit logo pend=%d sport.ini=%d node.tgt=%d\n",
819 				    !pend_frames_empty, node->sport->enable_ini, node->targ);
820 
821 			if((!pend_frames_empty) || (node->sport->enable_ini && node->targ)) {
822 				uint8_t send_plogi = FALSE;
823 				if (node->sport->enable_ini && node->targ) {
824 					/* we're an initiator and node shutting down is a target; we'll
825 					 * need to re-authenticate in initial state
826 					 */
827 					send_plogi = TRUE;
828 				}
829 
830 				/* transition to __ocs_d_init (will retain HW node resources) */
831 				ocs_scsi_io_alloc_enable(node);
832 				node->req_free = 0;
833 
834 				/* either pending frames exist, or we're re-authenticating with PLOGI
835 				 * (or both); in either case, return to initial state
836 				 */
837 				ocs_node_init_device(node, send_plogi);
838 			}
839 			/* else: let node shutdown occur */
840 			break;
841 		}
842 		case OCS_NODE_SHUTDOWN_DEFAULT:
843 		default:
844 			/* shutdown due to link down, node going away (xport event) or
845 			 * sport shutdown, purge pending and proceed to cleanup node
846 			 */
847 
848 			/* cleanup any pending LS_ACC ELSs */
849 			ocs_node_send_ls_io_cleanup(node);
850 			ocs_assert(ocs_els_io_list_empty(node, &node->els_io_pend_list), NULL);
851 
852 			node_printf(node, "Shutdown reason: default, purge pending\n");
853 			ocs_node_purge_pending(node);
854 			break;
855 		}
856 
857 		break;
858 	}
859 	case OCS_EVT_EXIT:
860 		ocs_node_accept_frames(node);
861 		break;
862 
863 	default:
864 		__ocs_node_common(__func__, ctx, evt, arg);
865 		return NULL;
866 	}
867 
868 	return NULL;
869 }
870 
871 /**
872  * @ingroup common_node
873  * @brief Checks to see if ELS's have been quiesced
874  *
875  * Check if ELS's have been quiesced. If so, transition to the
876  * next state in the shutdown process.
877  *
878  * @param node Node for which ELS's are checked
879  *
880  * @return Returns 1 if ELS's have been quiesced, 0 otherwise.
881  */
882 static int
ocs_node_check_els_quiesced(ocs_node_t * node)883 ocs_node_check_els_quiesced(ocs_node_t *node)
884 {
885 	ocs_assert(node, -1);
886 
887 	/* check to see if ELS requests, completions are quiesced */
888 	if ((node->els_req_cnt == 0) && (node->els_cmpl_cnt == 0) &&
889 	    ocs_els_io_list_empty(node, &node->els_io_active_list)) {
890 		if (!node->attached) {
891 			/* hw node detach already completed, proceed */
892 			node_printf(node, "HW node not attached\n");
893 			ocs_node_transition(node, __ocs_node_wait_ios_shutdown, NULL);
894 		} else {
895 			/* hw node detach hasn't completed, transition and wait */
896 			node_printf(node, "HW node still attached\n");
897 			ocs_node_transition(node, __ocs_node_wait_node_free, NULL);
898 		}
899 		return 1;
900 	}
901 	return 0;
902 }
903 
904 /**
905  * @ingroup common_node
906  * @brief Initiate node IO cleanup.
907  *
908  * Note: this function must be called with a non-attached node
909  * or a node for which the node detach (ocs_hw_node_detach())
910  * has already been initiated.
911  *
912  * @param node Node for which shutdown is initiated
913  *
914  * @return Returns None.
915  */
916 
917 void
ocs_node_initiate_cleanup(ocs_node_t * node)918 ocs_node_initiate_cleanup(ocs_node_t *node)
919 {
920 	ocs_io_t *els;
921 	ocs_io_t *els_next;
922 	ocs_t *ocs;
923 	ocs_assert(node);
924 	ocs = node->ocs;
925 
926 	/* first cleanup ELS's that are pending (not yet active) */
927 	ocs_lock(&node->active_ios_lock);
928 		ocs_list_foreach_safe(&node->els_io_pend_list, els, els_next) {
929 			/* skip the ELS IO for which a response will be sent after shutdown */
930 			if ((node->send_ls_acc != OCS_NODE_SEND_LS_ACC_NONE) &&
931 			    (els == node->ls_acc_io)) {
932 				continue;
933 			}
934 			/* can't call ocs_els_io_free() because lock is held; cleanup manually */
935                         node_printf(node, "Freeing pending els %s\n", els->display_name);
936 			ocs_list_remove(&node->els_io_pend_list, els);
937 
938 			ocs_io_free(node->ocs, els);
939 		}
940 	ocs_unlock(&node->active_ios_lock);
941 
942 	if (node->ls_acc_io && node->ls_acc_io->hio != NULL) {
943 		/*
944 		 * if there's an IO that will result in an LS_ACC after
945 		 * shutdown and its HW IO is non-NULL, it better be an
946 		 * implicit logout in vanilla sequence coalescing. In this
947 		 * case, force the LS_ACC to go out on another XRI (hio)
948 		 * since the previous will have been aborted by the UNREG_RPI
949 		 */
950 		ocs_assert(node->shutdown_reason == OCS_NODE_SHUTDOWN_IMPLICIT_LOGO);
951 		ocs_assert(node->send_ls_acc == OCS_NODE_SEND_LS_ACC_PLOGI);
952 		node_printf(node, "invalidating ls_acc_io due to implicit logo\n");
953 
954 		/* No need to abort because the unreg_rpi takes care of it, just free */
955 		ocs_hw_io_free(&ocs->hw, node->ls_acc_io->hio);
956 
957 		/* NULL out hio to force the LS_ACC to grab a new XRI */
958 		node->ls_acc_io->hio = NULL;
959 	}
960 
961 	/*
962 	 * if ELS's have already been quiesced, will move to next state
963 	 * if ELS's have not been quiesced, abort them
964 	 */
965 	if (ocs_node_check_els_quiesced(node) == 0) {
966 		/*
967 		 * Abort all ELS's since ELS's won't be aborted by HW
968 		 * node free.
969 		 */
970 		ocs_node_abort_all_els(node);
971 		ocs_node_transition(node, __ocs_node_wait_els_shutdown, NULL);
972 	}
973 }
974 
975 /**
976  * @ingroup node_common
977  * @brief Node state machine: Wait for all ELSs to complete.
978  *
979  * <h3 class="desc">Description</h3>
980  * State waits for all ELSs to complete after aborting all
981  * outstanding .
982  *
983  * @param ctx Remote node state machine context.
984  * @param evt Event to process.
985  * @param arg Per event optional argument.
986  *
987  * @return Returns NULL.
988  */
989 
990 void *
__ocs_node_wait_els_shutdown(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)991 __ocs_node_wait_els_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
992 {
993 	uint8_t check_quiesce = FALSE;
994 	std_node_state_decl();
995 
996 	node_sm_trace();
997 
998 	switch(evt) {
999 	case OCS_EVT_ENTER: {
1000 		ocs_node_hold_frames(node);
1001 		if (ocs_els_io_list_empty(node, &node->els_io_active_list)) {
1002 			node_printf(node, "All ELS IOs complete\n");
1003 			check_quiesce = TRUE;
1004 		}
1005 		break;
1006 	}
1007 	case OCS_EVT_EXIT:
1008 		ocs_node_accept_frames(node);
1009 		break;
1010 
1011 	case OCS_EVT_SRRS_ELS_REQ_OK:
1012 	case OCS_EVT_SRRS_ELS_REQ_FAIL:
1013 	case OCS_EVT_SRRS_ELS_REQ_RJT:
1014 	case OCS_EVT_ELS_REQ_ABORTED:
1015 		ocs_assert(node->els_req_cnt, NULL);
1016 		node->els_req_cnt--;
1017 		check_quiesce = TRUE;
1018 		break;
1019 
1020 	case OCS_EVT_SRRS_ELS_CMPL_OK:
1021 	case OCS_EVT_SRRS_ELS_CMPL_FAIL:
1022 		ocs_assert(node->els_cmpl_cnt, NULL);
1023 		node->els_cmpl_cnt--;
1024 		check_quiesce = TRUE;
1025 		break;
1026 
1027 	case OCS_EVT_ALL_CHILD_NODES_FREE:
1028 		/* all ELS IO's complete */
1029 		node_printf(node, "All ELS IOs complete\n");
1030 		ocs_assert(ocs_els_io_list_empty(node, &node->els_io_active_list), NULL);
1031 		check_quiesce = TRUE;
1032 		break;
1033 
1034 	case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
1035 		break;
1036 
1037 	case OCS_EVT_DOMAIN_ATTACH_OK:
1038 		/* don't care about domain_attach_ok */
1039 		break;
1040 
1041 	/* ignore shutdown events as we're already in shutdown path */
1042 	case OCS_EVT_SHUTDOWN:
1043 		/* have default shutdown event take precedence */
1044 		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1045 		/* fall through */
1046 	case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
1047 	case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
1048 		node_printf(node, "%s received\n", ocs_sm_event_name(evt));
1049 		break;
1050 
1051 	default:
1052 		__ocs_node_common(__func__, ctx, evt, arg);
1053 		return NULL;
1054 	}
1055 
1056 	if (check_quiesce) {
1057 		ocs_node_check_els_quiesced(node);
1058 	}
1059 	return NULL;
1060 }
1061 
1062 /**
1063  * @ingroup node_command
1064  * @brief Node state machine: Wait for a HW node free event to
1065  * complete.
1066  *
1067  * <h3 class="desc">Description</h3>
1068  * State waits for the node free event to be received from the HW.
1069  *
1070  * @param ctx Remote node state machine context.
1071  * @param evt Event to process.
1072  * @param arg Per event optional argument.
1073  *
1074  * @return Returns NULL.
1075  */
1076 
1077 void *
__ocs_node_wait_node_free(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)1078 __ocs_node_wait_node_free(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1079 {
1080 	std_node_state_decl();
1081 
1082 	node_sm_trace();
1083 
1084 	switch(evt) {
1085 	case OCS_EVT_ENTER:
1086 		ocs_node_hold_frames(node);
1087 		break;
1088 
1089 	case OCS_EVT_EXIT:
1090 		ocs_node_accept_frames(node);
1091 		break;
1092 
1093 	case OCS_EVT_NODE_FREE_OK:
1094 		/* node is officially no longer attached */
1095 		node->attached = FALSE;
1096 		ocs_node_transition(node, __ocs_node_wait_ios_shutdown, NULL);
1097 		break;
1098 
1099 	case OCS_EVT_ALL_CHILD_NODES_FREE:
1100 	case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
1101 		/* As IOs and ELS IO's complete we expect to get these events */
1102 		break;
1103 
1104 	case OCS_EVT_DOMAIN_ATTACH_OK:
1105 		/* don't care about domain_attach_ok */
1106 		break;
1107 
1108 	/* ignore shutdown events as we're already in shutdown path */
1109 	case OCS_EVT_SHUTDOWN:
1110 		/* have default shutdown event take precedence */
1111 		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1112 		/* Fall through */
1113 	case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
1114 	case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
1115 		node_printf(node, "%s received\n", ocs_sm_event_name(evt));
1116 		break;
1117 	default:
1118 		__ocs_node_common(__func__, ctx, evt, arg);
1119 		return NULL;
1120 	}
1121 
1122 	return NULL;
1123 }
1124 
1125 /**
1126  * @ingroup node_common
1127  * @brief state: initiate node shutdown
1128  *
1129  * State is entered when a node receives a shutdown event, and it's waiting
1130  * for all the active IOs and ELS IOs associated with the node to complete.
1131  *
1132  * @param ctx remote node sm context
1133  * @param evt event to process
1134  * @param arg per event optional argument
1135  *
1136  * @return returns NULL
1137  */
1138 
1139 void *
__ocs_node_wait_ios_shutdown(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)1140 __ocs_node_wait_ios_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1141 {
1142 	ocs_io_t *io;
1143 	ocs_io_t *next;
1144 	std_node_state_decl();
1145 
1146 	node_sm_trace();
1147 
1148 	switch(evt) {
1149 	case OCS_EVT_ENTER:
1150 		ocs_node_hold_frames(node);
1151 
1152 		/* first check to see if no ELS IOs are outstanding */
1153 		if (ocs_els_io_list_empty(node, &node->els_io_active_list)) {
1154 			/* If there are any active IOS, Free them. */
1155 			if (!ocs_node_active_ios_empty(node)) {
1156 				ocs_lock(&node->active_ios_lock);
1157 				ocs_list_foreach_safe(&node->active_ios, io, next) {
1158 					ocs_list_remove(&io->node->active_ios, io);
1159 					ocs_io_free(node->ocs, io);
1160 				}
1161 				ocs_unlock(&node->active_ios_lock);
1162 			}
1163 			ocs_node_transition(node, __ocs_node_shutdown, NULL);
1164 		}
1165 		break;
1166 
1167 	case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
1168 	case OCS_EVT_ALL_CHILD_NODES_FREE: {
1169 		if (ocs_node_active_ios_empty(node) &&
1170 		    ocs_els_io_list_empty(node, &node->els_io_active_list)) {
1171 			ocs_node_transition(node, __ocs_node_shutdown, NULL);
1172 		}
1173 		break;
1174 	}
1175 
1176 	case OCS_EVT_EXIT:
1177 		ocs_node_accept_frames(node);
1178 		break;
1179 
1180 	case OCS_EVT_SRRS_ELS_REQ_FAIL:
1181 		/* Can happen as ELS IO IO's complete */
1182 		ocs_assert(node->els_req_cnt, NULL);
1183 		node->els_req_cnt--;
1184 		break;
1185 
1186 	/* ignore shutdown events as we're already in shutdown path */
1187 	case OCS_EVT_SHUTDOWN:
1188 		/* have default shutdown event take precedence */
1189 		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1190 		/* fall through */
1191 	case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
1192 	case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
1193 		ocs_log_debug(ocs, "[%s] %-20s\n", node->display_name, ocs_sm_event_name(evt));
1194 		break;
1195 	case OCS_EVT_DOMAIN_ATTACH_OK:
1196 		/* don't care about domain_attach_ok */
1197 		break;
1198 	default:
1199 		__ocs_node_common(__func__, ctx, evt, arg);
1200 		return NULL;
1201 	}
1202 
1203 	return NULL;
1204 }
1205 
1206 /**
1207  * @ingroup node_common
1208  * @brief state: common node event handler
1209  *
1210  * Handle common/shared node events
1211  *
1212  * @param funcname calling function's name
1213  * @param ctx remote node sm context
1214  * @param evt event to process
1215  * @param arg per event optional argument
1216  *
1217  * @return returns NULL
1218  */
1219 
1220 void *
__ocs_node_common(const char * funcname,ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)1221 __ocs_node_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1222 {
1223 	ocs_node_t *node = NULL;
1224 	ocs_t *ocs = NULL;
1225 	ocs_node_cb_t *cbdata = arg;
1226 	ocs_assert(ctx, NULL);
1227 	ocs_assert(ctx->app, NULL);
1228 	node = ctx->app;
1229 	ocs_assert(node->ocs, NULL);
1230 	ocs = node->ocs;
1231 
1232 	switch(evt) {
1233 	case OCS_EVT_ENTER:
1234 	case OCS_EVT_REENTER:
1235 	case OCS_EVT_EXIT:
1236 	case OCS_EVT_SPORT_TOPOLOGY_NOTIFY:
1237 	case OCS_EVT_NODE_MISSING:
1238 	case OCS_EVT_FCP_CMD_RCVD:
1239 		break;
1240 
1241 	case OCS_EVT_NODE_REFOUND:
1242 		node->refound = 1;
1243 		break;
1244 
1245 	/* node->attached must be set appropriately for all node attach/detach events */
1246 	case OCS_EVT_NODE_ATTACH_OK:
1247 		node->attached = TRUE;
1248 		break;
1249 
1250 	case OCS_EVT_NODE_FREE_OK:
1251 	case OCS_EVT_NODE_ATTACH_FAIL:
1252 		node->attached = FALSE;
1253 		break;
1254 
1255 	/* handle any ELS completions that other states either didn't care about
1256 	 * or forgot about
1257 	 */
1258 	case OCS_EVT_SRRS_ELS_CMPL_OK:
1259 	case OCS_EVT_SRRS_ELS_CMPL_FAIL:
1260 		ocs_assert(node->els_cmpl_cnt, NULL);
1261 		node->els_cmpl_cnt--;
1262 		break;
1263 
1264 	/* handle any ELS request completions that other states either didn't care about
1265 	 * or forgot about
1266 	 */
1267 	case OCS_EVT_SRRS_ELS_REQ_OK:
1268 	case OCS_EVT_SRRS_ELS_REQ_FAIL:
1269 	case OCS_EVT_SRRS_ELS_REQ_RJT:
1270 	case OCS_EVT_ELS_REQ_ABORTED:
1271 		ocs_assert(node->els_req_cnt, NULL);
1272 		node->els_req_cnt--;
1273 		break;
1274 
1275 	case OCS_EVT_ELS_RCVD: {
1276 		fc_header_t *hdr = cbdata->header->dma.virt;
1277 
1278 		/* Unsupported ELS was received, send LS_RJT, command not supported */
1279 		ocs_log_debug(ocs, "[%s] (%s) ELS x%02x, LS_RJT not supported\n",
1280 			      node->display_name, funcname, ((uint8_t*)cbdata->payload->dma.virt)[0]);
1281 		ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id),
1282 			FC_REASON_COMMAND_NOT_SUPPORTED, FC_EXPL_NO_ADDITIONAL, 0,
1283 			NULL, NULL);
1284 		break;
1285 	}
1286 
1287 	case OCS_EVT_PLOGI_RCVD:
1288 	case OCS_EVT_FLOGI_RCVD:
1289 	case OCS_EVT_LOGO_RCVD:
1290 	case OCS_EVT_PRLI_RCVD:
1291 	case OCS_EVT_PRLO_RCVD:
1292 	case OCS_EVT_PDISC_RCVD:
1293 	case OCS_EVT_FDISC_RCVD:
1294 	case OCS_EVT_ADISC_RCVD:
1295 	case OCS_EVT_RSCN_RCVD:
1296 	case OCS_EVT_SCR_RCVD: {
1297 		fc_header_t *hdr = cbdata->header->dma.virt;
1298 		/* sm: / send ELS_RJT */
1299 		ocs_log_debug(ocs, "[%s] (%s) %s sending ELS_RJT\n",
1300 			      node->display_name, funcname, ocs_sm_event_name(evt));
1301 		/* if we didn't catch this in a state, send generic LS_RJT */
1302 		ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id),
1303 			FC_REASON_UNABLE_TO_PERFORM, FC_EXPL_NO_ADDITIONAL, 0,
1304 			NULL, NULL);
1305 
1306 		break;
1307 	}
1308 	case OCS_EVT_GID_PT_RCVD:
1309 	case OCS_EVT_RFT_ID_RCVD:
1310 	case OCS_EVT_RFF_ID_RCVD: {
1311 		fc_header_t *hdr = cbdata->header->dma.virt;
1312 		ocs_log_debug(ocs, "[%s] (%s) %s sending CT_REJECT\n",
1313 			      node->display_name, funcname, ocs_sm_event_name(evt));
1314 		ocs_send_ct_rsp(cbdata->io, hdr->ox_id, cbdata->payload->dma.virt, FCCT_HDR_CMDRSP_REJECT, FCCT_COMMAND_NOT_SUPPORTED, 0);
1315 		break;
1316 	}
1317 
1318 	case OCS_EVT_ABTS_RCVD: {
1319 		fc_header_t *hdr = cbdata->header->dma.virt;
1320 		ocs_log_debug(ocs, "[%s] (%s) %s sending BA_ACC\n",
1321 			      node->display_name, funcname, ocs_sm_event_name(evt));
1322 
1323 		/* sm: send BA_ACC */
1324 		ocs_bls_send_acc_hdr(cbdata->io, hdr);
1325 		break;
1326 	}
1327 
1328 	default:
1329 		ocs_log_test(node->ocs, "[%s] %-20s %-20s not handled\n", node->display_name, funcname,
1330 			ocs_sm_event_name(evt));
1331 		break;
1332 	}
1333 	return NULL;
1334 }
1335 
1336 /**
1337  * @ingroup node_common
1338  * @brief save node service parameters
1339  *
1340  * Service parameters are copyed into the node structure
1341  *
1342  * @param node pointer to node structure
1343  * @param payload pointer to service parameters to save
1344  *
1345  * @return none
1346  */
1347 
1348 void
ocs_node_save_sparms(ocs_node_t * node,void * payload)1349 ocs_node_save_sparms(ocs_node_t *node, void *payload)
1350 {
1351 	ocs_memcpy(node->service_params, payload, sizeof(node->service_params));
1352 }
1353 
1354 /**
1355  * @ingroup node_common
1356  * @brief Post event to node state machine context
1357  *
1358  * This is used by the node state machine code to post events to the nodes.  Upon
1359  * completion of the event posting, if the nesting depth is zero and we're not holding
1360  * inbound frames, then the pending frames are processed.
1361  *
1362  * @param node pointer to node
1363  * @param evt event to post
1364  * @param arg event posting argument
1365  *
1366  * @return none
1367  */
1368 
1369 void
ocs_node_post_event(ocs_node_t * node,ocs_sm_event_t evt,void * arg)1370 ocs_node_post_event(ocs_node_t *node, ocs_sm_event_t evt, void *arg)
1371 {
1372 	int free_node = FALSE;
1373 	ocs_assert(node);
1374 
1375 	ocs_node_lock(node);
1376 		node->evtdepth ++;
1377 
1378 		ocs_sm_post_event(&node->sm, evt, arg);
1379 
1380 		/* If our event call depth is one and we're not holding frames
1381 		 * then we can dispatch any pending frames.   We don't want to allow
1382 		 * the ocs_process_node_pending() call to recurse.
1383 		 */
1384 		if (!node->hold_frames && (node->evtdepth == 1)) {
1385 			ocs_process_node_pending(node);
1386 		}
1387 		node->evtdepth --;
1388 
1389 		/* Free the node object if so requested, and we're at an event
1390 		 * call depth of zero
1391 		 */
1392 		if ((node->evtdepth == 0) && node->req_free) {
1393 			free_node = TRUE;
1394 		}
1395 	ocs_node_unlock(node);
1396 
1397 	if (free_node) {
1398 		ocs_node_free(node);
1399 	}
1400 
1401 	return;
1402 }
1403 
1404 /**
1405  * @ingroup node_common
1406  * @brief transition state of a node
1407  *
1408  * The node's state is transitioned to the requested state.  Entry/Exit
1409  * events are posted as needed.
1410  *
1411  * @param node pointer to node
1412  * @param state state to transition to
1413  * @param data transition data
1414  *
1415  * @return none
1416  */
1417 
1418 void
ocs_node_transition(ocs_node_t * node,ocs_sm_function_t state,void * data)1419 ocs_node_transition(ocs_node_t *node, ocs_sm_function_t state, void *data)
1420 {
1421 	ocs_sm_ctx_t *ctx = &node->sm;
1422 
1423 	ocs_node_lock(node);
1424 		if (ctx->current_state == state) {
1425 			ocs_node_post_event(node, OCS_EVT_REENTER, data);
1426 		} else {
1427 			ocs_node_post_event(node, OCS_EVT_EXIT, data);
1428 			ctx->current_state = state;
1429 			ocs_node_post_event(node, OCS_EVT_ENTER, data);
1430 		}
1431 	ocs_node_unlock(node);
1432 }
1433 
1434 /**
1435  * @ingroup node_common
1436  * @brief build EUI formatted WWN
1437  *
1438  * Build a WWN given the somewhat transport agnostic iScsi naming specification, for FC
1439  * use the eui. format, an ascii string such as: "eui.10000000C9A19501"
1440  *
1441  * @param buffer buffer to place formatted name into
1442  * @param buffer_len length in bytes of the buffer
1443  * @param eui_name cpu endian 64 bit WWN value
1444  *
1445  * @return none
1446  */
1447 
1448 void
ocs_node_build_eui_name(char * buffer,uint32_t buffer_len,uint64_t eui_name)1449 ocs_node_build_eui_name(char *buffer, uint32_t buffer_len, uint64_t eui_name)
1450 {
1451 	ocs_memset(buffer, 0, buffer_len);
1452 
1453 	ocs_snprintf(buffer, buffer_len, "eui.%016llx", (unsigned long long)eui_name);
1454 }
1455 
1456 /**
1457  * @ingroup node_common
1458  * @brief return nodes' WWPN as a uint64_t
1459  *
1460  * The WWPN is computed from service parameters and returned as a uint64_t
1461  *
1462  * @param node pointer to node structure
1463  *
1464  * @return WWPN
1465  *
1466  */
1467 
1468 uint64_t
ocs_node_get_wwpn(ocs_node_t * node)1469 ocs_node_get_wwpn(ocs_node_t *node)
1470 {
1471 	fc_plogi_payload_t *sp = (fc_plogi_payload_t*) node->service_params;
1472 
1473 	return (((uint64_t)ocs_be32toh(sp->port_name_hi) << 32ll) | (ocs_be32toh(sp->port_name_lo)));
1474 }
1475 
1476 /**
1477  * @ingroup node_common
1478  * @brief return nodes' WWNN as a uint64_t
1479  *
1480  * The WWNN is computed from service parameters and returned as a uint64_t
1481  *
1482  * @param node pointer to node structure
1483  *
1484  * @return WWNN
1485  *
1486  */
1487 
1488 uint64_t
ocs_node_get_wwnn(ocs_node_t * node)1489 ocs_node_get_wwnn(ocs_node_t *node)
1490 {
1491 	fc_plogi_payload_t *sp = (fc_plogi_payload_t*) node->service_params;
1492 
1493 	return (((uint64_t)ocs_be32toh(sp->node_name_hi) << 32ll) | (ocs_be32toh(sp->node_name_lo)));
1494 }
1495 
1496 /**
1497  * @brief Generate node ddump data
1498  *
1499  * Generates the node ddumpdata
1500  *
1501  * @param textbuf pointer to text buffer
1502  * @param node pointer to node context
1503  *
1504  * @return Returns 0 on success, or a negative value on failure.
1505  */
1506 
1507 int
ocs_ddump_node(ocs_textbuf_t * textbuf,ocs_node_t * node)1508 ocs_ddump_node(ocs_textbuf_t *textbuf, ocs_node_t *node)
1509 {
1510 	ocs_io_t *io;
1511 	ocs_io_t *els;
1512 	int retval = 0;
1513 
1514 	ocs_ddump_section(textbuf, "node", node->instance_index);
1515 	ocs_ddump_value(textbuf, "display_name", "%s", node->display_name);
1516 	ocs_ddump_value(textbuf, "current_state", "%s", node->current_state_name);
1517 	ocs_ddump_value(textbuf, "prev_state", "%s", node->prev_state_name);
1518 	ocs_ddump_value(textbuf, "current_evt", "%s", ocs_sm_event_name(node->current_evt));
1519 	ocs_ddump_value(textbuf, "prev_evt", "%s", ocs_sm_event_name(node->prev_evt));
1520 
1521 	ocs_ddump_value(textbuf, "indicator", "%#x", node->rnode.indicator);
1522 	ocs_ddump_value(textbuf, "fc_id", "%#06x", node->rnode.fc_id);
1523 	ocs_ddump_value(textbuf, "attached", "%d", node->rnode.attached);
1524 
1525 	ocs_ddump_value(textbuf, "hold_frames", "%d", node->hold_frames);
1526 	ocs_ddump_value(textbuf, "io_alloc_enabled", "%d", node->io_alloc_enabled);
1527 	ocs_ddump_value(textbuf, "shutdown_reason", "%d", node->shutdown_reason);
1528 	ocs_ddump_value(textbuf, "send_ls_acc", "%d", node->send_ls_acc);
1529 	ocs_ddump_value(textbuf, "ls_acc_did", "%d", node->ls_acc_did);
1530 	ocs_ddump_value(textbuf, "ls_acc_oxid", "%#04x", node->ls_acc_oxid);
1531 	ocs_ddump_value(textbuf, "req_free", "%d", node->req_free);
1532 	ocs_ddump_value(textbuf, "els_req_cnt", "%d", node->els_req_cnt);
1533 	ocs_ddump_value(textbuf, "els_cmpl_cnt", "%d", node->els_cmpl_cnt);
1534 
1535 	ocs_ddump_value(textbuf, "targ", "%d", node->targ);
1536 	ocs_ddump_value(textbuf, "init", "%d", node->init);
1537 	ocs_ddump_value(textbuf, "wwnn", "%s", node->wwnn);
1538 	ocs_ddump_value(textbuf, "wwpn", "%s", node->wwpn);
1539 	ocs_ddump_value(textbuf, "login_state", "%d", (node->sm.current_state == __ocs_d_device_ready) ? 1 : 0);
1540 	ocs_ddump_value(textbuf, "chained_io_count", "%d", node->chained_io_count);
1541 	ocs_ddump_value(textbuf, "abort_cnt", "%d", node->abort_cnt);
1542 
1543 	ocs_display_sparams(NULL, "node_sparams", 1, textbuf, node->service_params+4);
1544 
1545 	ocs_lock(&node->pend_frames_lock);
1546 		if (!ocs_list_empty(&node->pend_frames)) {
1547 			ocs_hw_sequence_t *frame;
1548 			ocs_ddump_section(textbuf, "pending_frames", 0);
1549 			ocs_list_foreach(&node->pend_frames, frame) {
1550 				fc_header_t *hdr;
1551 				char buf[128];
1552 
1553 				hdr = frame->header->dma.virt;
1554 				ocs_snprintf(buf, sizeof(buf), "%02x/%04x/%04x len %zu",
1555 				 hdr->r_ctl, ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id),
1556 				 frame->payload->dma.len);
1557 				ocs_ddump_value(textbuf, "frame", "%s", buf);
1558 			}
1559 			ocs_ddump_endsection(textbuf, "pending_frames", 0);
1560 		}
1561 	ocs_unlock(&node->pend_frames_lock);
1562 
1563 	ocs_scsi_ini_ddump(textbuf, OCS_SCSI_DDUMP_NODE, node);
1564 	ocs_scsi_tgt_ddump(textbuf, OCS_SCSI_DDUMP_NODE, node);
1565 
1566 	ocs_lock(&node->active_ios_lock);
1567 		ocs_ddump_section(textbuf, "active_ios", 0);
1568 		ocs_list_foreach(&node->active_ios, io) {
1569 			ocs_ddump_io(textbuf, io);
1570 		}
1571 		ocs_ddump_endsection(textbuf, "active_ios", 0);
1572 
1573 		ocs_ddump_section(textbuf, "els_io_pend_list", 0);
1574 		ocs_list_foreach(&node->els_io_pend_list, els) {
1575 			ocs_ddump_els(textbuf, els);
1576 		}
1577 		ocs_ddump_endsection(textbuf, "els_io_pend_list", 0);
1578 
1579 		ocs_ddump_section(textbuf, "els_io_active_list", 0);
1580 		ocs_list_foreach(&node->els_io_active_list, els) {
1581 			ocs_ddump_els(textbuf, els);
1582 		}
1583 		ocs_ddump_endsection(textbuf, "els_io_active_list", 0);
1584 	ocs_unlock(&node->active_ios_lock);
1585 
1586 	ocs_ddump_endsection(textbuf, "node", node->instance_index);
1587 
1588 	return retval;
1589 }
1590 
1591 /**
1592  * @brief check ELS request completion
1593  *
1594  * Check ELS request completion event to make sure it's for the
1595  * ELS request we expect. If not, invoke given common event
1596  * handler and return an error.
1597  *
1598  * @param ctx state machine context
1599  * @param evt ELS request event
1600  * @param arg event argument
1601  * @param cmd ELS command expected
1602  * @param node_common_func common event handler to call if ELS
1603  *      		   doesn't match
1604  * @param funcname function name that called this
1605  *
1606  * @return zero if ELS command matches, -1 otherwise
1607  */
1608 int32_t
node_check_els_req(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg,uint8_t cmd,ocs_node_common_func_t node_common_func,const char * funcname)1609 node_check_els_req(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg, uint8_t cmd, ocs_node_common_func_t node_common_func, const char *funcname)
1610 {
1611 	ocs_node_t *node = NULL;
1612 	ocs_t *ocs = NULL;
1613 	ocs_node_cb_t *cbdata = arg;
1614 	fc_els_gen_t *els_gen = NULL;
1615 	ocs_assert(ctx, -1);
1616 	node = ctx->app;
1617 	ocs_assert(node, -1);
1618 	ocs = node->ocs;
1619 	ocs_assert(ocs, -1);
1620 	cbdata = arg;
1621 	ocs_assert(cbdata, -1);
1622 	ocs_assert(cbdata->els, -1);
1623 	els_gen = (fc_els_gen_t *)cbdata->els->els_req.virt;
1624 	ocs_assert(els_gen, -1);
1625 
1626 	if ((cbdata->els->hio_type != OCS_HW_ELS_REQ) || (els_gen->command_code != cmd)) {
1627 		if (cbdata->els->hio_type != OCS_HW_ELS_REQ) {
1628 			ocs_log_debug(node->ocs, "[%s] %-20s expecting ELS cmd=x%x received type=%d\n",
1629 				node->display_name, funcname, cmd, cbdata->els->hio_type);
1630 		} else {
1631 			ocs_log_debug(node->ocs, "[%s] %-20s expecting ELS cmd=x%x received cmd=x%x\n",
1632 				node->display_name, funcname, cmd, els_gen->command_code);
1633 		}
1634 		/* send event to common handler */
1635 		node_common_func(funcname, ctx, evt, arg);
1636 		return -1;
1637 	}
1638 	return 0;
1639 }
1640 
1641 /**
1642  * @brief check NS request completion
1643  *
1644  * Check ELS request completion event to make sure it's for the
1645  * nameserver request we expect. If not, invoke given common
1646  * event handler and return an error.
1647  *
1648  * @param ctx state machine context
1649  * @param evt ELS request event
1650  * @param arg event argument
1651  * @param cmd nameserver command expected
1652  * @param node_common_func common event handler to call if
1653  *      		   nameserver cmd doesn't match
1654  * @param funcname function name that called this
1655  *
1656  * @return zero if NS command matches, -1 otherwise
1657  */
1658 int32_t
node_check_ns_req(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg,uint32_t cmd,ocs_node_common_func_t node_common_func,const char * funcname)1659 node_check_ns_req(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg, uint32_t cmd, ocs_node_common_func_t node_common_func, const char *funcname)
1660 {
1661 	ocs_node_t *node = NULL;
1662 	ocs_t *ocs = NULL;
1663 	ocs_node_cb_t *cbdata = arg;
1664 	fcct_iu_header_t *fcct = NULL;
1665 	ocs_assert(ctx, -1);
1666 	node = ctx->app;
1667 	ocs_assert(node, -1);
1668 	ocs = node->ocs;
1669 	ocs_assert(ocs, -1);
1670 	cbdata = arg;
1671 	ocs_assert(cbdata, -1);
1672 	ocs_assert(cbdata->els, -1);
1673 	fcct = (fcct_iu_header_t *)cbdata->els->els_req.virt;
1674 	ocs_assert(fcct, -1);
1675 
1676 	if ((cbdata->els->hio_type != OCS_HW_FC_CT) || fcct->cmd_rsp_code != ocs_htobe16(cmd)) {
1677 		if (cbdata->els->hio_type != OCS_HW_FC_CT) {
1678 			ocs_log_debug(node->ocs, "[%s] %-20s expecting NS cmd=x%x received type=%d\n",
1679 				node->display_name, funcname, cmd, cbdata->els->hio_type);
1680 		} else {
1681 			ocs_log_debug(node->ocs, "[%s] %-20s expecting NS cmd=x%x received cmd=x%x\n",
1682 				node->display_name, funcname, cmd, fcct->cmd_rsp_code);
1683 		}
1684 		/* send event to common handler */
1685 		node_common_func(funcname, ctx, evt, arg);
1686 		return -1;
1687 	}
1688 	return 0;
1689 }
1690 
1691 void
ocs_mgmt_node_list(ocs_textbuf_t * textbuf,void * object)1692 ocs_mgmt_node_list(ocs_textbuf_t *textbuf, void *object)
1693 {
1694 	ocs_io_t *io;
1695 	ocs_node_t *node = (ocs_node_t *)object;
1696 
1697 	ocs_mgmt_start_section(textbuf, "node", node->instance_index);
1698 
1699 	/* Readonly values */
1700 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "display_name");
1701 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "indicator");
1702 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "fc_id");
1703 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "attached");
1704 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "hold_frames");
1705 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "shutting_down");
1706 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "req_free");
1707 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ox_id");
1708 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ox_id_in_use");
1709 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "abort_cnt");
1710 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "targ");
1711 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "init");
1712 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "wwpn");
1713 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "wwnn");
1714 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "pend_frames");
1715 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "chained_io_count");
1716 
1717 	/* Actions */
1718 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "resume");
1719 
1720 	ocs_lock(&node->active_ios_lock);
1721 	ocs_list_foreach(&node->active_ios, io) {
1722 		if ((io->mgmt_functions) && (io->mgmt_functions->get_list_handler)) {
1723 			io->mgmt_functions->get_list_handler(textbuf, io);
1724 		}
1725 	}
1726 	ocs_unlock(&node->active_ios_lock);
1727 
1728 	ocs_mgmt_end_section(textbuf, "node", node->instance_index);
1729 }
1730 
1731 int
ocs_mgmt_node_get(ocs_textbuf_t * textbuf,char * parent,char * name,void * object)1732 ocs_mgmt_node_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *object)
1733 {
1734 	ocs_io_t *io;
1735 	ocs_node_t *node = (ocs_node_t *)object;
1736 	char qualifier[80];
1737 	int retval = -1;
1738 
1739 	ocs_mgmt_start_section(textbuf, "node", node->instance_index);
1740 
1741 	ocs_snprintf(qualifier, sizeof(qualifier), "%s/node[%d]", parent, node->instance_index);
1742 
1743 	/* If it doesn't start with my qualifier I don't know what to do with it */
1744 	if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
1745 		char *unqualified_name = name + strlen(qualifier) +1;
1746 
1747 		/* See if it's a value I can supply */
1748 		if (ocs_strcmp(unqualified_name, "display_name") == 0) {
1749 			ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", node->display_name);
1750 			retval = 0;
1751 		} else if (ocs_strcmp(unqualified_name, "indicator") == 0) {
1752 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "indicator", "0x%x", node->rnode.indicator);
1753 			retval = 0;
1754 		} else if (ocs_strcmp(unqualified_name, "fc_id") == 0) {
1755 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fc_id", "0x%06x", node->rnode.fc_id);
1756 			retval = 0;
1757 		} else if (ocs_strcmp(unqualified_name, "attached") == 0) {
1758 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "attached", node->rnode.attached);
1759 			retval = 0;
1760 		} else if (ocs_strcmp(unqualified_name, "hold_frames") == 0) {
1761 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "hold_frames", node->hold_frames);
1762 			retval = 0;
1763 		} else if (ocs_strcmp(unqualified_name, "io_alloc_enabled") == 0) {
1764 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "io_alloc_enabled", node->io_alloc_enabled);
1765 			retval = 0;
1766 		} else if (ocs_strcmp(unqualified_name, "req_free") == 0) {
1767 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "req_free", node->req_free);
1768 			retval = 0;
1769 		} else if (ocs_strcmp(unqualified_name, "ls_acc_oxid") == 0) {
1770 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ls_acc_oxid", "0x%#04x", node->ls_acc_oxid);
1771 			retval = 0;
1772 		} else if (ocs_strcmp(unqualified_name, "ls_acc_did") == 0) {
1773 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ls_acc_did", "0x%#04x", node->ls_acc_did);
1774 			retval = 0;
1775 		} else if (ocs_strcmp(unqualified_name, "abort_cnt") == 0) {
1776 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "abort_cnt", "%d", node->abort_cnt);
1777 			retval = 0;
1778 		} else if (ocs_strcmp(unqualified_name, "targ") == 0) {
1779 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "targ",  node->targ);
1780 			retval = 0;
1781 		} else if (ocs_strcmp(unqualified_name, "init") == 0) {
1782 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "init",  node->init);
1783 			retval = 0;
1784 		} else if (ocs_strcmp(unqualified_name, "wwpn") == 0) {
1785 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwpn", "%s", node->wwpn);
1786 			retval = 0;
1787 		} else if (ocs_strcmp(unqualified_name, "wwnn") == 0) {
1788 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwnn", "%s", node->wwnn);
1789 			retval = 0;
1790 		} else if (ocs_strcmp(unqualified_name, "current_state") == 0) {
1791 			ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_state", node->current_state_name);
1792 			retval = 0;
1793 		} else if (ocs_strcmp(unqualified_name, "login_state") == 0) {
1794 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "login_state", "%d", (node->sm.current_state == __ocs_d_device_ready) ? 1 : 0);
1795 			retval = 0;
1796 		} else if (ocs_strcmp(unqualified_name, "pend_frames") == 0) {
1797 			ocs_hw_sequence_t *frame;
1798 			ocs_lock(&node->pend_frames_lock);
1799 				ocs_list_foreach(&node->pend_frames, frame) {
1800 					fc_header_t *hdr;
1801 					char buf[128];
1802 
1803 					hdr = frame->header->dma.virt;
1804 					ocs_snprintf(buf, sizeof(buf), "%02x/%04x/%04x len %zu", hdr->r_ctl,
1805 						 ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id),
1806 						 frame->payload->dma.len);
1807 					ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pend_frames", buf);
1808 				}
1809 			ocs_unlock(&node->pend_frames_lock);
1810 			retval = 0;
1811 		} else if (ocs_strcmp(unqualified_name, "chained_io_count") == 0) {
1812 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "chained_io_count", "%d", node->chained_io_count);
1813 			retval = 0;
1814 		} else {
1815 			/* If I didn't know the value of this status pass the request to each of my children */
1816 			ocs_lock(&node->active_ios_lock);
1817 				ocs_list_foreach(&node->active_ios, io) {
1818 					if ((io->mgmt_functions) && (io->mgmt_functions->get_handler)) {
1819 						retval = io->mgmt_functions->get_handler(textbuf, qualifier, name, io);
1820 					}
1821 
1822 					if (retval == 0) {
1823 						break;
1824 					}
1825 				}
1826 			ocs_unlock(&node->active_ios_lock);
1827 		}
1828 	}
1829 
1830 	ocs_mgmt_end_section(textbuf, "node", node->instance_index);
1831 
1832 	return retval;
1833 }
1834 
1835 void
ocs_mgmt_node_get_all(ocs_textbuf_t * textbuf,void * object)1836 ocs_mgmt_node_get_all(ocs_textbuf_t *textbuf, void *object)
1837 {
1838 	ocs_io_t *io;
1839 	ocs_node_t *node = (ocs_node_t *)object;
1840 	ocs_hw_sequence_t *frame;
1841 
1842 	ocs_mgmt_start_section(textbuf, "node", node->instance_index);
1843 
1844 	ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", node->display_name);
1845 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "indicator", "0x%x", node->rnode.indicator);
1846 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fc_id", "0x%06x", node->rnode.fc_id);
1847 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "attached", node->rnode.attached);
1848 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "hold_frames", node->hold_frames);
1849 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "io_alloc_enabled", node->io_alloc_enabled);
1850 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "req_free", node->req_free);
1851 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ls_acc_oxid", "0x%#04x", node->ls_acc_oxid);
1852 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ls_acc_did", "0x%#04x", node->ls_acc_did);
1853 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "abort_cnt", "%d", node->abort_cnt);
1854 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "targ",  node->targ);
1855 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "init",  node->init);
1856 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwpn", "%s", node->wwpn);
1857 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwnn", "%s", node->wwnn);
1858 
1859 	ocs_lock(&node->pend_frames_lock);
1860 	ocs_list_foreach(&node->pend_frames, frame) {
1861 		fc_header_t *hdr;
1862 		char buf[128];
1863 
1864 		hdr = frame->header->dma.virt;
1865 		ocs_snprintf(buf, sizeof(buf), "%02x/%04x/%04x len %zu", hdr->r_ctl,
1866 			     ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id),
1867 			     frame->payload->dma.len);
1868 		ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pend_frames", buf);
1869 	}
1870 	ocs_unlock(&node->pend_frames_lock);
1871 
1872 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "chained_io_count", "%d", node->chained_io_count);
1873 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "resume");
1874 	ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_state", node->current_state_name);
1875 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "login_state", "%d", (node->sm.current_state == __ocs_d_device_ready) ? 1 : 0);
1876 
1877 	ocs_lock(&node->active_ios_lock);
1878 	ocs_list_foreach(&node->active_ios, io) {
1879 		if ((io->mgmt_functions) && (io->mgmt_functions->get_all_handler)) {
1880 			io->mgmt_functions->get_all_handler(textbuf,io);
1881 		}
1882 	}
1883 	ocs_unlock(&node->active_ios_lock);
1884 
1885 	ocs_mgmt_end_section(textbuf, "node", node->instance_index);
1886 }
1887 
1888 int
ocs_mgmt_node_set(char * parent,char * name,char * value,void * object)1889 ocs_mgmt_node_set(char *parent, char *name, char *value, void *object)
1890 {
1891 	ocs_io_t *io;
1892 	ocs_node_t *node = (ocs_node_t *)object;
1893 	char qualifier[80];
1894 	int retval = -1;
1895 
1896 	ocs_snprintf(qualifier, sizeof(qualifier), "%s/node[%d]", parent, node->instance_index);
1897 
1898 	/* If it doesn't start with my qualifier I don't know what to do with it */
1899 	if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
1900 		ocs_lock(&node->active_ios_lock);
1901 		ocs_list_foreach(&node->active_ios, io) {
1902 			if ((io->mgmt_functions) && (io->mgmt_functions->set_handler)) {
1903 				retval = io->mgmt_functions->set_handler(qualifier, name, value, io);
1904 			}
1905 
1906 			if (retval == 0) {
1907 				break;
1908 			}
1909 		}
1910 		ocs_unlock(&node->active_ios_lock);
1911 	}
1912 
1913 	return retval;
1914 }
1915 
1916 int
ocs_mgmt_node_exec(char * parent,char * action,void * arg_in,uint32_t arg_in_length,void * arg_out,uint32_t arg_out_length,void * object)1917 ocs_mgmt_node_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length,
1918 		   void *arg_out, uint32_t arg_out_length, void *object)
1919 {
1920 	ocs_io_t *io;
1921 	ocs_node_t *node = (ocs_node_t *)object;
1922 	char qualifier[80];
1923 	int retval = -1;
1924 
1925 	ocs_snprintf(qualifier, sizeof(qualifier), "%s.node%d", parent, node->instance_index);
1926 
1927 	/* If it doesn't start with my qualifier I don't know what to do with it */
1928 	if (ocs_strncmp(action, qualifier, strlen(qualifier)) == 0) {
1929 		char *unqualified_name = action + strlen(qualifier) +1;
1930 
1931 		if (ocs_strcmp(unqualified_name, "resume") == 0) {
1932 			ocs_node_post_event(node, OCS_EVT_RESUME, NULL);
1933 		}
1934 
1935 		{
1936 			/* If I didn't know how to do this action pass the request to each of my children */
1937 			ocs_lock(&node->active_ios_lock);
1938 				ocs_list_foreach(&node->active_ios, io) {
1939 					if ((io->mgmt_functions) && (io->mgmt_functions->exec_handler)) {
1940 						retval = io->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length,
1941 							arg_out, arg_out_length, io);
1942 					}
1943 
1944 					if (retval == 0) {
1945 						break;
1946 					}
1947 				}
1948 			ocs_unlock(&node->active_ios_lock);
1949 		}
1950 	}
1951 
1952 	return retval;
1953 }
1954 
1955 /**
1956  * @brief Return TRUE if active ios list is empty
1957  *
1958  * Test if node->active_ios list is empty while holding the node->active_ios_lock.
1959  *
1960  * @param node pointer to node object
1961  *
1962  * @return TRUE if node active ios list is empty
1963  */
1964 
1965 int
ocs_node_active_ios_empty(ocs_node_t * node)1966 ocs_node_active_ios_empty(ocs_node_t *node)
1967 {
1968 	int empty;
1969 
1970 	ocs_lock(&node->active_ios_lock);
1971 		empty = ocs_list_empty(&node->active_ios);
1972 	ocs_unlock(&node->active_ios_lock);
1973 	return empty;
1974 }
1975 
1976 /**
1977  * @brief Pause a node
1978  *
1979  * The node is placed in the __ocs_node_paused state after saving the state
1980  * to return to
1981  *
1982  * @param node Pointer to node object
1983  * @param state State to resume to
1984  *
1985  * @return none
1986  */
1987 
1988 void
ocs_node_pause(ocs_node_t * node,ocs_sm_function_t state)1989 ocs_node_pause(ocs_node_t *node, ocs_sm_function_t state)
1990 {
1991 	node->nodedb_state = state;
1992 	ocs_node_transition(node, __ocs_node_paused, NULL);
1993 }
1994 
1995 /**
1996  * @brief Paused node state
1997  *
1998  * This state is entered when a state is "paused". When resumed, the node
1999  * is transitioned to a previously saved state (node->ndoedb_state)
2000  *
2001  * @param ctx Remote node state machine context.
2002  * @param evt Event to process.
2003  * @param arg Per event optional argument.
2004  *
2005  * @return returns NULL
2006  */
2007 
2008 void *
__ocs_node_paused(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)2009 __ocs_node_paused(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2010 {
2011 	std_node_state_decl();
2012 
2013 	node_sm_trace();
2014 
2015 	switch(evt) {
2016 	case OCS_EVT_ENTER:
2017 		node_printf(node, "Paused\n");
2018 		break;
2019 
2020 	case OCS_EVT_RESUME: {
2021 		ocs_sm_function_t pf = node->nodedb_state;
2022 
2023 		node->nodedb_state = NULL;
2024 		ocs_node_transition(node, pf, NULL);
2025 		break;
2026 	}
2027 
2028 	case OCS_EVT_DOMAIN_ATTACH_OK:
2029 		break;
2030 
2031 	case OCS_EVT_SHUTDOWN:
2032 		node->req_free = 1;
2033 		break;
2034 
2035 	default:
2036 		__ocs_node_common(__func__, ctx, evt, arg);
2037 		break;
2038 	}
2039 	return NULL;
2040 }
2041 
2042 /**
2043  * @brief Resume a paused state
2044  *
2045  * Posts a resume event to the paused node.
2046  *
2047  * @param node Pointer to node object
2048  *
2049  * @return returns 0 for success, a negative error code value for failure.
2050  */
2051 
2052 int32_t
ocs_node_resume(ocs_node_t * node)2053 ocs_node_resume(ocs_node_t *node)
2054 {
2055 	ocs_assert(node != NULL, -1);
2056 
2057 	ocs_node_post_event(node, OCS_EVT_RESUME, NULL);
2058 
2059 	return 0;
2060 }
2061 
2062 /**
2063  * @ingroup node_common
2064  * @brief Dispatch a ELS frame.
2065  *
2066  * <h3 class="desc">Description</h3>
2067  * An ELS frame is dispatched to the \c node state machine.
2068  * RQ Pair mode: this function is always called with a NULL hw
2069  * io.
2070  *
2071  * @param node Node that originated the frame.
2072  * @param seq header/payload sequence buffers
2073  *
2074  * @return Returns 0 if frame processed and RX buffers cleaned
2075  * up appropriately, -1 if frame not handled and RX buffers need
2076  * to be returned.
2077  */
2078 
2079 int32_t
ocs_node_recv_els_frame(ocs_node_t * node,ocs_hw_sequence_t * seq)2080 ocs_node_recv_els_frame(ocs_node_t *node, ocs_hw_sequence_t *seq)
2081 {
2082 	struct {
2083 		uint32_t cmd;
2084 		ocs_sm_event_t evt;
2085 		uint32_t payload_size;
2086 	} els_cmd_list[] = {
2087 		{FC_ELS_CMD_PLOGI,	OCS_EVT_PLOGI_RCVD, 	sizeof(fc_plogi_payload_t)},
2088 		{FC_ELS_CMD_FLOGI,	OCS_EVT_FLOGI_RCVD, 	sizeof(fc_plogi_payload_t)},
2089 		{FC_ELS_CMD_LOGO,	OCS_EVT_LOGO_RCVD, 	sizeof(fc_acc_payload_t)},
2090 		{FC_ELS_CMD_RRQ,	OCS_EVT_RRQ_RCVD, 	sizeof(fc_acc_payload_t)},
2091 		{FC_ELS_CMD_PRLI, 	OCS_EVT_PRLI_RCVD, 	sizeof(fc_prli_payload_t)},
2092 		{FC_ELS_CMD_PRLO, 	OCS_EVT_PRLO_RCVD, 	sizeof(fc_prlo_payload_t)},
2093 		{FC_ELS_CMD_PDISC, 	OCS_EVT_PDISC_RCVD, 	MAX_ACC_REJECT_PAYLOAD},
2094 		{FC_ELS_CMD_FDISC, 	OCS_EVT_FDISC_RCVD, 	MAX_ACC_REJECT_PAYLOAD},
2095 		{FC_ELS_CMD_ADISC, 	OCS_EVT_ADISC_RCVD, 	sizeof(fc_adisc_payload_t)},
2096 		{FC_ELS_CMD_RSCN, 	OCS_EVT_RSCN_RCVD, 	MAX_ACC_REJECT_PAYLOAD},
2097 		{FC_ELS_CMD_SCR	, 	OCS_EVT_SCR_RCVD, 	MAX_ACC_REJECT_PAYLOAD},
2098 	};
2099 	ocs_t *ocs = node->ocs;
2100 	ocs_node_cb_t cbdata;
2101 	fc_header_t *hdr = seq->header->dma.virt;
2102 	uint8_t *buf = seq->payload->dma.virt;
2103 	ocs_sm_event_t evt = OCS_EVT_ELS_RCVD;
2104 	uint32_t payload_size = MAX_ACC_REJECT_PAYLOAD;
2105 	uint32_t i;
2106 
2107 	ocs_memset(&cbdata, 0, sizeof(cbdata));
2108 	cbdata.header = seq->header;
2109 	cbdata.payload = seq->payload;
2110 
2111 	/* find a matching event for the ELS command */
2112 	for (i = 0; i < ARRAY_SIZE(els_cmd_list); i ++) {
2113 		if (els_cmd_list[i].cmd == buf[0]) {
2114 			evt = els_cmd_list[i].evt;
2115 			payload_size = els_cmd_list[i].payload_size;
2116 			break;
2117 		}
2118 	}
2119 
2120 	switch(evt) {
2121 	case OCS_EVT_FLOGI_RCVD:
2122 		ocs_display_sparams(node->display_name, "flogi rcvd req", 0, NULL, ((uint8_t*)seq->payload->dma.virt)+4);
2123 		break;
2124 	case OCS_EVT_FDISC_RCVD:
2125 		ocs_display_sparams(node->display_name, "fdisc rcvd req", 0, NULL, ((uint8_t*)seq->payload->dma.virt)+4);
2126 		break;
2127 	case OCS_EVT_PLOGI_RCVD:
2128 		ocs_display_sparams(node->display_name, "plogi rcvd req", 0, NULL, ((uint8_t*)seq->payload->dma.virt)+4);
2129 		break;
2130 	default:
2131 		break;
2132 	}
2133 
2134 	cbdata.io = ocs_els_io_alloc(node, payload_size, OCS_ELS_ROLE_RESPONDER);
2135 
2136 	if (cbdata.io != NULL) {
2137 		cbdata.io->hw_priv = seq->hw_priv;
2138 		/* if we're here, sequence initiative has been transferred */
2139 		cbdata.io->seq_init = 1;
2140 
2141 		ocs_node_post_event(node, evt, &cbdata);
2142 	} else {
2143 		node_printf(node, "failure to allocate SCSI IO for ELS s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2144 			    fc_be24toh(hdr->s_id), fc_be24toh(hdr->d_id), ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id));
2145 	}
2146 	ocs_hw_sequence_free(&ocs->hw, seq);
2147 	return 0;
2148 }
2149 
2150 /**
2151  * @ingroup node_common
2152  * @brief Dispatch a ABTS frame (RQ Pair/sequence coalescing).
2153  *
2154  * <h3 class="desc">Description</h3>
2155  * An ABTS frame is dispatched to the node state machine. This
2156  * function is used for both RQ Pair and sequence coalescing.
2157  *
2158  * @param node Node that originated the frame.
2159  * @param seq Header/payload sequence buffers
2160  *
2161  * @return Returns 0 if frame processed and RX buffers cleaned
2162  * up appropriately, -1 if frame not handled and RX buffers need
2163  * to be returned.
2164  */
2165 
2166 int32_t
ocs_node_recv_abts_frame(ocs_node_t * node,ocs_hw_sequence_t * seq)2167 ocs_node_recv_abts_frame(ocs_node_t *node, ocs_hw_sequence_t *seq)
2168 {
2169 	ocs_t *ocs = node->ocs;
2170 	ocs_xport_t *xport = ocs->xport;
2171 	fc_header_t *hdr = seq->header->dma.virt;
2172 	uint16_t ox_id = ocs_be16toh(hdr->ox_id);
2173 	uint16_t rx_id = ocs_be16toh(hdr->rx_id);
2174 	ocs_node_cb_t cbdata;
2175 	int32_t rc = 0;
2176 
2177 	node->abort_cnt++;
2178 
2179 	/*
2180 	 * Check to see if the IO we want to abort is active, if it not active,
2181 	 * then we can send the BA_ACC using the send frame option
2182 	 */
2183 	if (ocs_io_find_tgt_io(ocs, node, ox_id, rx_id) == NULL) {
2184 		uint32_t send_frame_capable;
2185 
2186 		ocs_log_debug(ocs, "IO not found (ox_id %04x)\n", ox_id);
2187 
2188 		/* If we have SEND_FRAME capability, then use it to send BA_ACC */
2189 		rc = ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &send_frame_capable);
2190 		if ((rc == 0) && send_frame_capable) {
2191 			rc = ocs_sframe_send_bls_acc(node, seq);
2192 			if (rc) {
2193 				ocs_log_test(ocs, "ocs_bls_acc_send_frame failed\n");
2194 			}
2195 			return rc;
2196 		}
2197 		/* continuing */
2198 	}
2199 
2200 	ocs_memset(&cbdata, 0, sizeof(cbdata));
2201 	cbdata.header = seq->header;
2202 	cbdata.payload = seq->payload;
2203 
2204 	cbdata.io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_RESPONDER);
2205 	if (cbdata.io != NULL) {
2206 		cbdata.io->hw_priv = seq->hw_priv;
2207 		/* If we got this far, SIT=1 */
2208 		cbdata.io->seq_init = 1;
2209 
2210 		/* fill out generic fields */
2211 		cbdata.io->ocs = ocs;
2212 		cbdata.io->node = node;
2213 		cbdata.io->cmd_tgt = TRUE;
2214 
2215 		ocs_node_post_event(node, OCS_EVT_ABTS_RCVD, &cbdata);
2216 	} else {
2217 		ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
2218 		node_printf(node, "SCSI IO allocation failed for ABTS received s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2219 			    fc_be24toh(hdr->s_id), fc_be24toh(hdr->d_id), ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id));
2220 	}
2221 
2222 	/* ABTS processed, return RX buffer to the chip */
2223 	ocs_hw_sequence_free(&ocs->hw, seq);
2224 	return 0;
2225 }
2226 
2227 /**
2228  * @ingroup node_common
2229  * @brief Dispatch a CT frame.
2230  *
2231  * <h3 class="desc">Description</h3>
2232  * A CT frame is dispatched to the \c node state machine.
2233  * RQ Pair mode: this function is always called with a NULL hw
2234  * io.
2235  *
2236  * @param node Node that originated the frame.
2237  * @param seq header/payload sequence buffers
2238  *
2239  * @return Returns 0 if frame processed and RX buffers cleaned
2240  * up appropriately, -1 if frame not handled and RX buffers need
2241  * to be returned.
2242  */
2243 
2244 int32_t
ocs_node_recv_ct_frame(ocs_node_t * node,ocs_hw_sequence_t * seq)2245 ocs_node_recv_ct_frame(ocs_node_t *node, ocs_hw_sequence_t *seq)
2246 {
2247 	ocs_t *ocs = node->ocs;
2248 	fc_header_t *hdr = seq->header->dma.virt;
2249 	fcct_iu_header_t *iu = seq->payload->dma.virt;
2250 	ocs_sm_event_t evt = OCS_EVT_ELS_RCVD;
2251 	uint32_t payload_size = MAX_ACC_REJECT_PAYLOAD;
2252 	uint16_t gscmd = ocs_be16toh(iu->cmd_rsp_code);
2253 	ocs_node_cb_t cbdata;
2254 	uint32_t i;
2255 	struct {
2256 		uint32_t cmd;
2257 		ocs_sm_event_t evt;
2258 		uint32_t payload_size;
2259 	} ct_cmd_list[] = {
2260 		{FC_GS_NAMESERVER_RFF_ID, OCS_EVT_RFF_ID_RCVD, 100},
2261 		{FC_GS_NAMESERVER_RFT_ID, OCS_EVT_RFT_ID_RCVD, 100},
2262 		{FC_GS_NAMESERVER_GNN_ID, OCS_EVT_GNN_ID_RCVD, 100},
2263 		{FC_GS_NAMESERVER_GPN_ID, OCS_EVT_GPN_ID_RCVD, 100},
2264 		{FC_GS_NAMESERVER_GFPN_ID, OCS_EVT_GFPN_ID_RCVD, 100},
2265 		{FC_GS_NAMESERVER_GFF_ID, OCS_EVT_GFF_ID_RCVD, 100},
2266 		{FC_GS_NAMESERVER_GID_FT, OCS_EVT_GID_FT_RCVD, 256},
2267 		{FC_GS_NAMESERVER_GID_PT, OCS_EVT_GID_PT_RCVD, 256},
2268 		{FC_GS_NAMESERVER_RPN_ID, OCS_EVT_RPN_ID_RCVD, 100},
2269 		{FC_GS_NAMESERVER_RNN_ID, OCS_EVT_RNN_ID_RCVD, 100},
2270 		{FC_GS_NAMESERVER_RCS_ID, OCS_EVT_RCS_ID_RCVD, 100},
2271 		{FC_GS_NAMESERVER_RSNN_NN, OCS_EVT_RSNN_NN_RCVD, 100},
2272 		{FC_GS_NAMESERVER_RSPN_ID, OCS_EVT_RSPN_ID_RCVD, 100},
2273 		{FC_GS_NAMESERVER_RHBA, OCS_EVT_RHBA_RCVD, 100},
2274 		{FC_GS_NAMESERVER_RPA, OCS_EVT_RPA_RCVD, 100},
2275 	};
2276 
2277 	ocs_memset(&cbdata, 0, sizeof(cbdata));
2278 	cbdata.header = seq->header;
2279 	cbdata.payload = seq->payload;
2280 
2281 	/* find a matching event for the ELS/GS command */
2282 	for (i = 0; i < ARRAY_SIZE(ct_cmd_list); i ++) {
2283 		if (ct_cmd_list[i].cmd == gscmd) {
2284 			evt = ct_cmd_list[i].evt;
2285 			payload_size = ct_cmd_list[i].payload_size;
2286 			break;
2287 		}
2288 	}
2289 
2290 	/* Allocate an IO and send a reject */
2291 	cbdata.io = ocs_els_io_alloc(node, payload_size, OCS_ELS_ROLE_RESPONDER);
2292 	if (cbdata.io == NULL) {
2293 		node_printf(node, "GS IO failed for s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2294 			fc_be24toh(hdr->s_id), fc_be24toh(hdr->d_id),
2295 			ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id));
2296 		return -1;
2297 	}
2298 	cbdata.io->hw_priv = seq->hw_priv;
2299 	ocs_node_post_event(node, evt, &cbdata);
2300 
2301 	ocs_hw_sequence_free(&ocs->hw, seq);
2302 	return 0;
2303 }
2304 
2305 /**
2306  * @ingroup node_common
2307  * @brief Dispatch a FCP command frame when the node is not ready.
2308  *
2309  * <h3 class="desc">Description</h3>
2310  * A frame is dispatched to the \c node state machine.
2311  *
2312  * @param node Node that originated the frame.
2313  * @param seq header/payload sequence buffers
2314  *
2315  * @return Returns 0 if frame processed and RX buffers cleaned
2316  * up appropriately, -1 if frame not handled.
2317  */
2318 
2319 int32_t
ocs_node_recv_fcp_cmd(ocs_node_t * node,ocs_hw_sequence_t * seq)2320 ocs_node_recv_fcp_cmd(ocs_node_t *node, ocs_hw_sequence_t *seq)
2321 {
2322 	ocs_node_cb_t cbdata;
2323 	ocs_t *ocs = node->ocs;
2324 
2325 	ocs_memset(&cbdata, 0, sizeof(cbdata));
2326 	cbdata.header = seq->header;
2327 	cbdata.payload = seq->payload;
2328 	ocs_node_post_event(node, OCS_EVT_FCP_CMD_RCVD, &cbdata);
2329 	ocs_hw_sequence_free(&ocs->hw, seq);
2330 	return 0;
2331 }
2332 
2333 /**
2334  * @ingroup node_common
2335  * @brief Stub handler for non-ABTS BLS frames
2336  *
2337  * <h3 class="desc">Description</h3>
2338  * Log message and drop. Customer can plumb it to their back-end as needed
2339  *
2340  * @param node Node that originated the frame.
2341  * @param seq header/payload sequence buffers
2342  *
2343  * @return Returns 0
2344  */
2345 
2346 int32_t
ocs_node_recv_bls_no_sit(ocs_node_t * node,ocs_hw_sequence_t * seq)2347 ocs_node_recv_bls_no_sit(ocs_node_t *node, ocs_hw_sequence_t *seq)
2348 {
2349 	fc_header_t *hdr = seq->header->dma.virt;
2350 
2351 	node_printf(node, "Dropping frame hdr = %08x %08x %08x %08x %08x %08x\n",
2352 		    ocs_htobe32(((uint32_t *)hdr)[0]),
2353 		    ocs_htobe32(((uint32_t *)hdr)[1]),
2354 		    ocs_htobe32(((uint32_t *)hdr)[2]),
2355 		    ocs_htobe32(((uint32_t *)hdr)[3]),
2356 		    ocs_htobe32(((uint32_t *)hdr)[4]),
2357 		    ocs_htobe32(((uint32_t *)hdr)[5]));
2358 
2359 	return -1;
2360 }
2361