brintos

brintos / linux-shallow public Read only

0
0
Text · 60.1 KiB · c25979d Raw
2294 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.4 *5 * Maintained at www.Open-FCoE.org6 */7 8/*9 * RPORT GENERAL INFO10 *11 * This file contains all processing regarding fc_rports. It contains the12 * rport state machine and does all rport interaction with the transport class.13 * There should be no other places in libfc that interact directly with the14 * transport class in regards to adding and deleting rports.15 *16 * fc_rport's represent N_Port's within the fabric.17 */18 19/*20 * RPORT LOCKING21 *22 * The rport should never hold the rport mutex and then attempt to acquire23 * either the lport or disc mutexes. The rport's mutex is considered lesser24 * than both the lport's mutex and the disc mutex. Refer to fc_lport.c for25 * more comments on the hierarchy.26 *27 * The locking strategy is similar to the lport's strategy. The lock protects28 * the rport's states and is held and released by the entry points to the rport29 * block. All _enter_* functions correspond to rport states and expect the rport30 * mutex to be locked before calling them. This means that rports only handle31 * one request or response at a time, since they're not critical for the I/O32 * path this potential over-use of the mutex is acceptable.33 */34 35/*36 * RPORT REFERENCE COUNTING37 *38 * A rport reference should be taken when:39 * - an rport is allocated40 * - a workqueue item is scheduled41 * - an ELS request is send42 * The reference should be dropped when:43 * - the workqueue function has finished44 * - the ELS response is handled45 * - an rport is removed46 */47 48#include <linux/kernel.h>49#include <linux/spinlock.h>50#include <linux/interrupt.h>51#include <linux/slab.h>52#include <linux/rcupdate.h>53#include <linux/timer.h>54#include <linux/workqueue.h>55#include <linux/export.h>56#include <linux/rculist.h>57 58#include <linux/unaligned.h>59 60#include <scsi/libfc.h>61 62#include "fc_encode.h"63#include "fc_libfc.h"64 65static struct workqueue_struct *rport_event_queue;66 67static void fc_rport_enter_flogi(struct fc_rport_priv *);68static void fc_rport_enter_plogi(struct fc_rport_priv *);69static void fc_rport_enter_prli(struct fc_rport_priv *);70static void fc_rport_enter_rtv(struct fc_rport_priv *);71static void fc_rport_enter_ready(struct fc_rport_priv *);72static void fc_rport_enter_logo(struct fc_rport_priv *);73static void fc_rport_enter_adisc(struct fc_rport_priv *);74 75static void fc_rport_recv_plogi_req(struct fc_lport *, struct fc_frame *);76static void fc_rport_recv_prli_req(struct fc_rport_priv *, struct fc_frame *);77static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *);78static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *);79static void fc_rport_timeout(struct work_struct *);80static void fc_rport_error(struct fc_rport_priv *, int);81static void fc_rport_error_retry(struct fc_rport_priv *, int);82static void fc_rport_work(struct work_struct *);83 84static const char *fc_rport_state_names[] = {85	[RPORT_ST_INIT] = "Init",86	[RPORT_ST_FLOGI] = "FLOGI",87	[RPORT_ST_PLOGI_WAIT] = "PLOGI_WAIT",88	[RPORT_ST_PLOGI] = "PLOGI",89	[RPORT_ST_PRLI] = "PRLI",90	[RPORT_ST_RTV] = "RTV",91	[RPORT_ST_READY] = "Ready",92	[RPORT_ST_ADISC] = "ADISC",93	[RPORT_ST_DELETE] = "Delete",94};95 96/**97 * fc_rport_lookup() - Lookup a remote port by port_id98 * @lport:   The local port to lookup the remote port on99 * @port_id: The remote port ID to look up100 *101 * The reference count of the fc_rport_priv structure is102 * increased by one.103 */104struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport,105				      u32 port_id)106{107	struct fc_rport_priv *rdata = NULL, *tmp_rdata;108 109	rcu_read_lock();110	list_for_each_entry_rcu(tmp_rdata, &lport->disc.rports, peers)111		if (tmp_rdata->ids.port_id == port_id &&112		    kref_get_unless_zero(&tmp_rdata->kref)) {113			rdata = tmp_rdata;114			break;115		}116	rcu_read_unlock();117	return rdata;118}119EXPORT_SYMBOL(fc_rport_lookup);120 121/**122 * fc_rport_create() - Create a new remote port123 * @lport: The local port this remote port will be associated with124 * @port_id:   The identifiers for the new remote port125 *126 * The remote port will start in the INIT state.127 */128struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id)129{130	struct fc_rport_priv *rdata;131	size_t rport_priv_size = sizeof(*rdata);132 133	lockdep_assert_held(&lport->disc.disc_mutex);134 135	rdata = fc_rport_lookup(lport, port_id);136	if (rdata) {137		kref_put(&rdata->kref, fc_rport_destroy);138		return rdata;139	}140 141	if (lport->rport_priv_size > 0)142		rport_priv_size = lport->rport_priv_size;143	rdata = kzalloc(rport_priv_size, GFP_KERNEL);144	if (!rdata)145		return NULL;146 147	rdata->ids.node_name = -1;148	rdata->ids.port_name = -1;149	rdata->ids.port_id = port_id;150	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;151 152	kref_init(&rdata->kref);153	mutex_init(&rdata->rp_mutex);154	rdata->local_port = lport;155	rdata->rp_state = RPORT_ST_INIT;156	rdata->event = RPORT_EV_NONE;157	rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;158	rdata->e_d_tov = lport->e_d_tov;159	rdata->r_a_tov = lport->r_a_tov;160	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;161	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);162	INIT_WORK(&rdata->event_work, fc_rport_work);163	if (port_id != FC_FID_DIR_SERV) {164		rdata->lld_event_callback = lport->tt.rport_event_callback;165		list_add_rcu(&rdata->peers, &lport->disc.rports);166	}167	return rdata;168}169EXPORT_SYMBOL(fc_rport_create);170 171/**172 * fc_rport_destroy() - Free a remote port after last reference is released173 * @kref: The remote port's kref174 */175void fc_rport_destroy(struct kref *kref)176{177	struct fc_rport_priv *rdata;178 179	rdata = container_of(kref, struct fc_rport_priv, kref);180	kfree_rcu(rdata, rcu);181}182EXPORT_SYMBOL(fc_rport_destroy);183 184/**185 * fc_rport_state() - Return a string identifying the remote port's state186 * @rdata: The remote port187 */188static const char *fc_rport_state(struct fc_rport_priv *rdata)189{190	const char *cp;191 192	cp = fc_rport_state_names[rdata->rp_state];193	if (!cp)194		cp = "Unknown";195	return cp;196}197 198/**199 * fc_set_rport_loss_tmo() - Set the remote port loss timeout200 * @rport:   The remote port that gets a new timeout value201 * @timeout: The new timeout value (in seconds)202 */203void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)204{205	if (timeout)206		rport->dev_loss_tmo = timeout;207	else208		rport->dev_loss_tmo = 1;209}210EXPORT_SYMBOL(fc_set_rport_loss_tmo);211 212/**213 * fc_plogi_get_maxframe() - Get the maximum payload from the common service214 *			     parameters in a FLOGI frame215 * @flp:    The FLOGI or PLOGI payload216 * @maxval: The maximum frame size upper limit; this may be less than what217 *	    is in the service parameters218 */219static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp,220					  unsigned int maxval)221{222	unsigned int mfs;223 224	/*225	 * Get max payload from the common service parameters and the226	 * class 3 receive data field size.227	 */228	mfs = ntohs(flp->fl_csp.sp_bb_data) & FC_SP_BB_DATA_MASK;229	if (mfs >= FC_SP_MIN_MAX_PAYLOAD && mfs < maxval)230		maxval = mfs;231	mfs = ntohs(flp->fl_cssp[3 - 1].cp_rdfs);232	if (mfs >= FC_SP_MIN_MAX_PAYLOAD && mfs < maxval)233		maxval = mfs;234	return maxval;235}236 237/**238 * fc_rport_state_enter() - Change the state of a remote port239 * @rdata: The remote port whose state should change240 * @new:   The new state241 */242static void fc_rport_state_enter(struct fc_rport_priv *rdata,243				 enum fc_rport_state new)244{245	lockdep_assert_held(&rdata->rp_mutex);246 247	if (rdata->rp_state != new)248		rdata->retries = 0;249	rdata->rp_state = new;250}251 252/**253 * fc_rport_work() - Handler for remote port events in the rport_event_queue254 * @work: Handle to the remote port being dequeued255 *256 * Reference counting: drops kref on return257 */258static void fc_rport_work(struct work_struct *work)259{260	u32 port_id;261	struct fc_rport_priv *rdata =262		container_of(work, struct fc_rport_priv, event_work);263	struct fc_rport_libfc_priv *rpriv;264	enum fc_rport_event event;265	struct fc_lport *lport = rdata->local_port;266	struct fc_rport_operations *rport_ops;267	struct fc_rport_identifiers ids;268	struct fc_rport *rport;269	struct fc4_prov *prov;270	u8 type;271 272	mutex_lock(&rdata->rp_mutex);273	event = rdata->event;274	rport_ops = rdata->ops;275	rport = rdata->rport;276 277	FC_RPORT_DBG(rdata, "work event %u\n", event);278 279	switch (event) {280	case RPORT_EV_READY:281		ids = rdata->ids;282		rdata->event = RPORT_EV_NONE;283		rdata->major_retries = 0;284		kref_get(&rdata->kref);285		mutex_unlock(&rdata->rp_mutex);286 287		if (!rport) {288			FC_RPORT_DBG(rdata, "No rport!\n");289			rport = fc_remote_port_add(lport->host, 0, &ids);290		}291		if (!rport) {292			FC_RPORT_DBG(rdata, "Failed to add the rport\n");293			fc_rport_logoff(rdata);294			kref_put(&rdata->kref, fc_rport_destroy);295			return;296		}297		mutex_lock(&rdata->rp_mutex);298		if (rdata->rport)299			FC_RPORT_DBG(rdata, "rport already allocated\n");300		rdata->rport = rport;301		rport->maxframe_size = rdata->maxframe_size;302		rport->supported_classes = rdata->supported_classes;303 304		rpriv = rport->dd_data;305		rpriv->local_port = lport;306		rpriv->rp_state = rdata->rp_state;307		rpriv->flags = rdata->flags;308		rpriv->e_d_tov = rdata->e_d_tov;309		rpriv->r_a_tov = rdata->r_a_tov;310		mutex_unlock(&rdata->rp_mutex);311 312		if (rport_ops && rport_ops->event_callback) {313			FC_RPORT_DBG(rdata, "callback ev %d\n", event);314			rport_ops->event_callback(lport, rdata, event);315		}316		if (rdata->lld_event_callback) {317			FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);318			rdata->lld_event_callback(lport, rdata, event);319		}320		kref_put(&rdata->kref, fc_rport_destroy);321		break;322 323	case RPORT_EV_FAILED:324	case RPORT_EV_LOGO:325	case RPORT_EV_STOP:326		if (rdata->prli_count) {327			mutex_lock(&fc_prov_mutex);328			for (type = 1; type < FC_FC4_PROV_SIZE; type++) {329				prov = fc_passive_prov[type];330				if (prov && prov->prlo)331					prov->prlo(rdata);332			}333			mutex_unlock(&fc_prov_mutex);334		}335		port_id = rdata->ids.port_id;336		mutex_unlock(&rdata->rp_mutex);337 338		if (rport_ops && rport_ops->event_callback) {339			FC_RPORT_DBG(rdata, "callback ev %d\n", event);340			rport_ops->event_callback(lport, rdata, event);341		}342		if (rdata->lld_event_callback) {343			FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);344			rdata->lld_event_callback(lport, rdata, event);345		}346		if (cancel_delayed_work_sync(&rdata->retry_work))347			kref_put(&rdata->kref, fc_rport_destroy);348 349		/*350		 * Reset any outstanding exchanges before freeing rport.351		 */352		lport->tt.exch_mgr_reset(lport, 0, port_id);353		lport->tt.exch_mgr_reset(lport, port_id, 0);354 355		if (rport) {356			rpriv = rport->dd_data;357			rpriv->rp_state = RPORT_ST_DELETE;358			mutex_lock(&rdata->rp_mutex);359			rdata->rport = NULL;360			mutex_unlock(&rdata->rp_mutex);361			fc_remote_port_delete(rport);362		}363 364		mutex_lock(&rdata->rp_mutex);365		if (rdata->rp_state == RPORT_ST_DELETE) {366			if (port_id == FC_FID_DIR_SERV) {367				rdata->event = RPORT_EV_NONE;368				mutex_unlock(&rdata->rp_mutex);369				kref_put(&rdata->kref, fc_rport_destroy);370			} else if ((rdata->flags & FC_RP_STARTED) &&371				   rdata->major_retries <372				   lport->max_rport_retry_count) {373				rdata->major_retries++;374				rdata->event = RPORT_EV_NONE;375				FC_RPORT_DBG(rdata, "work restart\n");376				fc_rport_enter_flogi(rdata);377				mutex_unlock(&rdata->rp_mutex);378			} else {379				mutex_unlock(&rdata->rp_mutex);380				FC_RPORT_DBG(rdata, "work delete\n");381				mutex_lock(&lport->disc.disc_mutex);382				list_del_rcu(&rdata->peers);383				mutex_unlock(&lport->disc.disc_mutex);384				kref_put(&rdata->kref, fc_rport_destroy);385			}386		} else {387			/*388			 * Re-open for events.  Reissue READY event if ready.389			 */390			rdata->event = RPORT_EV_NONE;391			if (rdata->rp_state == RPORT_ST_READY) {392				FC_RPORT_DBG(rdata, "work reopen\n");393				fc_rport_enter_ready(rdata);394			}395			mutex_unlock(&rdata->rp_mutex);396		}397		break;398 399	default:400		mutex_unlock(&rdata->rp_mutex);401		break;402	}403	kref_put(&rdata->kref, fc_rport_destroy);404}405 406/**407 * fc_rport_login() - Start the remote port login state machine408 * @rdata: The remote port to be logged in to409 *410 * Initiates the RP state machine. It is called from the LP module.411 * This function will issue the following commands to the N_Port412 * identified by the FC ID provided.413 *414 * - PLOGI415 * - PRLI416 * - RTV417 *418 * Locking Note: Called without the rport lock held. This419 * function will hold the rport lock, call an _enter_*420 * function and then unlock the rport.421 *422 * This indicates the intent to be logged into the remote port.423 * If it appears we are already logged in, ADISC is used to verify424 * the setup.425 */426int fc_rport_login(struct fc_rport_priv *rdata)427{428	mutex_lock(&rdata->rp_mutex);429 430	if (rdata->flags & FC_RP_STARTED) {431		FC_RPORT_DBG(rdata, "port already started\n");432		mutex_unlock(&rdata->rp_mutex);433		return 0;434	}435 436	rdata->flags |= FC_RP_STARTED;437	switch (rdata->rp_state) {438	case RPORT_ST_READY:439		FC_RPORT_DBG(rdata, "ADISC port\n");440		fc_rport_enter_adisc(rdata);441		break;442	case RPORT_ST_DELETE:443		FC_RPORT_DBG(rdata, "Restart deleted port\n");444		break;445	case RPORT_ST_INIT:446		FC_RPORT_DBG(rdata, "Login to port\n");447		fc_rport_enter_flogi(rdata);448		break;449	default:450		FC_RPORT_DBG(rdata, "Login in progress, state %s\n",451			     fc_rport_state(rdata));452		break;453	}454	mutex_unlock(&rdata->rp_mutex);455 456	return 0;457}458EXPORT_SYMBOL(fc_rport_login);459 460/**461 * fc_rport_enter_delete() - Schedule a remote port to be deleted462 * @rdata: The remote port to be deleted463 * @event: The event to report as the reason for deletion464 *465 * Allow state change into DELETE only once.466 *467 * Call queue_work only if there's no event already pending.468 * Set the new event so that the old pending event will not occur.469 * Since we have the mutex, even if fc_rport_work() is already started,470 * it'll see the new event.471 *472 * Reference counting: does not modify kref473 */474static void fc_rport_enter_delete(struct fc_rport_priv *rdata,475				  enum fc_rport_event event)476{477	lockdep_assert_held(&rdata->rp_mutex);478 479	if (rdata->rp_state == RPORT_ST_DELETE)480		return;481 482	FC_RPORT_DBG(rdata, "Delete port\n");483 484	fc_rport_state_enter(rdata, RPORT_ST_DELETE);485 486	if (rdata->event == RPORT_EV_NONE) {487		kref_get(&rdata->kref);488		if (!queue_work(rport_event_queue, &rdata->event_work))489			kref_put(&rdata->kref, fc_rport_destroy);490	}491 492	rdata->event = event;493}494 495/**496 * fc_rport_logoff() - Logoff and remove a remote port497 * @rdata: The remote port to be logged off of498 *499 * Locking Note: Called without the rport lock held. This500 * function will hold the rport lock, call an _enter_*501 * function and then unlock the rport.502 */503int fc_rport_logoff(struct fc_rport_priv *rdata)504{505	struct fc_lport *lport = rdata->local_port;506	u32 port_id = rdata->ids.port_id;507 508	mutex_lock(&rdata->rp_mutex);509 510	FC_RPORT_DBG(rdata, "Remove port\n");511 512	rdata->flags &= ~FC_RP_STARTED;513	if (rdata->rp_state == RPORT_ST_DELETE) {514		FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n");515		goto out;516	}517	/*518	 * FC-LS states:519	 * To explicitly Logout, the initiating Nx_Port shall terminate520	 * other open Sequences that it initiated with the destination521	 * Nx_Port prior to performing Logout.522	 */523	lport->tt.exch_mgr_reset(lport, 0, port_id);524	lport->tt.exch_mgr_reset(lport, port_id, 0);525 526	fc_rport_enter_logo(rdata);527 528	/*529	 * Change the state to Delete so that we discard530	 * the response.531	 */532	fc_rport_enter_delete(rdata, RPORT_EV_STOP);533out:534	mutex_unlock(&rdata->rp_mutex);535	return 0;536}537EXPORT_SYMBOL(fc_rport_logoff);538 539/**540 * fc_rport_enter_ready() - Transition to the RPORT_ST_READY state541 * @rdata: The remote port that is ready542 *543 * Reference counting: schedules workqueue, does not modify kref544 */545static void fc_rport_enter_ready(struct fc_rport_priv *rdata)546{547	lockdep_assert_held(&rdata->rp_mutex);548 549	fc_rport_state_enter(rdata, RPORT_ST_READY);550 551	FC_RPORT_DBG(rdata, "Port is Ready\n");552 553	kref_get(&rdata->kref);554	if (rdata->event == RPORT_EV_NONE &&555	    !queue_work(rport_event_queue, &rdata->event_work))556		kref_put(&rdata->kref, fc_rport_destroy);557 558	rdata->event = RPORT_EV_READY;559}560 561/**562 * fc_rport_timeout() - Handler for the retry_work timer563 * @work: Handle to the remote port that has timed out564 *565 * Locking Note: Called without the rport lock held. This566 * function will hold the rport lock, call an _enter_*567 * function and then unlock the rport.568 *569 * Reference counting: Drops kref on return.570 */571static void fc_rport_timeout(struct work_struct *work)572{573	struct fc_rport_priv *rdata =574		container_of(work, struct fc_rport_priv, retry_work.work);575 576	mutex_lock(&rdata->rp_mutex);577	FC_RPORT_DBG(rdata, "Port timeout, state %s\n", fc_rport_state(rdata));578 579	switch (rdata->rp_state) {580	case RPORT_ST_FLOGI:581		fc_rport_enter_flogi(rdata);582		break;583	case RPORT_ST_PLOGI:584		fc_rport_enter_plogi(rdata);585		break;586	case RPORT_ST_PRLI:587		fc_rport_enter_prli(rdata);588		break;589	case RPORT_ST_RTV:590		fc_rport_enter_rtv(rdata);591		break;592	case RPORT_ST_ADISC:593		fc_rport_enter_adisc(rdata);594		break;595	case RPORT_ST_PLOGI_WAIT:596	case RPORT_ST_READY:597	case RPORT_ST_INIT:598	case RPORT_ST_DELETE:599		break;600	}601 602	mutex_unlock(&rdata->rp_mutex);603	kref_put(&rdata->kref, fc_rport_destroy);604}605 606/**607 * fc_rport_error() - Error handler, called once retries have been exhausted608 * @rdata: The remote port the error is happened on609 * @err:   The error code610 *611 * Reference counting: does not modify kref612 */613static void fc_rport_error(struct fc_rport_priv *rdata, int err)614{615	struct fc_lport *lport = rdata->local_port;616 617	lockdep_assert_held(&rdata->rp_mutex);618 619	FC_RPORT_DBG(rdata, "Error %d in state %s, retries %d\n",620		     -err, fc_rport_state(rdata), rdata->retries);621 622	switch (rdata->rp_state) {623	case RPORT_ST_FLOGI:624		rdata->flags &= ~FC_RP_STARTED;625		fc_rport_enter_delete(rdata, RPORT_EV_FAILED);626		break;627	case RPORT_ST_PLOGI:628		if (lport->point_to_multipoint) {629			rdata->flags &= ~FC_RP_STARTED;630			fc_rport_enter_delete(rdata, RPORT_EV_FAILED);631		} else632			fc_rport_enter_logo(rdata);633		break;634	case RPORT_ST_RTV:635		fc_rport_enter_ready(rdata);636		break;637	case RPORT_ST_PRLI:638		fc_rport_enter_plogi(rdata);639		break;640	case RPORT_ST_ADISC:641		fc_rport_enter_logo(rdata);642		break;643	case RPORT_ST_PLOGI_WAIT:644	case RPORT_ST_DELETE:645	case RPORT_ST_READY:646	case RPORT_ST_INIT:647		break;648	}649}650 651/**652 * fc_rport_error_retry() - Handler for remote port state retries653 * @rdata: The remote port whose state is to be retried654 * @err:   The error code655 *656 * If the error was an exchange timeout retry immediately,657 * otherwise wait for E_D_TOV.658 *659 * Reference counting: increments kref when scheduling retry_work660 */661static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err)662{663	unsigned long delay = msecs_to_jiffies(rdata->e_d_tov);664 665	lockdep_assert_held(&rdata->rp_mutex);666 667	/* make sure this isn't an FC_EX_CLOSED error, never retry those */668	if (err == -FC_EX_CLOSED)669		goto out;670 671	if (rdata->retries < rdata->local_port->max_rport_retry_count) {672		FC_RPORT_DBG(rdata, "Error %d in state %s, retrying\n",673			     err, fc_rport_state(rdata));674		rdata->retries++;675		/* no additional delay on exchange timeouts */676		if (err == -FC_EX_TIMEOUT)677			delay = 0;678		kref_get(&rdata->kref);679		if (!schedule_delayed_work(&rdata->retry_work, delay))680			kref_put(&rdata->kref, fc_rport_destroy);681		return;682	}683 684out:685	fc_rport_error(rdata, err);686}687 688/**689 * fc_rport_login_complete() - Handle parameters and completion of p-mp login.690 * @rdata:  The remote port which we logged into or which logged into us.691 * @fp:     The FLOGI or PLOGI request or response frame692 *693 * Returns non-zero error if a problem is detected with the frame.694 * Does not free the frame.695 *696 * This is only used in point-to-multipoint mode for FIP currently.697 */698static int fc_rport_login_complete(struct fc_rport_priv *rdata,699				   struct fc_frame *fp)700{701	struct fc_lport *lport = rdata->local_port;702	struct fc_els_flogi *flogi;703	unsigned int e_d_tov;704	u16 csp_flags;705 706	flogi = fc_frame_payload_get(fp, sizeof(*flogi));707	if (!flogi)708		return -EINVAL;709 710	csp_flags = ntohs(flogi->fl_csp.sp_features);711 712	if (fc_frame_payload_op(fp) == ELS_FLOGI) {713		if (csp_flags & FC_SP_FT_FPORT) {714			FC_RPORT_DBG(rdata, "Fabric bit set in FLOGI\n");715			return -EINVAL;716		}717	} else {718 719		/*720		 * E_D_TOV is not valid on an incoming FLOGI request.721		 */722		e_d_tov = ntohl(flogi->fl_csp.sp_e_d_tov);723		if (csp_flags & FC_SP_FT_EDTR)724			e_d_tov /= 1000000;725		if (e_d_tov > rdata->e_d_tov)726			rdata->e_d_tov = e_d_tov;727	}728	rdata->maxframe_size = fc_plogi_get_maxframe(flogi, lport->mfs);729	return 0;730}731 732/**733 * fc_rport_flogi_resp() - Handle response to FLOGI request for p-mp mode734 * @sp:	    The sequence that the FLOGI was on735 * @fp:	    The FLOGI response frame736 * @rp_arg: The remote port that received the FLOGI response737 */738static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,739				void *rp_arg)740{741	struct fc_rport_priv *rdata = rp_arg;742	struct fc_lport *lport = rdata->local_port;743	struct fc_els_flogi *flogi;744	unsigned int r_a_tov;745	u8 opcode;746	int err = 0;747 748	FC_RPORT_DBG(rdata, "Received a FLOGI %s\n",749		     IS_ERR(fp) ? "error" : fc_els_resp_type(fp));750 751	if (fp == ERR_PTR(-FC_EX_CLOSED))752		goto put;753 754	mutex_lock(&rdata->rp_mutex);755 756	if (rdata->rp_state != RPORT_ST_FLOGI) {757		FC_RPORT_DBG(rdata, "Received a FLOGI response, but in state "758			     "%s\n", fc_rport_state(rdata));759		if (IS_ERR(fp))760			goto err;761		goto out;762	}763 764	if (IS_ERR(fp)) {765		fc_rport_error(rdata, PTR_ERR(fp));766		goto err;767	}768	opcode = fc_frame_payload_op(fp);769	if (opcode == ELS_LS_RJT) {770		struct fc_els_ls_rjt *rjt;771 772		rjt = fc_frame_payload_get(fp, sizeof(*rjt));773		FC_RPORT_DBG(rdata, "FLOGI ELS rejected, reason %x expl %x\n",774			     rjt->er_reason, rjt->er_explan);775		err = -FC_EX_ELS_RJT;776		goto bad;777	} else if (opcode != ELS_LS_ACC) {778		FC_RPORT_DBG(rdata, "FLOGI ELS invalid opcode %x\n", opcode);779		err = -FC_EX_ELS_RJT;780		goto bad;781	}782	if (fc_rport_login_complete(rdata, fp)) {783		FC_RPORT_DBG(rdata, "FLOGI failed, no login\n");784		err = -FC_EX_INV_LOGIN;785		goto bad;786	}787 788	flogi = fc_frame_payload_get(fp, sizeof(*flogi));789	if (!flogi) {790		err = -FC_EX_ALLOC_ERR;791		goto bad;792	}793	r_a_tov = ntohl(flogi->fl_csp.sp_r_a_tov);794	if (r_a_tov > rdata->r_a_tov)795		rdata->r_a_tov = r_a_tov;796 797	if (rdata->ids.port_name < lport->wwpn)798		fc_rport_enter_plogi(rdata);799	else800		fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);801out:802	fc_frame_free(fp);803err:804	mutex_unlock(&rdata->rp_mutex);805put:806	kref_put(&rdata->kref, fc_rport_destroy);807	return;808bad:809	FC_RPORT_DBG(rdata, "Bad FLOGI response\n");810	fc_rport_error_retry(rdata, err);811	goto out;812}813 814/**815 * fc_rport_enter_flogi() - Send a FLOGI request to the remote port for p-mp816 * @rdata: The remote port to send a FLOGI to817 *818 * Reference counting: increments kref when sending ELS819 */820static void fc_rport_enter_flogi(struct fc_rport_priv *rdata)821{822	struct fc_lport *lport = rdata->local_port;823	struct fc_frame *fp;824 825	lockdep_assert_held(&rdata->rp_mutex);826 827	if (!lport->point_to_multipoint)828		return fc_rport_enter_plogi(rdata);829 830	FC_RPORT_DBG(rdata, "Entered FLOGI state from %s state\n",831		     fc_rport_state(rdata));832 833	fc_rport_state_enter(rdata, RPORT_ST_FLOGI);834 835	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));836	if (!fp)837		return fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);838 839	kref_get(&rdata->kref);840	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI,841				  fc_rport_flogi_resp, rdata,842				  2 * lport->r_a_tov)) {843		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);844		kref_put(&rdata->kref, fc_rport_destroy);845	}846}847 848/**849 * fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode850 * @lport: The local port that received the PLOGI request851 * @rx_fp: The PLOGI request frame852 *853 * Reference counting: drops kref on return854 */855static void fc_rport_recv_flogi_req(struct fc_lport *lport,856				    struct fc_frame *rx_fp)857{858	struct fc_els_flogi *flp;859	struct fc_rport_priv *rdata;860	struct fc_frame *fp = rx_fp;861	struct fc_seq_els_data rjt_data;862	u32 sid;863 864	sid = fc_frame_sid(fp);865 866	FC_RPORT_ID_DBG(lport, sid, "Received FLOGI request\n");867 868	if (!lport->point_to_multipoint) {869		rjt_data.reason = ELS_RJT_UNSUP;870		rjt_data.explan = ELS_EXPL_NONE;871		goto reject;872	}873 874	flp = fc_frame_payload_get(fp, sizeof(*flp));875	if (!flp) {876		rjt_data.reason = ELS_RJT_LOGIC;877		rjt_data.explan = ELS_EXPL_INV_LEN;878		goto reject;879	}880 881	rdata = fc_rport_lookup(lport, sid);882	if (!rdata) {883		rjt_data.reason = ELS_RJT_FIP;884		rjt_data.explan = ELS_EXPL_NOT_NEIGHBOR;885		goto reject;886	}887	mutex_lock(&rdata->rp_mutex);888 889	FC_RPORT_DBG(rdata, "Received FLOGI in %s state\n",890		     fc_rport_state(rdata));891 892	switch (rdata->rp_state) {893	case RPORT_ST_INIT:894		/*895		 * If received the FLOGI request on RPORT which is INIT state896		 * (means not transition to FLOGI either fc_rport timeout897		 * function didn;t trigger or this end hasn;t received898		 * beacon yet from other end. In that case only, allow RPORT899		 * state machine to continue, otherwise fall through which900		 * causes the code to send reject response.901		 * NOTE; Not checking for FIP->state such as VNMP_UP or902		 * VNMP_CLAIM because if FIP state is not one of those,903		 * RPORT wouldn;t have created and 'rport_lookup' would have904		 * failed anyway in that case.905		 */906		break;907	case RPORT_ST_DELETE:908		mutex_unlock(&rdata->rp_mutex);909		rjt_data.reason = ELS_RJT_FIP;910		rjt_data.explan = ELS_EXPL_NOT_NEIGHBOR;911		goto reject_put;912	case RPORT_ST_FLOGI:913	case RPORT_ST_PLOGI_WAIT:914	case RPORT_ST_PLOGI:915		break;916	case RPORT_ST_PRLI:917	case RPORT_ST_RTV:918	case RPORT_ST_READY:919	case RPORT_ST_ADISC:920		/*921		 * Set the remote port to be deleted and to then restart.922		 * This queues work to be sure exchanges are reset.923		 */924		fc_rport_enter_delete(rdata, RPORT_EV_LOGO);925		mutex_unlock(&rdata->rp_mutex);926		rjt_data.reason = ELS_RJT_BUSY;927		rjt_data.explan = ELS_EXPL_NONE;928		goto reject_put;929	}930	if (fc_rport_login_complete(rdata, fp)) {931		mutex_unlock(&rdata->rp_mutex);932		rjt_data.reason = ELS_RJT_LOGIC;933		rjt_data.explan = ELS_EXPL_NONE;934		goto reject_put;935	}936 937	fp = fc_frame_alloc(lport, sizeof(*flp));938	if (!fp)939		goto out;940 941	fc_flogi_fill(lport, fp);942	flp = fc_frame_payload_get(fp, sizeof(*flp));943	flp->fl_cmd = ELS_LS_ACC;944 945	fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);946	lport->tt.frame_send(lport, fp);947 948	/*949	 * Do not proceed with the state machine if our950	 * FLOGI has crossed with an FLOGI from the951	 * remote port; wait for the FLOGI response instead.952	 */953	if (rdata->rp_state != RPORT_ST_FLOGI) {954		if (rdata->ids.port_name < lport->wwpn)955			fc_rport_enter_plogi(rdata);956		else957			fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);958	}959out:960	mutex_unlock(&rdata->rp_mutex);961	kref_put(&rdata->kref, fc_rport_destroy);962	fc_frame_free(rx_fp);963	return;964 965reject_put:966	kref_put(&rdata->kref, fc_rport_destroy);967reject:968	fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);969	fc_frame_free(rx_fp);970}971 972/**973 * fc_rport_plogi_resp() - Handler for ELS PLOGI responses974 * @sp:	       The sequence the PLOGI is on975 * @fp:	       The PLOGI response frame976 * @rdata_arg: The remote port that sent the PLOGI response977 *978 * Locking Note: This function will be called without the rport lock979 * held, but it will lock, call an _enter_* function or fc_rport_error980 * and then unlock the rport.981 */982static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,983				void *rdata_arg)984{985	struct fc_rport_priv *rdata = rdata_arg;986	struct fc_lport *lport = rdata->local_port;987	struct fc_els_flogi *plp = NULL;988	u16 csp_seq;989	u16 cssp_seq;990	u8 op;991 992	FC_RPORT_DBG(rdata, "Received a PLOGI %s\n", fc_els_resp_type(fp));993 994	if (fp == ERR_PTR(-FC_EX_CLOSED))995		goto put;996 997	mutex_lock(&rdata->rp_mutex);998 999	if (rdata->rp_state != RPORT_ST_PLOGI) {1000		FC_RPORT_DBG(rdata, "Received a PLOGI response, but in state "1001			     "%s\n", fc_rport_state(rdata));1002		if (IS_ERR(fp))1003			goto err;1004		goto out;1005	}1006 1007	if (IS_ERR(fp)) {1008		fc_rport_error_retry(rdata, PTR_ERR(fp));1009		goto err;1010	}1011 1012	op = fc_frame_payload_op(fp);1013	if (op == ELS_LS_ACC &&1014	    (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {1015		rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn);1016		rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn);1017 1018		/* save plogi response sp_features for further reference */1019		rdata->sp_features = ntohs(plp->fl_csp.sp_features);1020 1021		if (lport->point_to_multipoint)1022			fc_rport_login_complete(rdata, fp);1023		csp_seq = ntohs(plp->fl_csp.sp_tot_seq);1024		cssp_seq = ntohs(plp->fl_cssp[3 - 1].cp_con_seq);1025		if (cssp_seq < csp_seq)1026			csp_seq = cssp_seq;1027		rdata->max_seq = csp_seq;1028		rdata->maxframe_size = fc_plogi_get_maxframe(plp, lport->mfs);1029		fc_rport_enter_prli(rdata);1030	} else {1031		struct fc_els_ls_rjt *rjt;1032 1033		rjt = fc_frame_payload_get(fp, sizeof(*rjt));1034		if (!rjt)1035			FC_RPORT_DBG(rdata, "PLOGI bad response\n");1036		else1037			FC_RPORT_DBG(rdata, "PLOGI ELS rejected, reason %x expl %x\n",1038				     rjt->er_reason, rjt->er_explan);1039		fc_rport_error_retry(rdata, -FC_EX_ELS_RJT);1040	}1041out:1042	fc_frame_free(fp);1043err:1044	mutex_unlock(&rdata->rp_mutex);1045put:1046	kref_put(&rdata->kref, fc_rport_destroy);1047}1048 1049static bool1050fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata)1051{1052	if (rdata->ids.roles == FC_PORT_ROLE_UNKNOWN)1053		return true;1054	if ((rdata->ids.roles & FC_PORT_ROLE_FCP_TARGET) &&1055	    (lport->service_params & FCP_SPPF_INIT_FCN))1056		return true;1057	if ((rdata->ids.roles & FC_PORT_ROLE_FCP_INITIATOR) &&1058	    (lport->service_params & FCP_SPPF_TARG_FCN))1059		return true;1060	return false;1061}1062 1063/**1064 * fc_rport_enter_plogi() - Send Port Login (PLOGI) request1065 * @rdata: The remote port to send a PLOGI to1066 *1067 * Reference counting: increments kref when sending ELS1068 */1069static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)1070{1071	struct fc_lport *lport = rdata->local_port;1072	struct fc_frame *fp;1073 1074	lockdep_assert_held(&rdata->rp_mutex);1075 1076	if (!fc_rport_compatible_roles(lport, rdata)) {1077		FC_RPORT_DBG(rdata, "PLOGI suppressed for incompatible role\n");1078		fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);1079		return;1080	}1081 1082	FC_RPORT_DBG(rdata, "Port entered PLOGI state from %s state\n",1083		     fc_rport_state(rdata));1084 1085	fc_rport_state_enter(rdata, RPORT_ST_PLOGI);1086 1087	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;1088	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));1089	if (!fp) {1090		FC_RPORT_DBG(rdata, "%s frame alloc failed\n", __func__);1091		fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);1092		return;1093	}1094	rdata->e_d_tov = lport->e_d_tov;1095 1096	kref_get(&rdata->kref);1097	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI,1098				  fc_rport_plogi_resp, rdata,1099				  2 * lport->r_a_tov)) {1100		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);1101		kref_put(&rdata->kref, fc_rport_destroy);1102	}1103}1104 1105/**1106 * fc_rport_prli_resp() - Process Login (PRLI) response handler1107 * @sp:	       The sequence the PRLI response was on1108 * @fp:	       The PRLI response frame1109 * @rdata_arg: The remote port that sent the PRLI response1110 *1111 * Locking Note: This function will be called without the rport lock1112 * held, but it will lock, call an _enter_* function or fc_rport_error1113 * and then unlock the rport.1114 */1115static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,1116			       void *rdata_arg)1117{1118	struct fc_rport_priv *rdata = rdata_arg;1119	struct {1120		struct fc_els_prli prli;1121		struct fc_els_spp spp;1122	} *pp;1123	struct fc_els_spp temp_spp;1124	struct fc_els_ls_rjt *rjt;1125	struct fc4_prov *prov;1126	u32 roles = FC_RPORT_ROLE_UNKNOWN;1127	u32 fcp_parm = 0;1128	u8 op;1129	enum fc_els_spp_resp resp_code;1130 1131	FC_RPORT_DBG(rdata, "Received a PRLI %s\n", fc_els_resp_type(fp));1132 1133	if (fp == ERR_PTR(-FC_EX_CLOSED))1134		goto put;1135 1136	mutex_lock(&rdata->rp_mutex);1137 1138	if (rdata->rp_state != RPORT_ST_PRLI) {1139		FC_RPORT_DBG(rdata, "Received a PRLI response, but in state "1140			     "%s\n", fc_rport_state(rdata));1141		if (IS_ERR(fp))1142			goto err;1143		goto out;1144	}1145 1146	if (IS_ERR(fp)) {1147		fc_rport_error_retry(rdata, PTR_ERR(fp));1148		goto err;1149	}1150 1151	/* reinitialize remote port roles */1152	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;1153 1154	op = fc_frame_payload_op(fp);1155	if (op == ELS_LS_ACC) {1156		pp = fc_frame_payload_get(fp, sizeof(*pp));1157		if (!pp) {1158			fc_rport_error_retry(rdata, -FC_EX_SEQ_ERR);1159			goto out;1160		}1161 1162		resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);1163		FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x spp_type 0x%x\n",1164			     pp->spp.spp_flags, pp->spp.spp_type);1165 1166		rdata->spp_type = pp->spp.spp_type;1167		if (resp_code != FC_SPP_RESP_ACK) {1168			if (resp_code == FC_SPP_RESP_CONF)1169				fc_rport_error(rdata, -FC_EX_SEQ_ERR);1170			else1171				fc_rport_error_retry(rdata, -FC_EX_SEQ_ERR);1172			goto out;1173		}1174		if (pp->prli.prli_spp_len < sizeof(pp->spp)) {1175			fc_rport_error_retry(rdata, -FC_EX_SEQ_ERR);1176			goto out;1177		}1178 1179		fcp_parm = ntohl(pp->spp.spp_params);1180		if (fcp_parm & FCP_SPPF_RETRY)1181			rdata->flags |= FC_RP_FLAGS_RETRY;1182		if (fcp_parm & FCP_SPPF_CONF_COMPL)1183			rdata->flags |= FC_RP_FLAGS_CONF_REQ;1184 1185		/*1186		 * Call prli provider if we should act as a target1187		 */1188		if (rdata->spp_type < FC_FC4_PROV_SIZE) {1189			prov = fc_passive_prov[rdata->spp_type];1190			if (prov) {1191				memset(&temp_spp, 0, sizeof(temp_spp));1192				prov->prli(rdata, pp->prli.prli_spp_len,1193					   &pp->spp, &temp_spp);1194			}1195		}1196		/*1197		 * Check if the image pair could be established1198		 */1199		if (rdata->spp_type != FC_TYPE_FCP ||1200		    !(pp->spp.spp_flags & FC_SPP_EST_IMG_PAIR)) {1201			/*1202			 * Nope; we can't use this port as a target.1203			 */1204			fcp_parm &= ~FCP_SPPF_TARG_FCN;1205		}1206		rdata->supported_classes = FC_COS_CLASS3;1207		if (fcp_parm & FCP_SPPF_INIT_FCN)1208			roles |= FC_RPORT_ROLE_FCP_INITIATOR;1209		if (fcp_parm & FCP_SPPF_TARG_FCN)1210			roles |= FC_RPORT_ROLE_FCP_TARGET;1211 1212		rdata->ids.roles = roles;1213		fc_rport_enter_rtv(rdata);1214 1215	} else {1216		rjt = fc_frame_payload_get(fp, sizeof(*rjt));1217		if (!rjt)1218			FC_RPORT_DBG(rdata, "PRLI bad response\n");1219		else {1220			FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n",1221				     rjt->er_reason, rjt->er_explan);1222			if (rjt->er_reason == ELS_RJT_UNAB &&1223			    rjt->er_explan == ELS_EXPL_PLOGI_REQD) {1224				fc_rport_enter_plogi(rdata);1225				goto out;1226			}1227		}1228		fc_rport_error_retry(rdata, FC_EX_ELS_RJT);1229	}1230 1231out:1232	fc_frame_free(fp);1233err:1234	mutex_unlock(&rdata->rp_mutex);1235put:1236	kref_put(&rdata->kref, fc_rport_destroy);1237}1238 1239/**1240 * fc_rport_enter_prli() - Send Process Login (PRLI) request1241 * @rdata: The remote port to send the PRLI request to1242 *1243 * Reference counting: increments kref when sending ELS1244 */1245static void fc_rport_enter_prli(struct fc_rport_priv *rdata)1246{1247	struct fc_lport *lport = rdata->local_port;1248	struct {1249		struct fc_els_prli prli;1250		struct fc_els_spp spp;1251	} *pp;1252	struct fc_frame *fp;1253	struct fc4_prov *prov;1254 1255	lockdep_assert_held(&rdata->rp_mutex);1256 1257	/*1258	 * If the rport is one of the well known addresses1259	 * we skip PRLI and RTV and go straight to READY.1260	 */1261	if (rdata->ids.port_id >= FC_FID_DOM_MGR) {1262		fc_rport_enter_ready(rdata);1263		return;1264	}1265 1266	/*1267	 * And if the local port does not support the initiator function1268	 * there's no need to send a PRLI, either.1269	 */1270	if (!(lport->service_params & FCP_SPPF_INIT_FCN)) {1271		    fc_rport_enter_ready(rdata);1272		    return;1273	}1274 1275	FC_RPORT_DBG(rdata, "Port entered PRLI state from %s state\n",1276		     fc_rport_state(rdata));1277 1278	fc_rport_state_enter(rdata, RPORT_ST_PRLI);1279 1280	fp = fc_frame_alloc(lport, sizeof(*pp));1281	if (!fp) {1282		fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);1283		return;1284	}1285 1286	fc_prli_fill(lport, fp);1287 1288	prov = fc_passive_prov[FC_TYPE_FCP];1289	if (prov) {1290		pp = fc_frame_payload_get(fp, sizeof(*pp));1291		prov->prli(rdata, sizeof(pp->spp), NULL, &pp->spp);1292	}1293 1294	fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rdata->ids.port_id,1295		       fc_host_port_id(lport->host), FC_TYPE_ELS,1296		       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);1297 1298	kref_get(&rdata->kref);1299	if (!fc_exch_seq_send(lport, fp, fc_rport_prli_resp,1300			      NULL, rdata, 2 * lport->r_a_tov)) {1301		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);1302		kref_put(&rdata->kref, fc_rport_destroy);1303	}1304}1305 1306/**1307 * fc_rport_rtv_resp() - Handler for Request Timeout Value (RTV) responses1308 * @sp:	       The sequence the RTV was on1309 * @fp:	       The RTV response frame1310 * @rdata_arg: The remote port that sent the RTV response1311 *1312 * Many targets don't seem to support this.1313 *1314 * Locking Note: This function will be called without the rport lock1315 * held, but it will lock, call an _enter_* function or fc_rport_error1316 * and then unlock the rport.1317 */1318static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,1319			      void *rdata_arg)1320{1321	struct fc_rport_priv *rdata = rdata_arg;1322	u8 op;1323 1324	FC_RPORT_DBG(rdata, "Received a RTV %s\n", fc_els_resp_type(fp));1325 1326	if (fp == ERR_PTR(-FC_EX_CLOSED))1327		goto put;1328 1329	mutex_lock(&rdata->rp_mutex);1330 1331	if (rdata->rp_state != RPORT_ST_RTV) {1332		FC_RPORT_DBG(rdata, "Received a RTV response, but in state "1333			     "%s\n", fc_rport_state(rdata));1334		if (IS_ERR(fp))1335			goto err;1336		goto out;1337	}1338 1339	if (IS_ERR(fp)) {1340		fc_rport_error(rdata, PTR_ERR(fp));1341		goto err;1342	}1343 1344	op = fc_frame_payload_op(fp);1345	if (op == ELS_LS_ACC) {1346		struct fc_els_rtv_acc *rtv;1347		u32 toq;1348		u32 tov;1349 1350		rtv = fc_frame_payload_get(fp, sizeof(*rtv));1351		if (rtv) {1352			toq = ntohl(rtv->rtv_toq);1353			tov = ntohl(rtv->rtv_r_a_tov);1354			if (tov == 0)1355				tov = 1;1356			if (tov > rdata->r_a_tov)1357				rdata->r_a_tov = tov;1358			tov = ntohl(rtv->rtv_e_d_tov);1359			if (toq & FC_ELS_RTV_EDRES)1360				tov /= 1000000;1361			if (tov == 0)1362				tov = 1;1363			if (tov > rdata->e_d_tov)1364				rdata->e_d_tov = tov;1365		}1366	}1367 1368	fc_rport_enter_ready(rdata);1369 1370out:1371	fc_frame_free(fp);1372err:1373	mutex_unlock(&rdata->rp_mutex);1374put:1375	kref_put(&rdata->kref, fc_rport_destroy);1376}1377 1378/**1379 * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request1380 * @rdata: The remote port to send the RTV request to1381 *1382 * Reference counting: increments kref when sending ELS1383 */1384static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)1385{1386	struct fc_frame *fp;1387	struct fc_lport *lport = rdata->local_port;1388 1389	lockdep_assert_held(&rdata->rp_mutex);1390 1391	FC_RPORT_DBG(rdata, "Port entered RTV state from %s state\n",1392		     fc_rport_state(rdata));1393 1394	fc_rport_state_enter(rdata, RPORT_ST_RTV);1395 1396	fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv));1397	if (!fp) {1398		fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);1399		return;1400	}1401 1402	kref_get(&rdata->kref);1403	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV,1404				  fc_rport_rtv_resp, rdata,1405				  2 * lport->r_a_tov)) {1406		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);1407		kref_put(&rdata->kref, fc_rport_destroy);1408	}1409}1410 1411/**1412 * fc_rport_recv_rtv_req() - Handler for Read Timeout Value (RTV) requests1413 * @rdata: The remote port that sent the RTV request1414 * @in_fp: The RTV request frame1415 */1416static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata,1417				  struct fc_frame *in_fp)1418{1419	struct fc_lport *lport = rdata->local_port;1420	struct fc_frame *fp;1421	struct fc_els_rtv_acc *rtv;1422	struct fc_seq_els_data rjt_data;1423 1424	lockdep_assert_held(&rdata->rp_mutex);1425	lockdep_assert_held(&lport->lp_mutex);1426 1427	FC_RPORT_DBG(rdata, "Received RTV request\n");1428 1429	fp = fc_frame_alloc(lport, sizeof(*rtv));1430	if (!fp) {1431		rjt_data.reason = ELS_RJT_UNAB;1432		rjt_data.explan = ELS_EXPL_INSUF_RES;1433		fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);1434		goto drop;1435	}1436	rtv = fc_frame_payload_get(fp, sizeof(*rtv));1437	rtv->rtv_cmd = ELS_LS_ACC;1438	rtv->rtv_r_a_tov = htonl(lport->r_a_tov);1439	rtv->rtv_e_d_tov = htonl(lport->e_d_tov);1440	rtv->rtv_toq = 0;1441	fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0);1442	lport->tt.frame_send(lport, fp);1443drop:1444	fc_frame_free(in_fp);1445}1446 1447/**1448 * fc_rport_logo_resp() - Handler for logout (LOGO) responses1449 * @sp:	       The sequence the LOGO was on1450 * @fp:	       The LOGO response frame1451 * @rdata_arg: The remote port1452 */1453static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,1454			       void *rdata_arg)1455{1456	struct fc_rport_priv *rdata = rdata_arg;1457	struct fc_lport *lport = rdata->local_port;1458 1459	FC_RPORT_ID_DBG(lport, fc_seq_exch(sp)->did,1460			"Received a LOGO %s\n", fc_els_resp_type(fp));1461	if (!IS_ERR(fp))1462		fc_frame_free(fp);1463	kref_put(&rdata->kref, fc_rport_destroy);1464}1465 1466/**1467 * fc_rport_enter_logo() - Send a logout (LOGO) request1468 * @rdata: The remote port to send the LOGO request to1469 *1470 * Reference counting: increments kref when sending ELS1471 */1472static void fc_rport_enter_logo(struct fc_rport_priv *rdata)1473{1474	struct fc_lport *lport = rdata->local_port;1475	struct fc_frame *fp;1476 1477	lockdep_assert_held(&rdata->rp_mutex);1478 1479	FC_RPORT_DBG(rdata, "Port sending LOGO from %s state\n",1480		     fc_rport_state(rdata));1481 1482	fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo));1483	if (!fp)1484		return;1485	kref_get(&rdata->kref);1486	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO,1487				  fc_rport_logo_resp, rdata, 0))1488		kref_put(&rdata->kref, fc_rport_destroy);1489}1490 1491/**1492 * fc_rport_adisc_resp() - Handler for Address Discovery (ADISC) responses1493 * @sp:	       The sequence the ADISC response was on1494 * @fp:	       The ADISC response frame1495 * @rdata_arg: The remote port that sent the ADISC response1496 *1497 * Locking Note: This function will be called without the rport lock1498 * held, but it will lock, call an _enter_* function or fc_rport_error1499 * and then unlock the rport.1500 */1501static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp,1502				void *rdata_arg)1503{1504	struct fc_rport_priv *rdata = rdata_arg;1505	struct fc_els_adisc *adisc;1506	u8 op;1507 1508	FC_RPORT_DBG(rdata, "Received a ADISC response\n");1509 1510	if (fp == ERR_PTR(-FC_EX_CLOSED))1511		goto put;1512 1513	mutex_lock(&rdata->rp_mutex);1514 1515	if (rdata->rp_state != RPORT_ST_ADISC) {1516		FC_RPORT_DBG(rdata, "Received a ADISC resp but in state %s\n",1517			     fc_rport_state(rdata));1518		if (IS_ERR(fp))1519			goto err;1520		goto out;1521	}1522 1523	if (IS_ERR(fp)) {1524		fc_rport_error(rdata, PTR_ERR(fp));1525		goto err;1526	}1527 1528	/*1529	 * If address verification failed.  Consider us logged out of the rport.1530	 * Since the rport is still in discovery, we want to be1531	 * logged in, so go to PLOGI state.  Otherwise, go back to READY.1532	 */1533	op = fc_frame_payload_op(fp);1534	adisc = fc_frame_payload_get(fp, sizeof(*adisc));1535	if (op != ELS_LS_ACC || !adisc ||1536	    ntoh24(adisc->adisc_port_id) != rdata->ids.port_id ||1537	    get_unaligned_be64(&adisc->adisc_wwpn) != rdata->ids.port_name ||1538	    get_unaligned_be64(&adisc->adisc_wwnn) != rdata->ids.node_name) {1539		FC_RPORT_DBG(rdata, "ADISC error or mismatch\n");1540		fc_rport_enter_flogi(rdata);1541	} else {1542		FC_RPORT_DBG(rdata, "ADISC OK\n");1543		fc_rport_enter_ready(rdata);1544	}1545out:1546	fc_frame_free(fp);1547err:1548	mutex_unlock(&rdata->rp_mutex);1549put:1550	kref_put(&rdata->kref, fc_rport_destroy);1551}1552 1553/**1554 * fc_rport_enter_adisc() - Send Address Discover (ADISC) request1555 * @rdata: The remote port to send the ADISC request to1556 *1557 * Reference counting: increments kref when sending ELS1558 */1559static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)1560{1561	struct fc_lport *lport = rdata->local_port;1562	struct fc_frame *fp;1563 1564	lockdep_assert_held(&rdata->rp_mutex);1565 1566	FC_RPORT_DBG(rdata, "sending ADISC from %s state\n",1567		     fc_rport_state(rdata));1568 1569	fc_rport_state_enter(rdata, RPORT_ST_ADISC);1570 1571	fp = fc_frame_alloc(lport, sizeof(struct fc_els_adisc));1572	if (!fp) {1573		fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);1574		return;1575	}1576	kref_get(&rdata->kref);1577	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC,1578				  fc_rport_adisc_resp, rdata,1579				  2 * lport->r_a_tov)) {1580		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);1581		kref_put(&rdata->kref, fc_rport_destroy);1582	}1583}1584 1585/**1586 * fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests1587 * @rdata: The remote port that sent the ADISC request1588 * @in_fp: The ADISC request frame1589 */1590static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata,1591				    struct fc_frame *in_fp)1592{1593	struct fc_lport *lport = rdata->local_port;1594	struct fc_frame *fp;1595	struct fc_els_adisc *adisc;1596	struct fc_seq_els_data rjt_data;1597 1598	lockdep_assert_held(&rdata->rp_mutex);1599	lockdep_assert_held(&lport->lp_mutex);1600 1601	FC_RPORT_DBG(rdata, "Received ADISC request\n");1602 1603	adisc = fc_frame_payload_get(in_fp, sizeof(*adisc));1604	if (!adisc) {1605		rjt_data.reason = ELS_RJT_PROT;1606		rjt_data.explan = ELS_EXPL_INV_LEN;1607		fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);1608		goto drop;1609	}1610 1611	fp = fc_frame_alloc(lport, sizeof(*adisc));1612	if (!fp)1613		goto drop;1614	fc_adisc_fill(lport, fp);1615	adisc = fc_frame_payload_get(fp, sizeof(*adisc));1616	adisc->adisc_cmd = ELS_LS_ACC;1617	fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0);1618	lport->tt.frame_send(lport, fp);1619drop:1620	fc_frame_free(in_fp);1621}1622 1623/**1624 * fc_rport_recv_rls_req() - Handle received Read Link Status request1625 * @rdata: The remote port that sent the RLS request1626 * @rx_fp: The PRLI request frame1627 */1628static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,1629				  struct fc_frame *rx_fp)1630 1631{1632	struct fc_lport *lport = rdata->local_port;1633	struct fc_frame *fp;1634	struct fc_els_rls *rls;1635	struct fc_els_rls_resp *rsp;1636	struct fc_els_lesb *lesb;1637	struct fc_seq_els_data rjt_data;1638	struct fc_host_statistics *hst;1639 1640	lockdep_assert_held(&rdata->rp_mutex);1641 1642	FC_RPORT_DBG(rdata, "Received RLS request while in state %s\n",1643		     fc_rport_state(rdata));1644 1645	rls = fc_frame_payload_get(rx_fp, sizeof(*rls));1646	if (!rls) {1647		rjt_data.reason = ELS_RJT_PROT;1648		rjt_data.explan = ELS_EXPL_INV_LEN;1649		goto out_rjt;1650	}1651 1652	fp = fc_frame_alloc(lport, sizeof(*rsp));1653	if (!fp) {1654		rjt_data.reason = ELS_RJT_UNAB;1655		rjt_data.explan = ELS_EXPL_INSUF_RES;1656		goto out_rjt;1657	}1658 1659	rsp = fc_frame_payload_get(fp, sizeof(*rsp));1660	memset(rsp, 0, sizeof(*rsp));1661	rsp->rls_cmd = ELS_LS_ACC;1662	lesb = &rsp->rls_lesb;1663	if (lport->tt.get_lesb) {1664		/* get LESB from LLD if it supports it */1665		lport->tt.get_lesb(lport, lesb);1666	} else {1667		fc_get_host_stats(lport->host);1668		hst = &lport->host_stats;1669		lesb->lesb_link_fail = htonl(hst->link_failure_count);1670		lesb->lesb_sync_loss = htonl(hst->loss_of_sync_count);1671		lesb->lesb_sig_loss = htonl(hst->loss_of_signal_count);1672		lesb->lesb_prim_err = htonl(hst->prim_seq_protocol_err_count);1673		lesb->lesb_inv_word = htonl(hst->invalid_tx_word_count);1674		lesb->lesb_inv_crc = htonl(hst->invalid_crc_count);1675	}1676 1677	fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);1678	lport->tt.frame_send(lport, fp);1679	goto out;1680 1681out_rjt:1682	fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);1683out:1684	fc_frame_free(rx_fp);1685}1686 1687/**1688 * fc_rport_recv_els_req() - Handler for validated ELS requests1689 * @lport: The local port that received the ELS request1690 * @fp:	   The ELS request frame1691 *1692 * Handle incoming ELS requests that require port login.1693 * The ELS opcode has already been validated by the caller.1694 *1695 * Reference counting: does not modify kref1696 */1697static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)1698{1699	struct fc_rport_priv *rdata;1700	struct fc_seq_els_data els_data;1701 1702	lockdep_assert_held(&lport->lp_mutex);1703 1704	rdata = fc_rport_lookup(lport, fc_frame_sid(fp));1705	if (!rdata) {1706		FC_RPORT_ID_DBG(lport, fc_frame_sid(fp),1707				"Received ELS 0x%02x from non-logged-in port\n",1708				fc_frame_payload_op(fp));1709		goto reject;1710	}1711 1712	mutex_lock(&rdata->rp_mutex);1713 1714	switch (rdata->rp_state) {1715	case RPORT_ST_PRLI:1716	case RPORT_ST_RTV:1717	case RPORT_ST_READY:1718	case RPORT_ST_ADISC:1719		break;1720	case RPORT_ST_PLOGI:1721		if (fc_frame_payload_op(fp) == ELS_PRLI) {1722			FC_RPORT_DBG(rdata, "Reject ELS PRLI "1723				     "while in state %s\n",1724				     fc_rport_state(rdata));1725			mutex_unlock(&rdata->rp_mutex);1726			kref_put(&rdata->kref, fc_rport_destroy);1727			goto busy;1728		}1729		fallthrough;1730	default:1731		FC_RPORT_DBG(rdata,1732			     "Reject ELS 0x%02x while in state %s\n",1733			     fc_frame_payload_op(fp), fc_rport_state(rdata));1734		mutex_unlock(&rdata->rp_mutex);1735		kref_put(&rdata->kref, fc_rport_destroy);1736		goto reject;1737	}1738 1739	switch (fc_frame_payload_op(fp)) {1740	case ELS_PRLI:1741		fc_rport_recv_prli_req(rdata, fp);1742		break;1743	case ELS_PRLO:1744		fc_rport_recv_prlo_req(rdata, fp);1745		break;1746	case ELS_ADISC:1747		fc_rport_recv_adisc_req(rdata, fp);1748		break;1749	case ELS_RRQ:1750		fc_seq_els_rsp_send(fp, ELS_RRQ, NULL);1751		fc_frame_free(fp);1752		break;1753	case ELS_REC:1754		fc_seq_els_rsp_send(fp, ELS_REC, NULL);1755		fc_frame_free(fp);1756		break;1757	case ELS_RLS:1758		fc_rport_recv_rls_req(rdata, fp);1759		break;1760	case ELS_RTV:1761		fc_rport_recv_rtv_req(rdata, fp);1762		break;1763	default:1764		fc_frame_free(fp);	/* can't happen */1765		break;1766	}1767 1768	mutex_unlock(&rdata->rp_mutex);1769	kref_put(&rdata->kref, fc_rport_destroy);1770	return;1771 1772reject:1773	els_data.reason = ELS_RJT_UNAB;1774	els_data.explan = ELS_EXPL_PLOGI_REQD;1775	fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);1776	fc_frame_free(fp);1777	return;1778 1779busy:1780	els_data.reason = ELS_RJT_BUSY;1781	els_data.explan = ELS_EXPL_NONE;1782	fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);1783	fc_frame_free(fp);1784	return;1785}1786 1787/**1788 * fc_rport_recv_req() - Handler for requests1789 * @lport: The local port that received the request1790 * @fp:	   The request frame1791 *1792 * Reference counting: does not modify kref1793 */1794void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)1795{1796	struct fc_seq_els_data els_data;1797 1798	lockdep_assert_held(&lport->lp_mutex);1799 1800	/*1801	 * Handle FLOGI, PLOGI and LOGO requests separately, since they1802	 * don't require prior login.1803	 * Check for unsupported opcodes first and reject them.1804	 * For some ops, it would be incorrect to reject with "PLOGI required".1805	 */1806	switch (fc_frame_payload_op(fp)) {1807	case ELS_FLOGI:1808		fc_rport_recv_flogi_req(lport, fp);1809		break;1810	case ELS_PLOGI:1811		fc_rport_recv_plogi_req(lport, fp);1812		break;1813	case ELS_LOGO:1814		fc_rport_recv_logo_req(lport, fp);1815		break;1816	case ELS_PRLI:1817	case ELS_PRLO:1818	case ELS_ADISC:1819	case ELS_RRQ:1820	case ELS_REC:1821	case ELS_RLS:1822	case ELS_RTV:1823		fc_rport_recv_els_req(lport, fp);1824		break;1825	default:1826		els_data.reason = ELS_RJT_UNSUP;1827		els_data.explan = ELS_EXPL_NONE;1828		fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);1829		fc_frame_free(fp);1830		break;1831	}1832}1833EXPORT_SYMBOL(fc_rport_recv_req);1834 1835/**1836 * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests1837 * @lport: The local port that received the PLOGI request1838 * @rx_fp: The PLOGI request frame1839 *1840 * Reference counting: increments kref on return1841 */1842static void fc_rport_recv_plogi_req(struct fc_lport *lport,1843				    struct fc_frame *rx_fp)1844{1845	struct fc_disc *disc;1846	struct fc_rport_priv *rdata;1847	struct fc_frame *fp = rx_fp;1848	struct fc_els_flogi *pl;1849	struct fc_seq_els_data rjt_data;1850	u32 sid;1851 1852	lockdep_assert_held(&lport->lp_mutex);1853 1854	sid = fc_frame_sid(fp);1855 1856	FC_RPORT_ID_DBG(lport, sid, "Received PLOGI request\n");1857 1858	pl = fc_frame_payload_get(fp, sizeof(*pl));1859	if (!pl) {1860		FC_RPORT_ID_DBG(lport, sid, "Received PLOGI too short\n");1861		rjt_data.reason = ELS_RJT_PROT;1862		rjt_data.explan = ELS_EXPL_INV_LEN;1863		goto reject;1864	}1865 1866	disc = &lport->disc;1867	mutex_lock(&disc->disc_mutex);1868	rdata = fc_rport_create(lport, sid);1869	if (!rdata) {1870		mutex_unlock(&disc->disc_mutex);1871		rjt_data.reason = ELS_RJT_UNAB;1872		rjt_data.explan = ELS_EXPL_INSUF_RES;1873		goto reject;1874	}1875 1876	mutex_lock(&rdata->rp_mutex);1877	mutex_unlock(&disc->disc_mutex);1878 1879	rdata->ids.port_name = get_unaligned_be64(&pl->fl_wwpn);1880	rdata->ids.node_name = get_unaligned_be64(&pl->fl_wwnn);1881 1882	/*1883	 * If the rport was just created, possibly due to the incoming PLOGI,1884	 * set the state appropriately and accept the PLOGI.1885	 *1886	 * If we had also sent a PLOGI, and if the received PLOGI is from a1887	 * higher WWPN, we accept it, otherwise an LS_RJT is sent with reason1888	 * "command already in progress".1889	 *1890	 * XXX TBD: If the session was ready before, the PLOGI should result in1891	 * all outstanding exchanges being reset.1892	 */1893	switch (rdata->rp_state) {1894	case RPORT_ST_INIT:1895		FC_RPORT_DBG(rdata, "Received PLOGI in INIT state\n");1896		break;1897	case RPORT_ST_PLOGI_WAIT:1898		FC_RPORT_DBG(rdata, "Received PLOGI in PLOGI_WAIT state\n");1899		break;1900	case RPORT_ST_PLOGI:1901		FC_RPORT_DBG(rdata, "Received PLOGI in PLOGI state\n");1902		if (rdata->ids.port_name < lport->wwpn) {1903			mutex_unlock(&rdata->rp_mutex);1904			rjt_data.reason = ELS_RJT_INPROG;1905			rjt_data.explan = ELS_EXPL_NONE;1906			goto reject;1907		}1908		break;1909	case RPORT_ST_PRLI:1910	case RPORT_ST_RTV:1911	case RPORT_ST_READY:1912	case RPORT_ST_ADISC:1913		FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d "1914			     "- ignored for now\n", rdata->rp_state);1915		/* XXX TBD - should reset */1916		break;1917	case RPORT_ST_FLOGI:1918	case RPORT_ST_DELETE:1919		FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n",1920			     fc_rport_state(rdata));1921		mutex_unlock(&rdata->rp_mutex);1922		rjt_data.reason = ELS_RJT_BUSY;1923		rjt_data.explan = ELS_EXPL_NONE;1924		goto reject;1925	}1926	if (!fc_rport_compatible_roles(lport, rdata)) {1927		FC_RPORT_DBG(rdata, "Received PLOGI for incompatible role\n");1928		mutex_unlock(&rdata->rp_mutex);1929		rjt_data.reason = ELS_RJT_LOGIC;1930		rjt_data.explan = ELS_EXPL_NONE;1931		goto reject;1932	}1933 1934	/*1935	 * Get session payload size from incoming PLOGI.1936	 */1937	rdata->maxframe_size = fc_plogi_get_maxframe(pl, lport->mfs);1938 1939	/*1940	 * Send LS_ACC.	 If this fails, the originator should retry.1941	 */1942	fp = fc_frame_alloc(lport, sizeof(*pl));1943	if (!fp)1944		goto out;1945 1946	fc_plogi_fill(lport, fp, ELS_LS_ACC);1947	fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);1948	lport->tt.frame_send(lport, fp);1949	fc_rport_enter_prli(rdata);1950out:1951	mutex_unlock(&rdata->rp_mutex);1952	fc_frame_free(rx_fp);1953	return;1954 1955reject:1956	fc_seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);1957	fc_frame_free(fp);1958}1959 1960/**1961 * fc_rport_recv_prli_req() - Handler for process login (PRLI) requests1962 * @rdata: The remote port that sent the PRLI request1963 * @rx_fp: The PRLI request frame1964 */1965static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,1966				   struct fc_frame *rx_fp)1967{1968	struct fc_lport *lport = rdata->local_port;1969	struct fc_frame *fp;1970	struct {1971		struct fc_els_prli prli;1972		struct fc_els_spp spp;1973	} *pp;1974	struct fc_els_spp *rspp;	/* request service param page */1975	struct fc_els_spp *spp;	/* response spp */1976	unsigned int len;1977	unsigned int plen;1978	enum fc_els_spp_resp resp;1979	struct fc_seq_els_data rjt_data;1980	struct fc4_prov *prov;1981 1982	lockdep_assert_held(&rdata->rp_mutex);1983 1984	FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n",1985		     fc_rport_state(rdata));1986 1987	len = fr_len(rx_fp) - sizeof(struct fc_frame_header);1988	pp = fc_frame_payload_get(rx_fp, sizeof(*pp));1989	if (!pp)1990		goto reject_len;1991	plen = ntohs(pp->prli.prli_len);1992	if ((plen % 4) != 0 || plen > len || plen < 16)1993		goto reject_len;1994	if (plen < len)1995		len = plen;1996	plen = pp->prli.prli_spp_len;1997	if ((plen % 4) != 0 || plen < sizeof(*spp) ||1998	    plen > len || len < sizeof(*pp) || plen < 12)1999		goto reject_len;2000	rspp = &pp->spp;2001 2002	fp = fc_frame_alloc(lport, len);2003	if (!fp) {2004		rjt_data.reason = ELS_RJT_UNAB;2005		rjt_data.explan = ELS_EXPL_INSUF_RES;2006		goto reject;2007	}2008	pp = fc_frame_payload_get(fp, len);2009	WARN_ON(!pp);2010	memset(pp, 0, len);2011	pp->prli.prli_cmd = ELS_LS_ACC;2012	pp->prli.prli_spp_len = plen;2013	pp->prli.prli_len = htons(len);2014	len -= sizeof(struct fc_els_prli);2015 2016	/*2017	 * Go through all the service parameter pages and build2018	 * response.  If plen indicates longer SPP than standard,2019	 * use that.  The entire response has been pre-cleared above.2020	 */2021	spp = &pp->spp;2022	mutex_lock(&fc_prov_mutex);2023	while (len >= plen) {2024		rdata->spp_type = rspp->spp_type;2025		spp->spp_type = rspp->spp_type;2026		spp->spp_type_ext = rspp->spp_type_ext;2027		resp = 0;2028 2029		if (rspp->spp_type < FC_FC4_PROV_SIZE) {2030			enum fc_els_spp_resp active = 0, passive = 0;2031 2032			prov = fc_active_prov[rspp->spp_type];2033			if (prov)2034				active = prov->prli(rdata, plen, rspp, spp);2035			prov = fc_passive_prov[rspp->spp_type];2036			if (prov)2037				passive = prov->prli(rdata, plen, rspp, spp);2038			if (!active || passive == FC_SPP_RESP_ACK)2039				resp = passive;2040			else2041				resp = active;2042			FC_RPORT_DBG(rdata, "PRLI rspp type %x "2043				     "active %x passive %x\n",2044				     rspp->spp_type, active, passive);2045		}2046		if (!resp) {2047			if (spp->spp_flags & FC_SPP_EST_IMG_PAIR)2048				resp |= FC_SPP_RESP_CONF;2049			else2050				resp |= FC_SPP_RESP_INVL;2051		}2052		spp->spp_flags |= resp;2053		len -= plen;2054		rspp = (struct fc_els_spp *)((char *)rspp + plen);2055		spp = (struct fc_els_spp *)((char *)spp + plen);2056	}2057	mutex_unlock(&fc_prov_mutex);2058 2059	/*2060	 * Send LS_ACC.	 If this fails, the originator should retry.2061	 */2062	fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);2063	lport->tt.frame_send(lport, fp);2064 2065	goto drop;2066 2067reject_len:2068	rjt_data.reason = ELS_RJT_PROT;2069	rjt_data.explan = ELS_EXPL_INV_LEN;2070reject:2071	fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);2072drop:2073	fc_frame_free(rx_fp);2074}2075 2076/**2077 * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests2078 * @rdata: The remote port that sent the PRLO request2079 * @rx_fp: The PRLO request frame2080 */2081static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,2082				   struct fc_frame *rx_fp)2083{2084	struct fc_lport *lport = rdata->local_port;2085	struct fc_frame *fp;2086	struct {2087		struct fc_els_prlo prlo;2088		struct fc_els_spp spp;2089	} *pp;2090	struct fc_els_spp *rspp;	/* request service param page */2091	struct fc_els_spp *spp;		/* response spp */2092	unsigned int len;2093	unsigned int plen;2094	struct fc_seq_els_data rjt_data;2095 2096	lockdep_assert_held(&rdata->rp_mutex);2097 2098	FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n",2099		     fc_rport_state(rdata));2100 2101	len = fr_len(rx_fp) - sizeof(struct fc_frame_header);2102	pp = fc_frame_payload_get(rx_fp, sizeof(*pp));2103	if (!pp)2104		goto reject_len;2105	plen = ntohs(pp->prlo.prlo_len);2106	if (plen != 20)2107		goto reject_len;2108	if (plen < len)2109		len = plen;2110 2111	rspp = &pp->spp;2112 2113	fp = fc_frame_alloc(lport, len);2114	if (!fp) {2115		rjt_data.reason = ELS_RJT_UNAB;2116		rjt_data.explan = ELS_EXPL_INSUF_RES;2117		goto reject;2118	}2119 2120	pp = fc_frame_payload_get(fp, len);2121	WARN_ON(!pp);2122	memset(pp, 0, len);2123	pp->prlo.prlo_cmd = ELS_LS_ACC;2124	pp->prlo.prlo_obs = 0x10;2125	pp->prlo.prlo_len = htons(len);2126	spp = &pp->spp;2127	spp->spp_type = rspp->spp_type;2128	spp->spp_type_ext = rspp->spp_type_ext;2129	spp->spp_flags = FC_SPP_RESP_ACK;2130 2131	fc_rport_enter_prli(rdata);2132 2133	fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);2134	lport->tt.frame_send(lport, fp);2135	goto drop;2136 2137reject_len:2138	rjt_data.reason = ELS_RJT_PROT;2139	rjt_data.explan = ELS_EXPL_INV_LEN;2140reject:2141	fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);2142drop:2143	fc_frame_free(rx_fp);2144}2145 2146/**2147 * fc_rport_recv_logo_req() - Handler for logout (LOGO) requests2148 * @lport: The local port that received the LOGO request2149 * @fp:	   The LOGO request frame2150 *2151 * Reference counting: drops kref on return2152 */2153static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)2154{2155	struct fc_rport_priv *rdata;2156	u32 sid;2157 2158	lockdep_assert_held(&lport->lp_mutex);2159 2160	fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL);2161 2162	sid = fc_frame_sid(fp);2163 2164	rdata = fc_rport_lookup(lport, sid);2165	if (rdata) {2166		mutex_lock(&rdata->rp_mutex);2167		FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",2168			     fc_rport_state(rdata));2169 2170		fc_rport_enter_delete(rdata, RPORT_EV_STOP);2171		mutex_unlock(&rdata->rp_mutex);2172		kref_put(&rdata->kref, fc_rport_destroy);2173	} else2174		FC_RPORT_ID_DBG(lport, sid,2175				"Received LOGO from non-logged-in port\n");2176	fc_frame_free(fp);2177}2178 2179/**2180 * fc_rport_flush_queue() - Flush the rport_event_queue2181 */2182void fc_rport_flush_queue(void)2183{2184	flush_workqueue(rport_event_queue);2185}2186EXPORT_SYMBOL(fc_rport_flush_queue);2187 2188/**2189 * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator.2190 * @rdata: remote port private2191 * @spp_len: service parameter page length2192 * @rspp: received service parameter page2193 * @spp: response service parameter page2194 *2195 * Returns the value for the response code to be placed in spp_flags;2196 * Returns 0 if not an initiator.2197 */2198static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len,2199			     const struct fc_els_spp *rspp,2200			     struct fc_els_spp *spp)2201{2202	struct fc_lport *lport = rdata->local_port;2203	u32 fcp_parm;2204 2205	fcp_parm = ntohl(rspp->spp_params);2206	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;2207	if (fcp_parm & FCP_SPPF_INIT_FCN)2208		rdata->ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;2209	if (fcp_parm & FCP_SPPF_TARG_FCN)2210		rdata->ids.roles |= FC_RPORT_ROLE_FCP_TARGET;2211	if (fcp_parm & FCP_SPPF_RETRY)2212		rdata->flags |= FC_RP_FLAGS_RETRY;2213	rdata->supported_classes = FC_COS_CLASS3;2214 2215	if (!(lport->service_params & FCP_SPPF_INIT_FCN))2216		return 0;2217 2218	spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR;2219 2220	/*2221	 * OR in our service parameters with other providers (target), if any.2222	 */2223	fcp_parm = ntohl(spp->spp_params);2224	spp->spp_params = htonl(fcp_parm | lport->service_params);2225	return FC_SPP_RESP_ACK;2226}2227 2228/*2229 * FC-4 provider ops for FCP initiator.2230 */2231struct fc4_prov fc_rport_fcp_init = {2232	.prli = fc_rport_fcp_prli,2233};2234 2235/**2236 * fc_rport_t0_prli() - Handle incoming PRLI parameters for type 02237 * @rdata: remote port private2238 * @spp_len: service parameter page length2239 * @rspp: received service parameter page2240 * @spp: response service parameter page2241 */2242static int fc_rport_t0_prli(struct fc_rport_priv *rdata, u32 spp_len,2243			    const struct fc_els_spp *rspp,2244			    struct fc_els_spp *spp)2245{2246	if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR)2247		return FC_SPP_RESP_INVL;2248	return FC_SPP_RESP_ACK;2249}2250 2251/*2252 * FC-4 provider ops for type 0 service parameters.2253 *2254 * This handles the special case of type 0 which is always successful2255 * but doesn't do anything otherwise.2256 */2257struct fc4_prov fc_rport_t0_prov = {2258	.prli = fc_rport_t0_prli,2259};2260 2261/**2262 * fc_setup_rport() - Initialize the rport_event_queue2263 */2264int fc_setup_rport(void)2265{2266	rport_event_queue =2267		alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, "fc_rport_eq");2268	if (!rport_event_queue)2269		return -ENOMEM;2270	return 0;2271}2272 2273/**2274 * fc_destroy_rport() - Destroy the rport_event_queue2275 */2276void fc_destroy_rport(void)2277{2278	destroy_workqueue(rport_event_queue);2279}2280 2281/**2282 * fc_rport_terminate_io() - Stop all outstanding I/O on a remote port2283 * @rport: The remote port whose I/O should be terminated2284 */2285void fc_rport_terminate_io(struct fc_rport *rport)2286{2287	struct fc_rport_libfc_priv *rpriv = rport->dd_data;2288	struct fc_lport *lport = rpriv->local_port;2289 2290	lport->tt.exch_mgr_reset(lport, 0, rport->port_id);2291	lport->tt.exch_mgr_reset(lport, rport->port_id, 0);2292}2293EXPORT_SYMBOL(fc_rport_terminate_io);2294