brintos

brintos / linux-shallow public Read only

0
0
Text · 24.7 KiB · 84bc81d Raw
1095 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/*8 * Functions to build and send ELS/CT/BLS commands and responses.9 */10 11#include "efc.h"12#include "efc_els.h"13#include "../libefc_sli/sli4.h"14 15#define EFC_LOG_ENABLE_ELS_TRACE(efc)		\16		(((efc) != NULL) ? (((efc)->logmask & (1U << 1)) != 0) : 0)17 18#define node_els_trace()  \19	do { \20		if (EFC_LOG_ENABLE_ELS_TRACE(efc)) \21			efc_log_info(efc, "[%s] %-20s\n", \22				node->display_name, __func__); \23	} while (0)24 25#define els_io_printf(els, fmt, ...) \26	efc_log_err((struct efc *)els->node->efc,\27		      "[%s] %-8s " fmt, \28		      els->node->display_name,\29		      els->display_name, ##__VA_ARGS__)30 31#define EFC_ELS_RSP_LEN			102432#define EFC_ELS_GID_PT_RSP_LEN		809633 34struct efc_els_io_req *35efc_els_io_alloc(struct efc_node *node, u32 reqlen)36{37	return efc_els_io_alloc_size(node, reqlen, EFC_ELS_RSP_LEN);38}39 40struct efc_els_io_req *41efc_els_io_alloc_size(struct efc_node *node, u32 reqlen, u32 rsplen)42{43	struct efc *efc;44	struct efc_els_io_req *els;45	unsigned long flags = 0;46 47	efc = node->efc;48 49	if (!node->els_io_enabled) {50		efc_log_err(efc, "els io alloc disabled\n");51		return NULL;52	}53 54	els = mempool_alloc(efc->els_io_pool, GFP_ATOMIC);55	if (!els) {56		atomic_add_return(1, &efc->els_io_alloc_failed_count);57		return NULL;58	}59 60	/* initialize refcount */61	kref_init(&els->ref);62	els->release = _efc_els_io_free;63 64	/* populate generic io fields */65	els->node = node;66 67	/* now allocate DMA for request and response */68	els->io.req.size = reqlen;69	els->io.req.virt = dma_alloc_coherent(&efc->pci->dev, els->io.req.size,70					      &els->io.req.phys, GFP_KERNEL);71	if (!els->io.req.virt) {72		mempool_free(els, efc->els_io_pool);73		return NULL;74	}75 76	els->io.rsp.size = rsplen;77	els->io.rsp.virt = dma_alloc_coherent(&efc->pci->dev, els->io.rsp.size,78					      &els->io.rsp.phys, GFP_KERNEL);79	if (!els->io.rsp.virt) {80		dma_free_coherent(&efc->pci->dev, els->io.req.size,81				  els->io.req.virt, els->io.req.phys);82		mempool_free(els, efc->els_io_pool);83		els = NULL;84	}85 86	if (els) {87		/* initialize fields */88		els->els_retries_remaining = EFC_FC_ELS_DEFAULT_RETRIES;89 90		/* add els structure to ELS IO list */91		INIT_LIST_HEAD(&els->list_entry);92		spin_lock_irqsave(&node->els_ios_lock, flags);93		list_add_tail(&els->list_entry, &node->els_ios_list);94		spin_unlock_irqrestore(&node->els_ios_lock, flags);95	}96 97	return els;98}99 100void101efc_els_io_free(struct efc_els_io_req *els)102{103	kref_put(&els->ref, els->release);104}105 106void107_efc_els_io_free(struct kref *arg)108{109	struct efc_els_io_req *els =110				container_of(arg, struct efc_els_io_req, ref);111	struct efc *efc;112	struct efc_node *node;113	int send_empty_event = false;114	unsigned long flags = 0;115 116	node = els->node;117	efc = node->efc;118 119	spin_lock_irqsave(&node->els_ios_lock, flags);120 121	list_del(&els->list_entry);122	/* Send list empty event if the IO allocator123	 * is disabled, and the list is empty124	 * If node->els_io_enabled was not checked,125	 * the event would be posted continually126	 */127	send_empty_event = (!node->els_io_enabled &&128			   list_empty(&node->els_ios_list));129 130	spin_unlock_irqrestore(&node->els_ios_lock, flags);131 132	/* free ELS request and response buffers */133	dma_free_coherent(&efc->pci->dev, els->io.rsp.size,134			  els->io.rsp.virt, els->io.rsp.phys);135	dma_free_coherent(&efc->pci->dev, els->io.req.size,136			  els->io.req.virt, els->io.req.phys);137 138	mempool_free(els, efc->els_io_pool);139 140	if (send_empty_event)141		efc_scsi_io_list_empty(node->efc, node);142}143 144static void145efc_els_retry(struct efc_els_io_req *els);146 147static void148efc_els_delay_timer_cb(struct timer_list *t)149{150	struct efc_els_io_req *els = from_timer(els, t, delay_timer);151 152	/* Retry delay timer expired, retry the ELS request */153	efc_els_retry(els);154}155 156static int157efc_els_req_cb(void *arg, u32 length, int status, u32 ext_status)158{159	struct efc_els_io_req *els;160	struct efc_node *node;161	struct efc *efc;162	struct efc_node_cb cbdata;163	u32 reason_code;164 165	els = arg;166	node = els->node;167	efc = node->efc;168 169	if (status)170		els_io_printf(els, "status x%x ext x%x\n", status, ext_status);171 172	/* set the response len element of els->rsp */173	els->io.rsp.len = length;174 175	cbdata.status = status;176	cbdata.ext_status = ext_status;177	cbdata.header = NULL;178	cbdata.els_rsp = els->io.rsp;179 180	/* set the response len element of els->rsp */181	cbdata.rsp_len = length;182 183	/* FW returns the number of bytes received on the link in184	 * the WCQE, not the amount placed in the buffer; use this info to185	 * check if there was an overrun.186	 */187	if (length > els->io.rsp.size) {188		efc_log_warn(efc,189			     "ELS response returned len=%d > buflen=%zu\n",190			     length, els->io.rsp.size);191		efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_REQ_FAIL, &cbdata);192		return 0;193	}194 195	/* Post event to ELS IO object */196	switch (status) {197	case SLI4_FC_WCQE_STATUS_SUCCESS:198		efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_REQ_OK, &cbdata);199		break;200 201	case SLI4_FC_WCQE_STATUS_LS_RJT:202		reason_code = (ext_status >> 16) & 0xff;203 204		/* delay and retry if reason code is Logical Busy */205		switch (reason_code) {206		case ELS_RJT_BUSY:207			els->node->els_req_cnt--;208			els_io_printf(els,209				      "LS_RJT Logical Busy, delay and retry\n");210			timer_setup(&els->delay_timer,211				    efc_els_delay_timer_cb, 0);212			mod_timer(&els->delay_timer,213				  jiffies + msecs_to_jiffies(5000));214			break;215		default:216			efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_REQ_RJT,217					   &cbdata);218			break;219		}220		break;221 222	case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:223		switch (ext_status) {224		case SLI4_FC_LOCAL_REJECT_SEQUENCE_TIMEOUT:225			efc_els_retry(els);226			break;227		default:228			efc_log_err(efc, "LOCAL_REJECT with ext status:%x\n",229				    ext_status);230			efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_REQ_FAIL,231					   &cbdata);232			break;233		}234		break;235	default:	/* Other error */236		efc_log_warn(efc, "els req failed status x%x, ext_status x%x\n",237			     status, ext_status);238		efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_REQ_FAIL, &cbdata);239		break;240	}241 242	return 0;243}244 245void efc_disc_io_complete(struct efc_disc_io *io, u32 len, u32 status,246			  u32 ext_status)247{248	struct efc_els_io_req *els =249				container_of(io, struct efc_els_io_req, io);250 251	WARN_ON_ONCE(!els->cb);252 253	((efc_hw_srrs_cb_t)els->cb) (els, len, status, ext_status);254}255 256static int efc_els_send_req(struct efc_node *node, struct efc_els_io_req *els,257			    enum efc_disc_io_type io_type)258{259	int rc = 0;260	struct efc *efc = node->efc;261	struct efc_node_cb cbdata;262 263	/* update ELS request counter */264	els->node->els_req_cnt++;265 266	/* Prepare the IO request details */267	els->io.io_type = io_type;268	els->io.xmit_len = els->io.req.size;269	els->io.rsp_len = els->io.rsp.size;270	els->io.rpi = node->rnode.indicator;271	els->io.vpi = node->nport->indicator;272	els->io.s_id = node->nport->fc_id;273	els->io.d_id = node->rnode.fc_id;274 275	if (node->rnode.attached)276		els->io.rpi_registered = true;277 278	els->cb = efc_els_req_cb;279 280	rc = efc->tt.send_els(efc, &els->io);281	if (!rc)282		return rc;283 284	cbdata.status = EFC_STATUS_INVALID;285	cbdata.ext_status = EFC_STATUS_INVALID;286	cbdata.els_rsp = els->io.rsp;287	efc_log_err(efc, "efc_els_send failed: %d\n", rc);288	efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_REQ_FAIL, &cbdata);289 290	return rc;291}292 293static void294efc_els_retry(struct efc_els_io_req *els)295{296	struct efc *efc;297	struct efc_node_cb cbdata;298	u32 rc;299 300	efc = els->node->efc;301	cbdata.status = EFC_STATUS_INVALID;302	cbdata.ext_status = EFC_STATUS_INVALID;303	cbdata.els_rsp = els->io.rsp;304 305	if (els->els_retries_remaining) {306		els->els_retries_remaining--;307		rc = efc->tt.send_els(efc, &els->io);308	} else {309		rc = -EIO;310	}311 312	if (rc) {313		efc_log_err(efc, "ELS retries exhausted\n");314		efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_REQ_FAIL, &cbdata);315	}316}317 318static int319efc_els_acc_cb(void *arg, u32 length, int status, u32 ext_status)320{321	struct efc_els_io_req *els;322	struct efc_node *node;323	struct efc *efc;324	struct efc_node_cb cbdata;325 326	els = arg;327	node = els->node;328	efc = node->efc;329 330	cbdata.status = status;331	cbdata.ext_status = ext_status;332	cbdata.header = NULL;333	cbdata.els_rsp = els->io.rsp;334 335	/* Post node event */336	switch (status) {337	case SLI4_FC_WCQE_STATUS_SUCCESS:338		efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_CMPL_OK, &cbdata);339		break;340 341	default:	/* Other error */342		efc_log_warn(efc, "[%s] %-8s failed status x%x, ext x%x\n",343			     node->display_name, els->display_name,344			     status, ext_status);345		efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_CMPL_FAIL, &cbdata);346		break;347	}348 349	return 0;350}351 352static int353efc_els_send_rsp(struct efc_els_io_req *els, u32 rsplen)354{355	int rc = 0;356	struct efc_node_cb cbdata;357	struct efc_node *node = els->node;358	struct efc *efc = node->efc;359 360	/* increment ELS completion counter */361	node->els_cmpl_cnt++;362 363	els->io.io_type = EFC_DISC_IO_ELS_RESP;364	els->cb = efc_els_acc_cb;365 366	/* Prepare the IO request details */367	els->io.xmit_len = rsplen;368	els->io.rsp_len = els->io.rsp.size;369	els->io.rpi = node->rnode.indicator;370	els->io.vpi = node->nport->indicator;371	if (node->nport->fc_id != U32_MAX)372		els->io.s_id = node->nport->fc_id;373	else374		els->io.s_id = els->io.iparam.els.s_id;375	els->io.d_id = node->rnode.fc_id;376 377	if (node->attached)378		els->io.rpi_registered = true;379 380	rc = efc->tt.send_els(efc, &els->io);381	if (!rc)382		return rc;383 384	cbdata.status = EFC_STATUS_INVALID;385	cbdata.ext_status = EFC_STATUS_INVALID;386	cbdata.els_rsp = els->io.rsp;387	efc_els_io_cleanup(els, EFC_EVT_SRRS_ELS_CMPL_FAIL, &cbdata);388 389	return rc;390}391 392int393efc_send_plogi(struct efc_node *node)394{395	struct efc_els_io_req *els;396	struct efc *efc = node->efc;397	struct fc_els_flogi  *plogi;398 399	node_els_trace();400 401	els = efc_els_io_alloc(node, sizeof(*plogi));402	if (!els) {403		efc_log_err(efc, "IO alloc failed\n");404		return -EIO;405	}406	els->display_name = "plogi";407 408	/* Build PLOGI request */409	plogi = els->io.req.virt;410 411	memcpy(plogi, node->nport->service_params, sizeof(*plogi));412 413	plogi->fl_cmd = ELS_PLOGI;414	memset(plogi->_fl_resvd, 0, sizeof(plogi->_fl_resvd));415 416	return efc_els_send_req(node, els, EFC_DISC_IO_ELS_REQ);417}418 419int420efc_send_flogi(struct efc_node *node)421{422	struct efc_els_io_req *els;423	struct efc *efc;424	struct fc_els_flogi  *flogi;425 426	efc = node->efc;427 428	node_els_trace();429 430	els = efc_els_io_alloc(node, sizeof(*flogi));431	if (!els) {432		efc_log_err(efc, "IO alloc failed\n");433		return -EIO;434	}435 436	els->display_name = "flogi";437 438	/* Build FLOGI request */439	flogi = els->io.req.virt;440 441	memcpy(flogi, node->nport->service_params, sizeof(*flogi));442	flogi->fl_cmd = ELS_FLOGI;443	memset(flogi->_fl_resvd, 0, sizeof(flogi->_fl_resvd));444 445	return efc_els_send_req(node, els, EFC_DISC_IO_ELS_REQ);446}447 448int449efc_send_fdisc(struct efc_node *node)450{451	struct efc_els_io_req *els;452	struct efc *efc;453	struct fc_els_flogi *fdisc;454 455	efc = node->efc;456 457	node_els_trace();458 459	els = efc_els_io_alloc(node, sizeof(*fdisc));460	if (!els) {461		efc_log_err(efc, "IO alloc failed\n");462		return -EIO;463	}464 465	els->display_name = "fdisc";466 467	/* Build FDISC request */468	fdisc = els->io.req.virt;469 470	memcpy(fdisc, node->nport->service_params, sizeof(*fdisc));471	fdisc->fl_cmd = ELS_FDISC;472	memset(fdisc->_fl_resvd, 0, sizeof(fdisc->_fl_resvd));473 474	return efc_els_send_req(node, els, EFC_DISC_IO_ELS_REQ);475}476 477int478efc_send_prli(struct efc_node *node)479{480	struct efc *efc = node->efc;481	struct efc_els_io_req *els;482	struct {483		struct fc_els_prli prli;484		struct fc_els_spp spp;485	} *pp;486 487	node_els_trace();488 489	els = efc_els_io_alloc(node, sizeof(*pp));490	if (!els) {491		efc_log_err(efc, "IO alloc failed\n");492		return -EIO;493	}494 495	els->display_name = "prli";496 497	/* Build PRLI request */498	pp = els->io.req.virt;499 500	memset(pp, 0, sizeof(*pp));501 502	pp->prli.prli_cmd = ELS_PRLI;503	pp->prli.prli_spp_len = 16;504	pp->prli.prli_len = cpu_to_be16(sizeof(*pp));505	pp->spp.spp_type = FC_TYPE_FCP;506	pp->spp.spp_type_ext = 0;507	pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR;508	pp->spp.spp_params = cpu_to_be32(FCP_SPPF_RD_XRDY_DIS |509			       (node->nport->enable_ini ?510			       FCP_SPPF_INIT_FCN : 0) |511			       (node->nport->enable_tgt ?512			       FCP_SPPF_TARG_FCN : 0));513 514	return efc_els_send_req(node, els, EFC_DISC_IO_ELS_REQ);515}516 517int518efc_send_logo(struct efc_node *node)519{520	struct efc *efc = node->efc;521	struct efc_els_io_req *els;522	struct fc_els_logo *logo;523	struct fc_els_flogi  *sparams;524 525	node_els_trace();526 527	sparams = (struct fc_els_flogi *)node->nport->service_params;528 529	els = efc_els_io_alloc(node, sizeof(*logo));530	if (!els) {531		efc_log_err(efc, "IO alloc failed\n");532		return -EIO;533	}534 535	els->display_name = "logo";536 537	/* Build LOGO request */538 539	logo = els->io.req.virt;540 541	memset(logo, 0, sizeof(*logo));542	logo->fl_cmd = ELS_LOGO;543	hton24(logo->fl_n_port_id, node->rnode.nport->fc_id);544	logo->fl_n_port_wwn = sparams->fl_wwpn;545 546	return efc_els_send_req(node, els, EFC_DISC_IO_ELS_REQ);547}548 549int550efc_send_adisc(struct efc_node *node)551{552	struct efc *efc = node->efc;553	struct efc_els_io_req *els;554	struct fc_els_adisc *adisc;555	struct fc_els_flogi  *sparams;556	struct efc_nport *nport = node->nport;557 558	node_els_trace();559 560	sparams = (struct fc_els_flogi *)node->nport->service_params;561 562	els = efc_els_io_alloc(node, sizeof(*adisc));563	if (!els) {564		efc_log_err(efc, "IO alloc failed\n");565		return -EIO;566	}567 568	els->display_name = "adisc";569 570	/* Build ADISC request */571 572	adisc = els->io.req.virt;573 574	memset(adisc, 0, sizeof(*adisc));575	adisc->adisc_cmd = ELS_ADISC;576	hton24(adisc->adisc_hard_addr, nport->fc_id);577	adisc->adisc_wwpn = sparams->fl_wwpn;578	adisc->adisc_wwnn = sparams->fl_wwnn;579	hton24(adisc->adisc_port_id, node->rnode.nport->fc_id);580 581	return efc_els_send_req(node, els, EFC_DISC_IO_ELS_REQ);582}583 584int585efc_send_scr(struct efc_node *node)586{587	struct efc_els_io_req *els;588	struct efc *efc = node->efc;589	struct fc_els_scr *req;590 591	node_els_trace();592 593	els = efc_els_io_alloc(node, sizeof(*req));594	if (!els) {595		efc_log_err(efc, "IO alloc failed\n");596		return -EIO;597	}598 599	els->display_name = "scr";600 601	req = els->io.req.virt;602 603	memset(req, 0, sizeof(*req));604	req->scr_cmd = ELS_SCR;605	req->scr_reg_func = ELS_SCRF_FULL;606 607	return efc_els_send_req(node, els, EFC_DISC_IO_ELS_REQ);608}609 610int611efc_send_ls_rjt(struct efc_node *node, u32 ox_id, u32 reason_code,612		u32 reason_code_expl, u32 vendor_unique)613{614	struct efc *efc = node->efc;615	struct efc_els_io_req *els = NULL;616	struct fc_els_ls_rjt *rjt;617 618	els = efc_els_io_alloc(node, sizeof(*rjt));619	if (!els) {620		efc_log_err(efc, "els IO alloc failed\n");621		return -EIO;622	}623 624	node_els_trace();625 626	els->display_name = "ls_rjt";627 628	memset(&els->io.iparam, 0, sizeof(els->io.iparam));629	els->io.iparam.els.ox_id = ox_id;630 631	rjt = els->io.req.virt;632	memset(rjt, 0, sizeof(*rjt));633 634	rjt->er_cmd = ELS_LS_RJT;635	rjt->er_reason = reason_code;636	rjt->er_explan = reason_code_expl;637 638	return efc_els_send_rsp(els, sizeof(*rjt));639}640 641int642efc_send_plogi_acc(struct efc_node *node, u32 ox_id)643{644	struct efc *efc = node->efc;645	struct efc_els_io_req *els = NULL;646	struct fc_els_flogi  *plogi;647	struct fc_els_flogi  *req = (struct fc_els_flogi *)node->service_params;648 649	node_els_trace();650 651	els = efc_els_io_alloc(node, sizeof(*plogi));652	if (!els) {653		efc_log_err(efc, "els IO alloc failed\n");654		return -EIO;655	}656 657	els->display_name = "plogi_acc";658 659	memset(&els->io.iparam, 0, sizeof(els->io.iparam));660	els->io.iparam.els.ox_id = ox_id;661 662	plogi = els->io.req.virt;663 664	/* copy our port's service parameters to payload */665	memcpy(plogi, node->nport->service_params, sizeof(*plogi));666	plogi->fl_cmd = ELS_LS_ACC;667	memset(plogi->_fl_resvd, 0, sizeof(plogi->_fl_resvd));668 669	/* Set Application header support bit if requested */670	if (req->fl_csp.sp_features & cpu_to_be16(FC_SP_FT_BCAST))671		plogi->fl_csp.sp_features |= cpu_to_be16(FC_SP_FT_BCAST);672 673	return efc_els_send_rsp(els, sizeof(*plogi));674}675 676int677efc_send_flogi_p2p_acc(struct efc_node *node, u32 ox_id, u32 s_id)678{679	struct efc *efc = node->efc;680	struct efc_els_io_req *els = NULL;681	struct fc_els_flogi  *flogi;682 683	node_els_trace();684 685	els = efc_els_io_alloc(node, sizeof(*flogi));686	if (!els) {687		efc_log_err(efc, "els IO alloc failed\n");688		return -EIO;689	}690 691	els->display_name = "flogi_p2p_acc";692 693	memset(&els->io.iparam, 0, sizeof(els->io.iparam));694	els->io.iparam.els.ox_id = ox_id;695	els->io.iparam.els.s_id = s_id;696 697	flogi = els->io.req.virt;698 699	/* copy our port's service parameters to payload */700	memcpy(flogi, node->nport->service_params, sizeof(*flogi));701	flogi->fl_cmd = ELS_LS_ACC;702	memset(flogi->_fl_resvd, 0, sizeof(flogi->_fl_resvd));703 704	memset(flogi->fl_cssp, 0, sizeof(flogi->fl_cssp));705 706	return efc_els_send_rsp(els, sizeof(*flogi));707}708 709int710efc_send_prli_acc(struct efc_node *node, u32 ox_id)711{712	struct efc *efc = node->efc;713	struct efc_els_io_req *els = NULL;714	struct {715		struct fc_els_prli prli;716		struct fc_els_spp spp;717	} *pp;718 719	node_els_trace();720 721	els = efc_els_io_alloc(node, sizeof(*pp));722	if (!els) {723		efc_log_err(efc, "els IO alloc failed\n");724		return -EIO;725	}726 727	els->display_name = "prli_acc";728 729	memset(&els->io.iparam, 0, sizeof(els->io.iparam));730	els->io.iparam.els.ox_id = ox_id;731 732	pp = els->io.req.virt;733	memset(pp, 0, sizeof(*pp));734 735	pp->prli.prli_cmd = ELS_LS_ACC;736	pp->prli.prli_spp_len = 0x10;737	pp->prli.prli_len = cpu_to_be16(sizeof(*pp));738	pp->spp.spp_type = FC_TYPE_FCP;739	pp->spp.spp_type_ext = 0;740	pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR | FC_SPP_RESP_ACK;741 742	pp->spp.spp_params = cpu_to_be32(FCP_SPPF_RD_XRDY_DIS |743					(node->nport->enable_ini ?744					 FCP_SPPF_INIT_FCN : 0) |745					(node->nport->enable_tgt ?746					 FCP_SPPF_TARG_FCN : 0));747 748	return efc_els_send_rsp(els, sizeof(*pp));749}750 751int752efc_send_prlo_acc(struct efc_node *node, u32 ox_id)753{754	struct efc *efc = node->efc;755	struct efc_els_io_req *els = NULL;756	struct {757		struct fc_els_prlo prlo;758		struct fc_els_spp spp;759	} *pp;760 761	node_els_trace();762 763	els = efc_els_io_alloc(node, sizeof(*pp));764	if (!els) {765		efc_log_err(efc, "els IO alloc failed\n");766		return -EIO;767	}768 769	els->display_name = "prlo_acc";770 771	memset(&els->io.iparam, 0, sizeof(els->io.iparam));772	els->io.iparam.els.ox_id = ox_id;773 774	pp = els->io.req.virt;775	memset(pp, 0, sizeof(*pp));776	pp->prlo.prlo_cmd = ELS_LS_ACC;777	pp->prlo.prlo_obs = 0x10;778	pp->prlo.prlo_len = cpu_to_be16(sizeof(*pp));779 780	pp->spp.spp_type = FC_TYPE_FCP;781	pp->spp.spp_type_ext = 0;782	pp->spp.spp_flags = FC_SPP_RESP_ACK;783 784	return efc_els_send_rsp(els, sizeof(*pp));785}786 787int788efc_send_ls_acc(struct efc_node *node, u32 ox_id)789{790	struct efc *efc = node->efc;791	struct efc_els_io_req *els = NULL;792	struct fc_els_ls_acc *acc;793 794	node_els_trace();795 796	els = efc_els_io_alloc(node, sizeof(*acc));797	if (!els) {798		efc_log_err(efc, "els IO alloc failed\n");799		return -EIO;800	}801 802	els->display_name = "ls_acc";803 804	memset(&els->io.iparam, 0, sizeof(els->io.iparam));805	els->io.iparam.els.ox_id = ox_id;806 807	acc = els->io.req.virt;808	memset(acc, 0, sizeof(*acc));809 810	acc->la_cmd = ELS_LS_ACC;811 812	return efc_els_send_rsp(els, sizeof(*acc));813}814 815int816efc_send_logo_acc(struct efc_node *node, u32 ox_id)817{818	struct efc_els_io_req *els = NULL;819	struct efc *efc = node->efc;820	struct fc_els_ls_acc *logo;821 822	node_els_trace();823 824	els = efc_els_io_alloc(node, sizeof(*logo));825	if (!els) {826		efc_log_err(efc, "els IO alloc failed\n");827		return -EIO;828	}829 830	els->display_name = "logo_acc";831 832	memset(&els->io.iparam, 0, sizeof(els->io.iparam));833	els->io.iparam.els.ox_id = ox_id;834 835	logo = els->io.req.virt;836	memset(logo, 0, sizeof(*logo));837 838	logo->la_cmd = ELS_LS_ACC;839 840	return efc_els_send_rsp(els, sizeof(*logo));841}842 843int844efc_send_adisc_acc(struct efc_node *node, u32 ox_id)845{846	struct efc *efc = node->efc;847	struct efc_els_io_req *els = NULL;848	struct fc_els_adisc *adisc;849	struct fc_els_flogi  *sparams;850 851	node_els_trace();852 853	els = efc_els_io_alloc(node, sizeof(*adisc));854	if (!els) {855		efc_log_err(efc, "els IO alloc failed\n");856		return -EIO;857	}858 859	els->display_name = "adisc_acc";860 861	/* Go ahead and send the ELS_ACC */862	memset(&els->io.iparam, 0, sizeof(els->io.iparam));863	els->io.iparam.els.ox_id = ox_id;864 865	sparams = (struct fc_els_flogi  *)node->nport->service_params;866	adisc = els->io.req.virt;867	memset(adisc, 0, sizeof(*adisc));868	adisc->adisc_cmd = ELS_LS_ACC;869	adisc->adisc_wwpn = sparams->fl_wwpn;870	adisc->adisc_wwnn = sparams->fl_wwnn;871	hton24(adisc->adisc_port_id, node->rnode.nport->fc_id);872 873	return efc_els_send_rsp(els, sizeof(*adisc));874}875 876static inline void877fcct_build_req_header(struct fc_ct_hdr  *hdr, u16 cmd, u16 max_size)878{879	hdr->ct_rev = FC_CT_REV;880	hdr->ct_fs_type = FC_FST_DIR;881	hdr->ct_fs_subtype = FC_NS_SUBTYPE;882	hdr->ct_options = 0;883	hdr->ct_cmd = cpu_to_be16(cmd);884	/* words */885	hdr->ct_mr_size = cpu_to_be16(max_size / (sizeof(u32)));886	hdr->ct_reason = 0;887	hdr->ct_explan = 0;888	hdr->ct_vendor = 0;889}890 891int892efc_ns_send_rftid(struct efc_node *node)893{894	struct efc *efc = node->efc;895	struct efc_els_io_req *els;896	struct {897		struct fc_ct_hdr hdr;898		struct fc_ns_rft_id rftid;899	} *ct;900 901	node_els_trace();902 903	els = efc_els_io_alloc(node, sizeof(*ct));904	if (!els) {905		efc_log_err(efc, "IO alloc failed\n");906		return -EIO;907	}908 909	els->io.iparam.ct.r_ctl = FC_RCTL_ELS_REQ;910	els->io.iparam.ct.type = FC_TYPE_CT;911	els->io.iparam.ct.df_ctl = 0;912	els->io.iparam.ct.timeout = EFC_FC_ELS_SEND_DEFAULT_TIMEOUT;913 914	els->display_name = "rftid";915 916	ct = els->io.req.virt;917	memset(ct, 0, sizeof(*ct));918	fcct_build_req_header(&ct->hdr, FC_NS_RFT_ID,919			      sizeof(struct fc_ns_rft_id));920 921	hton24(ct->rftid.fr_fid.fp_fid, node->rnode.nport->fc_id);922	ct->rftid.fr_fts.ff_type_map[FC_TYPE_FCP / FC_NS_BPW] =923		cpu_to_be32(1 << (FC_TYPE_FCP % FC_NS_BPW));924 925	return efc_els_send_req(node, els, EFC_DISC_IO_CT_REQ);926}927 928int929efc_ns_send_rffid(struct efc_node *node)930{931	struct efc *efc = node->efc;932	struct efc_els_io_req *els;933	struct {934		struct fc_ct_hdr hdr;935		struct fc_ns_rff_id rffid;936	} *ct;937 938	node_els_trace();939 940	els = efc_els_io_alloc(node, sizeof(*ct));941	if (!els) {942		efc_log_err(efc, "IO alloc failed\n");943		return -EIO;944	}945 946	els->io.iparam.ct.r_ctl = FC_RCTL_ELS_REQ;947	els->io.iparam.ct.type = FC_TYPE_CT;948	els->io.iparam.ct.df_ctl = 0;949	els->io.iparam.ct.timeout = EFC_FC_ELS_SEND_DEFAULT_TIMEOUT;950 951	els->display_name = "rffid";952	ct = els->io.req.virt;953 954	memset(ct, 0, sizeof(*ct));955	fcct_build_req_header(&ct->hdr, FC_NS_RFF_ID,956			      sizeof(struct fc_ns_rff_id));957 958	hton24(ct->rffid.fr_fid.fp_fid, node->rnode.nport->fc_id);959	if (node->nport->enable_ini)960		ct->rffid.fr_feat |= FCP_FEAT_INIT;961	if (node->nport->enable_tgt)962		ct->rffid.fr_feat |= FCP_FEAT_TARG;963	ct->rffid.fr_type = FC_TYPE_FCP;964 965	return efc_els_send_req(node, els, EFC_DISC_IO_CT_REQ);966}967 968int969efc_ns_send_gidpt(struct efc_node *node)970{971	struct efc_els_io_req *els = NULL;972	struct efc *efc = node->efc;973	struct {974		struct fc_ct_hdr hdr;975		struct fc_ns_gid_pt gidpt;976	} *ct;977 978	node_els_trace();979 980	els = efc_els_io_alloc_size(node, sizeof(*ct), EFC_ELS_GID_PT_RSP_LEN);981	if (!els) {982		efc_log_err(efc, "IO alloc failed\n");983		return -EIO;984	}985 986	els->io.iparam.ct.r_ctl = FC_RCTL_ELS_REQ;987	els->io.iparam.ct.type = FC_TYPE_CT;988	els->io.iparam.ct.df_ctl = 0;989	els->io.iparam.ct.timeout = EFC_FC_ELS_SEND_DEFAULT_TIMEOUT;990 991	els->display_name = "gidpt";992 993	ct = els->io.req.virt;994 995	memset(ct, 0, sizeof(*ct));996	fcct_build_req_header(&ct->hdr, FC_NS_GID_PT,997			      sizeof(struct fc_ns_gid_pt));998 999	ct->gidpt.fn_pt_type = FC_TYPE_FCP;1000 1001	return efc_els_send_req(node, els, EFC_DISC_IO_CT_REQ);1002}1003 1004void1005efc_els_io_cleanup(struct efc_els_io_req *els, int evt, void *arg)1006{1007	/* don't want further events that could come; e.g. abort requests1008	 * from the node state machine; thus, disable state machine1009	 */1010	els->els_req_free = true;1011	efc_node_post_els_resp(els->node, evt, arg);1012 1013	efc_els_io_free(els);1014}1015 1016static int1017efc_ct_acc_cb(void *arg, u32 length, int status, u32 ext_status)1018{1019	struct efc_els_io_req *els = arg;1020 1021	efc_els_io_free(els);1022 1023	return 0;1024}1025 1026int1027efc_send_ct_rsp(struct efc *efc, struct efc_node *node, u16 ox_id,1028		struct fc_ct_hdr *ct_hdr, u32 cmd_rsp_code,1029		u32 reason_code, u32 reason_code_explanation)1030{1031	struct efc_els_io_req *els = NULL;1032	struct fc_ct_hdr  *rsp = NULL;1033 1034	els = efc_els_io_alloc(node, 256);1035	if (!els) {1036		efc_log_err(efc, "IO alloc failed\n");1037		return -EIO;1038	}1039 1040	rsp = els->io.rsp.virt;1041 1042	*rsp = *ct_hdr;1043 1044	fcct_build_req_header(rsp, cmd_rsp_code, 0);1045	rsp->ct_reason = reason_code;1046	rsp->ct_explan = reason_code_explanation;1047 1048	els->display_name = "ct_rsp";1049	els->cb = efc_ct_acc_cb;1050 1051	/* Prepare the IO request details */1052	els->io.io_type = EFC_DISC_IO_CT_RESP;1053	els->io.xmit_len = sizeof(*rsp);1054 1055	els->io.rpi = node->rnode.indicator;1056	els->io.d_id = node->rnode.fc_id;1057 1058	memset(&els->io.iparam, 0, sizeof(els->io.iparam));1059 1060	els->io.iparam.ct.ox_id = ox_id;1061	els->io.iparam.ct.r_ctl = 3;1062	els->io.iparam.ct.type = FC_TYPE_CT;1063	els->io.iparam.ct.df_ctl = 0;1064	els->io.iparam.ct.timeout = 5;1065 1066	if (efc->tt.send_els(efc, &els->io)) {1067		efc_els_io_free(els);1068		return -EIO;1069	}1070	return 0;1071}1072 1073int1074efc_send_bls_acc(struct efc_node *node, struct fc_frame_header *hdr)1075{1076	struct sli_bls_params bls;1077	struct fc_ba_acc *acc;1078	struct efc *efc = node->efc;1079 1080	memset(&bls, 0, sizeof(bls));1081	bls.ox_id = be16_to_cpu(hdr->fh_ox_id);1082	bls.rx_id = be16_to_cpu(hdr->fh_rx_id);1083	bls.s_id = ntoh24(hdr->fh_d_id);1084	bls.d_id = node->rnode.fc_id;1085	bls.rpi = node->rnode.indicator;1086	bls.vpi = node->nport->indicator;1087 1088	acc = (void *)bls.payload;1089	acc->ba_ox_id = cpu_to_be16(bls.ox_id);1090	acc->ba_rx_id = cpu_to_be16(bls.rx_id);1091	acc->ba_high_seq_cnt = cpu_to_be16(U16_MAX);1092 1093	return efc->tt.send_bls(efc, FC_RCTL_BA_ACC, &bls);1094}1095