brintos

brintos / linux-shallow public Read only

0
0
Text · 58.1 KiB · 310fa5a Raw
2201 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright(c) 2007 Intel Corporation. All rights reserved.4 *5 * Maintained at www.Open-FCoE.org6 */7 8/*9 * PORT LOCKING NOTES10 *11 * These comments only apply to the 'port code' which consists of the lport,12 * disc and rport blocks.13 *14 * MOTIVATION15 *16 * The lport, disc and rport blocks all have mutexes that are used to protect17 * those objects. The main motivation for these locks is to prevent from18 * having an lport reset just before we send a frame. In that scenario the19 * lport's FID would get set to zero and then we'd send a frame with an20 * invalid SID. We also need to ensure that states don't change unexpectedly21 * while processing another state.22 *23 * HIERARCHY24 *25 * The following hierarchy defines the locking rules. A greater lock26 * may be held before acquiring a lesser lock, but a lesser lock should never27 * be held while attempting to acquire a greater lock. Here is the hierarchy-28 *29 * lport > disc, lport > rport, disc > rport30 *31 * CALLBACKS32 *33 * The callbacks cause complications with this scheme. There is a callback34 * from the rport (to either lport or disc) and a callback from disc35 * (to the lport).36 *37 * As rports exit the rport state machine a callback is made to the owner of38 * the rport to notify success or failure. Since the callback is likely to39 * cause the lport or disc to grab its lock we cannot hold the rport lock40 * while making the callback. To ensure that the rport is not free'd while41 * processing the callback the rport callbacks are serialized through a42 * single-threaded workqueue. An rport would never be free'd while in a43 * callback handler because no other rport work in this queue can be executed44 * at the same time.45 *46 * When discovery succeeds or fails a callback is made to the lport as47 * notification. Currently, successful discovery causes the lport to take no48 * action. A failure will cause the lport to reset. There is likely a circular49 * locking problem with this implementation.50 */51 52/*53 * LPORT LOCKING54 *55 * The critical sections protected by the lport's mutex are quite broad and56 * may be improved upon in the future. The lport code and its locking doesn't57 * influence the I/O path, so excessive locking doesn't penalize I/O58 * performance.59 *60 * The strategy is to lock whenever processing a request or response. Note61 * that every _enter_* function corresponds to a state change. They generally62 * change the lports state and then send a request out on the wire. We lock63 * before calling any of these functions to protect that state change. This64 * means that the entry points into the lport block manage the locks while65 * the state machine can transition between states (i.e. _enter_* functions)66 * while always staying protected.67 *68 * When handling responses we also hold the lport mutex broadly. When the69 * lport receives the response frame it locks the mutex and then calls the70 * appropriate handler for the particuar response. Generally a response will71 * trigger a state change and so the lock must already be held.72 *73 * Retries also have to consider the locking. The retries occur from a work74 * context and the work function will lock the lport and then retry the state75 * (i.e. _enter_* function).76 */77 78#include <linux/timer.h>79#include <linux/delay.h>80#include <linux/module.h>81#include <linux/slab.h>82#include <linux/unaligned.h>83 84#include <scsi/fc/fc_gs.h>85 86#include <scsi/libfc.h>87#include <linux/scatterlist.h>88 89#include "fc_encode.h"90#include "fc_libfc.h"91 92/* Fabric IDs to use for point-to-point mode, chosen on whims. */93#define FC_LOCAL_PTP_FID_LO   0x01010194#define FC_LOCAL_PTP_FID_HI   0x01010295 96#define	DNS_DELAY		3 /* Discovery delay after RSCN (in seconds)*/97#define	MAX_CT_PAYLOAD		204898#define	DISCOVERED_PORTS	499#define	NUMBER_OF_PORTS		1100 101static void fc_lport_error(struct fc_lport *, struct fc_frame *);102 103static void fc_lport_enter_reset(struct fc_lport *);104static void fc_lport_enter_flogi(struct fc_lport *);105static void fc_lport_enter_dns(struct fc_lport *);106static void fc_lport_enter_ns(struct fc_lport *, enum fc_lport_state);107static void fc_lport_enter_scr(struct fc_lport *);108static void fc_lport_enter_ready(struct fc_lport *);109static void fc_lport_enter_logo(struct fc_lport *);110static void fc_lport_enter_fdmi(struct fc_lport *lport);111static void fc_lport_enter_ms(struct fc_lport *, enum fc_lport_state);112 113static const char *fc_lport_state_names[] = {114	[LPORT_ST_DISABLED] = "disabled",115	[LPORT_ST_FLOGI] =    "FLOGI",116	[LPORT_ST_DNS] =      "dNS",117	[LPORT_ST_RNN_ID] =   "RNN_ID",118	[LPORT_ST_RSNN_NN] =  "RSNN_NN",119	[LPORT_ST_RSPN_ID] =  "RSPN_ID",120	[LPORT_ST_RFT_ID] =   "RFT_ID",121	[LPORT_ST_RFF_ID] =   "RFF_ID",122	[LPORT_ST_FDMI] =     "FDMI",123	[LPORT_ST_RHBA] =     "RHBA",124	[LPORT_ST_RPA] =      "RPA",125	[LPORT_ST_DHBA] =     "DHBA",126	[LPORT_ST_DPRT] =     "DPRT",127	[LPORT_ST_SCR] =      "SCR",128	[LPORT_ST_READY] =    "Ready",129	[LPORT_ST_LOGO] =     "LOGO",130	[LPORT_ST_RESET] =    "reset",131};132 133/**134 * struct fc_bsg_info - FC Passthrough managemet structure135 * @job:      The passthrough job136 * @lport:    The local port to pass through a command137 * @rsp_code: The expected response code138 * @sg:	      job->reply_payload.sg_list139 * @nents:    job->reply_payload.sg_cnt140 * @offset:   The offset into the response data141 */142struct fc_bsg_info {143	struct bsg_job *job;144	struct fc_lport *lport;145	u16 rsp_code;146	struct scatterlist *sg;147	u32 nents;148	size_t offset;149};150 151/**152 * fc_frame_drop() - Dummy frame handler153 * @lport: The local port the frame was received on154 * @fp:	   The received frame155 */156static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)157{158	fc_frame_free(fp);159	return 0;160}161 162/**163 * fc_lport_rport_callback() - Event handler for rport events164 * @lport: The lport which is receiving the event165 * @rdata: private remote port data166 * @event: The event that occurred167 *168 * Locking Note: The rport lock should not be held when calling169 *		 this function.170 */171static void fc_lport_rport_callback(struct fc_lport *lport,172				    struct fc_rport_priv *rdata,173				    enum fc_rport_event event)174{175	FC_LPORT_DBG(lport, "Received a %d event for port (%6.6x)\n", event,176		     rdata->ids.port_id);177 178	mutex_lock(&lport->lp_mutex);179	switch (event) {180	case RPORT_EV_READY:181		if (lport->state == LPORT_ST_DNS) {182			lport->dns_rdata = rdata;183			fc_lport_enter_ns(lport, LPORT_ST_RNN_ID);184		} else if (lport->state == LPORT_ST_FDMI) {185			lport->ms_rdata = rdata;186			fc_lport_enter_ms(lport, LPORT_ST_DHBA);187		} else {188			FC_LPORT_DBG(lport, "Received an READY event "189				     "on port (%6.6x) for the directory "190				     "server, but the lport is not "191				     "in the DNS or FDMI state, it's in the "192				     "%d state", rdata->ids.port_id,193				     lport->state);194			fc_rport_logoff(rdata);195		}196		break;197	case RPORT_EV_LOGO:198	case RPORT_EV_FAILED:199	case RPORT_EV_STOP:200		if (rdata->ids.port_id == FC_FID_DIR_SERV)201			lport->dns_rdata = NULL;202		else if (rdata->ids.port_id == FC_FID_MGMT_SERV)203			lport->ms_rdata = NULL;204		break;205	case RPORT_EV_NONE:206		break;207	}208	mutex_unlock(&lport->lp_mutex);209}210 211/**212 * fc_lport_state() - Return a string which represents the lport's state213 * @lport: The lport whose state is to converted to a string214 */215static const char *fc_lport_state(struct fc_lport *lport)216{217	const char *cp;218 219	cp = fc_lport_state_names[lport->state];220	if (!cp)221		cp = "unknown";222	return cp;223}224 225/**226 * fc_lport_ptp_setup() - Create an rport for point-to-point mode227 * @lport:	 The lport to attach the ptp rport to228 * @remote_fid:	 The FID of the ptp rport229 * @remote_wwpn: The WWPN of the ptp rport230 * @remote_wwnn: The WWNN of the ptp rport231 */232static void fc_lport_ptp_setup(struct fc_lport *lport,233			       u32 remote_fid, u64 remote_wwpn,234			       u64 remote_wwnn)235{236	lockdep_assert_held(&lport->lp_mutex);237 238	if (lport->ptp_rdata) {239		fc_rport_logoff(lport->ptp_rdata);240		kref_put(&lport->ptp_rdata->kref, fc_rport_destroy);241	}242	mutex_lock(&lport->disc.disc_mutex);243	lport->ptp_rdata = fc_rport_create(lport, remote_fid);244	if (!lport->ptp_rdata) {245		printk(KERN_WARNING "libfc: Failed to setup lport 0x%x\n",246			lport->port_id);247		mutex_unlock(&lport->disc.disc_mutex);248		return;249	}250	kref_get(&lport->ptp_rdata->kref);251	lport->ptp_rdata->ids.port_name = remote_wwpn;252	lport->ptp_rdata->ids.node_name = remote_wwnn;253	mutex_unlock(&lport->disc.disc_mutex);254 255	fc_rport_login(lport->ptp_rdata);256 257	fc_lport_enter_ready(lport);258}259 260/**261 * fc_get_host_port_state() - Return the port state of the given Scsi_Host262 * @shost:  The SCSI host whose port state is to be determined263 */264void fc_get_host_port_state(struct Scsi_Host *shost)265{266	struct fc_lport *lport = shost_priv(shost);267 268	mutex_lock(&lport->lp_mutex);269	if (!lport->link_up)270		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;271	else272		switch (lport->state) {273		case LPORT_ST_READY:274			fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;275			break;276		default:277			fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;278		}279	mutex_unlock(&lport->lp_mutex);280}281EXPORT_SYMBOL(fc_get_host_port_state);282 283/**284 * fc_get_host_speed() - Return the speed of the given Scsi_Host285 * @shost: The SCSI host whose port speed is to be determined286 */287void fc_get_host_speed(struct Scsi_Host *shost)288{289	struct fc_lport *lport = shost_priv(shost);290 291	fc_host_speed(shost) = lport->link_speed;292}293EXPORT_SYMBOL(fc_get_host_speed);294 295/**296 * fc_get_host_stats() - Return the Scsi_Host's statistics297 * @shost: The SCSI host whose statistics are to be returned298 */299struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)300{301	struct fc_host_statistics *fc_stats;302	struct fc_lport *lport = shost_priv(shost);303	unsigned int cpu;304	u64 fcp_in_bytes = 0;305	u64 fcp_out_bytes = 0;306 307	fc_stats = &lport->host_stats;308	memset(fc_stats, 0, sizeof(struct fc_host_statistics));309 310	fc_stats->seconds_since_last_reset = (jiffies - lport->boot_time) / HZ;311 312	for_each_possible_cpu(cpu) {313		struct fc_stats *stats;314 315		stats = per_cpu_ptr(lport->stats, cpu);316 317		fc_stats->tx_frames += READ_ONCE(stats->TxFrames);318		fc_stats->tx_words += READ_ONCE(stats->TxWords);319		fc_stats->rx_frames += READ_ONCE(stats->RxFrames);320		fc_stats->rx_words += READ_ONCE(stats->RxWords);321		fc_stats->error_frames += READ_ONCE(stats->ErrorFrames);322		fc_stats->invalid_crc_count += READ_ONCE(stats->InvalidCRCCount);323		fc_stats->fcp_input_requests += READ_ONCE(stats->InputRequests);324		fc_stats->fcp_output_requests += READ_ONCE(stats->OutputRequests);325		fc_stats->fcp_control_requests += READ_ONCE(stats->ControlRequests);326		fcp_in_bytes += READ_ONCE(stats->InputBytes);327		fcp_out_bytes += READ_ONCE(stats->OutputBytes);328		fc_stats->fcp_packet_alloc_failures += READ_ONCE(stats->FcpPktAllocFails);329		fc_stats->fcp_packet_aborts += READ_ONCE(stats->FcpPktAborts);330		fc_stats->fcp_frame_alloc_failures += READ_ONCE(stats->FcpFrameAllocFails);331		fc_stats->link_failure_count += READ_ONCE(stats->LinkFailureCount);332	}333	fc_stats->fcp_input_megabytes = div_u64(fcp_in_bytes, 1000000);334	fc_stats->fcp_output_megabytes = div_u64(fcp_out_bytes, 1000000);335	fc_stats->lip_count = -1;336	fc_stats->nos_count = -1;337	fc_stats->loss_of_sync_count = -1;338	fc_stats->loss_of_signal_count = -1;339	fc_stats->prim_seq_protocol_err_count = -1;340	fc_stats->dumped_frames = -1;341 342	/* update exches stats */343	fc_exch_update_stats(lport);344 345	return fc_stats;346}347EXPORT_SYMBOL(fc_get_host_stats);348 349/**350 * fc_lport_flogi_fill() - Fill in FLOGI command for request351 * @lport: The local port the FLOGI is for352 * @flogi: The FLOGI command353 * @op:	   The opcode354 */355static void fc_lport_flogi_fill(struct fc_lport *lport,356				struct fc_els_flogi *flogi,357				unsigned int op)358{359	struct fc_els_csp *sp;360	struct fc_els_cssp *cp;361 362	memset(flogi, 0, sizeof(*flogi));363	flogi->fl_cmd = (u8) op;364	put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);365	put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);366	sp = &flogi->fl_csp;367	sp->sp_hi_ver = 0x20;368	sp->sp_lo_ver = 0x20;369	sp->sp_bb_cred = htons(10);	/* this gets set by gateway */370	sp->sp_bb_data = htons((u16) lport->mfs);371	cp = &flogi->fl_cssp[3 - 1];	/* class 3 parameters */372	cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);373	if (op != ELS_FLOGI) {374		sp->sp_features = htons(FC_SP_FT_CIRO);375		sp->sp_tot_seq = htons(255);	/* seq. we accept */376		sp->sp_rel_off = htons(0x1f);377		sp->sp_e_d_tov = htonl(lport->e_d_tov);378 379		cp->cp_rdfs = htons((u16) lport->mfs);380		cp->cp_con_seq = htons(255);381		cp->cp_open_seq = 1;382	}383}384 385/**386 * fc_lport_add_fc4_type() - Add a supported FC-4 type to a local port387 * @lport: The local port to add a new FC-4 type to388 * @type:  The new FC-4 type389 */390static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type)391{392	__be32 *mp;393 394	mp = &lport->fcts.ff_type_map[type / FC_NS_BPW];395	*mp = htonl(ntohl(*mp) | 1UL << (type % FC_NS_BPW));396}397 398/**399 * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report.400 * @lport: Fibre Channel local port receiving the RLIR401 * @fp:	   The RLIR request frame402 */403static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp)404{405	lockdep_assert_held(&lport->lp_mutex);406 407	FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n",408		     fc_lport_state(lport));409 410	fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL);411	fc_frame_free(fp);412}413 414/**415 * fc_lport_recv_echo_req() - Handle received ECHO request416 * @lport: The local port receiving the ECHO417 * @in_fp: ECHO request frame418 */419static void fc_lport_recv_echo_req(struct fc_lport *lport,420				   struct fc_frame *in_fp)421{422	struct fc_frame *fp;423	unsigned int len;424	void *pp;425	void *dp;426 427	lockdep_assert_held(&lport->lp_mutex);428 429	FC_LPORT_DBG(lport, "Received ECHO request while in state %s\n",430		     fc_lport_state(lport));431 432	len = fr_len(in_fp) - sizeof(struct fc_frame_header);433	pp = fc_frame_payload_get(in_fp, len);434 435	if (len < sizeof(__be32))436		len = sizeof(__be32);437 438	fp = fc_frame_alloc(lport, len);439	if (fp) {440		dp = fc_frame_payload_get(fp, len);441		memcpy(dp, pp, len);442		*((__be32 *)dp) = htonl(ELS_LS_ACC << 24);443		fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0);444		lport->tt.frame_send(lport, fp);445	}446	fc_frame_free(in_fp);447}448 449/**450 * fc_lport_recv_rnid_req() - Handle received Request Node ID data request451 * @lport: The local port receiving the RNID452 * @in_fp: The RNID request frame453 */454static void fc_lport_recv_rnid_req(struct fc_lport *lport,455				   struct fc_frame *in_fp)456{457	struct fc_frame *fp;458	struct fc_els_rnid *req;459	struct {460		struct fc_els_rnid_resp rnid;461		struct fc_els_rnid_cid cid;462		struct fc_els_rnid_gen gen;463	} *rp;464	struct fc_seq_els_data rjt_data;465	u8 fmt;466	size_t len;467 468	lockdep_assert_held(&lport->lp_mutex);469 470	FC_LPORT_DBG(lport, "Received RNID request while in state %s\n",471		     fc_lport_state(lport));472 473	req = fc_frame_payload_get(in_fp, sizeof(*req));474	if (!req) {475		rjt_data.reason = ELS_RJT_LOGIC;476		rjt_data.explan = ELS_EXPL_NONE;477		fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);478	} else {479		fmt = req->rnid_fmt;480		len = sizeof(*rp);481		if (fmt != ELS_RNIDF_GEN ||482		    ntohl(lport->rnid_gen.rnid_atype) == 0) {483			fmt = ELS_RNIDF_NONE;	/* nothing to provide */484			len -= sizeof(rp->gen);485		}486		fp = fc_frame_alloc(lport, len);487		if (fp) {488			rp = fc_frame_payload_get(fp, len);489			memset(rp, 0, len);490			rp->rnid.rnid_cmd = ELS_LS_ACC;491			rp->rnid.rnid_fmt = fmt;492			rp->rnid.rnid_cid_len = sizeof(rp->cid);493			rp->cid.rnid_wwpn = htonll(lport->wwpn);494			rp->cid.rnid_wwnn = htonll(lport->wwnn);495			if (fmt == ELS_RNIDF_GEN) {496				rp->rnid.rnid_sid_len = sizeof(rp->gen);497				memcpy(&rp->gen, &lport->rnid_gen,498				       sizeof(rp->gen));499			}500			fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0);501			lport->tt.frame_send(lport, fp);502		}503	}504	fc_frame_free(in_fp);505}506 507/**508 * fc_lport_recv_logo_req() - Handle received fabric LOGO request509 * @lport: The local port receiving the LOGO510 * @fp:	   The LOGO request frame511 */512static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)513{514	lockdep_assert_held(&lport->lp_mutex);515 516	fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL);517	fc_lport_enter_reset(lport);518	fc_frame_free(fp);519}520 521/**522 * fc_fabric_login() - Start the lport state machine523 * @lport: The local port that should log into the fabric524 *525 * Locking Note: This function should not be called526 *		 with the lport lock held.527 */528int fc_fabric_login(struct fc_lport *lport)529{530	int rc = -1;531 532	mutex_lock(&lport->lp_mutex);533	if (lport->state == LPORT_ST_DISABLED ||534	    lport->state == LPORT_ST_LOGO) {535		fc_lport_state_enter(lport, LPORT_ST_RESET);536		fc_lport_enter_reset(lport);537		rc = 0;538	}539	mutex_unlock(&lport->lp_mutex);540 541	return rc;542}543EXPORT_SYMBOL(fc_fabric_login);544 545/**546 * __fc_linkup() - Handler for transport linkup events547 * @lport: The lport whose link is up548 */549void __fc_linkup(struct fc_lport *lport)550{551	lockdep_assert_held(&lport->lp_mutex);552 553	if (!lport->link_up) {554		lport->link_up = 1;555 556		if (lport->state == LPORT_ST_RESET)557			fc_lport_enter_flogi(lport);558	}559}560 561/**562 * fc_linkup() - Handler for transport linkup events563 * @lport: The local port whose link is up564 */565void fc_linkup(struct fc_lport *lport)566{567	printk(KERN_INFO "host%d: libfc: Link up on port (%6.6x)\n",568	       lport->host->host_no, lport->port_id);569 570	mutex_lock(&lport->lp_mutex);571	__fc_linkup(lport);572	mutex_unlock(&lport->lp_mutex);573}574EXPORT_SYMBOL(fc_linkup);575 576/**577 * __fc_linkdown() - Handler for transport linkdown events578 * @lport: The lport whose link is down579 */580void __fc_linkdown(struct fc_lport *lport)581{582	lockdep_assert_held(&lport->lp_mutex);583 584	if (lport->link_up) {585		lport->link_up = 0;586		fc_lport_enter_reset(lport);587		lport->tt.fcp_cleanup(lport);588	}589}590 591/**592 * fc_linkdown() - Handler for transport linkdown events593 * @lport: The local port whose link is down594 */595void fc_linkdown(struct fc_lport *lport)596{597	printk(KERN_INFO "host%d: libfc: Link down on port (%6.6x)\n",598	       lport->host->host_no, lport->port_id);599 600	mutex_lock(&lport->lp_mutex);601	__fc_linkdown(lport);602	mutex_unlock(&lport->lp_mutex);603}604EXPORT_SYMBOL(fc_linkdown);605 606/**607 * fc_fabric_logoff() - Logout of the fabric608 * @lport: The local port to logoff the fabric609 *610 * Return value:611 *	0 for success, -1 for failure612 */613int fc_fabric_logoff(struct fc_lport *lport)614{615	lport->tt.disc_stop_final(lport);616	mutex_lock(&lport->lp_mutex);617	if (lport->dns_rdata)618		fc_rport_logoff(lport->dns_rdata);619	mutex_unlock(&lport->lp_mutex);620	fc_rport_flush_queue();621	mutex_lock(&lport->lp_mutex);622	fc_lport_enter_logo(lport);623	mutex_unlock(&lport->lp_mutex);624	cancel_delayed_work_sync(&lport->retry_work);625	return 0;626}627EXPORT_SYMBOL(fc_fabric_logoff);628 629/**630 * fc_lport_destroy() - Unregister a fc_lport631 * @lport: The local port to unregister632 *633 * Note:634 * exit routine for fc_lport instance635 * clean-up all the allocated memory636 * and free up other system resources.637 *638 */639int fc_lport_destroy(struct fc_lport *lport)640{641	mutex_lock(&lport->lp_mutex);642	lport->state = LPORT_ST_DISABLED;643	lport->link_up = 0;644	lport->tt.frame_send = fc_frame_drop;645	mutex_unlock(&lport->lp_mutex);646 647	lport->tt.fcp_abort_io(lport);648	lport->tt.disc_stop_final(lport);649	lport->tt.exch_mgr_reset(lport, 0, 0);650	cancel_delayed_work_sync(&lport->retry_work);651	fc_fc4_del_lport(lport);652	return 0;653}654EXPORT_SYMBOL(fc_lport_destroy);655 656/**657 * fc_set_mfs() - Set the maximum frame size for a local port658 * @lport: The local port to set the MFS for659 * @mfs:   The new MFS660 */661int fc_set_mfs(struct fc_lport *lport, u32 mfs)662{663	unsigned int old_mfs;664	int rc = -EINVAL;665 666	mutex_lock(&lport->lp_mutex);667 668	old_mfs = lport->mfs;669 670	if (mfs >= FC_MIN_MAX_FRAME) {671		mfs &= ~3;672		if (mfs > FC_MAX_FRAME)673			mfs = FC_MAX_FRAME;674		mfs -= sizeof(struct fc_frame_header);675		lport->mfs = mfs;676		rc = 0;677	}678 679	if (!rc && mfs < old_mfs)680		fc_lport_enter_reset(lport);681 682	mutex_unlock(&lport->lp_mutex);683 684	return rc;685}686EXPORT_SYMBOL(fc_set_mfs);687 688/**689 * fc_lport_disc_callback() - Callback for discovery events690 * @lport: The local port receiving the event691 * @event: The discovery event692 */693static void fc_lport_disc_callback(struct fc_lport *lport,694				   enum fc_disc_event event)695{696	switch (event) {697	case DISC_EV_SUCCESS:698		FC_LPORT_DBG(lport, "Discovery succeeded\n");699		break;700	case DISC_EV_FAILED:701		printk(KERN_ERR "host%d: libfc: "702		       "Discovery failed for port (%6.6x)\n",703		       lport->host->host_no, lport->port_id);704		mutex_lock(&lport->lp_mutex);705		fc_lport_enter_reset(lport);706		mutex_unlock(&lport->lp_mutex);707		break;708	case DISC_EV_NONE:709		WARN_ON(1);710		break;711	}712}713 714/**715 * fc_lport_enter_ready() - Enter the ready state and start discovery716 * @lport: The local port that is ready717 */718static void fc_lport_enter_ready(struct fc_lport *lport)719{720	lockdep_assert_held(&lport->lp_mutex);721 722	FC_LPORT_DBG(lport, "Entered READY from state %s\n",723		     fc_lport_state(lport));724 725	fc_lport_state_enter(lport, LPORT_ST_READY);726	if (lport->vport)727		fc_vport_set_state(lport->vport, FC_VPORT_ACTIVE);728	fc_vports_linkchange(lport);729 730	if (!lport->ptp_rdata)731		lport->tt.disc_start(fc_lport_disc_callback, lport);732}733 734/**735 * fc_lport_set_port_id() - set the local port Port ID736 * @lport: The local port which will have its Port ID set.737 * @port_id: The new port ID.738 * @fp: The frame containing the incoming request, or NULL.739 */740static void fc_lport_set_port_id(struct fc_lport *lport, u32 port_id,741				 struct fc_frame *fp)742{743	lockdep_assert_held(&lport->lp_mutex);744 745	if (port_id)746		printk(KERN_INFO "host%d: Assigned Port ID %6.6x\n",747		       lport->host->host_no, port_id);748 749	lport->port_id = port_id;750 751	/* Update the fc_host */752	fc_host_port_id(lport->host) = port_id;753 754	if (lport->tt.lport_set_port_id)755		lport->tt.lport_set_port_id(lport, port_id, fp);756}757 758/**759 * fc_lport_set_local_id() - set the local port Port ID for point-to-multipoint760 * @lport: The local port which will have its Port ID set.761 * @port_id: The new port ID.762 *763 * Called by the lower-level driver when transport sets the local port_id.764 * This is used in VN_port to VN_port mode for FCoE, and causes FLOGI and765 * discovery to be skipped.766 */767void fc_lport_set_local_id(struct fc_lport *lport, u32 port_id)768{769	mutex_lock(&lport->lp_mutex);770 771	fc_lport_set_port_id(lport, port_id, NULL);772 773	switch (lport->state) {774	case LPORT_ST_RESET:775	case LPORT_ST_FLOGI:776		if (port_id)777			fc_lport_enter_ready(lport);778		break;779	default:780		break;781	}782	mutex_unlock(&lport->lp_mutex);783}784EXPORT_SYMBOL(fc_lport_set_local_id);785 786/**787 * fc_lport_recv_flogi_req() - Receive a FLOGI request788 * @lport: The local port that received the request789 * @rx_fp: The FLOGI frame790 *791 * A received FLOGI request indicates a point-to-point connection.792 * Accept it with the common service parameters indicating our N port.793 * Set up to do a PLOGI if we have the higher-number WWPN.794 */795static void fc_lport_recv_flogi_req(struct fc_lport *lport,796				    struct fc_frame *rx_fp)797{798	struct fc_frame *fp;799	struct fc_frame_header *fh;800	struct fc_els_flogi *flp;801	struct fc_els_flogi *new_flp;802	u64 remote_wwpn;803	u32 remote_fid;804	u32 local_fid;805 806	lockdep_assert_held(&lport->lp_mutex);807 808	FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n",809		     fc_lport_state(lport));810 811	remote_fid = fc_frame_sid(rx_fp);812	flp = fc_frame_payload_get(rx_fp, sizeof(*flp));813	if (!flp)814		goto out;815	remote_wwpn = get_unaligned_be64(&flp->fl_wwpn);816	if (remote_wwpn == lport->wwpn) {817		printk(KERN_WARNING "host%d: libfc: Received FLOGI from port "818		       "with same WWPN %16.16llx\n",819		       lport->host->host_no, remote_wwpn);820		goto out;821	}822	FC_LPORT_DBG(lport, "FLOGI from port WWPN %16.16llx\n", remote_wwpn);823 824	/*825	 * XXX what is the right thing to do for FIDs?826	 * The originator might expect our S_ID to be 0xfffffe.827	 * But if so, both of us could end up with the same FID.828	 */829	local_fid = FC_LOCAL_PTP_FID_LO;830	if (remote_wwpn < lport->wwpn) {831		local_fid = FC_LOCAL_PTP_FID_HI;832		if (!remote_fid || remote_fid == local_fid)833			remote_fid = FC_LOCAL_PTP_FID_LO;834	} else if (!remote_fid) {835		remote_fid = FC_LOCAL_PTP_FID_HI;836	}837 838	fc_lport_set_port_id(lport, local_fid, rx_fp);839 840	fp = fc_frame_alloc(lport, sizeof(*flp));841	if (fp) {842		new_flp = fc_frame_payload_get(fp, sizeof(*flp));843		fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI);844		new_flp->fl_cmd = (u8) ELS_LS_ACC;845 846		/*847		 * Send the response.  If this fails, the originator should848		 * repeat the sequence.849		 */850		fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);851		fh = fc_frame_header_get(fp);852		hton24(fh->fh_s_id, local_fid);853		hton24(fh->fh_d_id, remote_fid);854		lport->tt.frame_send(lport, fp);855 856	} else {857		fc_lport_error(lport, fp);858	}859	fc_lport_ptp_setup(lport, remote_fid, remote_wwpn,860			   get_unaligned_be64(&flp->fl_wwnn));861out:862	fc_frame_free(rx_fp);863}864 865/**866 * fc_lport_recv_els_req() - The generic lport ELS request handler867 * @lport: The local port that received the request868 * @fp:	   The request frame869 *870 * This function will see if the lport handles the request or871 * if an rport should handle the request.872 *873 * Locking Note: This function should not be called with the lport874 *		 lock held because it will grab the lock.875 */876static void fc_lport_recv_els_req(struct fc_lport *lport,877				  struct fc_frame *fp)878{879	mutex_lock(&lport->lp_mutex);880 881	/*882	 * Handle special ELS cases like FLOGI, LOGO, and883	 * RSCN here.  These don't require a session.884	 * Even if we had a session, it might not be ready.885	 */886	if (!lport->link_up)887		fc_frame_free(fp);888	else {889		/*890		 * Check opcode.891		 */892		switch (fc_frame_payload_op(fp)) {893		case ELS_FLOGI:894			if (!lport->point_to_multipoint)895				fc_lport_recv_flogi_req(lport, fp);896			else897				fc_rport_recv_req(lport, fp);898			break;899		case ELS_LOGO:900			if (fc_frame_sid(fp) == FC_FID_FLOGI)901				fc_lport_recv_logo_req(lport, fp);902			else903				fc_rport_recv_req(lport, fp);904			break;905		case ELS_RSCN:906			lport->tt.disc_recv_req(lport, fp);907			break;908		case ELS_ECHO:909			fc_lport_recv_echo_req(lport, fp);910			break;911		case ELS_RLIR:912			fc_lport_recv_rlir_req(lport, fp);913			break;914		case ELS_RNID:915			fc_lport_recv_rnid_req(lport, fp);916			break;917		default:918			fc_rport_recv_req(lport, fp);919			break;920		}921	}922	mutex_unlock(&lport->lp_mutex);923}924 925static int fc_lport_els_prli(struct fc_rport_priv *rdata, u32 spp_len,926			     const struct fc_els_spp *spp_in,927			     struct fc_els_spp *spp_out)928{929	return FC_SPP_RESP_INVL;930}931 932struct fc4_prov fc_lport_els_prov = {933	.prli = fc_lport_els_prli,934	.recv = fc_lport_recv_els_req,935};936 937/**938 * fc_lport_recv() - The generic lport request handler939 * @lport: The lport that received the request940 * @fp: The frame the request is in941 *942 * Locking Note: This function should not be called with the lport943 *		 lock held because it may grab the lock.944 */945void fc_lport_recv(struct fc_lport *lport, struct fc_frame *fp)946{947	struct fc_frame_header *fh = fc_frame_header_get(fp);948	struct fc_seq *sp = fr_seq(fp);949	struct fc4_prov *prov;950 951	/*952	 * Use RCU read lock and module_lock to be sure module doesn't953	 * deregister and get unloaded while we're calling it.954	 * try_module_get() is inlined and accepts a NULL parameter.955	 * Only ELSes and FCP target ops should come through here.956	 * The locking is unfortunate, and a better scheme is being sought.957	 */958 959	rcu_read_lock();960	if (fh->fh_type >= FC_FC4_PROV_SIZE)961		goto drop;962	prov = rcu_dereference(fc_passive_prov[fh->fh_type]);963	if (!prov || !try_module_get(prov->module))964		goto drop;965	rcu_read_unlock();966	prov->recv(lport, fp);967	module_put(prov->module);968	return;969drop:970	rcu_read_unlock();971	FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type);972	fc_frame_free(fp);973	if (sp)974		fc_exch_done(sp);975}976EXPORT_SYMBOL(fc_lport_recv);977 978/**979 * fc_lport_reset() - Reset a local port980 * @lport: The local port which should be reset981 *982 * Locking Note: This functions should not be called with the983 *		 lport lock held.984 */985int fc_lport_reset(struct fc_lport *lport)986{987	cancel_delayed_work_sync(&lport->retry_work);988	mutex_lock(&lport->lp_mutex);989	fc_lport_enter_reset(lport);990	mutex_unlock(&lport->lp_mutex);991	return 0;992}993EXPORT_SYMBOL(fc_lport_reset);994 995/**996 * fc_lport_reset_locked() - Reset the local port w/ the lport lock held997 * @lport: The local port to be reset998 */999static void fc_lport_reset_locked(struct fc_lport *lport)1000{1001	lockdep_assert_held(&lport->lp_mutex);1002 1003	if (lport->dns_rdata) {1004		fc_rport_logoff(lport->dns_rdata);1005		lport->dns_rdata = NULL;1006	}1007 1008	if (lport->ptp_rdata) {1009		fc_rport_logoff(lport->ptp_rdata);1010		kref_put(&lport->ptp_rdata->kref, fc_rport_destroy);1011		lport->ptp_rdata = NULL;1012	}1013 1014	lport->tt.disc_stop(lport);1015 1016	lport->tt.exch_mgr_reset(lport, 0, 0);1017	fc_host_fabric_name(lport->host) = 0;1018 1019	if (lport->port_id && (!lport->point_to_multipoint || !lport->link_up))1020		fc_lport_set_port_id(lport, 0, NULL);1021}1022 1023/**1024 * fc_lport_enter_reset() - Reset the local port1025 * @lport: The local port to be reset1026 */1027static void fc_lport_enter_reset(struct fc_lport *lport)1028{1029	lockdep_assert_held(&lport->lp_mutex);1030 1031	FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",1032		     fc_lport_state(lport));1033 1034	if (lport->state == LPORT_ST_DISABLED || lport->state == LPORT_ST_LOGO)1035		return;1036 1037	if (lport->vport) {1038		if (lport->link_up)1039			fc_vport_set_state(lport->vport, FC_VPORT_INITIALIZING);1040		else1041			fc_vport_set_state(lport->vport, FC_VPORT_LINKDOWN);1042	}1043	fc_lport_state_enter(lport, LPORT_ST_RESET);1044	fc_host_post_event(lport->host, fc_get_event_number(),1045			   FCH_EVT_LIPRESET, 0);1046	fc_vports_linkchange(lport);1047	fc_lport_reset_locked(lport);1048	if (lport->link_up)1049		fc_lport_enter_flogi(lport);1050}1051 1052/**1053 * fc_lport_enter_disabled() - Disable the local port1054 * @lport: The local port to be reset1055 */1056static void fc_lport_enter_disabled(struct fc_lport *lport)1057{1058	lockdep_assert_held(&lport->lp_mutex);1059 1060	FC_LPORT_DBG(lport, "Entered disabled state from %s state\n",1061		     fc_lport_state(lport));1062 1063	fc_lport_state_enter(lport, LPORT_ST_DISABLED);1064	fc_vports_linkchange(lport);1065	fc_lport_reset_locked(lport);1066}1067 1068/**1069 * fc_lport_error() - Handler for any errors1070 * @lport: The local port that the error was on1071 * @fp:	   The error code encoded in a frame pointer1072 *1073 * If the error was caused by a resource allocation failure1074 * then wait for half a second and retry, otherwise retry1075 * after the e_d_tov time.1076 */1077static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)1078{1079	unsigned long delay = 0;1080	FC_LPORT_DBG(lport, "Error %ld in state %s, retries %d\n",1081		     IS_ERR(fp) ? -PTR_ERR(fp) : 0, fc_lport_state(lport),1082		     lport->retry_count);1083 1084	if (PTR_ERR(fp) == -FC_EX_CLOSED)1085		return;1086 1087	/*1088	 * Memory allocation failure, or the exchange timed out1089	 * or we received LS_RJT.1090	 * Retry after delay1091	 */1092	if (lport->retry_count < lport->max_retry_count) {1093		lport->retry_count++;1094		if (!fp)1095			delay = msecs_to_jiffies(500);1096		else1097			delay =	msecs_to_jiffies(lport->e_d_tov);1098 1099		schedule_delayed_work(&lport->retry_work, delay);1100	} else1101		fc_lport_enter_reset(lport);1102}1103 1104/**1105 * fc_lport_ns_resp() - Handle response to a name server1106 *			registration exchange1107 * @sp:	    current sequence in exchange1108 * @fp:	    response frame1109 * @lp_arg: Fibre Channel host port instance1110 *1111 * Locking Note: This function will be called without the lport lock1112 * held, but it will lock, call an _enter_* function or fc_lport_error()1113 * and then unlock the lport.1114 */1115static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp,1116			     void *lp_arg)1117{1118	struct fc_lport *lport = lp_arg;1119	struct fc_frame_header *fh;1120	struct fc_ct_hdr *ct;1121 1122	FC_LPORT_DBG(lport, "Received a ns %s\n", fc_els_resp_type(fp));1123 1124	if (fp == ERR_PTR(-FC_EX_CLOSED))1125		return;1126 1127	mutex_lock(&lport->lp_mutex);1128 1129	if (lport->state < LPORT_ST_RNN_ID || lport->state > LPORT_ST_RFF_ID) {1130		FC_LPORT_DBG(lport, "Received a name server response, "1131			     "but in state %s\n", fc_lport_state(lport));1132		if (IS_ERR(fp))1133			goto err;1134		goto out;1135	}1136 1137	if (IS_ERR(fp)) {1138		fc_lport_error(lport, fp);1139		goto err;1140	}1141 1142	fh = fc_frame_header_get(fp);1143	ct = fc_frame_payload_get(fp, sizeof(*ct));1144 1145	if (fh && ct && fh->fh_type == FC_TYPE_CT &&1146	    ct->ct_fs_type == FC_FST_DIR &&1147	    ct->ct_fs_subtype == FC_NS_SUBTYPE &&1148	    ntohs(ct->ct_cmd) == FC_FS_ACC)1149		switch (lport->state) {1150		case LPORT_ST_RNN_ID:1151			fc_lport_enter_ns(lport, LPORT_ST_RSNN_NN);1152			break;1153		case LPORT_ST_RSNN_NN:1154			fc_lport_enter_ns(lport, LPORT_ST_RSPN_ID);1155			break;1156		case LPORT_ST_RSPN_ID:1157			fc_lport_enter_ns(lport, LPORT_ST_RFT_ID);1158			break;1159		case LPORT_ST_RFT_ID:1160			fc_lport_enter_ns(lport, LPORT_ST_RFF_ID);1161			break;1162		case LPORT_ST_RFF_ID:1163			if (lport->fdmi_enabled)1164				fc_lport_enter_fdmi(lport);1165			else1166				fc_lport_enter_scr(lport);1167			break;1168		default:1169			/* should have already been caught by state checks */1170			break;1171		}1172	else1173		fc_lport_error(lport, fp);1174out:1175	fc_frame_free(fp);1176err:1177	mutex_unlock(&lport->lp_mutex);1178}1179 1180/**1181 * fc_lport_ms_resp() - Handle response to a management server1182 *			exchange1183 * @sp:	    current sequence in exchange1184 * @fp:	    response frame1185 * @lp_arg: Fibre Channel host port instance1186 *1187 * Locking Note: This function will be called without the lport lock1188 * held, but it will lock, call an _enter_* function or fc_lport_error()1189 * and then unlock the lport.1190 */1191static void fc_lport_ms_resp(struct fc_seq *sp, struct fc_frame *fp,1192			     void *lp_arg)1193{1194	struct fc_lport *lport = lp_arg;1195	struct fc_frame_header *fh;1196	struct fc_ct_hdr *ct;1197	struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);1198	FC_LPORT_DBG(lport, "Received a ms %s\n", fc_els_resp_type(fp));1199 1200	if (fp == ERR_PTR(-FC_EX_CLOSED))1201		return;1202 1203	mutex_lock(&lport->lp_mutex);1204 1205	if (lport->state < LPORT_ST_RHBA || lport->state > LPORT_ST_DPRT) {1206		FC_LPORT_DBG(lport, "Received a management server response, "1207			     "but in state %s\n", fc_lport_state(lport));1208		if (IS_ERR(fp))1209			goto err;1210		goto out;1211	}1212 1213	if (IS_ERR(fp)) {1214		fc_lport_error(lport, fp);1215		goto err;1216	}1217 1218	fh = fc_frame_header_get(fp);1219	ct = fc_frame_payload_get(fp, sizeof(*ct));1220 1221	if (fh && ct && fh->fh_type == FC_TYPE_CT &&1222	    ct->ct_fs_type == FC_FST_MGMT &&1223	    ct->ct_fs_subtype == FC_FDMI_SUBTYPE) {1224		FC_LPORT_DBG(lport, "Received a management server response, "1225				    "reason=%d explain=%d\n",1226				    ct->ct_reason,1227				    ct->ct_explan);1228 1229		switch (lport->state) {1230		case LPORT_ST_RHBA:1231			if ((ntohs(ct->ct_cmd) == FC_FS_RJT) && fc_host->fdmi_version == FDMI_V2) {1232				FC_LPORT_DBG(lport, "Error for FDMI-V2, fall back to FDMI-V1\n");1233				fc_host->fdmi_version = FDMI_V1;1234 1235				fc_lport_enter_ms(lport, LPORT_ST_RHBA);1236 1237			} else if (ntohs(ct->ct_cmd) == FC_FS_ACC)1238				fc_lport_enter_ms(lport, LPORT_ST_RPA);1239			else /* Error Skip RPA */1240				fc_lport_enter_scr(lport);1241			break;1242		case LPORT_ST_RPA:1243			fc_lport_enter_scr(lport);1244			break;1245		case LPORT_ST_DPRT:1246			fc_lport_enter_ms(lport, LPORT_ST_RHBA);1247			break;1248		case LPORT_ST_DHBA:1249			fc_lport_enter_ms(lport, LPORT_ST_DPRT);1250			break;1251		default:1252			/* should have already been caught by state checks */1253			break;1254		}1255	} else {1256		/* Invalid Frame? */1257		fc_lport_error(lport, fp);1258	}1259out:1260	fc_frame_free(fp);1261err:1262	mutex_unlock(&lport->lp_mutex);1263}1264 1265/**1266 * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request1267 * @sp:	    current sequence in SCR exchange1268 * @fp:	    response frame1269 * @lp_arg: Fibre Channel lport port instance that sent the registration request1270 *1271 * Locking Note: This function will be called without the lport lock1272 * held, but it will lock, call an _enter_* function or fc_lport_error1273 * and then unlock the lport.1274 */1275static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,1276			      void *lp_arg)1277{1278	struct fc_lport *lport = lp_arg;1279	u8 op;1280 1281	FC_LPORT_DBG(lport, "Received a SCR %s\n", fc_els_resp_type(fp));1282 1283	if (fp == ERR_PTR(-FC_EX_CLOSED))1284		return;1285 1286	mutex_lock(&lport->lp_mutex);1287 1288	if (lport->state != LPORT_ST_SCR) {1289		FC_LPORT_DBG(lport, "Received a SCR response, but in state "1290			     "%s\n", fc_lport_state(lport));1291		if (IS_ERR(fp))1292			goto err;1293		goto out;1294	}1295 1296	if (IS_ERR(fp)) {1297		fc_lport_error(lport, fp);1298		goto err;1299	}1300 1301	op = fc_frame_payload_op(fp);1302	if (op == ELS_LS_ACC)1303		fc_lport_enter_ready(lport);1304	else1305		fc_lport_error(lport, fp);1306 1307out:1308	fc_frame_free(fp);1309err:1310	mutex_unlock(&lport->lp_mutex);1311}1312 1313/**1314 * fc_lport_enter_scr() - Send a SCR (State Change Register) request1315 * @lport: The local port to register for state changes1316 */1317static void fc_lport_enter_scr(struct fc_lport *lport)1318{1319	struct fc_frame *fp;1320 1321	lockdep_assert_held(&lport->lp_mutex);1322 1323	FC_LPORT_DBG(lport, "Entered SCR state from %s state\n",1324		     fc_lport_state(lport));1325 1326	fc_lport_state_enter(lport, LPORT_ST_SCR);1327 1328	fp = fc_frame_alloc(lport, sizeof(struct fc_els_scr));1329	if (!fp) {1330		fc_lport_error(lport, fp);1331		return;1332	}1333 1334	if (!lport->tt.elsct_send(lport, FC_FID_FCTRL, fp, ELS_SCR,1335				  fc_lport_scr_resp, lport,1336				  2 * lport->r_a_tov))1337		fc_lport_error(lport, NULL);1338}1339 1340/**1341 * fc_lport_enter_ns() - register some object with the name server1342 * @lport: Fibre Channel local port to register1343 * @state: Local port state1344 */1345static void fc_lport_enter_ns(struct fc_lport *lport, enum fc_lport_state state)1346{1347	struct fc_frame *fp;1348	enum fc_ns_req cmd;1349	int size = sizeof(struct fc_ct_hdr);1350	size_t len;1351 1352	lockdep_assert_held(&lport->lp_mutex);1353 1354	FC_LPORT_DBG(lport, "Entered %s state from %s state\n",1355		     fc_lport_state_names[state],1356		     fc_lport_state(lport));1357 1358	fc_lport_state_enter(lport, state);1359 1360	switch (state) {1361	case LPORT_ST_RNN_ID:1362		cmd = FC_NS_RNN_ID;1363		size += sizeof(struct fc_ns_rn_id);1364		break;1365	case LPORT_ST_RSNN_NN:1366		len = strnlen(fc_host_symbolic_name(lport->host), 255);1367		/* if there is no symbolic name, skip to RFT_ID */1368		if (!len)1369			return fc_lport_enter_ns(lport, LPORT_ST_RFT_ID);1370		cmd = FC_NS_RSNN_NN;1371		size += sizeof(struct fc_ns_rsnn) + len;1372		break;1373	case LPORT_ST_RSPN_ID:1374		len = strnlen(fc_host_symbolic_name(lport->host), 255);1375		/* if there is no symbolic name, skip to RFT_ID */1376		if (!len)1377			return fc_lport_enter_ns(lport, LPORT_ST_RFT_ID);1378		cmd = FC_NS_RSPN_ID;1379		size += sizeof(struct fc_ns_rspn) + len;1380		break;1381	case LPORT_ST_RFT_ID:1382		cmd = FC_NS_RFT_ID;1383		size += sizeof(struct fc_ns_rft);1384		break;1385	case LPORT_ST_RFF_ID:1386		cmd = FC_NS_RFF_ID;1387		size += sizeof(struct fc_ns_rff_id);1388		break;1389	default:1390		fc_lport_error(lport, NULL);1391		return;1392	}1393 1394	fp = fc_frame_alloc(lport, size);1395	if (!fp) {1396		fc_lport_error(lport, fp);1397		return;1398	}1399 1400	if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, cmd,1401				  fc_lport_ns_resp,1402				  lport, 3 * lport->r_a_tov))1403		fc_lport_error(lport, fp);1404}1405 1406static struct fc_rport_operations fc_lport_rport_ops = {1407	.event_callback = fc_lport_rport_callback,1408};1409 1410/**1411 * fc_lport_enter_dns() - Create a fc_rport for the name server1412 * @lport: The local port requesting a remote port for the name server1413 */1414static void fc_lport_enter_dns(struct fc_lport *lport)1415{1416	struct fc_rport_priv *rdata;1417 1418	lockdep_assert_held(&lport->lp_mutex);1419 1420	FC_LPORT_DBG(lport, "Entered DNS state from %s state\n",1421		     fc_lport_state(lport));1422 1423	fc_lport_state_enter(lport, LPORT_ST_DNS);1424 1425	mutex_lock(&lport->disc.disc_mutex);1426	rdata = fc_rport_create(lport, FC_FID_DIR_SERV);1427	mutex_unlock(&lport->disc.disc_mutex);1428	if (!rdata)1429		goto err;1430 1431	rdata->ops = &fc_lport_rport_ops;1432	fc_rport_login(rdata);1433	return;1434 1435err:1436	fc_lport_error(lport, NULL);1437}1438 1439/**1440 * fc_lport_enter_ms() - management server commands1441 * @lport: Fibre Channel local port to register1442 * @state: Local port state1443 */1444static void fc_lport_enter_ms(struct fc_lport *lport, enum fc_lport_state state)1445{1446	struct fc_frame *fp;1447	enum fc_fdmi_req cmd;1448	int size = sizeof(struct fc_ct_hdr);1449	size_t len;1450	int numattrs;1451	struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);1452	lockdep_assert_held(&lport->lp_mutex);1453 1454	FC_LPORT_DBG(lport, "Entered %s state from %s state\n",1455		     fc_lport_state_names[state],1456		     fc_lport_state(lport));1457 1458	fc_lport_state_enter(lport, state);1459 1460	switch (state) {1461	case LPORT_ST_RHBA:1462		cmd = FC_FDMI_RHBA;1463		/* Number of HBA Attributes */1464		numattrs = 11;1465		len = sizeof(struct fc_fdmi_rhba);1466		len -= sizeof(struct fc_fdmi_attr_entry);1467 1468		len += FC_FDMI_HBA_ATTR_NODENAME_LEN;1469		len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;1470		len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;1471		len += FC_FDMI_HBA_ATTR_MODEL_LEN;1472		len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;1473		len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;1474		len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;1475		len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;1476		len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;1477		len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;1478		len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;1479 1480 1481		if (fc_host->fdmi_version == FDMI_V2) {1482			numattrs += 7;1483			len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;1484			len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;1485			len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;1486			len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;1487			len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;1488			len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;1489			len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;1490		}1491 1492		len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);1493 1494		size += len;1495		break;1496	case LPORT_ST_RPA:1497		cmd = FC_FDMI_RPA;1498		/* Number of Port Attributes */1499		numattrs = 6;1500		len = sizeof(struct fc_fdmi_rpa);1501		len -= sizeof(struct fc_fdmi_attr_entry);1502		len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;1503		len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;1504		len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;1505		len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;1506		len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;1507		len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;1508 1509		if (fc_host->fdmi_version == FDMI_V2) {1510			numattrs += 10;1511			len += FC_FDMI_PORT_ATTR_NODENAME_LEN;1512			len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;1513			len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;1514			len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;1515			len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;1516			len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;1517			len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;1518			len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;1519			len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;1520			len += FC_FDMI_PORT_ATTR_PORTID_LEN;1521		}1522 1523		len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);1524 1525		size += len;1526		break;1527	case LPORT_ST_DPRT:1528		cmd = FC_FDMI_DPRT;1529		len = sizeof(struct fc_fdmi_dprt);1530		size += len;1531		break;1532	case LPORT_ST_DHBA:1533		cmd = FC_FDMI_DHBA;1534		len = sizeof(struct fc_fdmi_dhba);1535		size += len;1536		break;1537	default:1538		fc_lport_error(lport, NULL);1539		return;1540	}1541 1542	FC_LPORT_DBG(lport, "Cmd=0x%x Len %d size %d\n",1543			     cmd, (int)len, size);1544	fp = fc_frame_alloc(lport, size);1545	if (!fp) {1546		fc_lport_error(lport, fp);1547		return;1548	}1549 1550	if (!lport->tt.elsct_send(lport, FC_FID_MGMT_SERV, fp, cmd,1551				  fc_lport_ms_resp,1552				  lport, 3 * lport->r_a_tov))1553		fc_lport_error(lport, fp);1554}1555 1556/**1557 * fc_lport_enter_fdmi() - Create a fc_rport for the management server1558 * @lport: The local port requesting a remote port for the management server1559 */1560static void fc_lport_enter_fdmi(struct fc_lport *lport)1561{1562	struct fc_rport_priv *rdata;1563 1564	lockdep_assert_held(&lport->lp_mutex);1565 1566	FC_LPORT_DBG(lport, "Entered FDMI state from %s state\n",1567		     fc_lport_state(lport));1568 1569	fc_lport_state_enter(lport, LPORT_ST_FDMI);1570 1571	mutex_lock(&lport->disc.disc_mutex);1572	rdata = fc_rport_create(lport, FC_FID_MGMT_SERV);1573	mutex_unlock(&lport->disc.disc_mutex);1574	if (!rdata)1575		goto err;1576 1577	rdata->ops = &fc_lport_rport_ops;1578	fc_rport_login(rdata);1579	return;1580 1581err:1582	fc_lport_error(lport, NULL);1583}1584 1585/**1586 * fc_lport_timeout() - Handler for the retry_work timer1587 * @work: The work struct of the local port1588 */1589static void fc_lport_timeout(struct work_struct *work)1590{1591	struct fc_lport *lport =1592		container_of(work, struct fc_lport,1593			     retry_work.work);1594	struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);1595 1596	mutex_lock(&lport->lp_mutex);1597 1598	switch (lport->state) {1599	case LPORT_ST_DISABLED:1600		break;1601	case LPORT_ST_READY:1602		break;1603	case LPORT_ST_RESET:1604		break;1605	case LPORT_ST_FLOGI:1606		fc_lport_enter_flogi(lport);1607		break;1608	case LPORT_ST_DNS:1609		fc_lport_enter_dns(lport);1610		break;1611	case LPORT_ST_RNN_ID:1612	case LPORT_ST_RSNN_NN:1613	case LPORT_ST_RSPN_ID:1614	case LPORT_ST_RFT_ID:1615	case LPORT_ST_RFF_ID:1616		fc_lport_enter_ns(lport, lport->state);1617		break;1618	case LPORT_ST_FDMI:1619		fc_lport_enter_fdmi(lport);1620		break;1621	case LPORT_ST_RHBA:1622		if (fc_host->fdmi_version == FDMI_V2) {1623			FC_LPORT_DBG(lport, "timeout for FDMI-V2 RHBA,fall back to FDMI-V1\n");1624			fc_host->fdmi_version = FDMI_V1;1625			fc_lport_enter_ms(lport, LPORT_ST_RHBA);1626			break;1627		}1628		fallthrough;1629	case LPORT_ST_RPA:1630	case LPORT_ST_DHBA:1631	case LPORT_ST_DPRT:1632		FC_LPORT_DBG(lport, "Skipping lport state %s to SCR\n",1633			     fc_lport_state(lport));1634		fallthrough;1635	case LPORT_ST_SCR:1636		fc_lport_enter_scr(lport);1637		break;1638	case LPORT_ST_LOGO:1639		fc_lport_enter_logo(lport);1640		break;1641	}1642 1643	mutex_unlock(&lport->lp_mutex);1644}1645 1646/**1647 * fc_lport_logo_resp() - Handle response to LOGO request1648 * @sp:	    The sequence that the LOGO was on1649 * @fp:	    The LOGO frame1650 * @lp_arg: The lport port that received the LOGO request1651 *1652 * Locking Note: This function will be called without the lport lock1653 * held, but it will lock, call an _enter_* function or fc_lport_error()1654 * and then unlock the lport.1655 */1656void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,1657			void *lp_arg)1658{1659	struct fc_lport *lport = lp_arg;1660	u8 op;1661 1662	FC_LPORT_DBG(lport, "Received a LOGO %s\n", fc_els_resp_type(fp));1663 1664	if (fp == ERR_PTR(-FC_EX_CLOSED))1665		return;1666 1667	mutex_lock(&lport->lp_mutex);1668 1669	if (lport->state != LPORT_ST_LOGO) {1670		FC_LPORT_DBG(lport, "Received a LOGO response, but in state "1671			     "%s\n", fc_lport_state(lport));1672		if (IS_ERR(fp))1673			goto err;1674		goto out;1675	}1676 1677	if (IS_ERR(fp)) {1678		fc_lport_error(lport, fp);1679		goto err;1680	}1681 1682	op = fc_frame_payload_op(fp);1683	if (op == ELS_LS_ACC)1684		fc_lport_enter_disabled(lport);1685	else1686		fc_lport_error(lport, fp);1687 1688out:1689	fc_frame_free(fp);1690err:1691	mutex_unlock(&lport->lp_mutex);1692}1693EXPORT_SYMBOL(fc_lport_logo_resp);1694 1695/**1696 * fc_lport_enter_logo() - Logout of the fabric1697 * @lport: The local port to be logged out1698 */1699static void fc_lport_enter_logo(struct fc_lport *lport)1700{1701	struct fc_frame *fp;1702	struct fc_els_logo *logo;1703 1704	lockdep_assert_held(&lport->lp_mutex);1705 1706	FC_LPORT_DBG(lport, "Entered LOGO state from %s state\n",1707		     fc_lport_state(lport));1708 1709	fc_lport_state_enter(lport, LPORT_ST_LOGO);1710	fc_vports_linkchange(lport);1711 1712	fp = fc_frame_alloc(lport, sizeof(*logo));1713	if (!fp) {1714		fc_lport_error(lport, fp);1715		return;1716	}1717 1718	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_LOGO,1719				  fc_lport_logo_resp, lport,1720				  2 * lport->r_a_tov))1721		fc_lport_error(lport, NULL);1722}1723 1724/**1725 * fc_lport_flogi_resp() - Handle response to FLOGI request1726 * @sp:	    The sequence that the FLOGI was on1727 * @fp:	    The FLOGI response frame1728 * @lp_arg: The lport port that received the FLOGI response1729 *1730 * Locking Note: This function will be called without the lport lock1731 * held, but it will lock, call an _enter_* function or fc_lport_error()1732 * and then unlock the lport.1733 */1734void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,1735			 void *lp_arg)1736{1737	struct fc_lport *lport = lp_arg;1738	struct fc_frame_header *fh;1739	struct fc_els_flogi *flp;1740	u32 did;1741	u16 csp_flags;1742	unsigned int r_a_tov;1743	unsigned int e_d_tov;1744	u16 mfs;1745 1746	FC_LPORT_DBG(lport, "Received a FLOGI %s\n", fc_els_resp_type(fp));1747 1748	if (fp == ERR_PTR(-FC_EX_CLOSED))1749		return;1750 1751	mutex_lock(&lport->lp_mutex);1752 1753	if (lport->state != LPORT_ST_FLOGI) {1754		FC_LPORT_DBG(lport, "Received a FLOGI response, but in state "1755			     "%s\n", fc_lport_state(lport));1756		if (IS_ERR(fp))1757			goto err;1758		goto out;1759	}1760 1761	if (IS_ERR(fp)) {1762		fc_lport_error(lport, fp);1763		goto err;1764	}1765 1766	fh = fc_frame_header_get(fp);1767	did = fc_frame_did(fp);1768	if (fh->fh_r_ctl != FC_RCTL_ELS_REP || did == 0 ||1769	    fc_frame_payload_op(fp) != ELS_LS_ACC) {1770		FC_LPORT_DBG(lport, "FLOGI not accepted or bad response\n");1771		fc_lport_error(lport, fp);1772		goto out;1773	}1774 1775	flp = fc_frame_payload_get(fp, sizeof(*flp));1776	if (!flp) {1777		FC_LPORT_DBG(lport, "FLOGI bad response\n");1778		fc_lport_error(lport, fp);1779		goto out;1780	}1781 1782	mfs = ntohs(flp->fl_csp.sp_bb_data) &1783		FC_SP_BB_DATA_MASK;1784 1785	if (mfs < FC_SP_MIN_MAX_PAYLOAD || mfs > FC_SP_MAX_MAX_PAYLOAD) {1786		FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, "1787			     "lport->mfs:%u\n", mfs, lport->mfs);1788		fc_lport_error(lport, fp);1789		goto out;1790	}1791 1792	if (mfs <= lport->mfs) {1793		lport->mfs = mfs;1794		fc_host_maxframe_size(lport->host) = mfs;1795	}1796 1797	csp_flags = ntohs(flp->fl_csp.sp_features);1798	r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);1799	e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);1800	if (csp_flags & FC_SP_FT_EDTR)1801		e_d_tov /= 1000000;1802 1803	lport->npiv_enabled = !!(csp_flags & FC_SP_FT_NPIV_ACC);1804 1805	if ((csp_flags & FC_SP_FT_FPORT) == 0) {1806		if (e_d_tov > lport->e_d_tov)1807			lport->e_d_tov = e_d_tov;1808		lport->r_a_tov = 2 * lport->e_d_tov;1809		fc_lport_set_port_id(lport, did, fp);1810		printk(KERN_INFO "host%d: libfc: "1811		       "Port (%6.6x) entered "1812		       "point-to-point mode\n",1813		       lport->host->host_no, did);1814		fc_lport_ptp_setup(lport, fc_frame_sid(fp),1815				   get_unaligned_be64(1816					   &flp->fl_wwpn),1817				   get_unaligned_be64(1818					   &flp->fl_wwnn));1819	} else {1820		if (e_d_tov > lport->e_d_tov)1821			lport->e_d_tov = e_d_tov;1822		if (r_a_tov > lport->r_a_tov)1823			lport->r_a_tov = r_a_tov;1824		fc_host_fabric_name(lport->host) =1825			get_unaligned_be64(&flp->fl_wwnn);1826		fc_lport_set_port_id(lport, did, fp);1827		fc_lport_enter_dns(lport);1828	}1829 1830out:1831	fc_frame_free(fp);1832err:1833	mutex_unlock(&lport->lp_mutex);1834}1835EXPORT_SYMBOL(fc_lport_flogi_resp);1836 1837/**1838 * fc_lport_enter_flogi() - Send a FLOGI request to the fabric manager1839 * @lport: Fibre Channel local port to be logged in to the fabric1840 */1841static void fc_lport_enter_flogi(struct fc_lport *lport)1842{1843	struct fc_frame *fp;1844 1845	lockdep_assert_held(&lport->lp_mutex);1846 1847	FC_LPORT_DBG(lport, "Entered FLOGI state from %s state\n",1848		     fc_lport_state(lport));1849 1850	fc_lport_state_enter(lport, LPORT_ST_FLOGI);1851 1852	if (lport->point_to_multipoint) {1853		if (lport->port_id)1854			fc_lport_enter_ready(lport);1855		return;1856	}1857 1858	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));1859	if (!fp)1860		return fc_lport_error(lport, fp);1861 1862	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp,1863				  lport->vport ? ELS_FDISC : ELS_FLOGI,1864				  fc_lport_flogi_resp, lport,1865				  lport->vport ? 2 * lport->r_a_tov :1866				  lport->e_d_tov))1867		fc_lport_error(lport, NULL);1868}1869 1870/**1871 * fc_lport_config() - Configure a fc_lport1872 * @lport: The local port to be configured1873 */1874int fc_lport_config(struct fc_lport *lport)1875{1876	INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);1877	mutex_init(&lport->lp_mutex);1878 1879	fc_lport_state_enter(lport, LPORT_ST_DISABLED);1880 1881	fc_lport_add_fc4_type(lport, FC_TYPE_FCP);1882	fc_lport_add_fc4_type(lport, FC_TYPE_CT);1883	fc_fc4_conf_lport_params(lport, FC_TYPE_FCP);1884 1885	return 0;1886}1887EXPORT_SYMBOL(fc_lport_config);1888 1889/**1890 * fc_lport_init() - Initialize the lport layer for a local port1891 * @lport: The local port to initialize the exchange layer for1892 */1893int fc_lport_init(struct fc_lport *lport)1894{1895	struct fc_host_attrs *fc_host;1896 1897	fc_host = shost_to_fc_host(lport->host);1898 1899	/* Set FDMI version to FDMI-2 specification*/1900	fc_host->fdmi_version = FDMI_V2;1901 1902	fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;1903	fc_host_node_name(lport->host) = lport->wwnn;1904	fc_host_port_name(lport->host) = lport->wwpn;1905	fc_host_supported_classes(lport->host) = FC_COS_CLASS3;1906	memset(fc_host_supported_fc4s(lport->host), 0,1907	       sizeof(fc_host_supported_fc4s(lport->host)));1908	fc_host_supported_fc4s(lport->host)[2] = 1;1909	fc_host_supported_fc4s(lport->host)[7] = 1;1910	fc_host_num_discovered_ports(lport->host) = 4;1911 1912	/* This value is also unchanging */1913	memset(fc_host_active_fc4s(lport->host), 0,1914	       sizeof(fc_host_active_fc4s(lport->host)));1915	fc_host_active_fc4s(lport->host)[2] = 1;1916	fc_host_active_fc4s(lport->host)[7] = 1;1917	fc_host_maxframe_size(lport->host) = lport->mfs;1918	fc_host_supported_speeds(lport->host) = 0;1919	if (lport->link_supported_speeds & FC_PORTSPEED_1GBIT)1920		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT;1921	if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)1922		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;1923	if (lport->link_supported_speeds & FC_PORTSPEED_40GBIT)1924		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_40GBIT;1925	if (lport->link_supported_speeds & FC_PORTSPEED_100GBIT)1926		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_100GBIT;1927	if (lport->link_supported_speeds & FC_PORTSPEED_25GBIT)1928		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_25GBIT;1929	if (lport->link_supported_speeds & FC_PORTSPEED_50GBIT)1930		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_50GBIT;1931	if (lport->link_supported_speeds & FC_PORTSPEED_100GBIT)1932		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_100GBIT;1933 1934	fc_fc4_add_lport(lport);1935 1936	fc_host_num_discovered_ports(lport->host) = DISCOVERED_PORTS;1937	fc_host_port_state(lport->host) = FC_PORTSTATE_ONLINE;1938	fc_host_max_ct_payload(lport->host) = MAX_CT_PAYLOAD;1939	fc_host_num_ports(lport->host) = NUMBER_OF_PORTS;1940	fc_host_bootbios_state(lport->host) = 0X00000000;1941	snprintf(fc_host_bootbios_version(lport->host),1942		FC_SYMBOLIC_NAME_SIZE, "%s", "Unknown");1943 1944	return 0;1945}1946EXPORT_SYMBOL(fc_lport_init);1947 1948/**1949 * fc_lport_bsg_resp() - The common response handler for FC Passthrough requests1950 * @sp:	      The sequence for the FC Passthrough response1951 * @fp:	      The response frame1952 * @info_arg: The BSG info that the response is for1953 */1954static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp,1955			      void *info_arg)1956{1957	struct fc_bsg_info *info = info_arg;1958	struct bsg_job *job = info->job;1959	struct fc_bsg_reply *bsg_reply = job->reply;1960	struct fc_lport *lport = info->lport;1961	struct fc_frame_header *fh;1962	size_t len;1963	void *buf;1964 1965	if (IS_ERR(fp)) {1966		bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ?1967			-ECONNABORTED : -ETIMEDOUT;1968		job->reply_len = sizeof(uint32_t);1969		bsg_job_done(job, bsg_reply->result,1970			       bsg_reply->reply_payload_rcv_len);1971		kfree(info);1972		return;1973	}1974 1975	mutex_lock(&lport->lp_mutex);1976	fh = fc_frame_header_get(fp);1977	len = fr_len(fp) - sizeof(*fh);1978	buf = fc_frame_payload_get(fp, 0);1979 1980	if (fr_sof(fp) == FC_SOF_I3 && !ntohs(fh->fh_seq_cnt)) {1981		/* Get the response code from the first frame payload */1982		unsigned short cmd = (info->rsp_code == FC_FS_ACC) ?1983			ntohs(((struct fc_ct_hdr *)buf)->ct_cmd) :1984			(unsigned short)fc_frame_payload_op(fp);1985 1986		/* Save the reply status of the job */1987		bsg_reply->reply_data.ctels_reply.status =1988			(cmd == info->rsp_code) ?1989			FC_CTELS_STATUS_OK : FC_CTELS_STATUS_REJECT;1990	}1991 1992	bsg_reply->reply_payload_rcv_len +=1993		fc_copy_buffer_to_sglist(buf, len, info->sg, &info->nents,1994					 &info->offset, NULL);1995 1996	if (fr_eof(fp) == FC_EOF_T &&1997	    (ntoh24(fh->fh_f_ctl) & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) ==1998	    (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) {1999		if (bsg_reply->reply_payload_rcv_len >2000		    job->reply_payload.payload_len)2001			bsg_reply->reply_payload_rcv_len =2002				job->reply_payload.payload_len;2003		bsg_reply->result = 0;2004		bsg_job_done(job, bsg_reply->result,2005			       bsg_reply->reply_payload_rcv_len);2006		kfree(info);2007	}2008	fc_frame_free(fp);2009	mutex_unlock(&lport->lp_mutex);2010}2011 2012/**2013 * fc_lport_els_request() - Send ELS passthrough request2014 * @job:   The BSG Passthrough job2015 * @lport: The local port sending the request2016 * @did:   The destination port id2017 * @tov:   The timeout period (in ms)2018 */2019static int fc_lport_els_request(struct bsg_job *job,2020				struct fc_lport *lport,2021				u32 did, u32 tov)2022{2023	struct fc_bsg_info *info;2024	struct fc_frame *fp;2025	struct fc_frame_header *fh;2026	char *pp;2027	int len;2028 2029	lockdep_assert_held(&lport->lp_mutex);2030 2031	fp = fc_frame_alloc(lport, job->request_payload.payload_len);2032	if (!fp)2033		return -ENOMEM;2034 2035	len = job->request_payload.payload_len;2036	pp = fc_frame_payload_get(fp, len);2037 2038	sg_copy_to_buffer(job->request_payload.sg_list,2039			  job->request_payload.sg_cnt,2040			  pp, len);2041 2042	fh = fc_frame_header_get(fp);2043	fh->fh_r_ctl = FC_RCTL_ELS_REQ;2044	hton24(fh->fh_d_id, did);2045	hton24(fh->fh_s_id, lport->port_id);2046	fh->fh_type = FC_TYPE_ELS;2047	hton24(fh->fh_f_ctl, FC_FCTL_REQ);2048	fh->fh_cs_ctl = 0;2049	fh->fh_df_ctl = 0;2050	fh->fh_parm_offset = 0;2051 2052	info = kzalloc(sizeof(struct fc_bsg_info), GFP_KERNEL);2053	if (!info) {2054		fc_frame_free(fp);2055		return -ENOMEM;2056	}2057 2058	info->job = job;2059	info->lport = lport;2060	info->rsp_code = ELS_LS_ACC;2061	info->nents = job->reply_payload.sg_cnt;2062	info->sg = job->reply_payload.sg_list;2063 2064	if (!fc_exch_seq_send(lport, fp, fc_lport_bsg_resp,2065			      NULL, info, tov)) {2066		kfree(info);2067		return -ECOMM;2068	}2069	return 0;2070}2071 2072/**2073 * fc_lport_ct_request() - Send CT Passthrough request2074 * @job:   The BSG Passthrough job2075 * @lport: The local port sending the request2076 * @did:   The destination FC-ID2077 * @tov:   The timeout period to wait for the response2078 */2079static int fc_lport_ct_request(struct bsg_job *job,2080			       struct fc_lport *lport, u32 did, u32 tov)2081{2082	struct fc_bsg_info *info;2083	struct fc_frame *fp;2084	struct fc_frame_header *fh;2085	struct fc_ct_req *ct;2086	size_t len;2087 2088	lockdep_assert_held(&lport->lp_mutex);2089 2090	fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +2091			    job->request_payload.payload_len);2092	if (!fp)2093		return -ENOMEM;2094 2095	len = job->request_payload.payload_len;2096	ct = fc_frame_payload_get(fp, len);2097 2098	sg_copy_to_buffer(job->request_payload.sg_list,2099			  job->request_payload.sg_cnt,2100			  ct, len);2101 2102	fh = fc_frame_header_get(fp);2103	fh->fh_r_ctl = FC_RCTL_DD_UNSOL_CTL;2104	hton24(fh->fh_d_id, did);2105	hton24(fh->fh_s_id, lport->port_id);2106	fh->fh_type = FC_TYPE_CT;2107	hton24(fh->fh_f_ctl, FC_FCTL_REQ);2108	fh->fh_cs_ctl = 0;2109	fh->fh_df_ctl = 0;2110	fh->fh_parm_offset = 0;2111 2112	info = kzalloc(sizeof(struct fc_bsg_info), GFP_KERNEL);2113	if (!info) {2114		fc_frame_free(fp);2115		return -ENOMEM;2116	}2117 2118	info->job = job;2119	info->lport = lport;2120	info->rsp_code = FC_FS_ACC;2121	info->nents = job->reply_payload.sg_cnt;2122	info->sg = job->reply_payload.sg_list;2123 2124	if (!fc_exch_seq_send(lport, fp, fc_lport_bsg_resp,2125			      NULL, info, tov)) {2126		kfree(info);2127		return -ECOMM;2128	}2129	return 0;2130}2131 2132/**2133 * fc_lport_bsg_request() - The common entry point for sending2134 *			    FC Passthrough requests2135 * @job: The BSG passthrough job2136 */2137int fc_lport_bsg_request(struct bsg_job *job)2138{2139	struct fc_bsg_request *bsg_request = job->request;2140	struct fc_bsg_reply *bsg_reply = job->reply;2141	struct Scsi_Host *shost = fc_bsg_to_shost(job);2142	struct fc_lport *lport = shost_priv(shost);2143	struct fc_rport *rport;2144	struct fc_rport_priv *rdata;2145	int rc = -EINVAL;2146	u32 did, tov;2147 2148	bsg_reply->reply_payload_rcv_len = 0;2149 2150	mutex_lock(&lport->lp_mutex);2151 2152	switch (bsg_request->msgcode) {2153	case FC_BSG_RPT_ELS:2154		rport = fc_bsg_to_rport(job);2155		if (!rport)2156			break;2157 2158		rdata = rport->dd_data;2159		rc = fc_lport_els_request(job, lport, rport->port_id,2160					  rdata->e_d_tov);2161		break;2162 2163	case FC_BSG_RPT_CT:2164		rport = fc_bsg_to_rport(job);2165		if (!rport)2166			break;2167 2168		rdata = rport->dd_data;2169		rc = fc_lport_ct_request(job, lport, rport->port_id,2170					 rdata->e_d_tov);2171		break;2172 2173	case FC_BSG_HST_CT:2174		did = ntoh24(bsg_request->rqst_data.h_ct.port_id);2175		if (did == FC_FID_DIR_SERV) {2176			rdata = lport->dns_rdata;2177			if (!rdata)2178				break;2179			tov = rdata->e_d_tov;2180		} else {2181			rdata = fc_rport_lookup(lport, did);2182			if (!rdata)2183				break;2184			tov = rdata->e_d_tov;2185			kref_put(&rdata->kref, fc_rport_destroy);2186		}2187 2188		rc = fc_lport_ct_request(job, lport, did, tov);2189		break;2190 2191	case FC_BSG_HST_ELS_NOLOGIN:2192		did = ntoh24(bsg_request->rqst_data.h_els.port_id);2193		rc = fc_lport_els_request(job, lport, did, lport->e_d_tov);2194		break;2195	}2196 2197	mutex_unlock(&lport->lp_mutex);2198	return rc;2199}2200EXPORT_SYMBOL(fc_lport_bsg_request);2201