brintos

brintos / linux-shallow public Read only

0
0
Text · 26.1 KiB · a1b4ce6 Raw
1103 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.5 */6 7#include "efc.h"8 9int10efc_remote_node_cb(void *arg, int event, void *data)11{12	struct efc *efc = arg;13	struct efc_remote_node *rnode = data;14	struct efc_node *node = rnode->node;15	unsigned long flags = 0;16 17	spin_lock_irqsave(&efc->lock, flags);18	efc_node_post_event(node, event, NULL);19	spin_unlock_irqrestore(&efc->lock, flags);20 21	return 0;22}23 24struct efc_node *25efc_node_find(struct efc_nport *nport, u32 port_id)26{27	/* Find an FC node structure given the FC port ID */28	return xa_load(&nport->lookup, port_id);29}30 31static void32_efc_node_free(struct kref *arg)33{34	struct efc_node *node = container_of(arg, struct efc_node, ref);35	struct efc *efc = node->efc;36	struct efc_dma *dma;37 38	dma = &node->sparm_dma_buf;39	dma_pool_free(efc->node_dma_pool, dma->virt, dma->phys);40	memset(dma, 0, sizeof(struct efc_dma));41	mempool_free(node, efc->node_pool);42}43 44struct efc_node *efc_node_alloc(struct efc_nport *nport,45				u32 port_id, bool init, bool targ)46{47	int rc;48	struct efc_node *node = NULL;49	struct efc *efc = nport->efc;50	struct efc_dma *dma;51 52	if (nport->shutting_down) {53		efc_log_debug(efc, "node allocation when shutting down %06x",54			      port_id);55		return NULL;56	}57 58	node = mempool_alloc(efc->node_pool, GFP_ATOMIC);59	if (!node) {60		efc_log_err(efc, "node allocation failed %06x", port_id);61		return NULL;62	}63	memset(node, 0, sizeof(*node));64 65	dma = &node->sparm_dma_buf;66	dma->size = NODE_SPARAMS_SIZE;67	dma->virt = dma_pool_zalloc(efc->node_dma_pool, GFP_ATOMIC, &dma->phys);68	if (!dma->virt) {69		efc_log_err(efc, "node dma alloc failed\n");70		goto dma_fail;71	}72	node->rnode.indicator = U32_MAX;73	node->nport = nport;74 75	node->efc = efc;76	node->init = init;77	node->targ = targ;78 79	spin_lock_init(&node->pend_frames_lock);80	INIT_LIST_HEAD(&node->pend_frames);81	spin_lock_init(&node->els_ios_lock);82	INIT_LIST_HEAD(&node->els_ios_list);83	node->els_io_enabled = true;84 85	rc = efc_cmd_node_alloc(efc, &node->rnode, port_id, nport);86	if (rc) {87		efc_log_err(efc, "efc_hw_node_alloc failed: %d\n", rc);88		goto hw_alloc_fail;89	}90 91	node->rnode.node = node;92	node->sm.app = node;93	node->evtdepth = 0;94 95	efc_node_update_display_name(node);96 97	rc = xa_err(xa_store(&nport->lookup, port_id, node, GFP_ATOMIC));98	if (rc) {99		efc_log_err(efc, "Node lookup store failed: %d\n", rc);100		goto xa_fail;101	}102 103	/* initialize refcount */104	kref_init(&node->ref);105	node->release = _efc_node_free;106	kref_get(&nport->ref);107 108	return node;109 110xa_fail:111	efc_node_free_resources(efc, &node->rnode);112hw_alloc_fail:113	dma_pool_free(efc->node_dma_pool, dma->virt, dma->phys);114dma_fail:115	mempool_free(node, efc->node_pool);116	return NULL;117}118 119void120efc_node_free(struct efc_node *node)121{122	struct efc_nport *nport;123	struct efc *efc;124	int rc = 0;125	struct efc_node *ns = NULL;126 127	nport = node->nport;128	efc = node->efc;129 130	node_printf(node, "Free'd\n");131 132	if (node->refound) {133		/*134		 * Save the name server node. We will send fake RSCN event at135		 * the end to handle ignored RSCN event during node deletion136		 */137		ns = efc_node_find(node->nport, FC_FID_DIR_SERV);138	}139 140	if (!node->nport) {141		efc_log_err(efc, "Node already Freed\n");142		return;143	}144 145	/* Free HW resources */146	rc = efc_node_free_resources(efc, &node->rnode);147	if (rc < 0)148		efc_log_err(efc, "efc_hw_node_free failed: %d\n", rc);149 150	/* if the gidpt_delay_timer is still running, then delete it */151	if (timer_pending(&node->gidpt_delay_timer))152		del_timer(&node->gidpt_delay_timer);153 154	xa_erase(&nport->lookup, node->rnode.fc_id);155 156	/*157	 * If the node_list is empty,158	 * then post a ALL_CHILD_NODES_FREE event to the nport,159	 * after the lock is released.160	 * The nport may be free'd as a result of the event.161	 */162	if (xa_empty(&nport->lookup))163		efc_sm_post_event(&nport->sm, EFC_EVT_ALL_CHILD_NODES_FREE,164				  NULL);165 166	node->nport = NULL;167	node->sm.current_state = NULL;168 169	kref_put(&nport->ref, nport->release);170	kref_put(&node->ref, node->release);171 172	if (ns) {173		/* sending fake RSCN event to name server node */174		efc_node_post_event(ns, EFC_EVT_RSCN_RCVD, NULL);175	}176}177 178static void179efc_dma_copy_in(struct efc_dma *dma, void *buffer, u32 buffer_length)180{181	if (!dma || !buffer || !buffer_length)182		return;183 184	if (buffer_length > dma->size)185		buffer_length = dma->size;186 187	memcpy(dma->virt, buffer, buffer_length);188	dma->len = buffer_length;189}190 191int192efc_node_attach(struct efc_node *node)193{194	int rc = 0;195	struct efc_nport *nport = node->nport;196	struct efc_domain *domain = nport->domain;197	struct efc *efc = node->efc;198 199	if (!domain->attached) {200		efc_log_err(efc, "Warning: unattached domain\n");201		return -EIO;202	}203	/* Update node->wwpn/wwnn */204 205	efc_node_build_eui_name(node->wwpn, sizeof(node->wwpn),206				efc_node_get_wwpn(node));207	efc_node_build_eui_name(node->wwnn, sizeof(node->wwnn),208				efc_node_get_wwnn(node));209 210	efc_dma_copy_in(&node->sparm_dma_buf, node->service_params + 4,211			sizeof(node->service_params) - 4);212 213	/* take lock to protect node->rnode.attached */214	rc = efc_cmd_node_attach(efc, &node->rnode, &node->sparm_dma_buf);215	if (rc < 0)216		efc_log_debug(efc, "efc_hw_node_attach failed: %d\n", rc);217 218	return rc;219}220 221void222efc_node_fcid_display(u32 fc_id, char *buffer, u32 buffer_length)223{224	switch (fc_id) {225	case FC_FID_FLOGI:226		snprintf(buffer, buffer_length, "fabric");227		break;228	case FC_FID_FCTRL:229		snprintf(buffer, buffer_length, "fabctl");230		break;231	case FC_FID_DIR_SERV:232		snprintf(buffer, buffer_length, "nserve");233		break;234	default:235		if (fc_id == FC_FID_DOM_MGR) {236			snprintf(buffer, buffer_length, "dctl%02x",237				 (fc_id & 0x0000ff));238		} else {239			snprintf(buffer, buffer_length, "%06x", fc_id);240		}241		break;242	}243}244 245void246efc_node_update_display_name(struct efc_node *node)247{248	u32 port_id = node->rnode.fc_id;249	struct efc_nport *nport = node->nport;250	char portid_display[16];251 252	efc_node_fcid_display(port_id, portid_display, sizeof(portid_display));253 254	snprintf(node->display_name, sizeof(node->display_name), "%s.%s",255		 nport->display_name, portid_display);256}257 258void259efc_node_send_ls_io_cleanup(struct efc_node *node)260{261	if (node->send_ls_acc != EFC_NODE_SEND_LS_ACC_NONE) {262		efc_log_debug(node->efc, "[%s] cleaning up LS_ACC oxid=0x%x\n",263			      node->display_name, node->ls_acc_oxid);264 265		node->send_ls_acc = EFC_NODE_SEND_LS_ACC_NONE;266		node->ls_acc_io = NULL;267	}268}269 270static void efc_node_handle_implicit_logo(struct efc_node *node)271{272	int rc;273 274	/*275	 * currently, only case for implicit logo is PLOGI276	 * recvd. Thus, node's ELS IO pending list won't be277	 * empty (PLOGI will be on it)278	 */279	WARN_ON(node->send_ls_acc != EFC_NODE_SEND_LS_ACC_PLOGI);280	node_printf(node, "Reason: implicit logout, re-authenticate\n");281 282	/* Re-attach node with the same HW node resources */283	node->req_free = false;284	rc = efc_node_attach(node);285	efc_node_transition(node, __efc_d_wait_node_attach, NULL);286	node->els_io_enabled = true;287 288	if (rc < 0)289		efc_node_post_event(node, EFC_EVT_NODE_ATTACH_FAIL, NULL);290}291 292static void efc_node_handle_explicit_logo(struct efc_node *node)293{294	s8 pend_frames_empty;295	unsigned long flags = 0;296 297	/* cleanup any pending LS_ACC ELSs */298	efc_node_send_ls_io_cleanup(node);299 300	spin_lock_irqsave(&node->pend_frames_lock, flags);301	pend_frames_empty = list_empty(&node->pend_frames);302	spin_unlock_irqrestore(&node->pend_frames_lock, flags);303 304	/*305	 * there are two scenarios where we want to keep306	 * this node alive:307	 * 1. there are pending frames that need to be308	 *    processed or309	 * 2. we're an initiator and the remote node is310	 *    a target and we need to re-authenticate311	 */312	node_printf(node, "Shutdown: explicit logo pend=%d ", !pend_frames_empty);313	node_printf(node, "nport.ini=%d node.tgt=%d\n",314		    node->nport->enable_ini, node->targ);315	if (!pend_frames_empty || (node->nport->enable_ini && node->targ)) {316		u8 send_plogi = false;317 318		if (node->nport->enable_ini && node->targ) {319			/*320			 * we're an initiator and321			 * node shutting down is a target;322			 * we'll need to re-authenticate in323			 * initial state324			 */325			send_plogi = true;326		}327 328		/*329		 * transition to __efc_d_init330		 * (will retain HW node resources)331		 */332		node->els_io_enabled = true;333		node->req_free = false;334 335		/*336		 * either pending frames exist or we are re-authenticating337		 * with PLOGI (or both); in either case, return to initial338		 * state339		 */340		efc_node_init_device(node, send_plogi);341	}342	/* else: let node shutdown occur */343}344 345static void346efc_node_purge_pending(struct efc_node *node)347{348	struct efc *efc = node->efc;349	struct efc_hw_sequence *frame, *next;350	unsigned long flags = 0;351 352	spin_lock_irqsave(&node->pend_frames_lock, flags);353 354	list_for_each_entry_safe(frame, next, &node->pend_frames, list_entry) {355		list_del(&frame->list_entry);356		efc->tt.hw_seq_free(efc, frame);357	}358 359	spin_unlock_irqrestore(&node->pend_frames_lock, flags);360}361 362void363__efc_node_shutdown(struct efc_sm_ctx *ctx,364		    enum efc_sm_event evt, void *arg)365{366	struct efc_node *node = ctx->app;367 368	efc_node_evt_set(ctx, evt, __func__);369 370	node_sm_trace();371 372	switch (evt) {373	case EFC_EVT_ENTER: {374		efc_node_hold_frames(node);375		WARN_ON(!efc_els_io_list_empty(node, &node->els_ios_list));376		/* by default, we will be freeing node after we unwind */377		node->req_free = true;378 379		switch (node->shutdown_reason) {380		case EFC_NODE_SHUTDOWN_IMPLICIT_LOGO:381			/* Node shutdown b/c of PLOGI received when node382			 * already logged in. We have PLOGI service383			 * parameters, so submit node attach; we won't be384			 * freeing this node385			 */386 387			efc_node_handle_implicit_logo(node);388			break;389 390		case EFC_NODE_SHUTDOWN_EXPLICIT_LOGO:391			efc_node_handle_explicit_logo(node);392			break;393 394		case EFC_NODE_SHUTDOWN_DEFAULT:395		default: {396			/*397			 * shutdown due to link down,398			 * node going away (xport event) or399			 * nport shutdown, purge pending and400			 * proceed to cleanup node401			 */402 403			/* cleanup any pending LS_ACC ELSs */404			efc_node_send_ls_io_cleanup(node);405 406			node_printf(node,407				    "Shutdown reason: default, purge pending\n");408			efc_node_purge_pending(node);409			break;410		}411		}412 413		break;414	}415	case EFC_EVT_EXIT:416		efc_node_accept_frames(node);417		break;418 419	default:420		__efc_node_common(__func__, ctx, evt, arg);421	}422}423 424static bool425efc_node_check_els_quiesced(struct efc_node *node)426{427	/* check to see if ELS requests, completions are quiesced */428	if (node->els_req_cnt == 0 && node->els_cmpl_cnt == 0 &&429	    efc_els_io_list_empty(node, &node->els_ios_list)) {430		if (!node->attached) {431			/* hw node detach already completed, proceed */432			node_printf(node, "HW node not attached\n");433			efc_node_transition(node,434					    __efc_node_wait_ios_shutdown,435					     NULL);436		} else {437			/*438			 * hw node detach hasn't completed,439			 * transition and wait440			 */441			node_printf(node, "HW node still attached\n");442			efc_node_transition(node, __efc_node_wait_node_free,443					    NULL);444		}445		return true;446	}447	return false;448}449 450void451efc_node_initiate_cleanup(struct efc_node *node)452{453	/*454	 * if ELS's have already been quiesced, will move to next state455	 * if ELS's have not been quiesced, abort them456	 */457	if (!efc_node_check_els_quiesced(node)) {458		efc_node_hold_frames(node);459		efc_node_transition(node, __efc_node_wait_els_shutdown, NULL);460	}461}462 463void464__efc_node_wait_els_shutdown(struct efc_sm_ctx *ctx,465			     enum efc_sm_event evt, void *arg)466{467	bool check_quiesce = false;468	struct efc_node *node = ctx->app;469 470	efc_node_evt_set(ctx, evt, __func__);471 472	node_sm_trace();473	/* Node state machine: Wait for all ELSs to complete */474	switch (evt) {475	case EFC_EVT_ENTER:476		efc_node_hold_frames(node);477		if (efc_els_io_list_empty(node, &node->els_ios_list)) {478			node_printf(node, "All ELS IOs complete\n");479			check_quiesce = true;480		}481		break;482	case EFC_EVT_EXIT:483		efc_node_accept_frames(node);484		break;485 486	case EFC_EVT_SRRS_ELS_REQ_OK:487	case EFC_EVT_SRRS_ELS_REQ_FAIL:488	case EFC_EVT_SRRS_ELS_REQ_RJT:489	case EFC_EVT_ELS_REQ_ABORTED:490		if (WARN_ON(!node->els_req_cnt))491			break;492		node->els_req_cnt--;493		check_quiesce = true;494		break;495 496	case EFC_EVT_SRRS_ELS_CMPL_OK:497	case EFC_EVT_SRRS_ELS_CMPL_FAIL:498		if (WARN_ON(!node->els_cmpl_cnt))499			break;500		node->els_cmpl_cnt--;501		check_quiesce = true;502		break;503 504	case EFC_EVT_ALL_CHILD_NODES_FREE:505		/* all ELS IO's complete */506		node_printf(node, "All ELS IOs complete\n");507		WARN_ON(!efc_els_io_list_empty(node, &node->els_ios_list));508		check_quiesce = true;509		break;510 511	case EFC_EVT_NODE_ACTIVE_IO_LIST_EMPTY:512		check_quiesce = true;513		break;514 515	case EFC_EVT_DOMAIN_ATTACH_OK:516		/* don't care about domain_attach_ok */517		break;518 519	/* ignore shutdown events as we're already in shutdown path */520	case EFC_EVT_SHUTDOWN:521		/* have default shutdown event take precedence */522		node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;523		fallthrough;524 525	case EFC_EVT_SHUTDOWN_EXPLICIT_LOGO:526	case EFC_EVT_SHUTDOWN_IMPLICIT_LOGO:527		node_printf(node, "%s received\n", efc_sm_event_name(evt));528		break;529 530	default:531		__efc_node_common(__func__, ctx, evt, arg);532	}533 534	if (check_quiesce)535		efc_node_check_els_quiesced(node);536}537 538void539__efc_node_wait_node_free(struct efc_sm_ctx *ctx,540			  enum efc_sm_event evt, void *arg)541{542	struct efc_node *node = ctx->app;543 544	efc_node_evt_set(ctx, evt, __func__);545 546	node_sm_trace();547 548	switch (evt) {549	case EFC_EVT_ENTER:550		efc_node_hold_frames(node);551		break;552 553	case EFC_EVT_EXIT:554		efc_node_accept_frames(node);555		break;556 557	case EFC_EVT_NODE_FREE_OK:558		/* node is officially no longer attached */559		node->attached = false;560		efc_node_transition(node, __efc_node_wait_ios_shutdown, NULL);561		break;562 563	case EFC_EVT_ALL_CHILD_NODES_FREE:564	case EFC_EVT_NODE_ACTIVE_IO_LIST_EMPTY:565		/* As IOs and ELS IO's complete we expect to get these events */566		break;567 568	case EFC_EVT_DOMAIN_ATTACH_OK:569		/* don't care about domain_attach_ok */570		break;571 572	/* ignore shutdown events as we're already in shutdown path */573	case EFC_EVT_SHUTDOWN:574		/* have default shutdown event take precedence */575		node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;576		fallthrough;577 578	case EFC_EVT_SHUTDOWN_EXPLICIT_LOGO:579	case EFC_EVT_SHUTDOWN_IMPLICIT_LOGO:580		node_printf(node, "%s received\n", efc_sm_event_name(evt));581		break;582	default:583		__efc_node_common(__func__, ctx, evt, arg);584	}585}586 587void588__efc_node_wait_ios_shutdown(struct efc_sm_ctx *ctx,589			     enum efc_sm_event evt, void *arg)590{591	struct efc_node *node = ctx->app;592	struct efc *efc = node->efc;593 594	efc_node_evt_set(ctx, evt, __func__);595 596	node_sm_trace();597 598	switch (evt) {599	case EFC_EVT_ENTER:600		efc_node_hold_frames(node);601 602		/* first check to see if no ELS IOs are outstanding */603		if (efc_els_io_list_empty(node, &node->els_ios_list))604			/* If there are any active IOS, Free them. */605			efc_node_transition(node, __efc_node_shutdown, NULL);606		break;607 608	case EFC_EVT_NODE_ACTIVE_IO_LIST_EMPTY:609	case EFC_EVT_ALL_CHILD_NODES_FREE:610		if (efc_els_io_list_empty(node, &node->els_ios_list))611			efc_node_transition(node, __efc_node_shutdown, NULL);612		break;613 614	case EFC_EVT_EXIT:615		efc_node_accept_frames(node);616		break;617 618	case EFC_EVT_SRRS_ELS_REQ_FAIL:619		/* Can happen as ELS IO IO's complete */620		if (WARN_ON(!node->els_req_cnt))621			break;622		node->els_req_cnt--;623		break;624 625	/* ignore shutdown events as we're already in shutdown path */626	case EFC_EVT_SHUTDOWN:627		/* have default shutdown event take precedence */628		node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;629		fallthrough;630 631	case EFC_EVT_SHUTDOWN_EXPLICIT_LOGO:632	case EFC_EVT_SHUTDOWN_IMPLICIT_LOGO:633		efc_log_debug(efc, "[%s] %-20s\n", node->display_name,634			      efc_sm_event_name(evt));635		break;636	case EFC_EVT_DOMAIN_ATTACH_OK:637		/* don't care about domain_attach_ok */638		break;639	default:640		__efc_node_common(__func__, ctx, evt, arg);641	}642}643 644void645__efc_node_common(const char *funcname, struct efc_sm_ctx *ctx,646		  enum efc_sm_event evt, void *arg)647{648	struct efc_node *node = NULL;649	struct efc *efc = NULL;650	struct efc_node_cb *cbdata = arg;651 652	node = ctx->app;653	efc = node->efc;654 655	switch (evt) {656	case EFC_EVT_ENTER:657	case EFC_EVT_REENTER:658	case EFC_EVT_EXIT:659	case EFC_EVT_NPORT_TOPOLOGY_NOTIFY:660	case EFC_EVT_NODE_MISSING:661	case EFC_EVT_FCP_CMD_RCVD:662		break;663 664	case EFC_EVT_NODE_REFOUND:665		node->refound = true;666		break;667 668	/*669	 * node->attached must be set appropriately670	 * for all node attach/detach events671	 */672	case EFC_EVT_NODE_ATTACH_OK:673		node->attached = true;674		break;675 676	case EFC_EVT_NODE_FREE_OK:677	case EFC_EVT_NODE_ATTACH_FAIL:678		node->attached = false;679		break;680 681	/*682	 * handle any ELS completions that683	 * other states either didn't care about684	 * or forgot about685	 */686	case EFC_EVT_SRRS_ELS_CMPL_OK:687	case EFC_EVT_SRRS_ELS_CMPL_FAIL:688		if (WARN_ON(!node->els_cmpl_cnt))689			break;690		node->els_cmpl_cnt--;691		break;692 693	/*694	 * handle any ELS request completions that695	 * other states either didn't care about696	 * or forgot about697	 */698	case EFC_EVT_SRRS_ELS_REQ_OK:699	case EFC_EVT_SRRS_ELS_REQ_FAIL:700	case EFC_EVT_SRRS_ELS_REQ_RJT:701	case EFC_EVT_ELS_REQ_ABORTED:702		if (WARN_ON(!node->els_req_cnt))703			break;704		node->els_req_cnt--;705		break;706 707	case EFC_EVT_ELS_RCVD: {708		struct fc_frame_header *hdr = cbdata->header->dma.virt;709 710		/*711		 * Unsupported ELS was received,712		 * send LS_RJT, command not supported713		 */714		efc_log_debug(efc,715			      "[%s] (%s) ELS x%02x, LS_RJT not supported\n",716			      node->display_name, funcname,717			      ((u8 *)cbdata->payload->dma.virt)[0]);718 719		efc_send_ls_rjt(node, be16_to_cpu(hdr->fh_ox_id),720				ELS_RJT_UNSUP, ELS_EXPL_NONE, 0);721		break;722	}723 724	case EFC_EVT_PLOGI_RCVD:725	case EFC_EVT_FLOGI_RCVD:726	case EFC_EVT_LOGO_RCVD:727	case EFC_EVT_PRLI_RCVD:728	case EFC_EVT_PRLO_RCVD:729	case EFC_EVT_PDISC_RCVD:730	case EFC_EVT_FDISC_RCVD:731	case EFC_EVT_ADISC_RCVD:732	case EFC_EVT_RSCN_RCVD:733	case EFC_EVT_SCR_RCVD: {734		struct fc_frame_header *hdr = cbdata->header->dma.virt;735 736		/* sm: / send ELS_RJT */737		efc_log_debug(efc, "[%s] (%s) %s sending ELS_RJT\n",738			      node->display_name, funcname,739			      efc_sm_event_name(evt));740		/* if we didn't catch this in a state, send generic LS_RJT */741		efc_send_ls_rjt(node, be16_to_cpu(hdr->fh_ox_id),742				ELS_RJT_UNAB, ELS_EXPL_NONE, 0);743		break;744	}745	case EFC_EVT_ABTS_RCVD: {746		efc_log_debug(efc, "[%s] (%s) %s sending BA_ACC\n",747			      node->display_name, funcname,748			      efc_sm_event_name(evt));749 750		/* sm: / send BA_ACC */751		efc_send_bls_acc(node, cbdata->header->dma.virt);752		break;753	}754 755	default:756		efc_log_debug(node->efc, "[%s] %-20s %-20s not handled\n",757			      node->display_name, funcname,758			      efc_sm_event_name(evt));759	}760}761 762void763efc_node_save_sparms(struct efc_node *node, void *payload)764{765	memcpy(node->service_params, payload, sizeof(node->service_params));766}767 768void769efc_node_post_event(struct efc_node *node,770		    enum efc_sm_event evt, void *arg)771{772	bool free_node = false;773 774	node->evtdepth++;775 776	efc_sm_post_event(&node->sm, evt, arg);777 778	/* If our event call depth is one and779	 * we're not holding frames780	 * then we can dispatch any pending frames.781	 * We don't want to allow the efc_process_node_pending()782	 * call to recurse.783	 */784	if (!node->hold_frames && node->evtdepth == 1)785		efc_process_node_pending(node);786 787	node->evtdepth--;788 789	/*790	 * Free the node object if so requested,791	 * and we're at an event call depth of zero792	 */793	if (node->evtdepth == 0 && node->req_free)794		free_node = true;795 796	if (free_node)797		efc_node_free(node);798}799 800void801efc_node_transition(struct efc_node *node,802		    void (*state)(struct efc_sm_ctx *,803				  enum efc_sm_event, void *), void *data)804{805	struct efc_sm_ctx *ctx = &node->sm;806 807	if (ctx->current_state == state) {808		efc_node_post_event(node, EFC_EVT_REENTER, data);809	} else {810		efc_node_post_event(node, EFC_EVT_EXIT, data);811		ctx->current_state = state;812		efc_node_post_event(node, EFC_EVT_ENTER, data);813	}814}815 816void817efc_node_build_eui_name(char *buf, u32 buf_len, uint64_t eui_name)818{819	memset(buf, 0, buf_len);820 821	snprintf(buf, buf_len, "eui.%016llX", (unsigned long long)eui_name);822}823 824u64825efc_node_get_wwpn(struct efc_node *node)826{827	struct fc_els_flogi *sp =828			(struct fc_els_flogi *)node->service_params;829 830	return be64_to_cpu(sp->fl_wwpn);831}832 833u64834efc_node_get_wwnn(struct efc_node *node)835{836	struct fc_els_flogi *sp =837			(struct fc_els_flogi *)node->service_params;838 839	return be64_to_cpu(sp->fl_wwnn);840}841 842int843efc_node_check_els_req(struct efc_sm_ctx *ctx, enum efc_sm_event evt, void *arg,844		u8 cmd, void (*efc_node_common_func)(const char *,845				struct efc_sm_ctx *, enum efc_sm_event, void *),846		const char *funcname)847{848	return 0;849}850 851int852efc_node_check_ns_req(struct efc_sm_ctx *ctx, enum efc_sm_event evt, void *arg,853		u16 cmd, void (*efc_node_common_func)(const char *,854				struct efc_sm_ctx *, enum efc_sm_event, void *),855		const char *funcname)856{857	return 0;858}859 860int861efc_els_io_list_empty(struct efc_node *node, struct list_head *list)862{863	int empty;864	unsigned long flags = 0;865 866	spin_lock_irqsave(&node->els_ios_lock, flags);867	empty = list_empty(list);868	spin_unlock_irqrestore(&node->els_ios_lock, flags);869	return empty;870}871 872void873efc_node_pause(struct efc_node *node,874	       void (*state)(struct efc_sm_ctx *,875			     enum efc_sm_event, void *))876 877{878	node->nodedb_state = state;879	efc_node_transition(node, __efc_node_paused, NULL);880}881 882void883__efc_node_paused(struct efc_sm_ctx *ctx,884		  enum efc_sm_event evt, void *arg)885{886	struct efc_node *node = ctx->app;887 888	efc_node_evt_set(ctx, evt, __func__);889 890	node_sm_trace();891 892	/*893	 * This state is entered when a state is "paused". When resumed, the894	 * node is transitioned to a previously saved state (node->ndoedb_state)895	 */896	switch (evt) {897	case EFC_EVT_ENTER:898		node_printf(node, "Paused\n");899		break;900 901	case EFC_EVT_RESUME: {902		void (*pf)(struct efc_sm_ctx *ctx,903			   enum efc_sm_event evt, void *arg);904 905		pf = node->nodedb_state;906 907		node->nodedb_state = NULL;908		efc_node_transition(node, pf, NULL);909		break;910	}911 912	case EFC_EVT_DOMAIN_ATTACH_OK:913		break;914 915	case EFC_EVT_SHUTDOWN:916		node->req_free = true;917		break;918 919	default:920		__efc_node_common(__func__, ctx, evt, arg);921	}922}923 924void925efc_node_recv_els_frame(struct efc_node *node,926			struct efc_hw_sequence *seq)927{928	u32 prli_size = sizeof(struct fc_els_prli) + sizeof(struct fc_els_spp);929	struct {930		u32 cmd;931		enum efc_sm_event evt;932		u32 payload_size;933	} els_cmd_list[] = {934		{ELS_PLOGI, EFC_EVT_PLOGI_RCVD,	sizeof(struct fc_els_flogi)},935		{ELS_FLOGI, EFC_EVT_FLOGI_RCVD,	sizeof(struct fc_els_flogi)},936		{ELS_LOGO, EFC_EVT_LOGO_RCVD, sizeof(struct fc_els_ls_acc)},937		{ELS_PRLI, EFC_EVT_PRLI_RCVD, prli_size},938		{ELS_PRLO, EFC_EVT_PRLO_RCVD, prli_size},939		{ELS_PDISC, EFC_EVT_PDISC_RCVD,	MAX_ACC_REJECT_PAYLOAD},940		{ELS_FDISC, EFC_EVT_FDISC_RCVD,	MAX_ACC_REJECT_PAYLOAD},941		{ELS_ADISC, EFC_EVT_ADISC_RCVD,	sizeof(struct fc_els_adisc)},942		{ELS_RSCN, EFC_EVT_RSCN_RCVD, MAX_ACC_REJECT_PAYLOAD},943		{ELS_SCR, EFC_EVT_SCR_RCVD, MAX_ACC_REJECT_PAYLOAD},944	};945	struct efc_node_cb cbdata;946	u8 *buf = seq->payload->dma.virt;947	enum efc_sm_event evt = EFC_EVT_ELS_RCVD;948	u32 i;949 950	memset(&cbdata, 0, sizeof(cbdata));951	cbdata.header = seq->header;952	cbdata.payload = seq->payload;953 954	/* find a matching event for the ELS command */955	for (i = 0; i < ARRAY_SIZE(els_cmd_list); i++) {956		if (els_cmd_list[i].cmd == buf[0]) {957			evt = els_cmd_list[i].evt;958			break;959		}960	}961 962	efc_node_post_event(node, evt, &cbdata);963}964 965void966efc_node_recv_ct_frame(struct efc_node *node,967		       struct efc_hw_sequence *seq)968{969	struct fc_ct_hdr *iu = seq->payload->dma.virt;970	struct fc_frame_header *hdr = seq->header->dma.virt;971	struct efc *efc = node->efc;972	u16 gscmd = be16_to_cpu(iu->ct_cmd);973 974	efc_log_err(efc, "[%s] Received cmd :%x sending CT_REJECT\n",975		    node->display_name, gscmd);976	efc_send_ct_rsp(efc, node, be16_to_cpu(hdr->fh_ox_id), iu,977			FC_FS_RJT, FC_FS_RJT_UNSUP, 0);978}979 980void981efc_node_recv_fcp_cmd(struct efc_node *node, struct efc_hw_sequence *seq)982{983	struct efc_node_cb cbdata;984 985	memset(&cbdata, 0, sizeof(cbdata));986	cbdata.header = seq->header;987	cbdata.payload = seq->payload;988 989	efc_node_post_event(node, EFC_EVT_FCP_CMD_RCVD, &cbdata);990}991 992void993efc_process_node_pending(struct efc_node *node)994{995	struct efc *efc = node->efc;996	struct efc_hw_sequence *seq = NULL;997	u32 pend_frames_processed = 0;998	unsigned long flags = 0;999 1000	for (;;) {1001		/* need to check for hold frames condition after each frame1002		 * processed because any given frame could cause a transition1003		 * to a state that holds frames1004		 */1005		if (node->hold_frames)1006			break;1007 1008		seq = NULL;1009		/* Get next frame/sequence */1010		spin_lock_irqsave(&node->pend_frames_lock, flags);1011 1012		if (!list_empty(&node->pend_frames)) {1013			seq = list_first_entry(&node->pend_frames,1014					struct efc_hw_sequence, list_entry);1015			list_del(&seq->list_entry);1016		}1017		spin_unlock_irqrestore(&node->pend_frames_lock, flags);1018 1019		if (!seq) {1020			pend_frames_processed =	node->pend_frames_processed;1021			node->pend_frames_processed = 0;1022			break;1023		}1024		node->pend_frames_processed++;1025 1026		/* now dispatch frame(s) to dispatch function */1027		efc_node_dispatch_frame(node, seq);1028		efc->tt.hw_seq_free(efc, seq);1029	}1030 1031	if (pend_frames_processed != 0)1032		efc_log_debug(efc, "%u node frames held and processed\n",1033			      pend_frames_processed);1034}1035 1036void1037efc_scsi_sess_reg_complete(struct efc_node *node, u32 status)1038{1039	unsigned long flags = 0;1040	enum efc_sm_event evt = EFC_EVT_NODE_SESS_REG_OK;1041	struct efc *efc = node->efc;1042 1043	if (status)1044		evt = EFC_EVT_NODE_SESS_REG_FAIL;1045 1046	spin_lock_irqsave(&efc->lock, flags);1047	/* Notify the node to resume */1048	efc_node_post_event(node, evt, NULL);1049	spin_unlock_irqrestore(&efc->lock, flags);1050}1051 1052void1053efc_scsi_del_initiator_complete(struct efc *efc, struct efc_node *node)1054{1055	unsigned long flags = 0;1056 1057	spin_lock_irqsave(&efc->lock, flags);1058	/* Notify the node to resume */1059	efc_node_post_event(node, EFC_EVT_NODE_DEL_INI_COMPLETE, NULL);1060	spin_unlock_irqrestore(&efc->lock, flags);1061}1062 1063void1064efc_scsi_del_target_complete(struct efc *efc, struct efc_node *node)1065{1066	unsigned long flags = 0;1067 1068	spin_lock_irqsave(&efc->lock, flags);1069	/* Notify the node to resume */1070	efc_node_post_event(node, EFC_EVT_NODE_DEL_TGT_COMPLETE, NULL);1071	spin_unlock_irqrestore(&efc->lock, flags);1072}1073 1074void1075efc_scsi_io_list_empty(struct efc *efc, struct efc_node *node)1076{1077	unsigned long flags = 0;1078 1079	spin_lock_irqsave(&efc->lock, flags);1080	efc_node_post_event(node, EFC_EVT_NODE_ACTIVE_IO_LIST_EMPTY, NULL);1081	spin_unlock_irqrestore(&efc->lock, flags);1082}1083 1084void efc_node_post_els_resp(struct efc_node *node, u32 evt, void *arg)1085{1086	struct efc *efc = node->efc;1087	unsigned long flags = 0;1088 1089	spin_lock_irqsave(&efc->lock, flags);1090	efc_node_post_event(node, evt, arg);1091	spin_unlock_irqrestore(&efc->lock, flags);1092}1093 1094void efc_node_post_shutdown(struct efc_node *node, void *arg)1095{1096	unsigned long flags = 0;1097	struct efc *efc = node->efc;1098 1099	spin_lock_irqsave(&efc->lock, flags);1100	efc_node_post_event(node, EFC_EVT_SHUTDOWN, arg);1101	spin_unlock_irqrestore(&efc->lock, flags);1102}1103