]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.drivers/open-fcoe-beta3-update
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / open-fcoe-beta3-update
CommitLineData
2cb7cef9
BS
1Subject: Open-FCoE update for Beta3
2From: John Fastabend <john.r.fastabend@intel.com>
3Date: Thu Nov 6 13:01:32 2008 +0100:
4Git: 2d8ac46f55c5f06ac3fe9830c899386789aa8900
5References: bnc#438954
6
7Incremental Open-FCoE update for Beta3.
8
9Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
10Acked-by: Hannes Reinecke <hare@suse.de>
11
12diff --git a/drivers/scsi/fcoe/fcoe_if.c b/drivers/scsi/fcoe/fcoe_if.c
13index 7f983e2..73b83ce 100644
14--- a/drivers/scsi/fcoe/fcoe_if.c
15+++ b/drivers/scsi/fcoe/fcoe_if.c
16@@ -155,18 +155,18 @@ int fcoe_destroy_interface(const char *ifname)
17 list_del(&fc->list);
18 write_unlock_bh(&fci->fcoe_hostlist_lock);
19
20- /* Cleanup the fc_lport */
21- fc_lport_destroy(lp);
22- fc_fcp_destroy(lp);
23- if (lp->emp)
24- fc_exch_mgr_free(lp->emp);
25+ /* Don't listen for Ethernet packets anymore */
26+ dev_remove_pack(&fc->fcoe_packet_type);
27
28 /* Detach from the scsi-ml */
29 fc_remove_host(lp->host);
30 scsi_remove_host(lp->host);
31
32- /* Don't listen for Ethernet packets anymore */
33- dev_remove_pack(&fc->fcoe_packet_type);
34+ /* Cleanup the fc_lport */
35+ fc_lport_destroy(lp);
36+ fc_fcp_destroy(lp);
37+ if (lp->emp)
38+ fc_exch_mgr_free(lp->emp);
39
40 /* Delete secondary MAC addresses */
41 rtnl_lock();
42@@ -388,8 +388,7 @@ static int libfc_config(struct fc_lport *lp)
43 fc_exch_init(lp);
44 fc_lport_init(lp);
45 fc_rport_init(lp);
46- fc_ns_init(lp);
47- fc_attr_init(lp);
48+ fc_disc_init(lp);
49
50 return 0;
51 }
52diff --git a/drivers/scsi/fcoe/fcoeinit.c b/drivers/scsi/fcoe/fcoeinit.c
53index e069835..7d52ed5 100644
54--- a/drivers/scsi/fcoe/fcoeinit.c
55+++ b/drivers/scsi/fcoe/fcoeinit.c
56@@ -53,8 +53,8 @@ struct scsi_transport_template *fcoe_transport_template;
57
58 static int fcoe_reset(struct Scsi_Host *shost)
59 {
60- struct fc_lport *lp = shost_priv(shost);
61- fc_lport_enter_reset(lp);
62+ struct fc_lport *lport = shost_priv(shost);
63+ fc_lport_reset(lport);
64 return 0;
65 }
66
67@@ -66,11 +66,10 @@ struct fc_function_template fcoe_transport_function = {
68 .show_host_active_fc4s = 1,
69 .show_host_maxframe_size = 1,
70
71- .get_host_port_id = fc_get_host_port_id,
72 .show_host_port_id = 1,
73+ .show_host_supported_speeds = 1,
74 .get_host_speed = fc_get_host_speed,
75 .show_host_speed = 1,
76- .get_host_port_type = fc_get_host_port_type,
77 .show_host_port_type = 1,
78 .get_host_port_state = fc_get_host_port_state,
79 .show_host_port_state = 1,
80@@ -80,7 +79,6 @@ struct fc_function_template fcoe_transport_function = {
81 .show_rport_maxframe_size = 1,
82 .show_rport_supported_classes = 1,
83
84- .get_host_fabric_name = fc_get_host_fabric_name,
85 .show_host_fabric_name = 1,
86 .show_starget_node_name = 1,
87 .show_starget_port_name = 1,
88@@ -89,6 +87,8 @@ struct fc_function_template fcoe_transport_function = {
89 .show_rport_dev_loss_tmo = 1,
90 .get_fc_host_stats = fc_get_host_stats,
91 .issue_fc_host_lip = fcoe_reset,
92+
93+ .terminate_rport_io = fc_rport_terminate_io,
94 };
95
96 struct fcoe_percpu_s *fcoe_percpu[NR_CPUS];
97diff --git a/drivers/scsi/libfc/Makefile b/drivers/scsi/libfc/Makefile
98index 0a31ca2..e6d4086 100644
99--- a/drivers/scsi/libfc/Makefile
100+++ b/drivers/scsi/libfc/Makefile
101@@ -3,10 +3,9 @@
102 obj-$(CONFIG_LIBFC) += libfc.o
103
104 libfc-objs := \
105- fc_ns.o \
106+ fc_disc.o \
107 fc_exch.o \
108 fc_frame.o \
109 fc_lport.o \
110 fc_rport.o \
111- fc_attr.o \
112 fc_fcp.o
113diff --git a/drivers/scsi/libfc/fc_attr.c b/drivers/scsi/libfc/fc_attr.c
114deleted file mode 100644
115index d73f39e..0000000
116--- a/drivers/scsi/libfc/fc_attr.c
117+++ /dev/null
118@@ -1,129 +0,0 @@
119-/*
120- * Copyright(c) 2007 Intel Corporation. All rights reserved.
121- *
122- * This program is free software; you can redistribute it and/or modify it
123- * under the terms and conditions of the GNU General Public License,
124- * version 2, as published by the Free Software Foundation.
125- *
126- * This program is distributed in the hope it will be useful, but WITHOUT
127- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
128- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
129- * more details.
130- *
131- * You should have received a copy of the GNU General Public License along with
132- * this program; if not, write to the Free Software Foundation, Inc.,
133- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
134- *
135- * Maintained at www.Open-FCoE.org
136- */
137-
138-#include <linux/kernel.h>
139-#include <linux/types.h>
140-
141-#include <scsi/scsi_host.h>
142-
143-#include <scsi/libfc/libfc.h>
144-
145-MODULE_AUTHOR("Open-FCoE.org");
146-MODULE_DESCRIPTION("libfc");
147-MODULE_LICENSE("GPL");
148-
149-void fc_get_host_port_id(struct Scsi_Host *shost)
150-{
151- struct fc_lport *lp = shost_priv(shost);
152-
153- fc_host_port_id(shost) = fc_lport_get_fid(lp);
154-}
155-EXPORT_SYMBOL(fc_get_host_port_id);
156-
157-void fc_get_host_speed(struct Scsi_Host *shost)
158-{
159- /*
160- * should be obtain from DEC or Enet Driver
161- */
162- fc_host_speed(shost) = 1; /* for now it is 1g */
163-}
164-EXPORT_SYMBOL(fc_get_host_speed);
165-
166-void fc_get_host_port_type(struct Scsi_Host *shost)
167-{
168- fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
169-}
170-EXPORT_SYMBOL(fc_get_host_port_type);
171-
172-void fc_get_host_fabric_name(struct Scsi_Host *shost)
173-{
174- struct fc_lport *lp = shost_priv(shost);
175-
176- fc_host_fabric_name(shost) = lp->wwnn;
177-}
178-EXPORT_SYMBOL(fc_get_host_fabric_name);
179-
180-void fc_attr_init(struct fc_lport *lp)
181-{
182- fc_host_node_name(lp->host) = lp->wwnn;
183- fc_host_port_name(lp->host) = lp->wwpn;
184- fc_host_supported_classes(lp->host) = FC_COS_CLASS3;
185- memset(fc_host_supported_fc4s(lp->host), 0,
186- sizeof(fc_host_supported_fc4s(lp->host)));
187- fc_host_supported_fc4s(lp->host)[2] = 1;
188- fc_host_supported_fc4s(lp->host)[7] = 1;
189- /* This value is also unchanging */
190- memset(fc_host_active_fc4s(lp->host), 0,
191- sizeof(fc_host_active_fc4s(lp->host)));
192- fc_host_active_fc4s(lp->host)[2] = 1;
193- fc_host_active_fc4s(lp->host)[7] = 1;
194- fc_host_maxframe_size(lp->host) = lp->mfs;
195-}
196-EXPORT_SYMBOL(fc_attr_init);
197-
198-void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
199-{
200- if (timeout)
201- rport->dev_loss_tmo = timeout + 5;
202- else
203- rport->dev_loss_tmo = 30;
204-
205-}
206-EXPORT_SYMBOL(fc_set_rport_loss_tmo);
207-
208-struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
209-{
210- int i;
211- struct fc_host_statistics *fcoe_stats;
212- struct fc_lport *lp = shost_priv(shost);
213- struct timespec v0, v1;
214-
215- fcoe_stats = &lp->host_stats;
216- memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
217-
218- jiffies_to_timespec(jiffies, &v0);
219- jiffies_to_timespec(lp->boot_time, &v1);
220- fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec);
221-
222- for_each_online_cpu(i) {
223- struct fcoe_dev_stats *stats = lp->dev_stats[i];
224- if (stats == NULL)
225- continue;
226- fcoe_stats->tx_frames += stats->TxFrames;
227- fcoe_stats->tx_words += stats->TxWords;
228- fcoe_stats->rx_frames += stats->RxFrames;
229- fcoe_stats->rx_words += stats->RxWords;
230- fcoe_stats->error_frames += stats->ErrorFrames;
231- fcoe_stats->invalid_crc_count += stats->InvalidCRCCount;
232- fcoe_stats->fcp_input_requests += stats->InputRequests;
233- fcoe_stats->fcp_output_requests += stats->OutputRequests;
234- fcoe_stats->fcp_control_requests += stats->ControlRequests;
235- fcoe_stats->fcp_input_megabytes += stats->InputMegabytes;
236- fcoe_stats->fcp_output_megabytes += stats->OutputMegabytes;
237- fcoe_stats->link_failure_count += stats->LinkFailureCount;
238- }
239- fcoe_stats->lip_count = -1;
240- fcoe_stats->nos_count = -1;
241- fcoe_stats->loss_of_sync_count = -1;
242- fcoe_stats->loss_of_signal_count = -1;
243- fcoe_stats->prim_seq_protocol_err_count = -1;
244- fcoe_stats->dumped_frames = -1;
245- return fcoe_stats;
246-}
247-EXPORT_SYMBOL(fc_get_host_stats);
248diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
249new file mode 100644
250index 0000000..30403aa
251--- /dev/null
252+++ b/drivers/scsi/libfc/fc_disc.c
253@@ -0,0 +1,599 @@
254+/*
255+ * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
256+ *
257+ * This program is free software; you can redistribute it and/or modify it
258+ * under the terms and conditions of the GNU General Public License,
259+ * version 2, as published by the Free Software Foundation.
260+ *
261+ * This program is distributed in the hope it will be useful, but WITHOUT
262+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
263+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
264+ * more details.
265+ *
266+ * You should have received a copy of the GNU General Public License along with
267+ * this program; if not, write to the Free Software Foundation, Inc.,
268+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
269+ *
270+ * Maintained at www.Open-FCoE.org
271+ */
272+
273+/*
274+ * Target Discovery
275+ * Actually, this discovers all FC-4 remote ports, including FCP initiators.
276+ */
277+
278+#include <linux/timer.h>
279+#include <linux/err.h>
280+#include <asm/unaligned.h>
281+
282+#include <scsi/fc/fc_gs.h>
283+
284+#include <scsi/libfc/libfc.h>
285+
286+#define FC_DISC_RETRY_LIMIT 3 /* max retries */
287+#define FC_DISC_RETRY_DELAY 500UL /* (msecs) delay */
288+
289+int fc_disc_debug;
290+
291+static void fc_disc_gpn_ft_req(struct fc_lport *);
292+static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
293+static int fc_disc_new_target(struct fc_lport *, struct fc_rport *,
294+ struct fc_rport_identifiers *);
295+static void fc_disc_del_target(struct fc_lport *, struct fc_rport *);
296+static void fc_disc_done(struct fc_lport *);
297+static void fc_disc_error(struct fc_lport *, struct fc_frame *);
298+static void fc_disc_timeout(struct work_struct *);
299+static void fc_disc_single(struct fc_lport *, struct fc_disc_port *);
300+static int fc_disc_restart(struct fc_lport *);
301+
302+/**
303+ * fc_disc_rscn_req - Handle Registered State Change Notification (RSCN)
304+ * @sp: Current sequence of the RSCN exchange
305+ * @fp: RSCN Frame
306+ * @lp: Fibre Channel host port instance
307+ */
308+static void fc_disc_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
309+ struct fc_lport *lp)
310+{
311+ struct fc_els_rscn *rp;
312+ struct fc_els_rscn_page *pp;
313+ struct fc_seq_els_data rjt_data;
314+ unsigned int len;
315+ int redisc = 0;
316+ enum fc_els_rscn_ev_qual ev_qual;
317+ enum fc_els_rscn_addr_fmt fmt;
318+ LIST_HEAD(disc_list);
319+ struct fc_disc_port *dp, *next;
320+
321+ rp = fc_frame_payload_get(fp, sizeof(*rp));
322+
323+ if (!rp || rp->rscn_page_len != sizeof(*pp))
324+ goto reject;
325+
326+ len = ntohs(rp->rscn_plen);
327+ if (len < sizeof(*rp))
328+ goto reject;
329+ len -= sizeof(*rp);
330+
331+ for (pp = (void *)(rp + 1); len; len -= sizeof(*pp), pp++) {
332+ ev_qual = pp->rscn_page_flags >> ELS_RSCN_EV_QUAL_BIT;
333+ ev_qual &= ELS_RSCN_EV_QUAL_MASK;
334+ fmt = pp->rscn_page_flags >> ELS_RSCN_ADDR_FMT_BIT;
335+ fmt &= ELS_RSCN_ADDR_FMT_MASK;
336+ /*
337+ * if we get an address format other than port
338+ * (area, domain, fabric), then do a full discovery
339+ */
340+ switch (fmt) {
341+ case ELS_ADDR_FMT_PORT:
342+ dp = kzalloc(sizeof(*dp), GFP_KERNEL);
343+ if (!dp) {
344+ redisc = 1;
345+ break;
346+ }
347+ dp->lp = lp;
348+ dp->ids.port_id = ntoh24(pp->rscn_fid);
349+ dp->ids.port_name = -1;
350+ dp->ids.node_name = -1;
351+ dp->ids.roles = FC_RPORT_ROLE_UNKNOWN;
352+ list_add_tail(&dp->peers, &disc_list);
353+ break;
354+ case ELS_ADDR_FMT_AREA:
355+ case ELS_ADDR_FMT_DOM:
356+ case ELS_ADDR_FMT_FAB:
357+ default:
358+ redisc = 1;
359+ break;
360+ }
361+ }
362+ lp->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
363+ if (redisc) {
364+ if (fc_disc_debug)
365+ FC_DBG("RSCN received: rediscovering\n");
366+ list_for_each_entry_safe(dp, next, &disc_list, peers) {
367+ list_del(&dp->peers);
368+ kfree(dp);
369+ }
370+ fc_disc_restart(lp);
371+ } else {
372+ if (fc_disc_debug)
373+ FC_DBG("RSCN received: not rediscovering. "
374+ "redisc %d state %d in_prog %d\n",
375+ redisc, lp->state, lp->disc_pending);
376+ list_for_each_entry_safe(dp, next, &disc_list, peers) {
377+ list_del(&dp->peers);
378+ fc_disc_single(lp, dp);
379+ }
380+ }
381+ fc_frame_free(fp);
382+ return;
383+reject:
384+ rjt_data.fp = NULL;
385+ rjt_data.reason = ELS_RJT_LOGIC;
386+ rjt_data.explan = ELS_EXPL_NONE;
387+ lp->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
388+ fc_frame_free(fp);
389+}
390+
391+static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
392+ struct fc_lport *lp)
393+{
394+ switch (fc_frame_payload_op(fp)) {
395+ case ELS_RSCN:
396+ fc_disc_rscn_req(sp, fp, lp);
397+ break;
398+ default:
399+ FC_DBG("fc_disc recieved an unexpected request\n");
400+ break;
401+ }
402+}
403+
404+/*
405+ * Refresh target discovery, perhaps due to an RSCN.
406+ * A configurable delay is introduced to collect any subsequent RSCNs.
407+ */
408+static int fc_disc_restart(struct fc_lport *lp)
409+{
410+ if (!lp->disc_requested && !lp->disc_pending) {
411+ schedule_delayed_work(&lp->disc_work,
412+ msecs_to_jiffies(lp->disc_delay * 1000));
413+ }
414+ lp->disc_requested = 1;
415+ return 0;
416+}
417+
418+/*
419+ * Fibre Channel Target discovery.
420+ *
421+ * Returns non-zero if discovery cannot be started.
422+ *
423+ * Callback is called for each target remote port found in discovery.
424+ * When discovery is complete, the callback is called with a NULL remote port.
425+ * Discovery may be restarted after an RSCN is received, causing the
426+ * callback to be called after discovery complete is indicated.
427+ */
428+int fc_disc_start(struct fc_lport *lp)
429+{
430+ struct fc_rport *rport;
431+ int error;
432+ struct fc_rport_identifiers ids;
433+
434+ /*
435+ * If not ready, or already running discovery, just set request flag.
436+ */
437+ if (!fc_lport_test_ready(lp) || lp->disc_pending) {
438+ lp->disc_requested = 1;
439+
440+ return 0;
441+ }
442+ lp->disc_pending = 1;
443+ lp->disc_requested = 0;
444+ lp->disc_retry_count = 0;
445+
446+ /*
447+ * Handle point-to-point mode as a simple discovery
448+ * of the remote port.
449+ */
450+ rport = lp->ptp_rp;
451+ if (rport) {
452+ ids.port_id = rport->port_id;
453+ ids.port_name = rport->port_name;
454+ ids.node_name = rport->node_name;
455+ ids.roles = FC_RPORT_ROLE_UNKNOWN;
456+ get_device(&rport->dev);
457+
458+ error = fc_disc_new_target(lp, rport, &ids);
459+ put_device(&rport->dev);
460+ if (!error)
461+ fc_disc_done(lp);
462+ } else {
463+ fc_block_rports(lp);
464+ fc_disc_gpn_ft_req(lp); /* get ports by FC-4 type */
465+ error = 0;
466+ }
467+ return error;
468+}
469+
470+/*
471+ * Restart discovery after a delay due to resource shortages.
472+ * If the error persists, the discovery will be abandoned.
473+ */
474+static void fc_disc_retry(struct fc_lport *lp)
475+{
476+ unsigned long delay = FC_DISC_RETRY_DELAY;
477+
478+ if (!lp->disc_retry_count)
479+ delay /= 4; /* timeout faster first time */
480+ if (lp->disc_retry_count++ < FC_DISC_RETRY_LIMIT)
481+ schedule_delayed_work(&lp->disc_work,
482+ msecs_to_jiffies(delay));
483+ else
484+ fc_disc_done(lp);
485+}
486+
487+/*
488+ * Handle new target found by discovery.
489+ * Create remote port and session if needed.
490+ * Ignore returns of our own FID & WWPN.
491+ *
492+ * If a non-NULL rp is passed in, it is held for the caller, but not for us.
493+ *
494+ * Events delivered are:
495+ * FC_EV_READY, when remote port is rediscovered.
496+ */
497+static int fc_disc_new_target(struct fc_lport *lp,
498+ struct fc_rport *rport,
499+ struct fc_rport_identifiers *ids)
500+{
501+ struct fc_rport_libfc_priv *rp;
502+ int error = 0;
503+
504+ if (rport && ids->port_name) {
505+ if (rport->port_name == -1) {
506+ /*
507+ * Set WWN and fall through to notify of create.
508+ */
509+ fc_rport_set_name(rport, ids->port_name,
510+ rport->node_name);
511+ } else if (rport->port_name != ids->port_name) {
512+ /*
513+ * This is a new port with the same FCID as
514+ * a previously-discovered port. Presumably the old
515+ * port logged out and a new port logged in and was
516+ * assigned the same FCID. This should be rare.
517+ * Delete the old one and fall thru to re-create.
518+ */
519+ fc_disc_del_target(lp, rport);
520+ rport = NULL;
521+ }
522+ }
523+ if (((ids->port_name != -1) || (ids->port_id != -1)) &&
524+ ids->port_id != lp->fid && ids->port_name != lp->wwpn) {
525+ if (!rport) {
526+ rport = lp->tt.rport_lookup(lp, ids->port_id);
527+ if (!rport) {
528+ struct fc_disc_port dp;
529+ dp.lp = lp;
530+ dp.ids.port_id = ids->port_id;
531+ dp.ids.port_name = ids->port_name;
532+ dp.ids.node_name = ids->node_name;
533+ dp.ids.roles = ids->roles;
534+ rport = fc_rport_dummy_create(&dp);
535+ }
536+ if (!rport)
537+ error = ENOMEM;
538+ }
539+ if (rport) {
540+ rp = rport->dd_data;
541+ rp->event_callback = lp->tt.event_callback;
542+ rp->rp_state = RPORT_ST_INIT;
543+ lp->tt.rport_login(rport);
544+ }
545+ }
546+ return error;
547+}
548+
549+/*
550+ * Delete the remote port.
551+ */
552+static void fc_disc_del_target(struct fc_lport *lp, struct fc_rport *rport)
553+{
554+ lp->tt.rport_reset(rport);
555+ fc_remote_port_delete(rport); /* release hold from create */
556+}
557+
558+/*
559+ * Done with discovery
560+ */
561+static void fc_disc_done(struct fc_lport *lp)
562+{
563+ lp->disc_done = 1;
564+ lp->disc_pending = 0;
565+ if (lp->disc_requested)
566+ lp->tt.disc_start(lp);
567+}
568+
569+/**
570+ * fc_disc_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request
571+ * @lp: Fibre Channel host port instance
572+ */
573+static void fc_disc_gpn_ft_req(struct fc_lport *lp)
574+{
575+ struct fc_frame *fp;
576+ struct fc_seq *sp = NULL;
577+ struct req {
578+ struct fc_ct_hdr ct;
579+ struct fc_ns_gid_ft gid;
580+ } *rp;
581+ int error = 0;
582+
583+ lp->disc_buf_len = 0;
584+ lp->disc_seq_count = 0;
585+ fp = fc_frame_alloc(lp, sizeof(*rp));
586+ if (fp == NULL) {
587+ error = ENOMEM;
588+ } else {
589+ rp = fc_frame_payload_get(fp, sizeof(*rp));
590+ fc_fill_dns_hdr(lp, &rp->ct, FC_NS_GPN_FT, sizeof(rp->gid));
591+ rp->gid.fn_fc4_type = FC_TYPE_FCP;
592+
593+ WARN_ON(!fc_lport_test_ready(lp));
594+
595+ fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
596+ sp = lp->tt.exch_seq_send(lp, fp,
597+ fc_disc_gpn_ft_resp, NULL,
598+ lp, lp->e_d_tov,
599+ lp->fid,
600+ FC_FID_DIR_SERV,
601+ FC_FC_SEQ_INIT | FC_FC_END_SEQ);
602+ }
603+ if (error || sp == NULL)
604+ fc_disc_retry(lp);
605+}
606+
607+/*
608+ * Handle error on dNS request.
609+ */
610+static void fc_disc_error(struct fc_lport *lp, struct fc_frame *fp)
611+{
612+ int err = PTR_ERR(fp);
613+
614+ switch (err) {
615+ case -FC_EX_TIMEOUT:
616+ if (lp->disc_retry_count++ < FC_DISC_RETRY_LIMIT) {
617+ fc_disc_gpn_ft_req(lp);
618+ } else {
619+ FC_DBG("err %d - ending\n", err);
620+ fc_disc_done(lp);
621+ }
622+ break;
623+ default:
624+ FC_DBG("err %d - ending\n", err);
625+ fc_disc_done(lp);
626+ break;
627+ }
628+}
629+
630+/**
631+ * fc_disc_gpn_ft_parse - Parse the list of IDs and names resulting from a request
632+ * @lp: Fibre Channel host port instance
633+ * @buf: GPN_FT response buffer
634+ * @len: size of response buffer
635+ */
636+static int fc_disc_gpn_ft_parse(struct fc_lport *lp, void *buf, size_t len)
637+{
638+ struct fc_gpn_ft_resp *np;
639+ char *bp;
640+ size_t plen;
641+ size_t tlen;
642+ int error = 0;
643+ struct fc_disc_port dp;
644+ struct fc_rport *rp;
645+ struct fc_rport_libfc_priv *rpp;
646+
647+ /*
648+ * Handle partial name record left over from previous call.
649+ */
650+ bp = buf;
651+ plen = len;
652+ np = (struct fc_gpn_ft_resp *)bp;
653+ tlen = lp->disc_buf_len;
654+ if (tlen) {
655+ WARN_ON(tlen >= sizeof(*np));
656+ plen = sizeof(*np) - tlen;
657+ WARN_ON(plen <= 0);
658+ WARN_ON(plen >= sizeof(*np));
659+ if (plen > len)
660+ plen = len;
661+ np = &lp->disc_buf;
662+ memcpy((char *)np + tlen, bp, plen);
663+
664+ /*
665+ * Set bp so that the loop below will advance it to the
666+ * first valid full name element.
667+ */
668+ bp -= tlen;
669+ len += tlen;
670+ plen += tlen;
671+ lp->disc_buf_len = (unsigned char) plen;
672+ if (plen == sizeof(*np))
673+ lp->disc_buf_len = 0;
674+ }
675+
676+ /*
677+ * Handle full name records, including the one filled from above.
678+ * Normally, np == bp and plen == len, but from the partial case above,
679+ * bp, len describe the overall buffer, and np, plen describe the
680+ * partial buffer, which if would usually be full now.
681+ * After the first time through the loop, things return to "normal".
682+ */
683+ while (plen >= sizeof(*np)) {
684+ dp.lp = lp;
685+ dp.ids.port_id = ntoh24(np->fp_fid);
686+ dp.ids.port_name = ntohll(np->fp_wwpn);
687+ dp.ids.node_name = -1;
688+ dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
689+
690+ if ((dp.ids.port_id != lp->fid) &&
691+ (dp.ids.port_name != lp->wwpn)) {
692+ rp = fc_rport_dummy_create(&dp);
693+ if (rp) {
694+ rpp = rp->dd_data;
695+ rpp->local_port = lp;
696+ lp->tt.rport_login(rp);
697+ } else
698+ FC_DBG("Failed to allocate memory for "
699+ "the newly discovered port (%6x)\n",
700+ dp.ids.port_id);
701+ }
702+
703+ if (np->fp_flags & FC_NS_FID_LAST) {
704+ fc_disc_done(lp);
705+ len = 0;
706+ break;
707+ }
708+ len -= sizeof(*np);
709+ bp += sizeof(*np);
710+ np = (struct fc_gpn_ft_resp *)bp;
711+ plen = len;
712+ }
713+
714+ /*
715+ * Save any partial record at the end of the buffer for next time.
716+ */
717+ if (error == 0 && len > 0 && len < sizeof(*np)) {
718+ if (np != &lp->disc_buf)
719+ memcpy(&lp->disc_buf, np, len);
720+ lp->disc_buf_len = (unsigned char) len;
721+ } else {
722+ lp->disc_buf_len = 0;
723+ }
724+ return error;
725+}
726+
727+/*
728+ * Handle retry of memory allocation for remote ports.
729+ */
730+static void fc_disc_timeout(struct work_struct *work)
731+{
732+ struct fc_lport *lp;
733+
734+ lp = container_of(work, struct fc_lport, disc_work.work);
735+
736+ if (lp->disc_pending)
737+ fc_disc_gpn_ft_req(lp);
738+ else
739+ lp->tt.disc_start(lp);
740+}
741+
742+/**
743+ * fc_disc_gpn_ft_resp - Handle a response frame from Get Port Names (GPN_FT)
744+ * @sp: Current sequence of GPN_FT exchange
745+ * @fp: response frame
746+ * @lp_arg: Fibre Channel host port instance
747+ *
748+ * The response may be in multiple frames
749+ */
750+static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
751+ void *lp_arg)
752+{
753+ struct fc_lport *lp = lp_arg;
754+ struct fc_ct_hdr *cp;
755+ struct fc_frame_header *fh;
756+ unsigned int seq_cnt;
757+ void *buf = NULL;
758+ unsigned int len;
759+ int error;
760+
761+ if (IS_ERR(fp)) {
762+ fc_disc_error(lp, fp);
763+ return;
764+ }
765+
766+ WARN_ON(!fc_frame_is_linear(fp)); /* buffer must be contiguous */
767+ fh = fc_frame_header_get(fp);
768+ len = fr_len(fp) - sizeof(*fh);
769+ seq_cnt = ntohs(fh->fh_seq_cnt);
770+ if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 &&
771+ lp->disc_seq_count == 0) {
772+ cp = fc_frame_payload_get(fp, sizeof(*cp));
773+ if (cp == NULL) {
774+ FC_DBG("GPN_FT response too short, len %d\n",
775+ fr_len(fp));
776+ } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
777+
778+ /*
779+ * Accepted. Parse response.
780+ */
781+ buf = cp + 1;
782+ len -= sizeof(*cp);
783+ } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
784+ FC_DBG("GPN_FT rejected reason %x exp %x "
785+ "(check zoning)\n", cp->ct_reason,
786+ cp->ct_explan);
787+ fc_disc_done(lp);
788+ } else {
789+ FC_DBG("GPN_FT unexpected response code %x\n",
790+ ntohs(cp->ct_cmd));
791+ }
792+ } else if (fr_sof(fp) == FC_SOF_N3 &&
793+ seq_cnt == lp->disc_seq_count) {
794+ buf = fh + 1;
795+ } else {
796+ FC_DBG("GPN_FT unexpected frame - out of sequence? "
797+ "seq_cnt %x expected %x sof %x eof %x\n",
798+ seq_cnt, lp->disc_seq_count, fr_sof(fp), fr_eof(fp));
799+ }
800+ if (buf) {
801+ error = fc_disc_gpn_ft_parse(lp, buf, len);
802+ if (error)
803+ fc_disc_retry(lp);
804+ else
805+ lp->disc_seq_count++;
806+ }
807+ fc_frame_free(fp);
808+}
809+
810+/*
811+ * Discover the directory information for a single target.
812+ * This could be from an RSCN that reported a change for the target.
813+ */
814+static void fc_disc_single(struct fc_lport *lp, struct fc_disc_port *dp)
815+{
816+ struct fc_rport *rport;
817+ struct fc_rport *rp;
818+ struct fc_rport_libfc_priv *rpp;
819+
820+ if (dp->ids.port_id == lp->fid)
821+ goto out;
822+
823+ rport = lp->tt.rport_lookup(lp, dp->ids.port_id);
824+ if (rport) {
825+ fc_disc_del_target(lp, rport);
826+ put_device(&rport->dev); /* hold from lookup */
827+ }
828+
829+ rp = fc_rport_dummy_create(dp);
830+ if (rp) {
831+ rpp = rp->dd_data;
832+ kfree(dp);
833+ lp->tt.rport_login(rp);
834+ }
835+ return;
836+out:
837+ kfree(dp);
838+}
839+
840+int fc_disc_init(struct fc_lport *lp)
841+{
842+ INIT_DELAYED_WORK(&lp->disc_work, fc_disc_timeout);
843+
844+ if (!lp->tt.disc_start)
845+ lp->tt.disc_start = fc_disc_start;
846+
847+ if (!lp->tt.disc_recv_req)
848+ lp->tt.disc_recv_req = fc_disc_recv_req;
849+
850+ return 0;
851+}
852+EXPORT_SYMBOL(fc_disc_init);
853diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
854index 11a03bd..ed74d95 100644
855--- a/drivers/scsi/libfc/fc_exch.c
856+++ b/drivers/scsi/libfc/fc_exch.c
857@@ -1,5 +1,7 @@
858 /*
859 * Copyright(c) 2007 Intel Corporation. All rights reserved.
860+ * Copyright(c) 2008 Red Hat, Inc. All rights reserved.
861+ * Copyright(c) 2008 Mike Christie
862 *
863 * This program is free software; you can redistribute it and/or modify it
864 * under the terms and conditions of the GNU General Public License,
865@@ -73,6 +75,9 @@ struct fc_exch;
866 * esb_stat, f_ctl, seq.ssb_stat, seq.f_ctl.
867 * seq_id
868 * sequence allocation
869+ *
870+ * If the em_lock and ex_lock must be taken at the same time, the
871+ * em_lock must be taken before the ex_lock.
872 */
873 struct fc_exch {
874 struct fc_exch_mgr *em; /* exchange manager */
875@@ -95,13 +100,16 @@ struct fc_exch {
876 u8 fh_type; /* frame type */
877 enum fc_class class; /* class of service */
878 struct fc_seq seq; /* single sequence */
879- struct fc_exch *aborted_ep; /* ref to ep rrq is cleaning up */
880-
881 /*
882 * Handler for responses to this current exchange.
883 */
884 void (*resp)(struct fc_seq *, struct fc_frame *, void *);
885- void *resp_arg; /* 3rd arg for exchange resp handler */
886+ void (*destructor)(struct fc_seq *, void *);
887+ /*
888+ * arg is passed as void pointer to exchange
889+ * resp and destructor handlers
890+ */
891+ void *arg;
892 };
893
894 /*
895@@ -297,6 +305,8 @@ static void fc_exch_release(struct fc_exch *ep)
896
897 if (atomic_dec_and_test(&ep->ex_refcnt)) {
898 mp = ep->em;
899+ if (ep->destructor)
900+ ep->destructor(&ep->seq, ep->arg);
901 if (ep->lp->tt.exch_put)
902 ep->lp->tt.exch_put(ep->lp, mp, ep->xid);
903 WARN_ON(!ep->esb_stat & ESB_ST_COMPLETE);
904@@ -324,7 +334,6 @@ static int fc_exch_done_locked(struct fc_exch *ep)
905 ep->state |= FC_EX_DONE;
906 if (del_timer(&ep->ex_timer))
907 atomic_dec(&ep->ex_refcnt); /* drop hold for timer */
908- atomic_dec(&ep->ex_refcnt); /* drop hold from alloc */
909 rc = 0;
910 }
911 return rc;
912@@ -341,6 +350,7 @@ static void fc_exch_mgr_delete_ep(struct fc_exch *ep)
913 mp->exches[ep->xid - mp->min_xid] = NULL;
914 list_del(&ep->ex_list);
915 spin_unlock_bh(&mp->em_lock);
916+ fc_exch_release(ep); /* drop hold for exch in mp */
917 }
918
919 /*
920@@ -441,13 +451,13 @@ static void fc_exch_timeout(unsigned long ep_arg)
921 e_stat = ep->esb_stat;
922 if (e_stat & ESB_ST_COMPLETE) {
923 ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL;
924- spin_unlock_bh(&ep->ex_lock);
925 if (e_stat & ESB_ST_REC_QUAL)
926 fc_exch_rrq(ep);
927+ spin_unlock_bh(&ep->ex_lock);
928 goto done;
929 } else {
930 resp = ep->resp;
931- arg = ep->resp_arg;
932+ arg = ep->arg;
933 ep->resp = NULL;
934 if (e_stat & ESB_ST_ABNORMAL)
935 rc = fc_exch_done_locked(ep);
936@@ -492,6 +502,7 @@ static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id)
937 *
938 * if xid is supplied zero then assign next free exchange ID
939 * from exchange manager, otherwise use supplied xid.
940+ * Returns with exch lock held.
941 */
942 struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, u16 xid)
943 {
944@@ -540,16 +551,24 @@ struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, u16 xid)
945 xid = fc_exch_next_xid(mp, xid);
946 }
947
948- if (likely(mp->exches[xid - min_xid] == NULL)) {
949- mp->last_xid = xid;
950- } else {
951- spin_unlock_bh(&mp->em_lock);
952- atomic_inc(&mp->stats.no_free_exch_xid);
953- mempool_free(ep, mp->ep_pool);
954- goto out;
955- }
956+ if (unlikely(mp->exches[xid - min_xid] != NULL))
957+ goto err;
958+ mp->last_xid = xid;
959 }
960
961+ /* lport lock ? */
962+ if (mp->lp->state == LPORT_ST_RESET)
963+ goto err; /* don't add new ep during local port reset */
964+
965+ fc_exch_hold(ep); /* hold for exch in mp */
966+ spin_lock_init(&ep->ex_lock);
967+ /*
968+ * Hold exch lock for caller to prevent fc_exch_reset()
969+ * from releasing exch while fc_exch_alloc() caller is
970+ * still working on exch.
971+ */
972+ spin_lock_bh(&ep->ex_lock);
973+
974 mp->exches[xid - min_xid] = ep;
975 list_add_tail(&ep->ex_list, &mp->ex_list);
976 fc_seq_alloc(ep, ep->seq_id++);
977@@ -565,13 +584,14 @@ struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, u16 xid)
978 ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */
979 ep->rxid = FC_XID_UNKNOWN;
980 ep->class = mp->class;
981-
982- spin_lock_init(&ep->ex_lock);
983 setup_timer(&ep->ex_timer, fc_exch_timeout, (unsigned long)ep);
984-
985- fc_exch_hold(ep); /* hold for caller */
986 out:
987 return ep;
988+err:
989+ spin_unlock_bh(&mp->em_lock);
990+ atomic_inc(&mp->stats.no_free_exch_xid);
991+ mempool_free(ep, mp->ep_pool);
992+ return NULL;
993 }
994 EXPORT_SYMBOL(fc_exch_alloc);
995
996@@ -654,6 +674,8 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
997 WARN_ON(rxid != FC_XID_UNKNOWN);
998 fh->fh_rx_id = htons(ep->rxid);
999 }
1000+ fc_exch_hold(ep); /* hold for caller */
1001+ spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */
1002 }
1003 return ep;
1004 }
1005@@ -667,7 +689,7 @@ static enum fc_pf_rjt_reason
1006 fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp)
1007 {
1008 struct fc_frame_header *fh = fc_frame_header_get(fp);
1009- struct fc_exch *ep = NULL, *new_ep = NULL;
1010+ struct fc_exch *ep = NULL;
1011 struct fc_seq *sp = NULL;
1012 enum fc_pf_rjt_reason reject = FC_RJT_NONE;
1013 u32 f_ctl;
1014@@ -717,12 +739,11 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp)
1015 reject = FC_RJT_RX_ID;
1016 goto rel;
1017 }
1018- new_ep = ep = fc_exch_resp(mp, fp);
1019+ ep = fc_exch_resp(mp, fp);
1020 if (!ep) {
1021 reject = FC_RJT_EXCH_EST; /* XXX */
1022 goto out;
1023 }
1024- fc_exch_hold(ep); /* Additional hold for caller */
1025 xid = ep->xid; /* get our XID */
1026 } else if (!ep) {
1027 atomic_inc(&mp->stats.xid_not_found);
1028@@ -760,9 +781,8 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp)
1029 out:
1030 return reject;
1031 rel:
1032- fc_exch_release(ep);
1033- if (new_ep)
1034- fc_exch_release(new_ep);
1035+ fc_exch_done(&ep->seq);
1036+ fc_exch_release(ep); /* hold from fc_exch_find/fc_exch_resp */
1037 return reject;
1038 }
1039
1040@@ -1160,7 +1180,7 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
1041 * first.
1042 */
1043 if (ep->resp)
1044- ep->resp(sp, fp, ep->resp_arg);
1045+ ep->resp(sp, fp, ep->arg);
1046 else
1047 lp->tt.lport_recv(lp, sp, fp);
1048 fc_exch_release(ep); /* release from lookup */
1049@@ -1222,7 +1242,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1050 if (fc_sof_needs_ack(sof))
1051 fc_seq_send_ack(sp, fp);
1052 resp = ep->resp;
1053- ex_resp_arg = ep->resp_arg;
1054+ ex_resp_arg = ep->arg;
1055
1056 if (fh->fh_type != FC_TYPE_FCP && fr_eof(fp) == FC_EOF_T &&
1057 (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) ==
1058@@ -1332,7 +1352,7 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
1059 }
1060
1061 resp = ep->resp;
1062- ex_resp_arg = ep->resp_arg;
1063+ ex_resp_arg = ep->arg;
1064
1065 /* do we need to do some other checks here. Can we reuse more of
1066 * fc_exch_recv_seq_resp
1067@@ -1341,7 +1361,7 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
1068 /*
1069 * do we want to check END_SEQ as well as LAST_SEQ here?
1070 */
1071- if (fh->fh_type != FC_TYPE_FCP &&
1072+ if (ep->fh_type != FC_TYPE_FCP &&
1073 ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ)
1074 rc = fc_exch_done_locked(ep);
1075 spin_unlock_bh(&ep->ex_lock);
1076@@ -1485,11 +1505,9 @@ static void fc_exch_reset(struct fc_exch *ep)
1077 if (ep->esb_stat & ESB_ST_REC_QUAL)
1078 atomic_dec(&ep->ex_refcnt); /* drop hold for rec_qual */
1079 ep->esb_stat &= ~ESB_ST_REC_QUAL;
1080- arg = ep->resp_arg;
1081+ arg = ep->arg;
1082 sp = &ep->seq;
1083-
1084- if (ep->fh_type != FC_TYPE_FCP)
1085- rc = fc_exch_done_locked(ep);
1086+ rc = fc_exch_done_locked(ep);
1087 spin_unlock_bh(&ep->ex_lock);
1088 if (!rc)
1089 fc_exch_mgr_delete_ep(ep);
1090@@ -1640,9 +1658,7 @@ reject:
1091 */
1092 static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1093 {
1094- struct fc_exch *ep = fc_seq_exch(sp);
1095- struct fc_exch *aborted_ep;
1096-
1097+ struct fc_exch *aborted_ep = arg;
1098 unsigned int op;
1099
1100 if (IS_ERR(fp)) {
1101@@ -1669,16 +1685,9 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1102 }
1103
1104 cleanup:
1105- spin_lock_bh(&ep->ex_lock);
1106- aborted_ep = ep->aborted_ep;
1107- ep->aborted_ep = NULL;
1108- spin_unlock_bh(&ep->ex_lock);
1109-
1110- if (aborted_ep) {
1111- fc_exch_done(&aborted_ep->seq);
1112- /* drop hold for rec qual */
1113- fc_exch_release(aborted_ep);
1114- }
1115+ fc_exch_done(&aborted_ep->seq);
1116+ /* drop hold for rec qual */
1117+ fc_exch_release(aborted_ep);
1118 }
1119
1120 /*
1121@@ -1692,7 +1701,6 @@ static void fc_exch_rrq(struct fc_exch *ep)
1122 struct fc_els_rrq *rrq;
1123 struct fc_frame *fp;
1124 struct fc_seq *rrq_sp;
1125- struct fc_exch *rrq_ep;
1126 u32 did;
1127
1128 lp = ep->lp;
1129@@ -1711,18 +1719,14 @@ static void fc_exch_rrq(struct fc_exch *ep)
1130 did = ep->did;
1131 if (ep->esb_stat & ESB_ST_RESP)
1132 did = ep->sid;
1133- rrq_sp = fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, ep, lp->e_d_tov,
1134- lp->fid, did, FC_FC_SEQ_INIT | FC_FC_END_SEQ);
1135+ rrq_sp = fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep,
1136+ lp->e_d_tov, lp->fid, did,
1137+ FC_FC_SEQ_INIT | FC_FC_END_SEQ);
1138 if (!rrq_sp) {
1139- spin_lock_bh(&ep->ex_lock);
1140 ep->esb_stat |= ESB_ST_REC_QUAL;
1141 fc_exch_timer_set_locked(ep, ep->r_a_tov);
1142- spin_unlock_bh(&ep->ex_lock);
1143 return;
1144 }
1145-
1146- rrq_ep = fc_seq_exch(rrq_sp);
1147- rrq_ep->aborted_ep = ep;
1148 }
1149
1150
1151@@ -1860,13 +1864,15 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
1152 void (*resp)(struct fc_seq *,
1153 struct fc_frame *fp,
1154 void *arg),
1155- void *resp_arg, u32 timer_msec,
1156+ void (*destructor)(struct fc_seq *, void *),
1157+ void *arg, u32 timer_msec,
1158 u32 sid, u32 did, u32 f_ctl)
1159 {
1160 struct fc_exch *ep;
1161 struct fc_seq *sp = NULL;
1162 struct fc_frame_header *fh;
1163 u16 fill;
1164+ int rc = 1;
1165
1166 ep = lp->tt.exch_get(lp, fp);
1167 if (!ep) {
1168@@ -1876,7 +1882,8 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
1169 ep->esb_stat |= ESB_ST_SEQ_INIT;
1170 fc_exch_set_addr(ep, sid, did);
1171 ep->resp = resp;
1172- ep->resp_arg = resp_arg;
1173+ ep->destructor = destructor;
1174+ ep->arg = arg;
1175 ep->r_a_tov = FC_DEF_R_A_TOV;
1176 ep->lp = lp;
1177 sp = &ep->seq;
1178@@ -1912,7 +1919,6 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
1179 if (unlikely(lp->tt.frame_send(lp, fp)))
1180 goto err;
1181
1182- spin_lock_bh(&ep->ex_lock);
1183 if (timer_msec)
1184 fc_exch_timer_set_locked(ep, timer_msec);
1185 sp->f_ctl = f_ctl; /* save for possible abort */
1186@@ -1924,7 +1930,10 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
1187 spin_unlock_bh(&ep->ex_lock);
1188 return sp;
1189 err:
1190- fc_exch_done(sp);
1191+ rc = fc_exch_done_locked(ep);
1192+ spin_unlock_bh(&ep->ex_lock);
1193+ if (!rc)
1194+ fc_exch_mgr_delete_ep(ep);
1195 return NULL;
1196 }
1197 EXPORT_SYMBOL(fc_exch_seq_send);
1198@@ -1938,6 +1947,7 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
1199 struct fc_frame_header *fh = fc_frame_header_get(fp);
1200 u32 f_ctl;
1201
1202+ /* lport lock ? */
1203 if (!lp || !mp || (lp->state == LPORT_ST_NONE)) {
1204 FC_DBG("fc_lport or EM is not allocated and configured");
1205 fc_frame_free(fp);
1206diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
1207index 97da731..2566eed 100644
1208--- a/drivers/scsi/libfc/fc_fcp.c
1209+++ b/drivers/scsi/libfc/fc_fcp.c
1210@@ -38,6 +38,10 @@
1211
1212 #include <scsi/libfc/libfc.h>
1213
1214+MODULE_AUTHOR("Open-FCoE.org");
1215+MODULE_DESCRIPTION("libfc");
1216+MODULE_LICENSE("GPL");
1217+
1218 int fc_fcp_debug;
1219 static struct kmem_cache *scsi_pkt_cachep;
1220
1221@@ -206,6 +210,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp)
1222 atomic_set(&sp->ref_cnt, 1);
1223 init_timer(&sp->timer);
1224 INIT_LIST_HEAD(&sp->list);
1225+ spin_lock_init(&sp->scsi_pkt_lock);
1226 }
1227 return sp;
1228 }
1229@@ -233,6 +238,22 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *sp)
1230 }
1231
1232 /**
1233+ * fc_fcp_pkt_destory - release hold on scsi_pkt packet
1234+ *
1235+ * @sp: exchange sequence
1236+ * @fsp: fcp packet struct
1237+ *
1238+ * Release hold on scsi_pkt packet set to keep scsi_pkt
1239+ * till EM layer exch resource is not freed.
1240+ * Context : called from from EM layer.
1241+ * no locking required
1242+ */
1243+static void fc_fcp_pkt_destroy(struct fc_seq *sp, void *arg)
1244+{
1245+ fc_fcp_pkt_release(arg);
1246+}
1247+
1248+/**
1249 * fc_fcp_lock_pkt - lock a packet and get a ref to it.
1250 * @fsp: fcp packet
1251 *
1252@@ -604,13 +625,31 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *sp,
1253 return 0;
1254 }
1255
1256-static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame_header *fh)
1257+static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
1258 {
1259- /*
1260- * we will let the command timeout and scsi-ml escalate if
1261- * the abort was rejected
1262- */
1263- if (fh->fh_r_ctl == FC_RCTL_BA_ACC) {
1264+ int ba_done = 1;
1265+ struct fc_ba_rjt *brp;
1266+ struct fc_frame_header *fh;
1267+
1268+ fh = fc_frame_header_get(fp);
1269+ switch (fh->fh_r_ctl) {
1270+ case FC_RCTL_BA_ACC:
1271+ break;
1272+ case FC_RCTL_BA_RJT:
1273+ brp = fc_frame_payload_get(fp, sizeof(*brp));
1274+ if (brp && brp->br_reason == FC_BA_RJT_LOG_ERR)
1275+ break;
1276+ /* fall thru */
1277+ default:
1278+ /*
1279+ * we will let the command timeout
1280+ * and scsi-ml recover in this case,
1281+ * therefore cleared the ba_done flag.
1282+ */
1283+ ba_done = 0;
1284+ }
1285+
1286+ if (ba_done) {
1287 fsp->state |= FC_SRB_ABORTED;
1288 fsp->state &= ~FC_SRB_ABORT_PENDING;
1289
1290@@ -666,7 +705,7 @@ static void fc_fcp_recv(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1291 struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)arg;
1292 struct fc_lport *lp;
1293 struct fc_frame_header *fh;
1294- struct fc_data_desc *dd;
1295+ struct fcp_txrdy *dd;
1296 u8 r_ctl;
1297 int rc = 0;
1298
1299@@ -684,7 +723,7 @@ static void fc_fcp_recv(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1300 fsp->last_pkt_time = jiffies;
1301
1302 if (fh->fh_type == FC_TYPE_BLS) {
1303- fc_fcp_abts_resp(fsp, fh);
1304+ fc_fcp_abts_resp(fsp, fp);
1305 goto unlock;
1306 }
1307
1308@@ -701,8 +740,8 @@ static void fc_fcp_recv(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1309 WARN_ON(!dd);
1310
1311 rc = fc_fcp_send_data(fsp, sp,
1312- (size_t) ntohl(dd->dd_offset),
1313- (size_t) ntohl(dd->dd_len), fp,
1314+ (size_t) ntohl(dd->ft_data_ro),
1315+ (size_t) ntohl(dd->ft_burst_len), fp,
1316 lp->capabilities & TRANS_C_SG);
1317 if (!rc)
1318 lp->tt.seq_set_rec_data(sp, fsp->xfer_len);
1319@@ -1025,6 +1064,7 @@ static int fc_fcp_send_cmd(struct fc_fcp_pkt *fsp)
1320 rp = rport->dd_data;
1321 sp = lp->tt.exch_seq_send(lp, fp,
1322 fc_fcp_recv,
1323+ fc_fcp_pkt_destroy,
1324 fsp, 0,
1325 rp->local_port->fid,
1326 rport->port_id,
1327@@ -1034,7 +1074,9 @@ static int fc_fcp_send_cmd(struct fc_fcp_pkt *fsp)
1328 rc = -1;
1329 goto unlock;
1330 }
1331+ fsp->last_pkt_time = jiffies;
1332 fsp->seq_ptr = sp;
1333+ fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
1334
1335 setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
1336 fc_fcp_timer_set(fsp,
1337@@ -1131,6 +1173,7 @@ static void fc_lun_reset_send(unsigned long data)
1338 rp = rport->dd_data;
1339 sp = lp->tt.exch_seq_send(lp, fp,
1340 fc_tm_done,
1341+ fc_fcp_pkt_destroy,
1342 fsp, 0,
1343 rp->local_port->fid,
1344 rport->port_id,
1345@@ -1138,6 +1181,7 @@ static void fc_lun_reset_send(unsigned long data)
1346
1347 if (sp) {
1348 fsp->seq_ptr = sp;
1349+ fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
1350 goto unlock;
1351 }
1352 /*
1353@@ -1183,12 +1227,6 @@ static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
1354
1355 spin_lock_bh(&fsp->scsi_pkt_lock);
1356 if (fsp->seq_ptr) {
1357- /* TODO:
1358- * if the exch resp function is running and trying to grab
1359- * the scsi_pkt_lock, this could free the exch from under
1360- * it and it could allow the fsp to be freed from under
1361- * fc_tm_done.
1362- */
1363 lp->tt.exch_done(fsp->seq_ptr);
1364 fsp->seq_ptr = NULL;
1365 }
1366@@ -1231,9 +1269,6 @@ static void fc_tm_done(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1367
1368 /*
1369 * raced with eh timeout handler.
1370- *
1371- * TODO: If this happens we could be freeing the fsp right now and
1372- * would oops. Next patches will fix this race.
1373 */
1374 if ((fsp->state & FC_SRB_COMPL) || !fsp->seq_ptr ||
1375 !fsp->wait_for_comp) {
1376@@ -1288,14 +1323,13 @@ static void fc_fcp_timeout(unsigned long data)
1377
1378 if (rp->flags & FC_RP_FLAGS_REC_SUPPORTED)
1379 fc_fcp_rec(fsp);
1380- /* TODO: change this to time_before/after */
1381- else if (jiffies - fsp->last_pkt_time < FC_SCSI_ER_TIMEOUT / 2)
1382+ else if (time_after_eq(fsp->last_pkt_time + (FC_SCSI_ER_TIMEOUT / 2),
1383+ jiffies))
1384 fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
1385 else if (fsp->state & FC_SRB_RCV_STATUS)
1386 fc_fcp_complete(fsp);
1387 else
1388 fc_timeout_error(fsp);
1389-
1390 fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;
1391 unlock:
1392 fc_fcp_unlock_pkt(fsp);
1393@@ -1340,7 +1374,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
1394 fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
1395 fc_frame_set_offset(fp, 0);
1396 sp = lp->tt.exch_seq_send(lp, fp,
1397- fc_fcp_rec_resp,
1398+ fc_fcp_rec_resp, NULL,
1399 fsp, jiffies_to_msecs(FC_SCSI_REC_TOV),
1400 rp->local_port->fid,
1401 rport->port_id,
1402@@ -1402,9 +1436,14 @@ static void fc_fcp_rec_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1403 if (fc_fcp_debug)
1404 FC_DBG("device does not support REC\n");
1405 rp = fsp->rport->dd_data;
1406+ /*
1407+ * if we do not spport RECs or got some bogus
1408+ * reason then resetup timer so we check for
1409+ * making progress.
1410+ */
1411 rp->flags &= ~FC_RP_FLAGS_REC_SUPPORTED;
1412- /* fall through */
1413-
1414+ fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
1415+ break;
1416 case ELS_RJT_LOGIC:
1417 case ELS_RJT_UNAB:
1418 /*
1419@@ -1595,7 +1634,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
1420 fc_frame_setup(fp, FC_RCTL_ELS4_REQ, FC_TYPE_FCP);
1421 fc_frame_set_offset(fp, 0);
1422 sp = lp->tt.exch_seq_send(lp, fp,
1423- fc_fcp_srr_resp,
1424+ fc_fcp_srr_resp, NULL,
1425 fsp, jiffies_to_msecs(FC_SCSI_REC_TOV),
1426 rp->local_port->fid,
1427 rport->port_id,
1428@@ -2048,7 +2087,7 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd)
1429 shost_printk(KERN_INFO, shost, "Host reset succeeded.\n");
1430 return SUCCESS;
1431 } else {
1432- shost_printk(KERN_INFO, shost, "Host reset succeeded failed."
1433+ shost_printk(KERN_INFO, shost, "Host reset failed. "
1434 "lport not ready.\n");
1435 return FAILED;
1436 }
1437diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
1438index b390a32..b1854b9 100644
1439--- a/drivers/scsi/libfc/fc_lport.c
1440+++ b/drivers/scsi/libfc/fc_lport.c
1441@@ -36,76 +36,130 @@
1442
1443 static int fc_lport_debug;
1444
1445+static void fc_lport_error(struct fc_lport *, struct fc_frame *);
1446+
1447+static void fc_lport_enter_reset(struct fc_lport *);
1448 static void fc_lport_enter_flogi(struct fc_lport *);
1449+static void fc_lport_enter_dns(struct fc_lport *);
1450+static void fc_lport_enter_rpn_id(struct fc_lport *);
1451+static void fc_lport_enter_rft_id(struct fc_lport *);
1452+static void fc_lport_enter_scr(struct fc_lport *);
1453+static void fc_lport_enter_ready(struct fc_lport *);
1454 static void fc_lport_enter_logo(struct fc_lport *);
1455
1456 static const char *fc_lport_state_names[] = {
1457 [LPORT_ST_NONE] = "none",
1458 [LPORT_ST_FLOGI] = "FLOGI",
1459 [LPORT_ST_DNS] = "dNS",
1460- [LPORT_ST_REG_PN] = "REG_PN",
1461- [LPORT_ST_REG_FT] = "REG_FT",
1462+ [LPORT_ST_RPN_ID] = "RPN_ID",
1463+ [LPORT_ST_RFT_ID] = "RFT_ID",
1464 [LPORT_ST_SCR] = "SCR",
1465- [LPORT_ST_READY] = "ready",
1466- [LPORT_ST_DNS_STOP] = "stop",
1467+ [LPORT_ST_READY] = "Ready",
1468 [LPORT_ST_LOGO] = "LOGO",
1469 [LPORT_ST_RESET] = "reset",
1470 };
1471
1472-static int fc_frame_drop(struct fc_lport *lp, struct fc_frame *fp)
1473+static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
1474 {
1475 fc_frame_free(fp);
1476 return 0;
1477 }
1478
1479-static const char *fc_lport_state(struct fc_lport *lp)
1480+/**
1481+ * fc_lport_rport_event - Event handler for rport events
1482+ * @lport: The lport which is receiving the event
1483+ * @port_id: The FID of the rport which the event has occured on
1484+ * @event: The event that occured
1485+ *
1486+ * Locking Note: The rport lock should not be held when calling
1487+ * this function.
1488+ */
1489+static void fc_lport_rport_event(struct fc_lport *lport, u32 port_id,
1490+ enum fc_lport_event event)
1491+{
1492+ struct fc_rport *rport = lport->tt.rport_lookup(lport, port_id);
1493+
1494+ if (fc_lport_debug)
1495+ FC_DBG("Received a %d event for port (%6x)\n", event, port_id);
1496+
1497+ if (port_id == FC_FID_DIR_SERV) {
1498+ mutex_lock(&lport->lp_mutex);
1499+ switch (event) {
1500+ case LPORT_EV_RPORT_CREATED:
1501+ if (rport) {
1502+ lport->dns_rp = rport;
1503+ fc_lport_enter_rpn_id(lport);
1504+ }
1505+ break;
1506+ case LPORT_EV_RPORT_LOGO:
1507+ case LPORT_EV_RPORT_FAILED:
1508+ lport->dns_rp = NULL;
1509+ fc_lport_enter_dns(lport);
1510+ break;
1511+ case LPORT_EV_RPORT_NONE:
1512+ break;
1513+ }
1514+ mutex_unlock(&lport->lp_mutex);
1515+ }
1516+}
1517+
1518+/**
1519+ * fc_lport_state - Return a string which represents the lport's state
1520+ * @lport: The lport whose state is to converted to a string
1521+ */
1522+static const char *fc_lport_state(struct fc_lport *lport)
1523 {
1524 const char *cp;
1525
1526- cp = fc_lport_state_names[lp->state];
1527+ cp = fc_lport_state_names[lport->state];
1528 if (!cp)
1529 cp = "unknown";
1530 return cp;
1531 }
1532
1533-static void fc_lport_ptp_setup(struct fc_lport *lp,
1534- u32 remote_fid, u64 remote_wwpn,
1535- u64 remote_wwnn)
1536+/**
1537+ * fc_lport_ptp_clear - Delete the ptp rport
1538+ * @lport: The lport whose ptp rport should be removed
1539+ */
1540+static void fc_lport_ptp_clear(struct fc_lport *lport)
1541 {
1542- struct fc_rport *rport;
1543- struct fc_rport_identifiers ids = {
1544- .port_id = remote_fid,
1545- .port_name = remote_wwpn,
1546- .node_name = remote_wwnn,
1547- };
1548-
1549- /*
1550- * if we have to create a rport the fc class can sleep so we must
1551- * drop the lock here
1552- */
1553- fc_lport_unlock(lp);
1554- rport = lp->tt.rport_lookup(lp, ids.port_id); /* lookup and hold */
1555- if (rport == NULL)
1556- rport = lp->tt.rport_create(lp, &ids); /* create and hold */
1557- fc_lport_lock(lp);
1558- if (rport) {
1559- if (lp->ptp_rp)
1560- fc_remote_port_delete(lp->ptp_rp);
1561- lp->ptp_rp = rport;
1562- fc_lport_state_enter(lp, LPORT_ST_READY);
1563+ if (lport->ptp_rp) {
1564+ fc_remote_port_delete(lport->ptp_rp);
1565+ lport->ptp_rp = NULL;
1566 }
1567 }
1568
1569-static void fc_lport_ptp_clear(struct fc_lport *lp)
1570+/**
1571+ * fc_lport_ptp_setup - Create an rport for point-to-point mode
1572+ * @lport: The lport to attach the ptp rport to
1573+ * @fid: The FID of the ptp rport
1574+ * @remote_wwpn: The WWPN of the ptp rport
1575+ * @remote_wwnn: The WWNN of the ptp rport
1576+ */
1577+static void fc_lport_ptp_setup(struct fc_lport *lport,
1578+ u32 remote_fid, u64 remote_wwpn,
1579+ u64 remote_wwnn)
1580 {
1581- if (lp->ptp_rp) {
1582- fc_remote_port_delete(lp->ptp_rp);
1583- lp->ptp_rp = NULL;
1584- }
1585+ struct fc_disc_port dp;
1586+
1587+ dp.lp = lport;
1588+ dp.ids.port_id = remote_fid;
1589+ dp.ids.port_name = remote_wwpn;
1590+ dp.ids.node_name = remote_wwnn;
1591+ dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
1592+
1593+ fc_lport_ptp_clear(lport);
1594+
1595+ lport->ptp_rp = fc_rport_dummy_create(&dp);
1596+
1597+ lport->tt.rport_login(lport->ptp_rp);
1598+
1599+ fc_lport_enter_ready(lport);
1600 }
1601
1602-/*
1603- * Routines to support struct fc_function_template
1604+/**
1605+ * fc_get_host_port_state - supports fc_function_template
1606+ * @shost: The host whose port state should be returned
1607 */
1608 void fc_get_host_port_state(struct Scsi_Host *shost)
1609 {
1610@@ -118,82 +172,130 @@ void fc_get_host_port_state(struct Scsi_Host *shost)
1611 }
1612 EXPORT_SYMBOL(fc_get_host_port_state);
1613
1614+void fc_get_host_speed(struct Scsi_Host *shost)
1615+{
1616+ struct fc_lport *lport = shost_priv(shost);
1617+
1618+ fc_host_speed(shost) = lport->link_speed;
1619+}
1620+EXPORT_SYMBOL(fc_get_host_speed);
1621+
1622+struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
1623+{
1624+ int i;
1625+ struct fc_host_statistics *fcoe_stats;
1626+ struct fc_lport *lp = shost_priv(shost);
1627+ struct timespec v0, v1;
1628+
1629+ fcoe_stats = &lp->host_stats;
1630+ memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
1631+
1632+ jiffies_to_timespec(jiffies, &v0);
1633+ jiffies_to_timespec(lp->boot_time, &v1);
1634+ fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec);
1635+
1636+ for_each_online_cpu(i) {
1637+ struct fcoe_dev_stats *stats = lp->dev_stats[i];
1638+ if (stats == NULL)
1639+ continue;
1640+ fcoe_stats->tx_frames += stats->TxFrames;
1641+ fcoe_stats->tx_words += stats->TxWords;
1642+ fcoe_stats->rx_frames += stats->RxFrames;
1643+ fcoe_stats->rx_words += stats->RxWords;
1644+ fcoe_stats->error_frames += stats->ErrorFrames;
1645+ fcoe_stats->invalid_crc_count += stats->InvalidCRCCount;
1646+ fcoe_stats->fcp_input_requests += stats->InputRequests;
1647+ fcoe_stats->fcp_output_requests += stats->OutputRequests;
1648+ fcoe_stats->fcp_control_requests += stats->ControlRequests;
1649+ fcoe_stats->fcp_input_megabytes += stats->InputMegabytes;
1650+ fcoe_stats->fcp_output_megabytes += stats->OutputMegabytes;
1651+ fcoe_stats->link_failure_count += stats->LinkFailureCount;
1652+ }
1653+ fcoe_stats->lip_count = -1;
1654+ fcoe_stats->nos_count = -1;
1655+ fcoe_stats->loss_of_sync_count = -1;
1656+ fcoe_stats->loss_of_signal_count = -1;
1657+ fcoe_stats->prim_seq_protocol_err_count = -1;
1658+ fcoe_stats->dumped_frames = -1;
1659+ return fcoe_stats;
1660+}
1661+EXPORT_SYMBOL(fc_get_host_stats);
1662+
1663 /*
1664 * Fill in FLOGI command for request.
1665 */
1666 static void
1667-fc_lport_flogi_fill(struct fc_lport *lp,
1668- struct fc_els_flogi *flogi, unsigned int op)
1669+fc_lport_flogi_fill(struct fc_lport *lport, struct fc_els_flogi *flogi,
1670+ unsigned int op)
1671 {
1672 struct fc_els_csp *sp;
1673 struct fc_els_cssp *cp;
1674
1675 memset(flogi, 0, sizeof(*flogi));
1676 flogi->fl_cmd = (u8) op;
1677- put_unaligned_be64(lp->wwpn, &flogi->fl_wwpn);
1678- put_unaligned_be64(lp->wwnn, &flogi->fl_wwnn);
1679+ put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
1680+ put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
1681 sp = &flogi->fl_csp;
1682 sp->sp_hi_ver = 0x20;
1683 sp->sp_lo_ver = 0x20;
1684 sp->sp_bb_cred = htons(10); /* this gets set by gateway */
1685- sp->sp_bb_data = htons((u16) lp->mfs);
1686+ sp->sp_bb_data = htons((u16) lport->mfs);
1687 cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */
1688 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
1689 if (op != ELS_FLOGI) {
1690 sp->sp_features = htons(FC_SP_FT_CIRO);
1691 sp->sp_tot_seq = htons(255); /* seq. we accept */
1692 sp->sp_rel_off = htons(0x1f);
1693- sp->sp_e_d_tov = htonl(lp->e_d_tov);
1694+ sp->sp_e_d_tov = htonl(lport->e_d_tov);
1695
1696- cp->cp_rdfs = htons((u16) lp->mfs);
1697+ cp->cp_rdfs = htons((u16) lport->mfs);
1698 cp->cp_con_seq = htons(255);
1699 cp->cp_open_seq = 1;
1700 }
1701 }
1702
1703 /*
1704- * Set the fid. This indicates that we have a new connection to the
1705- * fabric so we should reset our list of fc_rports. Passing a fid of
1706- * 0 will also reset the rport list regardless of the previous fid.
1707- */
1708-static void fc_lport_set_fid(struct fc_lport *lp, u32 fid)
1709-{
1710- if (fid != 0 && lp->fid == fid)
1711- return;
1712-
1713- if (fc_lport_debug)
1714- FC_DBG("changing local port fid from %x to %x\n",
1715- lp->fid, fid);
1716- lp->fid = fid;
1717- lp->tt.rport_reset_list(lp);
1718-}
1719-
1720-/*
1721 * Add a supported FC-4 type.
1722 */
1723-static void fc_lport_add_fc4_type(struct fc_lport *lp, enum fc_fh_type type)
1724+static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type)
1725 {
1726 __be32 *mp;
1727
1728- mp = &lp->fcts.ff_type_map[type / FC_NS_BPW];
1729+ mp = &lport->fcts.ff_type_map[type / FC_NS_BPW];
1730 *mp = htonl(ntohl(*mp) | 1UL << (type % FC_NS_BPW));
1731 }
1732
1733-/*
1734- * Handle received RLIR - registered link incident report.
1735+/**
1736+ * fc_lport_recv_rlir_req - Handle received Registered Link Incident Report.
1737+ * @lport: Fibre Channel local port recieving the RLIR
1738+ * @sp: current sequence in the RLIR exchange
1739+ * @fp: RLIR request frame
1740+ *
1741+ * Locking Note: The lport lock is exected to be held before calling
1742+ * this function.
1743 */
1744-static void fc_lport_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
1745- struct fc_lport *lp)
1746+static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
1747+ struct fc_lport *lport)
1748 {
1749- lp->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
1750+ if (fc_lport_debug)
1751+ FC_DBG("Received RLIR request while in state %s\n",
1752+ fc_lport_state(lport));
1753+
1754+ lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
1755 fc_frame_free(fp);
1756 }
1757
1758-/*
1759- * Handle received ECHO.
1760+/**
1761+ * fc_lport_recv_echo_req - Handle received ECHO request
1762+ * @lport: Fibre Channel local port recieving the ECHO
1763+ * @sp: current sequence in the ECHO exchange
1764+ * @fp: ECHO request frame
1765+ *
1766+ * Locking Note: The lport lock is exected to be held before calling
1767+ * this function.
1768 */
1769-static void fc_lport_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
1770- struct fc_lport *lp)
1771+static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
1772+ struct fc_lport *lport)
1773 {
1774 struct fc_frame *fp;
1775 unsigned int len;
1776@@ -201,29 +303,40 @@ static void fc_lport_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
1777 void *dp;
1778 u32 f_ctl;
1779
1780+ if (fc_lport_debug)
1781+ FC_DBG("Received RLIR request while in state %s\n",
1782+ fc_lport_state(lport));
1783+
1784 len = fr_len(in_fp) - sizeof(struct fc_frame_header);
1785 pp = fc_frame_payload_get(in_fp, len);
1786
1787 if (len < sizeof(__be32))
1788 len = sizeof(__be32);
1789- fp = fc_frame_alloc(lp, len);
1790+
1791+ fp = fc_frame_alloc(lport, len);
1792 if (fp) {
1793 dp = fc_frame_payload_get(fp, len);
1794 memcpy(dp, pp, len);
1795 *((u32 *)dp) = htonl(ELS_LS_ACC << 24);
1796- sp = lp->tt.seq_start_next(sp);
1797+ sp = lport->tt.seq_start_next(sp);
1798 f_ctl = FC_FC_LAST_SEQ | FC_FC_END_SEQ;
1799 fc_frame_setup(fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
1800- lp->tt.seq_send(lp, sp, fp, f_ctl);
1801+ lport->tt.seq_send(lport, sp, fp, f_ctl);
1802 }
1803 fc_frame_free(in_fp);
1804 }
1805
1806-/*
1807- * Handle received RNID.
1808+/**
1809+ * fc_lport_recv_echo_req - Handle received Request Node ID data request
1810+ * @lport: Fibre Channel local port recieving the RNID
1811+ * @sp: current sequence in the RNID exchange
1812+ * @fp: RNID request frame
1813+ *
1814+ * Locking Note: The lport lock is exected to be held before calling
1815+ * this function.
1816 */
1817-static void fc_lport_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
1818- struct fc_lport *lp)
1819+static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
1820+ struct fc_lport *lport)
1821 {
1822 struct fc_frame *fp;
1823 struct fc_els_rnid *req;
1824@@ -237,146 +350,165 @@ static void fc_lport_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
1825 size_t len;
1826 u32 f_ctl;
1827
1828+ if (fc_lport_debug)
1829+ FC_DBG("Received RNID request while in state %s\n",
1830+ fc_lport_state(lport));
1831+
1832 req = fc_frame_payload_get(in_fp, sizeof(*req));
1833 if (!req) {
1834 rjt_data.fp = NULL;
1835 rjt_data.reason = ELS_RJT_LOGIC;
1836 rjt_data.explan = ELS_EXPL_NONE;
1837- lp->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
1838+ lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
1839 } else {
1840 fmt = req->rnid_fmt;
1841 len = sizeof(*rp);
1842 if (fmt != ELS_RNIDF_GEN ||
1843- ntohl(lp->rnid_gen.rnid_atype) == 0) {
1844+ ntohl(lport->rnid_gen.rnid_atype) == 0) {
1845 fmt = ELS_RNIDF_NONE; /* nothing to provide */
1846 len -= sizeof(rp->gen);
1847 }
1848- fp = fc_frame_alloc(lp, len);
1849+ fp = fc_frame_alloc(lport, len);
1850 if (fp) {
1851 rp = fc_frame_payload_get(fp, len);
1852 memset(rp, 0, len);
1853 rp->rnid.rnid_cmd = ELS_LS_ACC;
1854 rp->rnid.rnid_fmt = fmt;
1855 rp->rnid.rnid_cid_len = sizeof(rp->cid);
1856- rp->cid.rnid_wwpn = htonll(lp->wwpn);
1857- rp->cid.rnid_wwnn = htonll(lp->wwnn);
1858+ rp->cid.rnid_wwpn = htonll(lport->wwpn);
1859+ rp->cid.rnid_wwnn = htonll(lport->wwnn);
1860 if (fmt == ELS_RNIDF_GEN) {
1861 rp->rnid.rnid_sid_len = sizeof(rp->gen);
1862- memcpy(&rp->gen, &lp->rnid_gen,
1863+ memcpy(&rp->gen, &lport->rnid_gen,
1864 sizeof(rp->gen));
1865 }
1866- sp = lp->tt.seq_start_next(sp);
1867+ sp = lport->tt.seq_start_next(sp);
1868 f_ctl = FC_FC_SEQ_INIT | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
1869 fc_frame_setup(fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
1870- lp->tt.seq_send(lp, sp, fp, f_ctl);
1871+ lport->tt.seq_send(lport, sp, fp, f_ctl);
1872 }
1873 }
1874 fc_frame_free(in_fp);
1875 }
1876
1877-/*
1878- * Handle received fabric logout request.
1879+/**
1880+ * fc_lport_recv_logo_req - Handle received fabric LOGO request
1881+ * @lport: Fibre Channel local port recieving the LOGO
1882+ * @sp: current sequence in the LOGO exchange
1883+ * @fp: LOGO request frame
1884+ *
1885+ * Locking Note: The lport lock is exected to be held before calling
1886+ * this function.
1887 */
1888 static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp,
1889- struct fc_lport *lp)
1890+ struct fc_lport *lport)
1891 {
1892- lp->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
1893- fc_lport_enter_reset(lp);
1894+ lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
1895+ fc_lport_enter_reset(lport);
1896 fc_frame_free(fp);
1897 }
1898
1899-/*
1900- * Receive request frame
1901+/**
1902+ * fc_fabric_login - Start the lport state machine
1903+ * @lport: The lport that should log into the fabric
1904+ *
1905+ * Locking Note: This function should not be called
1906+ * with the lport lock held.
1907 */
1908-
1909-int fc_fabric_login(struct fc_lport *lp)
1910+int fc_fabric_login(struct fc_lport *lport)
1911 {
1912 int rc = -1;
1913
1914- if (lp->state == LPORT_ST_NONE) {
1915- fc_lport_lock(lp);
1916- fc_lport_enter_reset(lp);
1917- fc_lport_unlock(lp);
1918+ mutex_lock(&lport->lp_mutex);
1919+ if (lport->state == LPORT_ST_NONE) {
1920+ fc_lport_enter_reset(lport);
1921 rc = 0;
1922 }
1923+ mutex_unlock(&lport->lp_mutex);
1924+
1925 return rc;
1926 }
1927 EXPORT_SYMBOL(fc_fabric_login);
1928
1929 /**
1930- * fc_linkup - link up notification
1931- * @dev: Pointer to fc_lport .
1932- **/
1933-void fc_linkup(struct fc_lport *lp)
1934+ * fc_linkup - Handler for transport linkup events
1935+ * @lport: The lport whose link is up
1936+ */
1937+void fc_linkup(struct fc_lport *lport)
1938 {
1939- if ((lp->link_status & FC_LINK_UP) != FC_LINK_UP) {
1940- lp->link_status |= FC_LINK_UP;
1941- fc_lport_lock(lp);
1942- if (lp->state == LPORT_ST_RESET)
1943- lp->tt.lport_login(lp);
1944- fc_lport_unlock(lp);
1945+ mutex_lock(&lport->lp_mutex);
1946+ if ((lport->link_status & FC_LINK_UP) != FC_LINK_UP) {
1947+ lport->link_status |= FC_LINK_UP;
1948+
1949+ if (lport->state == LPORT_ST_RESET)
1950+ fc_lport_enter_flogi(lport);
1951 }
1952+ mutex_unlock(&lport->lp_mutex);
1953 }
1954 EXPORT_SYMBOL(fc_linkup);
1955
1956 /**
1957- * fc_linkdown - link down notification
1958- * @dev: Pointer to fc_lport .
1959- **/
1960-void fc_linkdown(struct fc_lport *lp)
1961+ * fc_linkdown - Handler for transport linkdown events
1962+ * @lport: The lport whose link is down
1963+ */
1964+void fc_linkdown(struct fc_lport *lport)
1965 {
1966- if ((lp->link_status & FC_LINK_UP) == FC_LINK_UP) {
1967- lp->link_status &= ~(FC_LINK_UP);
1968- fc_lport_enter_reset(lp);
1969- lp->tt.scsi_cleanup(lp);
1970+ mutex_lock(&lport->lp_mutex);
1971+
1972+ if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) {
1973+ lport->link_status &= ~(FC_LINK_UP);
1974+ fc_lport_enter_reset(lport);
1975+ lport->tt.scsi_cleanup(lport);
1976 }
1977+
1978+ mutex_unlock(&lport->lp_mutex);
1979 }
1980 EXPORT_SYMBOL(fc_linkdown);
1981
1982-void fc_pause(struct fc_lport *lp)
1983+/**
1984+ * fc_pause - Pause the flow of frames
1985+ * @lport: The lport to be paused
1986+ */
1987+void fc_pause(struct fc_lport *lport)
1988 {
1989- lp->link_status |= FC_PAUSE;
1990+ mutex_lock(&lport->lp_mutex);
1991+ lport->link_status |= FC_PAUSE;
1992+ mutex_unlock(&lport->lp_mutex);
1993 }
1994 EXPORT_SYMBOL(fc_pause);
1995
1996-void fc_unpause(struct fc_lport *lp)
1997+/**
1998+ * fc_unpause - Unpause the flow of frames
1999+ * @lport: The lport to be unpaused
2000+ */
2001+void fc_unpause(struct fc_lport *lport)
2002 {
2003- lp->link_status &= ~(FC_PAUSE);
2004+ mutex_lock(&lport->lp_mutex);
2005+ lport->link_status &= ~(FC_PAUSE);
2006+ mutex_unlock(&lport->lp_mutex);
2007 }
2008 EXPORT_SYMBOL(fc_unpause);
2009
2010-int fc_fabric_logoff(struct fc_lport *lp)
2011+/**
2012+ * fc_fabric_logoff - Logout of the fabric
2013+ * @lport: fc_lport pointer to logoff the fabric
2014+ *
2015+ * Return value:
2016+ * 0 for success, -1 for failure
2017+ **/
2018+int fc_fabric_logoff(struct fc_lport *lport)
2019 {
2020- fc_lport_lock(lp);
2021- switch (lp->state) {
2022- case LPORT_ST_NONE:
2023- break;
2024- case LPORT_ST_FLOGI:
2025- case LPORT_ST_LOGO:
2026- case LPORT_ST_RESET:
2027- fc_lport_enter_reset(lp);
2028- break;
2029- case LPORT_ST_DNS:
2030- case LPORT_ST_DNS_STOP:
2031- fc_lport_enter_logo(lp);
2032- break;
2033- case LPORT_ST_REG_PN:
2034- case LPORT_ST_REG_FT:
2035- case LPORT_ST_SCR:
2036- case LPORT_ST_READY:
2037- lp->tt.disc_stop(lp);
2038- break;
2039- }
2040- fc_lport_unlock(lp);
2041- lp->tt.scsi_cleanup(lp);
2042-
2043+ mutex_lock(&lport->lp_mutex);
2044+ fc_lport_enter_logo(lport);
2045+ lport->tt.scsi_cleanup(lport);
2046+ mutex_unlock(&lport->lp_mutex);
2047 return 0;
2048 }
2049 EXPORT_SYMBOL(fc_fabric_logoff);
2050
2051 /**
2052 * fc_lport_destroy - unregister a fc_lport
2053- * @lp: fc_lport pointer to unregister
2054+ * @lport: fc_lport pointer to unregister
2055 *
2056 * Return value:
2057 * None
2058@@ -386,30 +518,26 @@ EXPORT_SYMBOL(fc_fabric_logoff);
2059 * and free up other system resources.
2060 *
2061 **/
2062-int fc_lport_destroy(struct fc_lport *lp)
2063+int fc_lport_destroy(struct fc_lport *lport)
2064 {
2065- fc_lport_lock(lp);
2066- fc_lport_state_enter(lp, LPORT_ST_LOGO);
2067- fc_lport_unlock(lp);
2068-
2069- cancel_delayed_work_sync(&lp->ns_disc_work);
2070-
2071- lp->tt.scsi_abort_io(lp);
2072-
2073- lp->tt.frame_send = fc_frame_drop;
2074-
2075- lp->tt.exch_mgr_reset(lp->emp, 0, 0);
2076-
2077+ mutex_lock(&lport->lp_mutex);
2078+ cancel_delayed_work_sync(&lport->disc_work);
2079+ lport->tt.scsi_abort_io(lport);
2080+ lport->tt.frame_send = fc_frame_drop;
2081+ lport->tt.exch_mgr_reset(lport->emp, 0, 0);
2082+ mutex_unlock(&lport->lp_mutex);
2083 return 0;
2084 }
2085 EXPORT_SYMBOL(fc_lport_destroy);
2086
2087-int fc_set_mfs(struct fc_lport *lp, u32 mfs)
2088+int fc_set_mfs(struct fc_lport *lport, u32 mfs)
2089 {
2090 unsigned int old_mfs;
2091 int rc = -1;
2092
2093- old_mfs = lp->mfs;
2094+ mutex_lock(&lport->lp_mutex);
2095+
2096+ old_mfs = lport->mfs;
2097
2098 if (mfs >= FC_MIN_MAX_FRAME) {
2099 mfs &= ~3;
2100@@ -417,97 +545,55 @@ int fc_set_mfs(struct fc_lport *lp, u32 mfs)
2101 if (mfs > FC_MAX_FRAME)
2102 mfs = FC_MAX_FRAME;
2103 mfs -= sizeof(struct fc_frame_header);
2104- lp->mfs = mfs;
2105+ lport->mfs = mfs;
2106 rc = 0;
2107 }
2108
2109 if (!rc && mfs < old_mfs) {
2110- lp->ns_disc_done = 0;
2111- fc_lport_enter_reset(lp);
2112+ lport->disc_done = 0;
2113+ fc_lport_enter_reset(lport);
2114 }
2115+
2116+ mutex_unlock(&lport->lp_mutex);
2117+
2118 return rc;
2119 }
2120 EXPORT_SYMBOL(fc_set_mfs);
2121
2122-/*
2123- * re-enter state for retrying a request after a timeout or alloc failure.
2124+/**
2125+ * fc_rport_enter_ready - Enter the ready state and start discovery
2126+ * @lport: Fibre Channel local port that is ready
2127+ *
2128+ * Locking Note: The lport lock is expected to be held before calling
2129+ * this routine.
2130 */
2131-static void fc_lport_enter_retry(struct fc_lport *lp)
2132+static void fc_lport_enter_ready(struct fc_lport *lport)
2133 {
2134- switch (lp->state) {
2135- case LPORT_ST_NONE:
2136- case LPORT_ST_READY:
2137- case LPORT_ST_RESET:
2138- case LPORT_ST_DNS:
2139- case LPORT_ST_DNS_STOP:
2140- case LPORT_ST_REG_PN:
2141- case LPORT_ST_REG_FT:
2142- case LPORT_ST_SCR:
2143- WARN_ON(1);
2144- break;
2145- case LPORT_ST_FLOGI:
2146- fc_lport_enter_flogi(lp);
2147- break;
2148- case LPORT_ST_LOGO:
2149- fc_lport_enter_logo(lp);
2150- break;
2151- }
2152-}
2153+ if (fc_lport_debug)
2154+ FC_DBG("Port (%6x) entered Ready from state %s\n",
2155+ lport->fid, fc_lport_state(lport));
2156
2157-/*
2158- * enter next state for handling an exchange reject or retry exhaustion
2159- * in the current state.
2160- */
2161-static void fc_lport_enter_reject(struct fc_lport *lp)
2162-{
2163- switch (lp->state) {
2164- case LPORT_ST_NONE:
2165- case LPORT_ST_READY:
2166- case LPORT_ST_RESET:
2167- case LPORT_ST_REG_PN:
2168- case LPORT_ST_REG_FT:
2169- case LPORT_ST_SCR:
2170- case LPORT_ST_DNS_STOP:
2171- case LPORT_ST_DNS:
2172- WARN_ON(1);
2173- break;
2174- case LPORT_ST_FLOGI:
2175- fc_lport_enter_flogi(lp);
2176- break;
2177- case LPORT_ST_LOGO:
2178- fc_lport_enter_reset(lp);
2179- break;
2180- }
2181-}
2182+ fc_lport_state_enter(lport, LPORT_ST_READY);
2183
2184-/*
2185- * Handle resource allocation problem by retrying in a bit.
2186- */
2187-static void fc_lport_retry(struct fc_lport *lp)
2188-{
2189- if (lp->retry_count == 0)
2190- FC_DBG("local port %6x alloc failure in state %s "
2191- "- will retry\n", lp->fid, fc_lport_state(lp));
2192- if (lp->retry_count < lp->max_retry_count) {
2193- lp->retry_count++;
2194- mod_timer(&lp->state_timer,
2195- jiffies + msecs_to_jiffies(lp->e_d_tov));
2196- } else {
2197- FC_DBG("local port %6x alloc failure in state %s "
2198- "- retries exhausted\n", lp->fid,
2199- fc_lport_state(lp));
2200- fc_lport_enter_reject(lp);
2201- }
2202+ lport->tt.disc_start(lport);
2203 }
2204
2205-/*
2206+/**
2207+ * fc_lport_recv_flogi_req - Receive a FLOGI request
2208+ * @sp_in: The sequence the FLOGI is on
2209+ * @rx_fp: The frame the FLOGI is in
2210+ * @lport: The lport that recieved the request
2211+ *
2212 * A received FLOGI request indicates a point-to-point connection.
2213 * Accept it with the common service parameters indicating our N port.
2214 * Set up to do a PLOGI if we have the higher-number WWPN.
2215+ *
2216+ * Locking Note: The lport lock is exected to be held before calling
2217+ * this function.
2218 */
2219 static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
2220 struct fc_frame *rx_fp,
2221- struct fc_lport *lp)
2222+ struct fc_lport *lport)
2223 {
2224 struct fc_frame *fp;
2225 struct fc_frame_header *fh;
2226@@ -519,19 +605,22 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
2227 u32 local_fid;
2228 u32 f_ctl;
2229
2230+ if (fc_lport_debug)
2231+ FC_DBG("Received FLOGI request while in state %s\n",
2232+ fc_lport_state(lport));
2233+
2234 fh = fc_frame_header_get(rx_fp);
2235 remote_fid = ntoh24(fh->fh_s_id);
2236 flp = fc_frame_payload_get(rx_fp, sizeof(*flp));
2237 if (!flp)
2238 goto out;
2239 remote_wwpn = get_unaligned_be64(&flp->fl_wwpn);
2240- if (remote_wwpn == lp->wwpn) {
2241+ if (remote_wwpn == lport->wwpn) {
2242 FC_DBG("FLOGI from port with same WWPN %llx "
2243 "possible configuration error\n", remote_wwpn);
2244 goto out;
2245 }
2246 FC_DBG("FLOGI from port WWPN %llx\n", remote_wwpn);
2247- fc_lport_lock(lp);
2248
2249 /*
2250 * XXX what is the right thing to do for FIDs?
2251@@ -539,20 +628,21 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
2252 * But if so, both of us could end up with the same FID.
2253 */
2254 local_fid = FC_LOCAL_PTP_FID_LO;
2255- if (remote_wwpn < lp->wwpn) {
2256+ if (remote_wwpn < lport->wwpn) {
2257 local_fid = FC_LOCAL_PTP_FID_HI;
2258 if (!remote_fid || remote_fid == local_fid)
2259 remote_fid = FC_LOCAL_PTP_FID_LO;
2260 } else if (!remote_fid) {
2261 remote_fid = FC_LOCAL_PTP_FID_HI;
2262 }
2263- fc_lport_set_fid(lp, local_fid);
2264
2265- fp = fc_frame_alloc(lp, sizeof(*flp));
2266+ lport->fid = local_fid;
2267+
2268+ fp = fc_frame_alloc(lport, sizeof(*flp));
2269 if (fp) {
2270- sp = lp->tt.seq_start_next(fr_seq(rx_fp));
2271+ sp = lport->tt.seq_start_next(fr_seq(rx_fp));
2272 new_flp = fc_frame_payload_get(fp, sizeof(*flp));
2273- fc_lport_flogi_fill(lp, new_flp, ELS_FLOGI);
2274+ fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI);
2275 new_flp->fl_cmd = (u8) ELS_LS_ACC;
2276
2277 /*
2278@@ -561,23 +651,35 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
2279 */
2280 f_ctl = FC_FC_LAST_SEQ | FC_FC_END_SEQ;
2281 fc_frame_setup(fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
2282- lp->tt.seq_send(lp, sp, fp, f_ctl);
2283+ lport->tt.seq_send(lport, sp, fp, f_ctl);
2284
2285 } else {
2286- fc_lport_retry(lp);
2287+ fc_lport_error(lport, fp);
2288 }
2289- fc_lport_ptp_setup(lp, remote_fid, remote_wwpn,
2290+ fc_lport_ptp_setup(lport, remote_fid, remote_wwpn,
2291 get_unaligned_be64(&flp->fl_wwnn));
2292- fc_lport_unlock(lp);
2293- if (lp->tt.disc_start(lp))
2294+
2295+ if (lport->tt.disc_start(lport))
2296 FC_DBG("target discovery start error\n");
2297 out:
2298 sp = fr_seq(rx_fp);
2299 fc_frame_free(rx_fp);
2300 }
2301
2302-static void fc_lport_recv(struct fc_lport *lp, struct fc_seq *sp,
2303- struct fc_frame *fp)
2304+/**
2305+ * fc_lport_recv_req - The generic lport request handler
2306+ * @lport: The lport that received the request
2307+ * @sp: The sequence the request is on
2308+ * @fp: The frame the request is in
2309+ *
2310+ * This function will see if the lport handles the request or
2311+ * if an rport should handle the request.
2312+ *
2313+ * Locking Note: This function should not be called with the lport
2314+ * lock held becuase it will grab the lock.
2315+ */
2316+static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
2317+ struct fc_frame *fp)
2318 {
2319 struct fc_frame_header *fh = fc_frame_header_get(fp);
2320 void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *);
2321@@ -586,6 +688,8 @@ static void fc_lport_recv(struct fc_lport *lp, struct fc_seq *sp,
2322 u32 d_id;
2323 struct fc_seq_els_data rjt_data;
2324
2325+ mutex_lock(&lport->lp_mutex);
2326+
2327 /*
2328 * Handle special ELS cases like FLOGI, LOGO, and
2329 * RSCN here. These don't require a session.
2330@@ -606,21 +710,21 @@ static void fc_lport_recv(struct fc_lport *lp, struct fc_seq *sp,
2331 recv = fc_lport_recv_logo_req;
2332 break;
2333 case ELS_RSCN:
2334- recv = lp->tt.disc_recv_req;
2335+ recv = lport->tt.disc_recv_req;
2336 break;
2337 case ELS_ECHO:
2338- recv = fc_lport_echo_req;
2339+ recv = fc_lport_recv_echo_req;
2340 break;
2341 case ELS_RLIR:
2342- recv = fc_lport_rlir_req;
2343+ recv = fc_lport_recv_rlir_req;
2344 break;
2345 case ELS_RNID:
2346- recv = fc_lport_rnid_req;
2347+ recv = fc_lport_recv_rnid_req;
2348 break;
2349 }
2350
2351 if (recv)
2352- recv(sp, fp, lp);
2353+ recv(sp, fp, lport);
2354 else {
2355 /*
2356 * Find session.
2357@@ -629,16 +733,17 @@ static void fc_lport_recv(struct fc_lport *lp, struct fc_seq *sp,
2358 s_id = ntoh24(fh->fh_s_id);
2359 d_id = ntoh24(fh->fh_d_id);
2360
2361- rport = lp->tt.rport_lookup(lp, s_id);
2362+ rport = lport->tt.rport_lookup(lport, s_id);
2363 if (rport) {
2364- lp->tt.rport_recv_req(sp, fp, rport);
2365+ lport->tt.rport_recv_req(sp, fp, rport);
2366 put_device(&rport->dev); /* hold from lookup */
2367 } else {
2368 rjt_data.fp = NULL;
2369 rjt_data.reason = ELS_RJT_UNAB;
2370 rjt_data.explan = ELS_EXPL_NONE;
2371- lp->tt.seq_els_rsp_send(sp,
2372- ELS_LS_RJT, &rjt_data);
2373+ lport->tt.seq_els_rsp_send(sp,
2374+ ELS_LS_RJT,
2375+ &rjt_data);
2376 fc_frame_free(fp);
2377 }
2378 }
2379@@ -646,151 +751,572 @@ static void fc_lport_recv(struct fc_lport *lp, struct fc_seq *sp,
2380 FC_DBG("dropping invalid frame (eof %x)\n", fr_eof(fp));
2381 fc_frame_free(fp);
2382 }
2383+ mutex_unlock(&lport->lp_mutex);
2384+}
2385
2386- /*
2387- * The common exch_done for all request may not be good
2388- * if any request requires longer hold on exhange. XXX
2389- */
2390- lp->tt.exch_done(sp);
2391+/**
2392+ * fc_lport_reset - Reset an lport
2393+ * @lport: The lport which should be reset
2394+ *
2395+ * Locking Note: This functions should not be called with the
2396+ * lport lock held.
2397+ */
2398+int fc_lport_reset(struct fc_lport *lport)
2399+{
2400+ mutex_lock(&lport->lp_mutex);
2401+ fc_lport_enter_reset(lport);
2402+ mutex_unlock(&lport->lp_mutex);
2403+ return 0;
2404 }
2405+EXPORT_SYMBOL(fc_lport_reset);
2406
2407-/*
2408- * Put the local port back into the initial state. Reset all sessions.
2409- * This is called after a SCSI reset or the driver is unloading
2410- * or the program is exiting.
2411+/**
2412+ * fc_rport_enter_reset - Reset the local port
2413+ * @lport: Fibre Channel local port to be reset
2414+ *
2415+ * Locking Note: The lport lock is expected to be held before calling
2416+ * this routine.
2417 */
2418-int fc_lport_enter_reset(struct fc_lport *lp)
2419+static void fc_lport_enter_reset(struct fc_lport *lport)
2420 {
2421 if (fc_lport_debug)
2422- FC_DBG("Processing RESET state\n");
2423+ FC_DBG("Port (%6x) entered RESET state from %s state\n",
2424+ lport->fid, fc_lport_state(lport));
2425+
2426+ fc_lport_state_enter(lport, LPORT_ST_RESET);
2427
2428- if (lp->dns_rp) {
2429- fc_remote_port_delete(lp->dns_rp);
2430- lp->dns_rp = NULL;
2431+ if (lport->dns_rp) {
2432+ fc_remote_port_delete(lport->dns_rp);
2433+ lport->dns_rp = NULL;
2434 }
2435- fc_lport_ptp_clear(lp);
2436+ fc_lport_ptp_clear(lport);
2437
2438- /*
2439- * Setting state RESET keeps fc_lport_error() callbacks
2440- * by exch_mgr_reset() from recursing on the lock.
2441- * It also causes fc_lport_sess_event() to ignore events.
2442- * The lock is held for the duration of the time in RESET state.
2443- */
2444- fc_lport_state_enter(lp, LPORT_ST_RESET);
2445- lp->tt.exch_mgr_reset(lp->emp, 0, 0);
2446- fc_lport_set_fid(lp, 0);
2447- if ((lp->link_status & FC_LINK_UP) == FC_LINK_UP)
2448- fc_lport_enter_flogi(lp);
2449- return 0;
2450+ fc_block_rports(lport);
2451+
2452+ lport->tt.rport_reset_list(lport);
2453+ lport->tt.exch_mgr_reset(lport->emp, 0, 0);
2454+ fc_host_fabric_name(lport->host) = 0;
2455+ lport->fid = 0;
2456+
2457+ if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP)
2458+ fc_lport_enter_flogi(lport);
2459 }
2460-EXPORT_SYMBOL(fc_lport_enter_reset);
2461
2462-/*
2463- * Handle errors on local port requests.
2464- * Don't get locks if in RESET state.
2465- * The only possible errors so far are exchange TIMEOUT and CLOSED (reset).
2466+/**
2467+ * fc_lport_error - Handler for any errors
2468+ * @lport: The fc_lport object
2469+ * @fp: The frame pointer
2470+ *
2471+ * If the error was caused by a resource allocation failure
2472+ * then wait for half a second and retry, otherwise retry
2473+ * after the e_d_tov time.
2474+ */
2475+static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
2476+{
2477+ unsigned long delay = 0;
2478+ if (fc_lport_debug)
2479+ FC_DBG("Error %ld in state %s, retries %d\n",
2480+ PTR_ERR(fp), fc_lport_state(lport),
2481+ lport->retry_count);
2482+
2483+ if (lport->retry_count < lport->max_retry_count) {
2484+ lport->retry_count++;
2485+ if (!fp)
2486+ delay = msecs_to_jiffies(500);
2487+ else
2488+ delay = jiffies +
2489+ msecs_to_jiffies(lport->e_d_tov);
2490+
2491+ schedule_delayed_work(&lport->retry_work, delay);
2492+ } else {
2493+ switch (lport->state) {
2494+ case LPORT_ST_NONE:
2495+ case LPORT_ST_READY:
2496+ case LPORT_ST_RESET:
2497+ case LPORT_ST_RPN_ID:
2498+ case LPORT_ST_RFT_ID:
2499+ case LPORT_ST_SCR:
2500+ case LPORT_ST_DNS:
2501+ case LPORT_ST_FLOGI:
2502+ case LPORT_ST_LOGO:
2503+ fc_lport_enter_reset(lport);
2504+ break;
2505+ }
2506+ }
2507+}
2508+
2509+/**
2510+ * fc_lport_rft_id_resp - Handle response to Register Fibre
2511+ * Channel Types by ID (RPN_ID) request
2512+ * @sp: current sequence in RPN_ID exchange
2513+ * @fp: response frame
2514+ * @lp_arg: Fibre Channel host port instance
2515+ *
2516+ * Locking Note: This function will be called without the lport lock
2517+ * held, but it will lock, call an _enter_* function or fc_lport_error
2518+ * and then unlock the lport.
2519+ */
2520+static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
2521+ void *lp_arg)
2522+{
2523+ struct fc_lport *lport = lp_arg;
2524+ struct fc_frame_header *fh;
2525+ struct fc_ct_hdr *ct;
2526+
2527+ mutex_lock(&lport->lp_mutex);
2528+
2529+ if (fc_lport_debug)
2530+ FC_DBG("Received a RFT_ID response\n");
2531+
2532+ if (lport->state != LPORT_ST_RFT_ID) {
2533+ FC_DBG("Received a RFT_ID response, but in state %s\n",
2534+ fc_lport_state(lport));
2535+ goto out;
2536+ }
2537+
2538+ if (IS_ERR(fp)) {
2539+ fc_lport_error(lport, fp);
2540+ goto out;
2541+ }
2542+
2543+ fh = fc_frame_header_get(fp);
2544+ ct = fc_frame_payload_get(fp, sizeof(*ct));
2545+
2546+ if (fh && ct && fh->fh_type == FC_TYPE_CT &&
2547+ ct->ct_fs_type == FC_FST_DIR &&
2548+ ct->ct_fs_subtype == FC_NS_SUBTYPE &&
2549+ ntohs(ct->ct_cmd) == FC_FS_ACC)
2550+ fc_lport_enter_scr(lport);
2551+ else
2552+ fc_lport_error(lport, fp);
2553+out:
2554+ mutex_unlock(&lport->lp_mutex);
2555+ fc_frame_free(fp);
2556+}
2557+
2558+/**
2559+ * fc_lport_rpn_id_resp - Handle response to Register Port
2560+ * Name by ID (RPN_ID) request
2561+ * @sp: current sequence in RPN_ID exchange
2562+ * @fp: response frame
2563+ * @lp_arg: Fibre Channel host port instance
2564+ *
2565+ * Locking Note: This function will be called without the lport lock
2566+ * held, but it will lock, call an _enter_* function or fc_lport_error
2567+ * and then unlock the lport.
2568+ */
2569+static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
2570+ void *lp_arg)
2571+{
2572+ struct fc_lport *lport = lp_arg;
2573+ struct fc_frame_header *fh;
2574+ struct fc_ct_hdr *ct;
2575+
2576+ mutex_lock(&lport->lp_mutex);
2577+
2578+ if (fc_lport_debug)
2579+ FC_DBG("Received a RPN_ID response\n");
2580+
2581+ if (lport->state != LPORT_ST_RPN_ID) {
2582+ FC_DBG("Received a RPN_ID response, but in state %s\n",
2583+ fc_lport_state(lport));
2584+ goto out;
2585+ }
2586+
2587+ if (IS_ERR(fp)) {
2588+ fc_lport_error(lport, fp);
2589+ goto out;
2590+ }
2591+
2592+ fh = fc_frame_header_get(fp);
2593+ ct = fc_frame_payload_get(fp, sizeof(*ct));
2594+ if (fh && ct && fh->fh_type == FC_TYPE_CT &&
2595+ ct->ct_fs_type == FC_FST_DIR &&
2596+ ct->ct_fs_subtype == FC_NS_SUBTYPE &&
2597+ ntohs(ct->ct_cmd) == FC_FS_ACC)
2598+ fc_lport_enter_rft_id(lport);
2599+ else
2600+ fc_lport_error(lport, fp);
2601+
2602+out:
2603+ mutex_unlock(&lport->lp_mutex);
2604+ fc_frame_free(fp);
2605+}
2606+
2607+/**
2608+ * fc_lport_scr_resp - Handle response to State Change Register (SCR) request
2609+ * @sp: current sequence in SCR exchange
2610+ * @fp: response frame
2611+ * @lp_arg: Fibre Channel lport port instance that sent the registration request
2612+ *
2613+ * Locking Note: This function will be called without the lport lock
2614+ * held, but it will lock, call an _enter_* function or fc_lport_error
2615+ * and then unlock the lport.
2616 */
2617-static void fc_lport_error(struct fc_lport *lp, struct fc_frame *fp)
2618+static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
2619+ void *lp_arg)
2620 {
2621- if (lp->state == LPORT_ST_RESET)
2622+ struct fc_lport *lport = lp_arg;
2623+ u8 op;
2624+
2625+ mutex_lock(&lport->lp_mutex);
2626+
2627+ if (fc_lport_debug)
2628+ FC_DBG("Received a SCR response\n");
2629+
2630+ if (lport->state != LPORT_ST_SCR) {
2631+ FC_DBG("Received a SCR response, but in state %s\n",
2632+ fc_lport_state(lport));
2633+ goto out;
2634+ }
2635+
2636+ if (IS_ERR(fp)) {
2637+ fc_lport_error(lport, fp);
2638+ goto out;
2639+ }
2640+
2641+ op = fc_frame_payload_op(fp);
2642+ if (op == ELS_LS_ACC)
2643+ fc_lport_enter_ready(lport);
2644+ else
2645+ fc_lport_error(lport, fp);
2646+
2647+out:
2648+ mutex_unlock(&lport->lp_mutex);
2649+ fc_frame_free(fp);
2650+}
2651+
2652+/**
2653+ * fc_lport_enter_scr - Send a State Change Register (SCR) request
2654+ * @lport: Fibre Channel local port to register for state changes
2655+ *
2656+ * Locking Note: The lport lock is expected to be held before calling
2657+ * this routine.
2658+ */
2659+static void fc_lport_enter_scr(struct fc_lport *lport)
2660+{
2661+ struct fc_frame *fp;
2662+ struct fc_els_scr *scr;
2663+
2664+ if (fc_lport_debug)
2665+ FC_DBG("Port (%6x) entered SCR state from %s state\n",
2666+ lport->fid, fc_lport_state(lport));
2667+
2668+ fc_lport_state_enter(lport, LPORT_ST_SCR);
2669+
2670+ fp = fc_frame_alloc(lport, sizeof(*scr));
2671+ if (!fp) {
2672+ fc_lport_error(lport, fp);
2673 return;
2674+ }
2675
2676- fc_lport_lock(lp);
2677- if (PTR_ERR(fp) == -FC_EX_TIMEOUT) {
2678- if (lp->retry_count < lp->max_retry_count) {
2679- lp->retry_count++;
2680- fc_lport_enter_retry(lp);
2681- } else {
2682- fc_lport_enter_reject(lp);
2683+ scr = fc_frame_payload_get(fp, sizeof(*scr));
2684+ memset(scr, 0, sizeof(*scr));
2685+ scr->scr_cmd = ELS_SCR;
2686+ scr->scr_reg_func = ELS_SCRF_FULL;
2687+ fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
2688+ fc_frame_set_offset(fp, 0);
2689+
2690+ if (!lport->tt.exch_seq_send(lport, fp,
2691+ fc_lport_scr_resp, NULL,
2692+ lport, lport->e_d_tov,
2693+ lport->fid, FC_FID_FCTRL,
2694+ FC_FC_SEQ_INIT | FC_FC_END_SEQ))
2695+ fc_lport_error(lport, fp);
2696+}
2697+
2698+/**
2699+ * fc_lport_enter_rft_id - Register FC4-types with the name server
2700+ * @lport: Fibre Channel local port to register
2701+ *
2702+ * Locking Note: The lport lock is expected to be held before calling
2703+ * this routine.
2704+ */
2705+static void fc_lport_enter_rft_id(struct fc_lport *lport)
2706+{
2707+ struct fc_frame *fp;
2708+ struct req {
2709+ struct fc_ct_hdr ct;
2710+ struct fc_ns_fid fid; /* port ID object */
2711+ struct fc_ns_fts fts; /* FC4-types object */
2712+ } *req;
2713+ struct fc_ns_fts *lps;
2714+ int i;
2715+
2716+ if (fc_lport_debug)
2717+ FC_DBG("Port (%6x) entered RFT_ID state from %s state\n",
2718+ lport->fid, fc_lport_state(lport));
2719
2720+ fc_lport_state_enter(lport, LPORT_ST_RFT_ID);
2721+
2722+ lps = &lport->fcts;
2723+ i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
2724+ while (--i >= 0)
2725+ if (ntohl(lps->ff_type_map[i]) != 0)
2726+ break;
2727+ if (i < 0) {
2728+ /* nothing to register, move on to SCR */
2729+ fc_lport_enter_scr(lport);
2730+ } else {
2731+ fp = fc_frame_alloc(lport, sizeof(*req));
2732+ if (!fp) {
2733+ fc_lport_error(lport, fp);
2734+ return;
2735 }
2736+
2737+ req = fc_frame_payload_get(fp, sizeof(*req));
2738+ fc_fill_dns_hdr(lport, &req->ct,
2739+ FC_NS_RFT_ID,
2740+ sizeof(*req) -
2741+ sizeof(struct fc_ct_hdr));
2742+ hton24(req->fid.fp_fid, lport->fid);
2743+ req->fts = *lps;
2744+ fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
2745+
2746+ if (!lport->tt.exch_seq_send(lport, fp,
2747+ fc_lport_rft_id_resp, NULL,
2748+ lport, lport->e_d_tov,
2749+ lport->fid,
2750+ FC_FID_DIR_SERV,
2751+ FC_FC_SEQ_INIT |
2752+ FC_FC_END_SEQ))
2753+ fc_lport_error(lport, fp);
2754+ }
2755+}
2756+
2757+/**
2758+ * fc_rport_enter_rft_id - Register port name with the name server
2759+ * @lport: Fibre Channel local port to register
2760+ *
2761+ * Locking Note: The lport lock is expected to be held before calling
2762+ * this routine.
2763+ */
2764+static void fc_lport_enter_rpn_id(struct fc_lport *lport)
2765+{
2766+ struct fc_frame *fp;
2767+ struct req {
2768+ struct fc_ct_hdr ct;
2769+ struct fc_ns_rn_id rn;
2770+ } *req;
2771+
2772+ if (fc_lport_debug)
2773+ FC_DBG("Port (%6x) entered RPN_ID state from %s state\n",
2774+ lport->fid, fc_lport_state(lport));
2775+
2776+ fc_lport_state_enter(lport, LPORT_ST_RPN_ID);
2777+
2778+ fp = fc_frame_alloc(lport, sizeof(*req));
2779+ if (!fp) {
2780+ fc_lport_error(lport, fp);
2781+ return;
2782 }
2783+
2784+ req = fc_frame_payload_get(fp, sizeof(*req));
2785+ memset(req, 0, sizeof(*req));
2786+ fc_fill_dns_hdr(lport, &req->ct, FC_NS_RPN_ID, sizeof(req->rn));
2787+ hton24(req->rn.fr_fid.fp_fid, lport->fid);
2788+ put_unaligned_be64(lport->wwpn, &req->rn.fr_wwn);
2789+ fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
2790+
2791+ if (!lport->tt.exch_seq_send(lport, fp,
2792+ fc_lport_rpn_id_resp, NULL,
2793+ lport, lport->e_d_tov,
2794+ lport->fid,
2795+ FC_FID_DIR_SERV,
2796+ FC_FC_SEQ_INIT | FC_FC_END_SEQ))
2797+ fc_lport_error(lport, fp);
2798+
2799+}
2800+
2801+/**
2802+ * fc_rport_enter_dns - Create a rport to the name server
2803+ * @lport: Fibre Channel local port requesting a rport for the name server
2804+ *
2805+ * Locking Note: The lport lock is expected to be held before calling
2806+ * this routine.
2807+ */
2808+static void fc_lport_enter_dns(struct fc_lport *lport)
2809+{
2810+ struct fc_rport *rport;
2811+ struct fc_rport_libfc_priv *rdata;
2812+ struct fc_disc_port dp;
2813+
2814+ dp.ids.port_id = FC_FID_DIR_SERV;
2815+ dp.ids.port_name = -1;
2816+ dp.ids.node_name = -1;
2817+ dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
2818+ dp.lp = lport;
2819+
2820 if (fc_lport_debug)
2821- FC_DBG("error %ld retries %d limit %d\n",
2822- PTR_ERR(fp), lp->retry_count, lp->max_retry_count);
2823- fc_lport_unlock(lp);
2824+ FC_DBG("Port (%6x) entered DNS state from %s state\n",
2825+ lport->fid, fc_lport_state(lport));
2826+
2827+ fc_lport_state_enter(lport, LPORT_ST_DNS);
2828+
2829+ if (!lport->dns_rp) {
2830+ /* Set up a dummy rport to directory server */
2831+ rport = fc_rport_dummy_create(&dp);
2832+
2833+ if (!rport)
2834+ goto err;
2835+ lport->dns_rp = rport;
2836+ FC_DBG("created an rport for the NS\n");
2837+ }
2838+
2839+ rport = lport->dns_rp;
2840+ rdata = rport->dd_data;
2841+ rdata->event_callback = fc_lport_rport_event;
2842+ lport->tt.rport_login(rport);
2843+ return;
2844+
2845+err:
2846+ fc_lport_error(lport, NULL);
2847 }
2848
2849-static void fc_lport_timeout(unsigned long lp_arg)
2850+/**
2851+ * fc_lport_timeout - Handler for the retry_work timer.
2852+ * @work: The work struct of the fc_lport
2853+ */
2854+static void fc_lport_timeout(struct work_struct *work)
2855 {
2856- struct fc_lport *lp = (struct fc_lport *)lp_arg;
2857+ struct fc_lport *lport =
2858+ container_of(work, struct fc_lport,
2859+ retry_work.work);
2860
2861- fc_lport_lock(lp);
2862- fc_lport_enter_retry(lp);
2863- fc_lport_unlock(lp);
2864+ mutex_lock(&lport->lp_mutex);
2865+
2866+ switch (lport->state) {
2867+ case LPORT_ST_NONE:
2868+ case LPORT_ST_READY:
2869+ case LPORT_ST_RESET:
2870+ WARN_ON(1);
2871+ break;
2872+ case LPORT_ST_FLOGI:
2873+ fc_lport_enter_flogi(lport);
2874+ break;
2875+ case LPORT_ST_DNS:
2876+ fc_lport_enter_dns(lport);
2877+ break;
2878+ case LPORT_ST_RPN_ID:
2879+ fc_lport_enter_rpn_id(lport);
2880+ break;
2881+ case LPORT_ST_RFT_ID:
2882+ fc_lport_enter_rft_id(lport);
2883+ break;
2884+ case LPORT_ST_SCR:
2885+ fc_lport_enter_scr(lport);
2886+ break;
2887+ case LPORT_ST_LOGO:
2888+ fc_lport_enter_logo(lport);
2889+ break;
2890+ }
2891+
2892+ mutex_unlock(&lport->lp_mutex);
2893 }
2894
2895+/**
2896+ * fc_lport_logo_resp - Handle response to LOGO request
2897+ * @sp: current sequence in LOGO exchange
2898+ * @fp: response frame
2899+ * @lp_arg: Fibre Channel lport port instance that sent the LOGO request
2900+ *
2901+ * Locking Note: This function will be called without the lport lock
2902+ * held, but it will lock, call an _enter_* function or fc_lport_error
2903+ * and then unlock the lport.
2904+ */
2905 static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
2906 void *lp_arg)
2907 {
2908- struct fc_lport *lp = lp_arg;
2909+ struct fc_lport *lport = lp_arg;
2910+ u8 op;
2911
2912- if (IS_ERR(fp))
2913- fc_lport_error(lp, fp);
2914- else {
2915- fc_frame_free(fp);
2916- fc_lport_lock(lp);
2917- fc_lport_enter_reset(lp);
2918- fc_lport_unlock(lp);
2919+ mutex_lock(&lport->lp_mutex);
2920+
2921+ if (fc_lport_debug)
2922+ FC_DBG("Received a LOGO response\n");
2923+
2924+ if (lport->state != LPORT_ST_LOGO) {
2925+ FC_DBG("Received a LOGO response, but in state %s\n",
2926+ fc_lport_state(lport));
2927+ goto out;
2928 }
2929+
2930+ if (IS_ERR(fp)) {
2931+ fc_lport_error(lport, fp);
2932+ goto out;
2933+ }
2934+
2935+ op = fc_frame_payload_op(fp);
2936+ if (op == ELS_LS_ACC)
2937+ fc_lport_enter_reset(lport);
2938+ else
2939+ fc_lport_error(lport, fp);
2940+
2941+out:
2942+ mutex_unlock(&lport->lp_mutex);
2943+ fc_frame_free(fp);
2944 }
2945
2946-/* Logout of the FC fabric */
2947-static void fc_lport_enter_logo(struct fc_lport *lp)
2948+/**
2949+ * fc_rport_enter_logo - Logout of the fabric
2950+ * @lport: Fibre Channel local port to be logged out
2951+ *
2952+ * Locking Note: The lport lock is expected to be held before calling
2953+ * this routine.
2954+ */
2955+static void fc_lport_enter_logo(struct fc_lport *lport)
2956 {
2957 struct fc_frame *fp;
2958 struct fc_els_logo *logo;
2959
2960 if (fc_lport_debug)
2961- FC_DBG("Processing LOGO state\n");
2962+ FC_DBG("Port (%6x) entered LOGO state from %s state\n",
2963+ lport->fid, fc_lport_state(lport));
2964
2965- fc_lport_state_enter(lp, LPORT_ST_LOGO);
2966+ fc_lport_state_enter(lport, LPORT_ST_LOGO);
2967
2968 /* DNS session should be closed so we can release it here */
2969- if (lp->dns_rp) {
2970- fc_remote_port_delete(lp->dns_rp);
2971- lp->dns_rp = NULL;
2972+ if (lport->dns_rp) {
2973+ fc_remote_port_delete(lport->dns_rp);
2974+ lport->dns_rp = NULL;
2975 }
2976
2977- fp = fc_frame_alloc(lp, sizeof(*logo));
2978+ fp = fc_frame_alloc(lport, sizeof(*logo));
2979 if (!fp) {
2980- FC_DBG("failed to allocate frame\n");
2981+ fc_lport_error(lport, fp);
2982 return;
2983 }
2984
2985 logo = fc_frame_payload_get(fp, sizeof(*logo));
2986 memset(logo, 0, sizeof(*logo));
2987 logo->fl_cmd = ELS_LOGO;
2988- hton24(logo->fl_n_port_id, lp->fid);
2989- logo->fl_n_port_wwn = htonll(lp->wwpn);
2990-
2991+ hton24(logo->fl_n_port_id, lport->fid);
2992+ logo->fl_n_port_wwn = htonll(lport->wwpn);
2993 fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
2994 fc_frame_set_offset(fp, 0);
2995
2996- lp->tt.exch_seq_send(lp, fp,
2997- fc_lport_logo_resp,
2998- lp, lp->e_d_tov,
2999- lp->fid, FC_FID_FLOGI,
3000- FC_FC_SEQ_INIT | FC_FC_END_SEQ);
3001-}
3002-
3003-static int fc_lport_logout(struct fc_lport *lp)
3004-{
3005- fc_lport_lock(lp);
3006- if (lp->state != LPORT_ST_LOGO)
3007- fc_lport_enter_logo(lp);
3008- fc_lport_unlock(lp);
3009- return 0;
3010+ if (!lport->tt.exch_seq_send(lport, fp,
3011+ fc_lport_logo_resp, NULL,
3012+ lport, lport->e_d_tov,
3013+ lport->fid, FC_FID_FLOGI,
3014+ FC_FC_SEQ_INIT | FC_FC_END_SEQ))
3015+ fc_lport_error(lport, fp);
3016 }
3017
3018-/*
3019- * Handle incoming ELS FLOGI response.
3020- * Save parameters of remote switch. Finish exchange.
3021+/**
3022+ * fc_lport_flogi_resp - Handle response to FLOGI request
3023+ * @sp: current sequence in FLOGI exchange
3024+ * @fp: response frame
3025+ * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request
3026+ *
3027+ * Locking Note: This function will be called without the lport lock
3028+ * held, but it will lock, call an _enter_* function or fc_lport_error
3029+ * and then unlock the lport.
3030 */
3031-static void
3032-fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg)
3033+static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
3034+ void *lp_arg)
3035 {
3036- struct fc_lport *lp = lp_arg;
3037+ struct fc_lport *lport = lp_arg;
3038 struct fc_frame_header *fh;
3039 struct fc_els_flogi *flp;
3040 u32 did;
3041@@ -799,127 +1325,160 @@ fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg)
3042 unsigned int e_d_tov;
3043 u16 mfs;
3044
3045+ mutex_lock(&lport->lp_mutex);
3046+
3047+ if (fc_lport_debug)
3048+ FC_DBG("Received a FLOGI response\n");
3049+
3050+ if (lport->state != LPORT_ST_FLOGI) {
3051+ FC_DBG("Received a FLOGI response, but in state %s\n",
3052+ fc_lport_state(lport));
3053+ goto out;
3054+ }
3055+
3056 if (IS_ERR(fp)) {
3057- fc_lport_error(lp, fp);
3058- return;
3059+ fc_lport_error(lport, fp);
3060+ goto out;
3061 }
3062
3063 fh = fc_frame_header_get(fp);
3064 did = ntoh24(fh->fh_d_id);
3065 if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
3066 if (fc_lport_debug)
3067- FC_DBG("assigned fid %x\n", did);
3068- fc_lport_lock(lp);
3069- fc_lport_set_fid(lp, did);
3070+ FC_DBG("Assigned fid %x\n", did);
3071+
3072+ lport->fid = did;
3073 flp = fc_frame_payload_get(fp, sizeof(*flp));
3074 if (flp) {
3075 mfs = ntohs(flp->fl_csp.sp_bb_data) &
3076 FC_SP_BB_DATA_MASK;
3077 if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
3078- mfs < lp->mfs)
3079- lp->mfs = mfs;
3080+ mfs < lport->mfs)
3081+ lport->mfs = mfs;
3082 csp_flags = ntohs(flp->fl_csp.sp_features);
3083 r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
3084 e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
3085 if (csp_flags & FC_SP_FT_EDTR)
3086 e_d_tov /= 1000000;
3087 if ((csp_flags & FC_SP_FT_FPORT) == 0) {
3088- if (e_d_tov > lp->e_d_tov)
3089- lp->e_d_tov = e_d_tov;
3090- lp->r_a_tov = 2 * e_d_tov;
3091- FC_DBG("point-to-point mode\n");
3092- fc_lport_ptp_setup(lp, ntoh24(fh->fh_s_id),
3093+ if (e_d_tov > lport->e_d_tov)
3094+ lport->e_d_tov = e_d_tov;
3095+ lport->r_a_tov = 2 * e_d_tov;
3096+ FC_DBG("Point-to-Point mode\n");
3097+ fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id),
3098 get_unaligned_be64(
3099 &flp->fl_wwpn),
3100 get_unaligned_be64(
3101 &flp->fl_wwnn));
3102 } else {
3103- lp->e_d_tov = e_d_tov;
3104- lp->r_a_tov = r_a_tov;
3105- lp->tt.dns_register(lp);
3106+ lport->e_d_tov = e_d_tov;
3107+ lport->r_a_tov = r_a_tov;
3108+ fc_host_fabric_name(lport->host) =
3109+ get_unaligned_be64(&flp->fl_wwnn);
3110+ fc_lport_enter_dns(lport);
3111 }
3112 }
3113- fc_lport_unlock(lp);
3114+
3115 if (flp) {
3116 csp_flags = ntohs(flp->fl_csp.sp_features);
3117 if ((csp_flags & FC_SP_FT_FPORT) == 0) {
3118- if (lp->tt.disc_start(lp))
3119- FC_DBG("target disc start error\n");
3120+ if (lport->tt.disc_start(lport))
3121+ FC_DBG("Target disc start error\n");
3122 }
3123 }
3124 } else {
3125 FC_DBG("bad FLOGI response\n");
3126 }
3127+
3128+out:
3129+ mutex_unlock(&lport->lp_mutex);
3130 fc_frame_free(fp);
3131 }
3132
3133-/*
3134- * Send ELS (extended link service) FLOGI request to peer.
3135+/**
3136+ * fc_rport_enter_flogi - Send a FLOGI request to the fabric manager
3137+ * @lport: Fibre Channel local port to be logged in to the fabric
3138+ *
3139+ * Locking Note: The lport lock is expected to be held before calling
3140+ * this routine.
3141 */
3142-static void fc_lport_flogi_send(struct fc_lport *lp)
3143+void fc_lport_enter_flogi(struct fc_lport *lport)
3144 {
3145 struct fc_frame *fp;
3146 struct fc_els_flogi *flp;
3147
3148- fp = fc_frame_alloc(lp, sizeof(*flp));
3149+ if (fc_lport_debug)
3150+ FC_DBG("Processing FLOGI state\n");
3151+
3152+ fc_lport_state_enter(lport, LPORT_ST_FLOGI);
3153+
3154+ fp = fc_frame_alloc(lport, sizeof(*flp));
3155 if (!fp)
3156- return fc_lport_retry(lp);
3157+ return fc_lport_error(lport, fp);
3158
3159 flp = fc_frame_payload_get(fp, sizeof(*flp));
3160- fc_lport_flogi_fill(lp, flp, ELS_FLOGI);
3161+ fc_lport_flogi_fill(lport, flp, ELS_FLOGI);
3162
3163 fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
3164 fc_frame_set_offset(fp, 0);
3165
3166- if (!lp->tt.exch_seq_send(lp, fp,
3167- fc_lport_flogi_resp,
3168- lp, lp->e_d_tov,
3169- 0, FC_FID_FLOGI,
3170- FC_FC_SEQ_INIT | FC_FC_END_SEQ))
3171- fc_lport_retry(lp);
3172-
3173-}
3174+ if (!lport->tt.exch_seq_send(lport, fp,
3175+ fc_lport_flogi_resp, NULL,
3176+ lport, lport->e_d_tov,
3177+ 0, FC_FID_FLOGI,
3178+ FC_FC_SEQ_INIT | FC_FC_END_SEQ))
3179+ fc_lport_error(lport, fp);
3180
3181-void fc_lport_enter_flogi(struct fc_lport *lp)
3182-{
3183- if (fc_lport_debug)
3184- FC_DBG("Processing FLOGI state\n");
3185- fc_lport_state_enter(lp, LPORT_ST_FLOGI);
3186- fc_lport_flogi_send(lp);
3187 }
3188
3189 /* Configure a fc_lport */
3190-int fc_lport_config(struct fc_lport *lp)
3191+int fc_lport_config(struct fc_lport *lport)
3192 {
3193- setup_timer(&lp->state_timer, fc_lport_timeout, (unsigned long)lp);
3194- spin_lock_init(&lp->state_lock);
3195+ INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
3196+ mutex_init(&lport->lp_mutex);
3197
3198- fc_lport_lock(lp);
3199- fc_lport_state_enter(lp, LPORT_ST_NONE);
3200- fc_lport_unlock(lp);
3201+ fc_lport_state_enter(lport, LPORT_ST_NONE);
3202
3203- lp->ns_disc_delay = DNS_DELAY;
3204+ lport->disc_delay = DNS_DELAY;
3205
3206- fc_lport_add_fc4_type(lp, FC_TYPE_FCP);
3207- fc_lport_add_fc4_type(lp, FC_TYPE_CT);
3208+ fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
3209+ fc_lport_add_fc4_type(lport, FC_TYPE_CT);
3210
3211 return 0;
3212 }
3213 EXPORT_SYMBOL(fc_lport_config);
3214
3215-int fc_lport_init(struct fc_lport *lp)
3216+int fc_lport_init(struct fc_lport *lport)
3217 {
3218- if (!lp->tt.lport_recv)
3219- lp->tt.lport_recv = fc_lport_recv;
3220-
3221- if (!lp->tt.lport_login)
3222- lp->tt.lport_login = fc_lport_enter_reset;
3223-
3224- if (!lp->tt.lport_reset)
3225- lp->tt.lport_reset = fc_lport_enter_reset;
3226-
3227- if (!lp->tt.lport_logout)
3228- lp->tt.lport_logout = fc_lport_logout;
3229+ if (!lport->tt.lport_recv)
3230+ lport->tt.lport_recv = fc_lport_recv_req;
3231+
3232+ if (!lport->tt.lport_reset)
3233+ lport->tt.lport_reset = fc_lport_reset;
3234+
3235+ if (!lport->tt.event_callback)
3236+ lport->tt.event_callback = fc_lport_rport_event;
3237+
3238+ fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
3239+ fc_host_node_name(lport->host) = lport->wwnn;
3240+ fc_host_port_name(lport->host) = lport->wwpn;
3241+ fc_host_supported_classes(lport->host) = FC_COS_CLASS3;
3242+ memset(fc_host_supported_fc4s(lport->host), 0,
3243+ sizeof(fc_host_supported_fc4s(lport->host)));
3244+ fc_host_supported_fc4s(lport->host)[2] = 1;
3245+ fc_host_supported_fc4s(lport->host)[7] = 1;
3246+
3247+ /* This value is also unchanging */
3248+ memset(fc_host_active_fc4s(lport->host), 0,
3249+ sizeof(fc_host_active_fc4s(lport->host)));
3250+ fc_host_active_fc4s(lport->host)[2] = 1;
3251+ fc_host_active_fc4s(lport->host)[7] = 1;
3252+ fc_host_maxframe_size(lport->host) = lport->mfs;
3253+ fc_host_supported_speeds(lport->host) = 0;
3254+ if (lport->link_supported_speeds & FC_PORTSPEED_1GBIT)
3255+ fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT;
3256+ if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
3257+ fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
3258
3259 return 0;
3260 }
3261diff --git a/drivers/scsi/libfc/fc_ns.c b/drivers/scsi/libfc/fc_ns.c
3262deleted file mode 100644
3263index 5c9272c..0000000
3264--- a/drivers/scsi/libfc/fc_ns.c
3265+++ /dev/null
3266@@ -1,1283 +0,0 @@
3267-/*
3268- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
3269- *
3270- * This program is free software; you can redistribute it and/or modify it
3271- * under the terms and conditions of the GNU General Public License,
3272- * version 2, as published by the Free Software Foundation.
3273- *
3274- * This program is distributed in the hope it will be useful, but WITHOUT
3275- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3276- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
3277- * more details.
3278- *
3279- * You should have received a copy of the GNU General Public License along with
3280- * this program; if not, write to the Free Software Foundation, Inc.,
3281- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
3282- *
3283- * Maintained at www.Open-FCoE.org
3284- */
3285-
3286-/*
3287- * Target Discovery
3288- * Actually, this discovers all FC-4 remote ports, including FCP initiators.
3289- */
3290-
3291-#include <linux/timer.h>
3292-#include <linux/err.h>
3293-#include <asm/unaligned.h>
3294-
3295-#include <scsi/fc/fc_gs.h>
3296-
3297-#include <scsi/libfc/libfc.h>
3298-
3299-#define FC_NS_RETRY_LIMIT 3 /* max retries */
3300-#define FC_NS_RETRY_DELAY 500UL /* (msecs) delay */
3301-
3302-int fc_ns_debug;
3303-
3304-static void fc_ns_gpn_ft_req(struct fc_lport *);
3305-static void fc_ns_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
3306-static int fc_ns_new_target(struct fc_lport *, struct fc_rport *,
3307- struct fc_rport_identifiers *);
3308-static void fc_ns_del_target(struct fc_lport *, struct fc_rport *);
3309-static void fc_ns_disc_done(struct fc_lport *);
3310-static void fcdt_ns_error(struct fc_lport *, struct fc_frame *);
3311-static void fc_ns_timeout(struct work_struct *);
3312-
3313-/**
3314- * struct fc_ns_port - temporary discovery port to hold rport identifiers
3315- * @lp: Fibre Channel host port instance
3316- * @peers: node for list management during discovery and RSCN processing
3317- * @ids: identifiers structure to pass to fc_remote_port_add()
3318- */
3319-struct fc_ns_port {
3320- struct fc_lport *lp;
3321- struct list_head peers;
3322- struct fc_rport_identifiers ids;
3323-};
3324-
3325-static int fc_ns_gpn_id_req(struct fc_lport *, struct fc_ns_port *);
3326-static void fc_ns_gpn_id_resp(struct fc_seq *, struct fc_frame *, void *);
3327-static void fc_ns_gpn_id_error(struct fc_ns_port *rp, struct fc_frame *fp);
3328-
3329-static int fc_ns_gnn_id_req(struct fc_lport *, struct fc_ns_port *);
3330-static void fc_ns_gnn_id_resp(struct fc_seq *, struct fc_frame *, void *);
3331-static void fc_ns_gnn_id_error(struct fc_ns_port *, struct fc_frame *);
3332-static void fc_ns_enter_reg_pn(struct fc_lport *lp);
3333-static void fc_ns_error(struct fc_lport *lp, struct fc_frame *fp);
3334-static void fc_lport_fill_dns_hdr(struct fc_lport *lp, struct fc_ct_hdr *ct,
3335- unsigned int op, unsigned int req_size);
3336-static void fc_ns_resp(struct fc_seq *sp, struct fc_frame *fp,
3337- void *lp_arg);
3338-static void fc_ns_retry(struct fc_lport *lp);
3339-static void fc_ns_single(struct fc_lport *, struct fc_ns_port *);
3340-static int fc_ns_restart(struct fc_lport *);
3341-
3342-
3343-/**
3344- * fc_ns_rscn_req - Handle Registered State Change Notification (RSCN)
3345- * @sp: Current sequence of the RSCN exchange
3346- * @fp: RSCN Frame
3347- * @lp: Fibre Channel host port instance
3348- */
3349-static void fc_ns_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
3350- struct fc_lport *lp)
3351-{
3352- struct fc_els_rscn *rp;
3353- struct fc_els_rscn_page *pp;
3354- struct fc_seq_els_data rjt_data;
3355- unsigned int len;
3356- int redisc = 0;
3357- enum fc_els_rscn_ev_qual ev_qual;
3358- enum fc_els_rscn_addr_fmt fmt;
3359- LIST_HEAD(disc_list);
3360- struct fc_ns_port *dp, *next;
3361-
3362- rp = fc_frame_payload_get(fp, sizeof(*rp));
3363-
3364- if (!rp || rp->rscn_page_len != sizeof(*pp))
3365- goto reject;
3366-
3367- len = ntohs(rp->rscn_plen);
3368- if (len < sizeof(*rp))
3369- goto reject;
3370- len -= sizeof(*rp);
3371-
3372- for (pp = (void *)(rp + 1); len; len -= sizeof(*pp), pp++) {
3373- ev_qual = pp->rscn_page_flags >> ELS_RSCN_EV_QUAL_BIT;
3374- ev_qual &= ELS_RSCN_EV_QUAL_MASK;
3375- fmt = pp->rscn_page_flags >> ELS_RSCN_ADDR_FMT_BIT;
3376- fmt &= ELS_RSCN_ADDR_FMT_MASK;
3377- /*
3378- * if we get an address format other than port
3379- * (area, domain, fabric), then do a full discovery
3380- */
3381- switch (fmt) {
3382- case ELS_ADDR_FMT_PORT:
3383- dp = kzalloc(sizeof(*dp), GFP_KERNEL);
3384- if (!dp) {
3385- redisc = 1;
3386- break;
3387- }
3388- dp->lp = lp;
3389- dp->ids.port_id = ntoh24(pp->rscn_fid);
3390- dp->ids.port_name = -1;
3391- dp->ids.node_name = -1;
3392- dp->ids.roles = FC_RPORT_ROLE_UNKNOWN;
3393- list_add_tail(&dp->peers, &disc_list);
3394- break;
3395- case ELS_ADDR_FMT_AREA:
3396- case ELS_ADDR_FMT_DOM:
3397- case ELS_ADDR_FMT_FAB:
3398- default:
3399- redisc = 1;
3400- break;
3401- }
3402- }
3403- lp->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
3404- if (redisc) {
3405- if (fc_ns_debug)
3406- FC_DBG("RSCN received: rediscovering\n");
3407- list_for_each_entry_safe(dp, next, &disc_list, peers) {
3408- list_del(&dp->peers);
3409- kfree(dp);
3410- }
3411- fc_ns_restart(lp);
3412- } else {
3413- if (fc_ns_debug)
3414- FC_DBG("RSCN received: not rediscovering. "
3415- "redisc %d state %d in_prog %d\n",
3416- redisc, lp->state, lp->ns_disc_pending);
3417- list_for_each_entry_safe(dp, next, &disc_list, peers) {
3418- list_del(&dp->peers);
3419- fc_ns_single(lp, dp);
3420- }
3421- }
3422- fc_frame_free(fp);
3423- return;
3424-reject:
3425- rjt_data.fp = NULL;
3426- rjt_data.reason = ELS_RJT_LOGIC;
3427- rjt_data.explan = ELS_EXPL_NONE;
3428- lp->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
3429- fc_frame_free(fp);
3430-}
3431-
3432-static void fc_ns_recv_req(struct fc_seq *sp, struct fc_frame *fp,
3433- struct fc_lport *lp)
3434-{
3435- switch (fc_frame_payload_op(fp)) {
3436- case ELS_RSCN:
3437- fc_ns_rscn_req(sp, fp, lp);
3438- break;
3439- default:
3440- FC_DBG("fc_ns recieved an unexpected request\n");
3441- break;
3442- }
3443-}
3444-
3445-/**
3446- * fc_ns_scr_resp - Handle response to State Change Register (SCR) request
3447- * @sp: current sequence in SCR exchange
3448- * @fp: response frame
3449- * @lp_arg: Fibre Channel host port instance
3450- */
3451-static void fc_ns_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
3452- void *lp_arg)
3453-{
3454- struct fc_lport *lp = lp_arg;
3455- int err;
3456-
3457- if (IS_ERR(fp))
3458- fc_ns_error(lp, fp);
3459- else {
3460- fc_lport_lock(lp);
3461- fc_lport_state_enter(lp, LPORT_ST_READY);
3462- fc_lport_unlock(lp);
3463- err = lp->tt.disc_start(lp);
3464- if (err)
3465- FC_DBG("target discovery start error\n");
3466- fc_frame_free(fp);
3467- }
3468-}
3469-
3470-/**
3471- * fc_ns_enter scr - Send a State Change Register (SCR) request
3472- * @lp: Fibre Channel host port instance
3473- */
3474-static void fc_ns_enter_scr(struct fc_lport *lp)
3475-{
3476- struct fc_frame *fp;
3477- struct fc_els_scr *scr;
3478-
3479- if (fc_ns_debug)
3480- FC_DBG("Processing SCR state\n");
3481-
3482- fc_lport_state_enter(lp, LPORT_ST_SCR);
3483-
3484- fp = fc_frame_alloc(lp, sizeof(*scr));
3485- if (fp) {
3486- scr = fc_frame_payload_get(fp, sizeof(*scr));
3487- memset(scr, 0, sizeof(*scr));
3488- scr->scr_cmd = ELS_SCR;
3489- scr->scr_reg_func = ELS_SCRF_FULL;
3490- }
3491- fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
3492- fc_frame_set_offset(fp, 0);
3493-
3494- lp->tt.exch_seq_send(lp, fp,
3495- fc_ns_scr_resp,
3496- lp, lp->e_d_tov,
3497- lp->fid, FC_FID_FCTRL,
3498- FC_FC_SEQ_INIT | FC_FC_END_SEQ);
3499-}
3500-
3501-/**
3502- * fc_ns_enter_reg_ft - Register FC4-types with the name server
3503- * @lp: Fibre Channel host port instance
3504- */
3505-static void fc_ns_enter_reg_ft(struct fc_lport *lp)
3506-{
3507- struct fc_frame *fp;
3508- struct req {
3509- struct fc_ct_hdr ct;
3510- struct fc_ns_fid fid; /* port ID object */
3511- struct fc_ns_fts fts; /* FC4-types object */
3512- } *req;
3513- struct fc_ns_fts *lps;
3514- int i;
3515-
3516- if (fc_ns_debug)
3517- FC_DBG("Processing REG_FT state\n");
3518-
3519- fc_lport_state_enter(lp, LPORT_ST_REG_FT);
3520-
3521- lps = &lp->fcts;
3522- i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
3523- while (--i >= 0)
3524- if (ntohl(lps->ff_type_map[i]) != 0)
3525- break;
3526- if (i >= 0) {
3527- fp = fc_frame_alloc(lp, sizeof(*req));
3528- if (fp) {
3529- req = fc_frame_payload_get(fp, sizeof(*req));
3530- fc_lport_fill_dns_hdr(lp, &req->ct,
3531- FC_NS_RFT_ID,
3532- sizeof(*req) -
3533- sizeof(struct fc_ct_hdr));
3534- hton24(req->fid.fp_fid, lp->fid);
3535- req->fts = *lps;
3536- fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
3537- if (!lp->tt.exch_seq_send(lp, fp,
3538- fc_ns_resp, lp,
3539- lp->e_d_tov,
3540- lp->fid,
3541- lp->dns_rp->port_id,
3542- FC_FC_SEQ_INIT |
3543- FC_FC_END_SEQ))
3544- fc_ns_retry(lp);
3545- } else {
3546- fc_ns_retry(lp);
3547- }
3548- } else {
3549- fc_ns_enter_scr(lp);
3550- }
3551-}
3552-
3553-/*
3554- * enter next state for handling an exchange reject or retry exhaustion
3555- * in the current state.
3556- */
3557-static void fc_ns_enter_reject(struct fc_lport *lp)
3558-{
3559- switch (lp->state) {
3560- case LPORT_ST_NONE:
3561- case LPORT_ST_READY:
3562- case LPORT_ST_RESET:
3563- case LPORT_ST_FLOGI:
3564- case LPORT_ST_LOGO:
3565- WARN_ON(1);
3566- break;
3567- case LPORT_ST_REG_PN:
3568- fc_ns_enter_reg_ft(lp);
3569- break;
3570- case LPORT_ST_REG_FT:
3571- fc_ns_enter_scr(lp);
3572- break;
3573- case LPORT_ST_SCR:
3574- case LPORT_ST_DNS_STOP:
3575- lp->tt.disc_stop(lp);
3576- break;
3577- case LPORT_ST_DNS:
3578- lp->tt.lport_reset(lp);
3579- break;
3580- }
3581-}
3582-
3583-static void fc_ns_enter_retry(struct fc_lport *lp)
3584-{
3585- switch (lp->state) {
3586- case LPORT_ST_NONE:
3587- case LPORT_ST_RESET:
3588- case LPORT_ST_READY:
3589- case LPORT_ST_FLOGI:
3590- case LPORT_ST_LOGO:
3591- WARN_ON(1);
3592- break;
3593- case LPORT_ST_DNS:
3594- lp->tt.dns_register(lp);
3595- break;
3596- case LPORT_ST_DNS_STOP:
3597- lp->tt.disc_stop(lp);
3598- break;
3599- case LPORT_ST_REG_PN:
3600- fc_ns_enter_reg_pn(lp);
3601- break;
3602- case LPORT_ST_REG_FT:
3603- fc_ns_enter_reg_ft(lp);
3604- break;
3605- case LPORT_ST_SCR:
3606- fc_ns_enter_scr(lp);
3607- break;
3608- }
3609-}
3610-
3611-/*
3612- * Refresh target discovery, perhaps due to an RSCN.
3613- * A configurable delay is introduced to collect any subsequent RSCNs.
3614- */
3615-static int fc_ns_restart(struct fc_lport *lp)
3616-{
3617- fc_lport_lock(lp);
3618- if (!lp->ns_disc_requested && !lp->ns_disc_pending) {
3619- schedule_delayed_work(&lp->ns_disc_work,
3620- msecs_to_jiffies(lp->ns_disc_delay * 1000));
3621- }
3622- lp->ns_disc_requested = 1;
3623- fc_lport_unlock(lp);
3624- return 0;
3625-}
3626-
3627-/* unlocked varient of scsi_target_block from scsi_lib.c */
3628-#include "../scsi_priv.h"
3629-
3630-static void __device_block(struct scsi_device *sdev, void *data)
3631-{
3632- scsi_internal_device_block(sdev);
3633-}
3634-
3635-static int __target_block(struct device *dev, void *data)
3636-{
3637- if (scsi_is_target_device(dev))
3638- __starget_for_each_device(to_scsi_target(dev),
3639- NULL, __device_block);
3640- return 0;
3641-}
3642-
3643-static void __scsi_target_block(struct device *dev)
3644-{
3645- if (scsi_is_target_device(dev))
3646- __starget_for_each_device(to_scsi_target(dev),
3647- NULL, __device_block);
3648- else
3649- device_for_each_child(dev, NULL, __target_block);
3650-}
3651-
3652-static void fc_block_rports(struct fc_lport *lp)
3653-{
3654- struct Scsi_Host *shost = lp->host;
3655- struct fc_rport *rport;
3656- unsigned long flags;
3657-
3658- spin_lock_irqsave(shost->host_lock, flags);
3659- list_for_each_entry(rport, &fc_host_rports(shost), peers) {
3660- /* protect the name service remote port */
3661- if (rport == lp->dns_rp)
3662- continue;
3663- if (rport->port_state != FC_PORTSTATE_ONLINE)
3664- continue;
3665- rport->port_state = FC_PORTSTATE_BLOCKED;
3666- rport->flags |= FC_RPORT_DEVLOSS_PENDING;
3667- __scsi_target_block(&rport->dev);
3668- }
3669- spin_unlock_irqrestore(shost->host_lock, flags);
3670-}
3671-
3672-/*
3673- * Fibre Channel Target discovery.
3674- *
3675- * Returns non-zero if discovery cannot be started.
3676- *
3677- * Callback is called for each target remote port found in discovery.
3678- * When discovery is complete, the callback is called with a NULL remote port.
3679- * Discovery may be restarted after an RSCN is received, causing the
3680- * callback to be called after discovery complete is indicated.
3681- */
3682-int fc_ns_disc_start(struct fc_lport *lp)
3683-{
3684- struct fc_rport *rport;
3685- int error;
3686- struct fc_rport_identifiers ids;
3687-
3688- fc_lport_lock(lp);
3689-
3690- /*
3691- * If not ready, or already running discovery, just set request flag.
3692- */
3693- if (!fc_lport_test_ready(lp) || lp->ns_disc_pending) {
3694- lp->ns_disc_requested = 1;
3695- fc_lport_unlock(lp);
3696- return 0;
3697- }
3698- lp->ns_disc_pending = 1;
3699- lp->ns_disc_requested = 0;
3700- lp->ns_disc_retry_count = 0;
3701-
3702- /*
3703- * Handle point-to-point mode as a simple discovery
3704- * of the remote port.
3705- */
3706- rport = lp->ptp_rp;
3707- if (rport) {
3708- ids.port_id = rport->port_id;
3709- ids.port_name = rport->port_name;
3710- ids.node_name = rport->node_name;
3711- ids.roles = FC_RPORT_ROLE_UNKNOWN;
3712- get_device(&rport->dev);
3713- fc_lport_unlock(lp);
3714- error = fc_ns_new_target(lp, rport, &ids);
3715- put_device(&rport->dev);
3716- if (!error)
3717- fc_ns_disc_done(lp);
3718- } else {
3719- fc_lport_unlock(lp);
3720- fc_block_rports(lp);
3721- fc_ns_gpn_ft_req(lp); /* get ports by FC-4 type */
3722- error = 0;
3723- }
3724- return error;
3725-}
3726-
3727-/*
3728- * Handle resource allocation problem by retrying in a bit.
3729- */
3730-static void fc_ns_retry(struct fc_lport *lp)
3731-{
3732- if (lp->retry_count == 0)
3733- FC_DBG("local port %6x alloc failure "
3734- "- will retry\n", lp->fid);
3735- if (lp->retry_count < lp->max_retry_count) {
3736- lp->retry_count++;
3737- mod_timer(&lp->state_timer,
3738- jiffies + msecs_to_jiffies(lp->e_d_tov));
3739- } else {
3740- FC_DBG("local port %6x alloc failure "
3741- "- retries exhausted\n", lp->fid);
3742- fc_ns_enter_reject(lp);
3743- }
3744-}
3745-
3746-/*
3747- * Handle errors on local port requests.
3748- * Don't get locks if in RESET state.
3749- * The only possible errors so far are exchange TIMEOUT and CLOSED (reset).
3750- */
3751-static void fc_ns_error(struct fc_lport *lp, struct fc_frame *fp)
3752-{
3753- if (lp->state == LPORT_ST_RESET)
3754- return;
3755-
3756- fc_lport_lock(lp);
3757- if (PTR_ERR(fp) == -FC_EX_TIMEOUT) {
3758- if (lp->retry_count < lp->max_retry_count) {
3759- lp->retry_count++;
3760- fc_ns_enter_retry(lp);
3761- } else {
3762- fc_ns_enter_reject(lp);
3763- }
3764- }
3765- if (fc_ns_debug)
3766- FC_DBG("error %ld retries %d limit %d\n",
3767- PTR_ERR(fp), lp->retry_count, lp->max_retry_count);
3768- fc_lport_unlock(lp);
3769-}
3770-
3771-/*
3772- * Restart discovery after a delay due to resource shortages.
3773- * If the error persists, the discovery will be abandoned.
3774- */
3775-static void fcdt_ns_retry(struct fc_lport *lp)
3776-{
3777- unsigned long delay = FC_NS_RETRY_DELAY;
3778-
3779- if (!lp->ns_disc_retry_count)
3780- delay /= 4; /* timeout faster first time */
3781- if (lp->ns_disc_retry_count++ < FC_NS_RETRY_LIMIT)
3782- schedule_delayed_work(&lp->ns_disc_work,
3783- msecs_to_jiffies(delay));
3784- else
3785- fc_ns_disc_done(lp);
3786-}
3787-
3788-/*
3789- * Test for dNS accept in response payload.
3790- */
3791-static int fc_lport_dns_acc(struct fc_frame *fp)
3792-{
3793- struct fc_frame_header *fh;
3794- struct fc_ct_hdr *ct;
3795- int rc = 0;
3796-
3797- fh = fc_frame_header_get(fp);
3798- ct = fc_frame_payload_get(fp, sizeof(*ct));
3799- if (fh && ct && fh->fh_type == FC_TYPE_CT &&
3800- ct->ct_fs_type == FC_FST_DIR &&
3801- ct->ct_fs_subtype == FC_NS_SUBTYPE &&
3802- ntohs(ct->ct_cmd) == FC_FS_ACC) {
3803- rc = 1;
3804- }
3805- return rc;
3806-}
3807-
3808-/*
3809- * Handle response from name server.
3810- */
3811-static void
3812-fc_ns_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg)
3813-{
3814- struct fc_lport *lp = lp_arg;
3815-
3816- if (!IS_ERR(fp)) {
3817- fc_lport_lock(lp);
3818- del_timer(&lp->state_timer);
3819- if (fc_lport_dns_acc(fp)) {
3820- if (lp->state == LPORT_ST_REG_PN)
3821- fc_ns_enter_reg_ft(lp);
3822- else
3823- fc_ns_enter_scr(lp);
3824-
3825- } else {
3826- fc_ns_retry(lp);
3827- }
3828- fc_lport_unlock(lp);
3829- fc_frame_free(fp);
3830- } else
3831- fc_ns_error(lp, fp);
3832-}
3833-
3834-/*
3835- * Handle new target found by discovery.
3836- * Create remote port and session if needed.
3837- * Ignore returns of our own FID & WWPN.
3838- *
3839- * If a non-NULL rp is passed in, it is held for the caller, but not for us.
3840- *
3841- * Events delivered are:
3842- * FC_EV_READY, when remote port is rediscovered.
3843- */
3844-static int fc_ns_new_target(struct fc_lport *lp,
3845- struct fc_rport *rport,
3846- struct fc_rport_identifiers *ids)
3847-{
3848- struct fc_rport_libfc_priv *rp;
3849- int error = 0;
3850-
3851- if (rport && ids->port_name) {
3852- if (rport->port_name == -1) {
3853- /*
3854- * Set WWN and fall through to notify of create.
3855- */
3856- fc_rport_set_name(rport, ids->port_name,
3857- rport->node_name);
3858- } else if (rport->port_name != ids->port_name) {
3859- /*
3860- * This is a new port with the same FCID as
3861- * a previously-discovered port. Presumably the old
3862- * port logged out and a new port logged in and was
3863- * assigned the same FCID. This should be rare.
3864- * Delete the old one and fall thru to re-create.
3865- */
3866- fc_ns_del_target(lp, rport);
3867- rport = NULL;
3868- }
3869- }
3870- if (((ids->port_name != -1) || (ids->port_id != -1)) &&
3871- ids->port_id != lp->fid && ids->port_name != lp->wwpn) {
3872- if (!rport) {
3873- rport = lp->tt.rport_lookup(lp, ids->port_id);
3874- if (rport == NULL)
3875- rport = lp->tt.rport_create(lp, ids);
3876- if (!rport)
3877- error = ENOMEM;
3878- }
3879- if (rport) {
3880- rp = rport->dd_data;
3881- rp->rp_state = RPORT_ST_INIT;
3882- lp->tt.rport_login(rport);
3883- }
3884- }
3885- return error;
3886-}
3887-
3888-/*
3889- * Delete the remote port.
3890- */
3891-static void fc_ns_del_target(struct fc_lport *lp, struct fc_rport *rport)
3892-{
3893- lp->tt.rport_reset(rport);
3894- fc_remote_port_delete(rport); /* release hold from create */
3895-}
3896-
3897-/*
3898- * Done with discovery
3899- */
3900-static void fc_ns_disc_done(struct fc_lport *lp)
3901-{
3902- lp->ns_disc_done = 1;
3903- lp->ns_disc_pending = 0;
3904- if (lp->ns_disc_requested)
3905- lp->tt.disc_start(lp);
3906-}
3907-
3908-/**
3909- * fc_ns_fill_dns_hdr - Fill in a name service request header
3910- * @lp: Fibre Channel host port instance
3911- * @ct: Common Transport (CT) header structure
3912- * @op: Name Service request code
3913- * @req_size: Full size of Name Service request
3914- */
3915-static void fc_ns_fill_dns_hdr(struct fc_lport *lp, struct fc_ct_hdr *ct,
3916- unsigned int op, unsigned int req_size)
3917-{
3918- memset(ct, 0, sizeof(*ct) + req_size);
3919- ct->ct_rev = FC_CT_REV;
3920- ct->ct_fs_type = FC_FST_DIR;
3921- ct->ct_fs_subtype = FC_NS_SUBTYPE;
3922- ct->ct_cmd = htons((u16) op);
3923-}
3924-
3925-/**
3926- * fc_ns_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request
3927- * @lp: Fibre Channel host port instance
3928- */
3929-static void fc_ns_gpn_ft_req(struct fc_lport *lp)
3930-{
3931- struct fc_frame *fp;
3932- struct fc_seq *sp = NULL;
3933- struct req {
3934- struct fc_ct_hdr ct;
3935- struct fc_ns_gid_ft gid;
3936- } *rp;
3937- int error = 0;
3938-
3939- lp->ns_disc_buf_len = 0;
3940- lp->ns_disc_seq_count = 0;
3941- fp = fc_frame_alloc(lp, sizeof(*rp));
3942- if (fp == NULL) {
3943- error = ENOMEM;
3944- } else {
3945- rp = fc_frame_payload_get(fp, sizeof(*rp));
3946- fc_ns_fill_dns_hdr(lp, &rp->ct, FC_NS_GPN_FT, sizeof(rp->gid));
3947- rp->gid.fn_fc4_type = FC_TYPE_FCP;
3948-
3949- WARN_ON(!fc_lport_test_ready(lp));
3950-
3951- fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
3952- sp = lp->tt.exch_seq_send(lp, fp,
3953- fc_ns_gpn_ft_resp,
3954- lp, lp->e_d_tov,
3955- lp->fid,
3956- lp->dns_rp->port_id,
3957- FC_FC_SEQ_INIT | FC_FC_END_SEQ);
3958- }
3959- if (error || sp == NULL)
3960- fcdt_ns_retry(lp);
3961-}
3962-
3963-/*
3964- * Handle error on dNS request.
3965- */
3966-static void fcdt_ns_error(struct fc_lport *lp, struct fc_frame *fp)
3967-{
3968- int err = PTR_ERR(fp);
3969-
3970- switch (err) {
3971- case -FC_EX_TIMEOUT:
3972- if (lp->ns_disc_retry_count++ < FC_NS_RETRY_LIMIT) {
3973- fc_ns_gpn_ft_req(lp);
3974- } else {
3975- FC_DBG("err %d - ending\n", err);
3976- fc_ns_disc_done(lp);
3977- }
3978- break;
3979- default:
3980- FC_DBG("err %d - ending\n", err);
3981- fc_ns_disc_done(lp);
3982- break;
3983- }
3984-}
3985-
3986-/**
3987- * fc_ns_gpn_ft_parse - Parse the list of IDs and names resulting from a request
3988- * @lp: Fibre Channel host port instance
3989- * @buf: GPN_FT response buffer
3990- * @len: size of response buffer
3991- */
3992-static int fc_ns_gpn_ft_parse(struct fc_lport *lp, void *buf, size_t len)
3993-{
3994- struct fc_gpn_ft_resp *np;
3995- char *bp;
3996- size_t plen;
3997- size_t tlen;
3998- int error = 0;
3999- struct fc_ns_port *dp;
4000-
4001- /*
4002- * Handle partial name record left over from previous call.
4003- */
4004- bp = buf;
4005- plen = len;
4006- np = (struct fc_gpn_ft_resp *)bp;
4007- tlen = lp->ns_disc_buf_len;
4008- if (tlen) {
4009- WARN_ON(tlen >= sizeof(*np));
4010- plen = sizeof(*np) - tlen;
4011- WARN_ON(plen <= 0);
4012- WARN_ON(plen >= sizeof(*np));
4013- if (plen > len)
4014- plen = len;
4015- np = &lp->ns_disc_buf;
4016- memcpy((char *)np + tlen, bp, plen);
4017-
4018- /*
4019- * Set bp so that the loop below will advance it to the
4020- * first valid full name element.
4021- */
4022- bp -= tlen;
4023- len += tlen;
4024- plen += tlen;
4025- lp->ns_disc_buf_len = (unsigned char) plen;
4026- if (plen == sizeof(*np))
4027- lp->ns_disc_buf_len = 0;
4028- }
4029-
4030- /*
4031- * Handle full name records, including the one filled from above.
4032- * Normally, np == bp and plen == len, but from the partial case above,
4033- * bp, len describe the overall buffer, and np, plen describe the
4034- * partial buffer, which if would usually be full now.
4035- * After the first time through the loop, things return to "normal".
4036- */
4037- while (plen >= sizeof(*np)) {
4038- dp = kzalloc(sizeof(*dp), GFP_KERNEL);
4039- if (!dp)
4040- break;
4041- dp->lp = lp;
4042- dp->ids.port_id = ntoh24(np->fp_fid);
4043- dp->ids.port_name = ntohll(np->fp_wwpn);
4044- dp->ids.node_name = -1;
4045- dp->ids.roles = FC_RPORT_ROLE_UNKNOWN;
4046- error = fc_ns_gnn_id_req(lp, dp);
4047- if (error)
4048- break;
4049- if (np->fp_flags & FC_NS_FID_LAST) {
4050- fc_ns_disc_done(lp);
4051- len = 0;
4052- break;
4053- }
4054- len -= sizeof(*np);
4055- bp += sizeof(*np);
4056- np = (struct fc_gpn_ft_resp *)bp;
4057- plen = len;
4058- }
4059-
4060- /*
4061- * Save any partial record at the end of the buffer for next time.
4062- */
4063- if (error == 0 && len > 0 && len < sizeof(*np)) {
4064- if (np != &lp->ns_disc_buf)
4065- memcpy(&lp->ns_disc_buf, np, len);
4066- lp->ns_disc_buf_len = (unsigned char) len;
4067- } else {
4068- lp->ns_disc_buf_len = 0;
4069- }
4070- return error;
4071-}
4072-
4073-/*
4074- * Handle retry of memory allocation for remote ports.
4075- */
4076-static void fc_ns_timeout(struct work_struct *work)
4077-{
4078- struct fc_lport *lp;
4079-
4080- lp = container_of(work, struct fc_lport, ns_disc_work.work);
4081-
4082- if (lp->ns_disc_pending)
4083- fc_ns_gpn_ft_req(lp);
4084- else
4085- lp->tt.disc_start(lp);
4086-}
4087-
4088-/**
4089- * fc_ns_gpn_ft_resp - Handle a response frame from Get Port Names (GPN_FT)
4090- * @sp: Current sequence of GPN_FT exchange
4091- * @fp: response frame
4092- * @lp_arg: Fibre Channel host port instance
4093- *
4094- * The response may be in multiple frames
4095- */
4096-static void fc_ns_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
4097- void *lp_arg)
4098-{
4099- struct fc_lport *lp = lp_arg;
4100- struct fc_ct_hdr *cp;
4101- struct fc_frame_header *fh;
4102- unsigned int seq_cnt;
4103- void *buf = NULL;
4104- unsigned int len;
4105- int error;
4106-
4107- if (IS_ERR(fp)) {
4108- fcdt_ns_error(lp, fp);
4109- return;
4110- }
4111-
4112- WARN_ON(!fc_frame_is_linear(fp)); /* buffer must be contiguous */
4113- fh = fc_frame_header_get(fp);
4114- len = fr_len(fp) - sizeof(*fh);
4115- seq_cnt = ntohs(fh->fh_seq_cnt);
4116- if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 &&
4117- lp->ns_disc_seq_count == 0) {
4118- cp = fc_frame_payload_get(fp, sizeof(*cp));
4119- if (cp == NULL) {
4120- FC_DBG("GPN_FT response too short, len %d\n",
4121- fr_len(fp));
4122- } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
4123-
4124- /*
4125- * Accepted. Parse response.
4126- */
4127- buf = cp + 1;
4128- len -= sizeof(*cp);
4129- } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
4130- FC_DBG("GPN_FT rejected reason %x exp %x "
4131- "(check zoning)\n", cp->ct_reason,
4132- cp->ct_explan);
4133- fc_ns_disc_done(lp);
4134- } else {
4135- FC_DBG("GPN_FT unexpected response code %x\n",
4136- ntohs(cp->ct_cmd));
4137- }
4138- } else if (fr_sof(fp) == FC_SOF_N3 &&
4139- seq_cnt == lp->ns_disc_seq_count) {
4140- buf = fh + 1;
4141- } else {
4142- FC_DBG("GPN_FT unexpected frame - out of sequence? "
4143- "seq_cnt %x expected %x sof %x eof %x\n",
4144- seq_cnt, lp->ns_disc_seq_count, fr_sof(fp), fr_eof(fp));
4145- }
4146- if (buf) {
4147- error = fc_ns_gpn_ft_parse(lp, buf, len);
4148- if (error)
4149- fcdt_ns_retry(lp);
4150- else
4151- lp->ns_disc_seq_count++;
4152- }
4153- fc_frame_free(fp);
4154-}
4155-
4156-/*
4157- * Discover the directory information for a single target.
4158- * This could be from an RSCN that reported a change for the target.
4159- */
4160-static void fc_ns_single(struct fc_lport *lp, struct fc_ns_port *dp)
4161-{
4162- struct fc_rport *rport;
4163-
4164- if (dp->ids.port_id == lp->fid)
4165- goto out;
4166-
4167- rport = lp->tt.rport_lookup(lp, dp->ids.port_id);
4168- if (rport) {
4169- fc_ns_del_target(lp, rport);
4170- put_device(&rport->dev); /* hold from lookup */
4171- }
4172-
4173- if (fc_ns_gpn_id_req(lp, dp) != 0)
4174- goto error;
4175- return;
4176-error:
4177- fc_ns_restart(lp);
4178-out:
4179- kfree(dp);
4180-}
4181-
4182-/**
4183- * fc_ns_gpn_id_req - Send Get Port Name by ID (GPN_ID) request
4184- * @lp: Fibre Channel host port instance
4185- * @dp: Temporary discovery port for holding IDs and world wide names
4186- *
4187- * The remote port is held by the caller for us.
4188- */
4189-static int fc_ns_gpn_id_req(struct fc_lport *lp, struct fc_ns_port *dp)
4190-{
4191- struct fc_frame *fp;
4192- struct req {
4193- struct fc_ct_hdr ct;
4194- struct fc_ns_fid fid;
4195- } *cp;
4196- int error = 0;
4197-
4198- fp = fc_frame_alloc(lp, sizeof(*cp));
4199- if (fp == NULL)
4200- return -ENOMEM;
4201-
4202- cp = fc_frame_payload_get(fp, sizeof(*cp));
4203- fc_ns_fill_dns_hdr(lp, &cp->ct, FC_NS_GPN_ID, sizeof(cp->fid));
4204- hton24(cp->fid.fp_fid, dp->ids.port_id);
4205-
4206- WARN_ON(!fc_lport_test_ready(lp));
4207-
4208- fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
4209- if (!lp->tt.exch_seq_send(lp, fp,
4210- fc_ns_gpn_id_resp,
4211- dp, lp->e_d_tov,
4212- lp->fid,
4213- lp->dns_rp->port_id,
4214- FC_FC_SEQ_INIT | FC_FC_END_SEQ))
4215- error = -ENOMEM;
4216-
4217- return error;
4218-}
4219-
4220-/**
4221- * fc_ns_gpn_id_resp - Handle response to GPN_ID
4222- * @sp: Current sequence of GPN_ID exchange
4223- * @fp: response frame
4224- * @dp_arg: Temporary discovery port for holding IDs and world wide names
4225- */
4226-static void fc_ns_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
4227- void *dp_arg)
4228-{
4229- struct fc_ns_port *dp = dp_arg;
4230- struct fc_lport *lp;
4231- struct resp {
4232- struct fc_ct_hdr ct;
4233- __be64 wwn;
4234- } *cp;
4235- unsigned int cmd;
4236-
4237- if (IS_ERR(fp)) {
4238- fc_ns_gpn_id_error(dp, fp);
4239- return;
4240- }
4241-
4242- lp = dp->lp;
4243- WARN_ON(!fc_frame_is_linear(fp)); /* buffer must be contiguous */
4244-
4245- cp = fc_frame_payload_get(fp, sizeof(cp->ct));
4246- if (cp == NULL) {
4247- FC_DBG("GPN_ID response too short, len %d\n", fr_len(fp));
4248- return;
4249- }
4250- cmd = ntohs(cp->ct.ct_cmd);
4251- switch (cmd) {
4252- case FC_FS_ACC:
4253- cp = fc_frame_payload_get(fp, sizeof(*cp));
4254- if (cp == NULL) {
4255- FC_DBG("GPN_ID response payload too short, len %d\n",
4256- fr_len(fp));
4257- break;
4258- }
4259- dp->ids.port_name = ntohll(cp->wwn);
4260- fc_ns_gnn_id_req(lp, dp);
4261- break;
4262- case FC_FS_RJT:
4263- fc_ns_restart(lp);
4264- break;
4265- default:
4266- FC_DBG("GPN_ID unexpected CT response cmd %x\n", cmd);
4267- break;
4268- }
4269- fc_frame_free(fp);
4270-}
4271-
4272-/**
4273- * fc_ns_gpn_id_error - Handle error from GPN_ID
4274- * @dp: Temporary discovery port for holding IDs and world wide names
4275- * @fp: response frame
4276- */
4277-static void fc_ns_gpn_id_error(struct fc_ns_port *dp, struct fc_frame *fp)
4278-{
4279- struct fc_lport *lp = dp->lp;
4280-
4281- switch (PTR_ERR(fp)) {
4282- case -FC_EX_TIMEOUT:
4283- fc_ns_restart(lp);
4284- break;
4285- case -FC_EX_CLOSED:
4286- default:
4287- break;
4288- }
4289- kfree(dp);
4290-}
4291-
4292-/*
4293- * Setup session to dNS if not already set up.
4294- */
4295-static void fc_ns_enter_dns(struct fc_lport *lp)
4296-{
4297- struct fc_rport *rport;
4298- struct fc_rport_libfc_priv *rp;
4299- struct fc_rport_identifiers ids = {
4300- .port_id = FC_FID_DIR_SERV,
4301- .port_name = -1,
4302- .node_name = -1,
4303- .roles = FC_RPORT_ROLE_UNKNOWN,
4304- };
4305-
4306- if (fc_ns_debug)
4307- FC_DBG("Processing DNS state\n");
4308-
4309- fc_lport_state_enter(lp, LPORT_ST_DNS);
4310-
4311- if (!lp->dns_rp) {
4312- /*
4313- * Set up remote port to directory server.
4314- */
4315-
4316- /*
4317- * we are called with the state_lock, but if rport_lookup_create
4318- * needs to create a rport then it will sleep.
4319- */
4320- fc_lport_unlock(lp);
4321- rport = lp->tt.rport_lookup(lp, ids.port_id);
4322- if (rport == NULL)
4323- rport = lp->tt.rport_create(lp, &ids);
4324- fc_lport_lock(lp);
4325- if (!rport)
4326- goto err;
4327- lp->dns_rp = rport;
4328- }
4329-
4330- rport = lp->dns_rp;
4331- rp = rport->dd_data;
4332-
4333- /*
4334- * If dNS session isn't ready, start its logon.
4335- */
4336- if (rp->rp_state != RPORT_ST_READY) {
4337- lp->tt.rport_login(rport);
4338- } else {
4339- del_timer(&lp->state_timer);
4340- fc_ns_enter_reg_pn(lp);
4341- }
4342- return;
4343-
4344- /*
4345- * Resource allocation problem (malloc). Try again in 500 mS.
4346- */
4347-err:
4348- fc_ns_retry(lp);
4349-}
4350-
4351-/*
4352- * Logoff DNS session.
4353- * We should get an event call when the session has been logged out.
4354- */
4355-static void fc_ns_enter_dns_stop(struct fc_lport *lp)
4356-{
4357- struct fc_rport *rport = lp->dns_rp;
4358-
4359- if (fc_ns_debug)
4360- FC_DBG("Processing DNS_STOP state\n");
4361-
4362- fc_lport_state_enter(lp, LPORT_ST_DNS_STOP);
4363-
4364- if (rport)
4365- lp->tt.rport_logout(rport);
4366- else
4367- lp->tt.lport_logout(lp);
4368-}
4369-
4370-/*
4371- * Fill in dNS request header.
4372- */
4373-static void
4374-fc_lport_fill_dns_hdr(struct fc_lport *lp, struct fc_ct_hdr *ct,
4375- unsigned int op, unsigned int req_size)
4376-{
4377- memset(ct, 0, sizeof(*ct) + req_size);
4378- ct->ct_rev = FC_CT_REV;
4379- ct->ct_fs_type = FC_FST_DIR;
4380- ct->ct_fs_subtype = FC_NS_SUBTYPE;
4381- ct->ct_cmd = htons(op);
4382-}
4383-
4384-/*
4385- * Register port name with name server.
4386- */
4387-static void fc_ns_enter_reg_pn(struct fc_lport *lp)
4388-{
4389- struct fc_frame *fp;
4390- struct req {
4391- struct fc_ct_hdr ct;
4392- struct fc_ns_rn_id rn;
4393- } *req;
4394-
4395- if (fc_ns_debug)
4396- FC_DBG("Processing REG_PN state\n");
4397-
4398- fc_lport_state_enter(lp, LPORT_ST_REG_PN);
4399- fp = fc_frame_alloc(lp, sizeof(*req));
4400- if (!fp) {
4401- fc_ns_retry(lp);
4402- return;
4403- }
4404- req = fc_frame_payload_get(fp, sizeof(*req));
4405- memset(req, 0, sizeof(*req));
4406- fc_lport_fill_dns_hdr(lp, &req->ct, FC_NS_RPN_ID, sizeof(req->rn));
4407- hton24(req->rn.fr_fid.fp_fid, lp->fid);
4408- put_unaligned_be64(lp->wwpn, &req->rn.fr_wwn);
4409- fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
4410- if (!lp->tt.exch_seq_send(lp, fp,
4411- fc_ns_resp, lp,
4412- lp->e_d_tov,
4413- lp->fid,
4414- lp->dns_rp->port_id,
4415- FC_FC_SEQ_INIT | FC_FC_END_SEQ))
4416- fc_ns_retry(lp);
4417-}
4418-
4419-int fc_ns_init(struct fc_lport *lp)
4420-{
4421- INIT_DELAYED_WORK(&lp->ns_disc_work, fc_ns_timeout);
4422-
4423- if (!lp->tt.disc_start)
4424- lp->tt.disc_start = fc_ns_disc_start;
4425-
4426- if (!lp->tt.disc_recv_req)
4427- lp->tt.disc_recv_req = fc_ns_recv_req;
4428-
4429- if (!lp->tt.dns_register)
4430- lp->tt.dns_register = fc_ns_enter_dns;
4431-
4432- if (!lp->tt.disc_stop)
4433- lp->tt.disc_stop = fc_ns_enter_dns_stop;
4434-
4435- return 0;
4436-}
4437-EXPORT_SYMBOL(fc_ns_init);
4438-
4439-/**
4440- * fc_ns_gnn_id_req - Send Get Node Name by ID (GNN_ID) request
4441- * @lp: Fibre Channel host port instance
4442- * @dp: Temporary discovery port for holding IDs and world wide names
4443- *
4444- * The remote port is held by the caller for us.
4445- */
4446-static int fc_ns_gnn_id_req(struct fc_lport *lp, struct fc_ns_port *dp)
4447-{
4448- struct fc_frame *fp;
4449- struct req {
4450- struct fc_ct_hdr ct;
4451- struct fc_ns_fid fid;
4452- } *cp;
4453- int error = 0;
4454-
4455- fp = fc_frame_alloc(lp, sizeof(*cp));
4456- if (fp == NULL)
4457- return -ENOMEM;
4458-
4459- cp = fc_frame_payload_get(fp, sizeof(*cp));
4460- fc_ns_fill_dns_hdr(lp, &cp->ct, FC_NS_GNN_ID, sizeof(cp->fid));
4461- hton24(cp->fid.fp_fid, dp->ids.port_id);
4462-
4463- WARN_ON(!fc_lport_test_ready(lp));
4464-
4465- fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
4466- if (!lp->tt.exch_seq_send(lp, fp,
4467- fc_ns_gnn_id_resp,
4468- dp, lp->e_d_tov,
4469- lp->fid,
4470- lp->dns_rp->port_id,
4471- FC_FC_SEQ_INIT | FC_FC_END_SEQ))
4472- error = -ENOMEM;
4473-
4474- return error;
4475-}
4476-
4477-/**
4478- * fc_ns_gnn_id_resp - Handle response to GNN_ID
4479- * @sp: Current sequence of GNN_ID exchange
4480- * @fp: response frame
4481- * @dp_arg: Temporary discovery port for holding IDs and world wide names
4482- */
4483-static void fc_ns_gnn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
4484- void *dp_arg)
4485-{
4486- struct fc_ns_port *dp = dp_arg;
4487- struct fc_lport *lp;
4488- struct resp {
4489- struct fc_ct_hdr ct;
4490- __be64 wwn;
4491- } *cp;
4492- unsigned int cmd;
4493-
4494- if (IS_ERR(fp)) {
4495- fc_ns_gnn_id_error(dp, fp);
4496- return;
4497- }
4498-
4499- lp = dp->lp;
4500- WARN_ON(!fc_frame_is_linear(fp)); /* buffer must be contiguous */
4501-
4502- cp = fc_frame_payload_get(fp, sizeof(cp->ct));
4503- if (cp == NULL) {
4504- FC_DBG("GNN_ID response too short, len %d\n", fr_len(fp));
4505- return;
4506- }
4507- cmd = ntohs(cp->ct.ct_cmd);
4508- switch (cmd) {
4509- case FC_FS_ACC:
4510- cp = fc_frame_payload_get(fp, sizeof(*cp));
4511- if (cp == NULL) {
4512- FC_DBG("GNN_ID response payload too short, len %d\n",
4513- fr_len(fp));
4514- break;
4515- }
4516- dp->ids.node_name = ntohll(cp->wwn);
4517- fc_ns_new_target(lp, NULL, &dp->ids);
4518- break;
4519- case FC_FS_RJT:
4520- fc_ns_restart(lp);
4521- break;
4522- default:
4523- FC_DBG("GNN_ID unexpected CT response cmd %x\n", cmd);
4524- break;
4525- }
4526- kfree(dp);
4527- fc_frame_free(fp);
4528-}
4529-
4530-/**
4531- * fc_ns_gnn_id_error - Handle error from GNN_ID
4532- * @dp: Temporary discovery port for holding IDs and world wide names
4533- * @fp: response frame
4534- */
4535-static void fc_ns_gnn_id_error(struct fc_ns_port *dp, struct fc_frame *fp)
4536-{
4537- struct fc_lport *lp = dp->lp;
4538-
4539- switch (PTR_ERR(fp)) {
4540- case -FC_EX_TIMEOUT:
4541- fc_ns_restart(lp);
4542- break;
4543- case -FC_EX_CLOSED:
4544- default:
4545- break;
4546- }
4547- kfree(dp);
4548-}
4549-
4550diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
4551index 6d0c970..107b304 100644
4552--- a/drivers/scsi/libfc/fc_rport.c
4553+++ b/drivers/scsi/libfc/fc_rport.c
4554@@ -36,14 +36,12 @@
4555
4556 static int fc_rp_debug;
4557
4558-/*
4559- * static functions.
4560- */
4561-static void fc_rport_enter_start(struct fc_rport *);
4562 static void fc_rport_enter_plogi(struct fc_rport *);
4563 static void fc_rport_enter_prli(struct fc_rport *);
4564 static void fc_rport_enter_rtv(struct fc_rport *);
4565+static void fc_rport_enter_ready(struct fc_rport *);
4566 static void fc_rport_enter_logo(struct fc_rport *);
4567+
4568 static void fc_rport_recv_plogi_req(struct fc_rport *,
4569 struct fc_seq *, struct fc_frame *);
4570 static void fc_rport_recv_prli_req(struct fc_rport *,
4571@@ -53,9 +51,69 @@ static void fc_rport_recv_prlo_req(struct fc_rport *,
4572 static void fc_rport_recv_logo_req(struct fc_rport *,
4573 struct fc_seq *, struct fc_frame *);
4574 static void fc_rport_timeout(struct work_struct *);
4575+static void fc_rport_error(struct fc_rport *, struct fc_frame *);
4576+
4577+static const char *fc_rport_state_names[] = {
4578+ [RPORT_ST_NONE] = "None",
4579+ [RPORT_ST_INIT] = "Init",
4580+ [RPORT_ST_PLOGI] = "PLOGI",
4581+ [RPORT_ST_PRLI] = "PRLI",
4582+ [RPORT_ST_RTV] = "RTV",
4583+ [RPORT_ST_READY] = "Ready",
4584+ [RPORT_ST_LOGO] = "LOGO",
4585+};
4586+
4587+struct fc_rport *fc_rport_dummy_create(struct fc_disc_port *dp)
4588+{
4589+ struct fc_rport *rport;
4590+ struct fc_rport_libfc_priv *rdata;
4591+ rport = kzalloc(sizeof(*rport) + sizeof(*rdata), GFP_KERNEL);
4592
4593-static struct fc_rport *fc_remote_port_create(struct fc_lport *,
4594- struct fc_rport_identifiers *);
4595+ if (!rport)
4596+ return NULL;
4597+
4598+ rdata = RPORT_TO_PRIV(rport);
4599+
4600+ rport->dd_data = rdata;
4601+ rport->port_id = dp->ids.port_id;
4602+ rport->port_name = dp->ids.port_name;
4603+ rport->node_name = dp->ids.node_name;
4604+ rport->roles = dp->ids.roles;
4605+ rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
4606+
4607+ mutex_init(&rdata->rp_mutex);
4608+ rdata->local_port = dp->lp;
4609+ rdata->trans_state = FC_PORTSTATE_ROGUE;
4610+ rdata->rp_state = RPORT_ST_INIT;
4611+ rdata->event = LPORT_EV_RPORT_NONE;
4612+ rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;
4613+ rdata->event_callback = NULL;
4614+ rdata->e_d_tov = dp->lp->e_d_tov;
4615+ rdata->r_a_tov = dp->lp->r_a_tov;
4616+ INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
4617+
4618+ return rport;
4619+}
4620+
4621+void fc_rport_dummy_destroy(struct fc_rport *rport)
4622+{
4623+ kfree(rport);
4624+}
4625+
4626+/**
4627+ * fc_rport_state - return a string for the state the rport is in
4628+ * @rport: The rport whose state we want to get a string for
4629+ */
4630+static const char *fc_rport_state(struct fc_rport *rport)
4631+{
4632+ const char *cp;
4633+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
4634+
4635+ cp = fc_rport_state_names[rdata->rp_state];
4636+ if (!cp)
4637+ cp = "Unknown";
4638+ return cp;
4639+}
4640
4641 /**
4642 * fc_rport_lookup - lookup a remote port by port_id
4643@@ -82,48 +140,18 @@ struct fc_rport *fc_rport_lookup(const struct fc_lport *lp, u32 fid)
4644 }
4645
4646 /**
4647- * fc_remote_port_create - create a remote port
4648- * @lp: Fibre Channel host port instance
4649- * @ids: remote port identifiers (port_id, port_name, and node_name must be set)
4650+ * fc_set_rport_loss_tmo - Set the remote port loss timeout in seconds.
4651+ * @rport: Pointer to Fibre Channel remote port structure
4652+ * @timeout: timeout in seconds
4653 */
4654-static struct fc_rport *fc_remote_port_create(struct fc_lport *lp,
4655- struct fc_rport_identifiers *ids)
4656+void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
4657 {
4658- struct fc_rport_libfc_priv *rp;
4659- struct fc_rport *rport;
4660-
4661- rport = fc_remote_port_add(lp->host, 0, ids);
4662- if (!rport)
4663- return NULL;
4664-
4665- rp = rport->dd_data;
4666- rp->local_port = lp;
4667-
4668- /* default value until service parameters are exchanged in PLOGI */
4669- rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
4670-
4671- spin_lock_init(&rp->rp_lock);
4672- rp->rp_state = RPORT_ST_INIT;
4673- rp->local_port = lp;
4674- rp->e_d_tov = lp->e_d_tov;
4675- rp->r_a_tov = lp->r_a_tov;
4676- rp->flags = FC_RP_FLAGS_REC_SUPPORTED;
4677- INIT_DELAYED_WORK(&rp->retry_work, fc_rport_timeout);
4678-
4679- return rport;
4680-}
4681-
4682-static inline void fc_rport_lock(struct fc_rport *rport)
4683-{
4684- struct fc_rport_libfc_priv *rp = rport->dd_data;
4685- spin_lock_bh(&rp->rp_lock);
4686-}
4687-
4688-static inline void fc_rport_unlock(struct fc_rport *rport)
4689-{
4690- struct fc_rport_libfc_priv *rp = rport->dd_data;
4691- spin_unlock_bh(&rp->rp_lock);
4692+ if (timeout)
4693+ rport->dev_loss_tmo = timeout + 5;
4694+ else
4695+ rport->dev_loss_tmo = 30;
4696 }
4697+EXPORT_SYMBOL(fc_set_rport_loss_tmo);
4698
4699 /**
4700 * fc_plogi_get_maxframe - Get max payload from the common service parameters
4701@@ -150,12 +178,12 @@ fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval)
4702
4703 /**
4704 * fc_lport_plogi_fill - Fill in PLOGI command for request
4705- * @lp: Fibre Channel host port instance
4706+ * @lport: Fibre Channel host port instance
4707 * @plogi: PLOGI command structure to fill (same structure as FLOGI)
4708 * @op: either ELS_PLOGI for a localy generated request, or ELS_LS_ACC
4709 */
4710 static void
4711-fc_lport_plogi_fill(struct fc_lport *lp,
4712+fc_lport_plogi_fill(struct fc_lport *lport,
4713 struct fc_els_flogi *plogi, unsigned int op)
4714 {
4715 struct fc_els_csp *sp;
4716@@ -163,266 +191,241 @@ fc_lport_plogi_fill(struct fc_lport *lp,
4717
4718 memset(plogi, 0, sizeof(*plogi));
4719 plogi->fl_cmd = (u8) op;
4720- put_unaligned_be64(lp->wwpn, &plogi->fl_wwpn);
4721- put_unaligned_be64(lp->wwnn, &plogi->fl_wwnn);
4722+ put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn);
4723+ put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn);
4724
4725 sp = &plogi->fl_csp;
4726 sp->sp_hi_ver = 0x20;
4727 sp->sp_lo_ver = 0x20;
4728 sp->sp_bb_cred = htons(10); /* this gets set by gateway */
4729- sp->sp_bb_data = htons((u16) lp->mfs);
4730+ sp->sp_bb_data = htons((u16) lport->mfs);
4731 cp = &plogi->fl_cssp[3 - 1]; /* class 3 parameters */
4732 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
4733 if (op != ELS_FLOGI) {
4734 sp->sp_features = htons(FC_SP_FT_CIRO);
4735 sp->sp_tot_seq = htons(255); /* seq. we accept */
4736 sp->sp_rel_off = htons(0x1f);
4737- sp->sp_e_d_tov = htonl(lp->e_d_tov);
4738+ sp->sp_e_d_tov = htonl(lport->e_d_tov);
4739
4740- cp->cp_rdfs = htons((u16) lp->mfs);
4741+ cp->cp_rdfs = htons((u16) lport->mfs);
4742 cp->cp_con_seq = htons(255);
4743 cp->cp_open_seq = 1;
4744 }
4745 }
4746
4747+/**
4748+ * fc_rport_state_enter - Change the rport's state
4749+ * @rport: The rport whose state should change
4750+ * @new: The new state of the rport
4751+ *
4752+ * Locking Note: Called with the rport lock held
4753+ */
4754 static void fc_rport_state_enter(struct fc_rport *rport,
4755 enum fc_rport_state new)
4756 {
4757- struct fc_rport_libfc_priv *rp = rport->dd_data;
4758- if (rp->rp_state != new)
4759- rp->retries = 0;
4760- rp->rp_state = new;
4761+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
4762+ if (rdata->rp_state != new)
4763+ rdata->retries = 0;
4764+ rdata->rp_state = new;
4765+}
4766+
4767+static void fc_rport_unlock(struct fc_rport *rport)
4768+{
4769+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
4770+ enum fc_lport_event event = rdata->event;
4771+ struct fc_lport *lport = rdata->local_port;
4772+ u32 fid = rport->port_id;
4773+ void (*event_callback)(struct fc_lport *, u32,
4774+ enum fc_lport_event) =
4775+ rdata->event_callback;
4776+
4777+ if (event == LPORT_EV_RPORT_CREATED) {
4778+ struct fc_rport *new_rport;
4779+ struct fc_rport_libfc_priv *new_rdata;
4780+ struct fc_rport_identifiers ids;
4781+
4782+ ids.port_id = rport->port_id;
4783+ ids.roles = rport->roles;
4784+ ids.port_name = rport->port_name;
4785+ ids.node_name = rport->node_name;
4786+
4787+ new_rport = fc_remote_port_add(lport->host, 0, &ids);
4788+ if (new_rport) {
4789+ /*
4790+ * Switch from the dummy rport to the rport
4791+ * returned by the FC class.
4792+ */
4793+ new_rport->maxframe_size = rport->maxframe_size;
4794+
4795+ new_rdata = new_rport->dd_data;
4796+ new_rdata->e_d_tov = rdata->e_d_tov;
4797+ new_rdata->r_a_tov = rdata->r_a_tov;
4798+ new_rdata->event_callback = rdata->event_callback;
4799+ new_rdata->local_port = rdata->local_port;
4800+ new_rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;
4801+ new_rdata->trans_state = FC_PORTSTATE_REAL;
4802+ mutex_init(&new_rdata->rp_mutex);
4803+ INIT_DELAYED_WORK(&new_rdata->retry_work,
4804+ fc_rport_timeout);
4805+
4806+ fc_rport_state_enter(new_rport, RPORT_ST_READY);
4807+ fc_remote_port_rolechg(new_rport, rdata->roles);
4808+ } else {
4809+ FC_DBG("Failed to create the rport for port "
4810+ "(%6x).\n", ids.port_id);
4811+ event = LPORT_EV_RPORT_FAILED;
4812+ }
4813+
4814+ mutex_unlock(&rdata->rp_mutex);
4815+ fc_rport_dummy_destroy(rport);
4816+ rport = new_rport;
4817+ rdata = new_rport->dd_data;
4818+ } else if ((event == LPORT_EV_RPORT_FAILED) ||
4819+ (event == LPORT_EV_RPORT_LOGO)) {
4820+ if (rdata->trans_state == FC_PORTSTATE_ROGUE) {
4821+ mutex_unlock(&rdata->rp_mutex);
4822+ fc_rport_dummy_destroy(rport);
4823+ } else {
4824+ mutex_unlock(&rdata->rp_mutex);
4825+ fc_remote_port_delete(rport);
4826+ }
4827+ } else {
4828+ mutex_unlock(&rdata->rp_mutex);
4829+ }
4830+
4831+ if (event != LPORT_EV_RPORT_NONE && event_callback) {
4832+ event_callback(lport, fid, event);
4833+ rdata->event = LPORT_EV_RPORT_NONE;
4834+ }
4835 }
4836
4837 /**
4838 * fc_rport_login - Start the remote port login state machine
4839 * @rport: Fibre Channel remote port
4840+ *
4841+ * Locking Note: Called without the rport lock held. This
4842+ * function will hold the rport lock, call an _enter_*
4843+ * function and then unlock the rport.
4844 */
4845 int fc_rport_login(struct fc_rport *rport)
4846 {
4847- struct fc_rport_libfc_priv *rp = rport->dd_data;
4848- struct fc_lport *lp = rp->local_port;
4849+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
4850
4851- fc_rport_lock(rport);
4852- if (rp->rp_state == RPORT_ST_INIT) {
4853- fc_rport_unlock(rport);
4854- fc_rport_enter_start(rport);
4855- } else if (rp->rp_state == RPORT_ST_ERROR) {
4856- fc_rport_state_enter(rport, RPORT_ST_INIT);
4857- fc_rport_unlock(rport);
4858- if (fc_rp_debug)
4859- FC_DBG("remote %6x closed\n", rport->port_id);
4860-
4861- if (rport == lp->dns_rp &&
4862- lp->state != LPORT_ST_RESET) {
4863- fc_lport_lock(lp);
4864- del_timer(&lp->state_timer);
4865- lp->dns_rp = NULL;
4866-
4867- if (lp->state == LPORT_ST_DNS_STOP) {
4868- fc_lport_unlock(lp);
4869- lp->tt.lport_logout(lp);
4870- } else {
4871- lp->tt.lport_login(lp);
4872- fc_lport_unlock(lp);
4873- }
4874- fc_remote_port_delete(rport);
4875- }
4876- } else
4877- fc_rport_unlock(rport);
4878+ mutex_lock(&rdata->rp_mutex);
4879+
4880+ if (fc_rp_debug)
4881+ FC_DBG("Login to port (%6x)\n", rport->port_id);
4882+
4883+ fc_rport_enter_plogi(rport);
4884+
4885+ fc_rport_unlock(rport);
4886
4887 return 0;
4888 }
4889
4890-/*
4891- * Stop the session - log it off.
4892+/**
4893+ * fc_rport_logout - Logout of the remote port and delete it
4894+ * @rport: Fibre Channel remote port
4895+ *
4896+ * Locking Note: Called without the rport lock held. This
4897+ * function will hold the rport lock, call an _enter_*
4898+ * function and then unlock the rport.
4899 */
4900 int fc_rport_logout(struct fc_rport *rport)
4901 {
4902- struct fc_rport_libfc_priv *rp = rport->dd_data;
4903- struct fc_lport *lp = rp->local_port;
4904+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
4905
4906- fc_rport_lock(rport);
4907- switch (rp->rp_state) {
4908- case RPORT_ST_PRLI:
4909- case RPORT_ST_RTV:
4910- case RPORT_ST_READY:
4911- fc_rport_enter_logo(rport);
4912- fc_rport_unlock(rport);
4913- break;
4914- default:
4915- fc_rport_state_enter(rport, RPORT_ST_INIT);
4916- fc_rport_unlock(rport);
4917- if (fc_rp_debug)
4918- FC_DBG("remote %6x closed\n", rport->port_id);
4919- if (rport == lp->dns_rp &&
4920- lp->state != LPORT_ST_RESET) {
4921- fc_lport_lock(lp);
4922- del_timer(&lp->state_timer);
4923- lp->dns_rp = NULL;
4924-
4925- if (lp->state == LPORT_ST_DNS_STOP) {
4926- fc_lport_unlock(lp);
4927- lp->tt.lport_logout(lp);
4928- } else {
4929- lp->tt.lport_login(lp);
4930- fc_lport_unlock(lp);
4931- }
4932+ mutex_lock(&rdata->rp_mutex);
4933
4934- fc_remote_port_delete(rport);
4935- }
4936- break;
4937- }
4938+ if (fc_rp_debug)
4939+ FC_DBG("Logout of port (%6x)\n", rport->port_id);
4940+
4941+ fc_rport_enter_logo(rport);
4942+ fc_rport_unlock(rport);
4943
4944 return 0;
4945 }
4946
4947-/*
4948- * Reset the session - assume it is logged off. Used after fabric logoff.
4949- * The local port code takes care of resetting the exchange manager.
4950+/**
4951+ * fc_rport_reset - Reset the remote port
4952+ * @rport: Fibre Channel remote port
4953+ *
4954+ * XXX - This functionality is currently broken
4955+ *
4956+ * Locking Note: Called without the rport lock held. This
4957+ * function will hold the rport lock, call an _enter_*
4958+ * function and then unlock the rport.
4959 */
4960 void fc_rport_reset(struct fc_rport *rport)
4961 {
4962- struct fc_rport_libfc_priv *rp = rport->dd_data;
4963- struct fc_lport *lp;
4964+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
4965+
4966+ mutex_lock(&rdata->rp_mutex);
4967
4968 if (fc_rp_debug)
4969- FC_DBG("sess to %6x reset\n", rport->port_id);
4970- fc_rport_lock(rport);
4971+ FC_DBG("Reset port (%6x)\n", rport->port_id);
4972
4973- lp = rp->local_port;
4974- fc_rport_state_enter(rport, RPORT_ST_INIT);
4975- fc_rport_unlock(rport);
4976+ fc_rport_enter_plogi(rport);
4977
4978- if (fc_rp_debug)
4979- FC_DBG("remote %6x closed\n", rport->port_id);
4980- if (rport == lp->dns_rp &&
4981- lp->state != LPORT_ST_RESET) {
4982- fc_lport_lock(lp);
4983- del_timer(&lp->state_timer);
4984- lp->dns_rp = NULL;
4985- if (lp->state == LPORT_ST_DNS_STOP) {
4986- fc_lport_unlock(lp);
4987- lp->tt.lport_logout(lp);
4988- } else {
4989- lp->tt.lport_login(lp);
4990- fc_lport_unlock(lp);
4991- }
4992- fc_remote_port_delete(rport);
4993- }
4994+ fc_rport_unlock(rport);
4995 }
4996
4997-/*
4998- * Reset all sessions for a local port session list.
4999+/**
5000+ * fc_rport_reset_list - Reset all sessions for a local port session list.
5001+ * @lport: The lport whose rports should be reset
5002+ *
5003+ * Locking Note: TBD
5004 */
5005-void fc_rport_reset_list(struct fc_lport *lp)
5006+void fc_rport_reset_list(struct fc_lport *lport)
5007 {
5008- struct Scsi_Host *shost = lp->host;
5009+ struct Scsi_Host *shost = lport->host;
5010 struct fc_rport *rport;
5011 struct fc_rport *next;
5012 unsigned long flags;
5013
5014 spin_lock_irqsave(shost->host_lock, flags);
5015 list_for_each_entry_safe(rport, next, &fc_host_rports(shost), peers) {
5016- lp->tt.rport_reset(rport);
5017+ lport->tt.rport_reset(rport);
5018 }
5019 spin_unlock_irqrestore(shost->host_lock, flags);
5020 }
5021
5022-static void fc_rport_enter_start(struct fc_rport *rport)
5023+/**
5024+ * fc_rport_enter_ready - The rport is ready
5025+ * @rport: Fibre Channel remote port that is ready
5026+ *
5027+ * Locking Note: The rport lock is expected to be held before calling
5028+ * this routine.
5029+ */
5030+static void fc_rport_enter_ready(struct fc_rport *rport)
5031 {
5032- struct fc_rport_libfc_priv *rp = rport->dd_data;
5033- struct fc_lport *lp = rp->local_port;
5034+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5035
5036- /*
5037- * If the local port is already logged on, advance to next state.
5038- * Otherwise the local port will be logged on by fc_rport_unlock().
5039- */
5040- fc_rport_state_enter(rport, RPORT_ST_STARTED);
5041+ fc_rport_state_enter(rport, RPORT_ST_READY);
5042
5043- if (rport == lp->dns_rp || fc_lport_test_ready(lp))
5044- fc_rport_enter_plogi(rport);
5045-}
5046+ if (fc_rp_debug)
5047+ FC_DBG("Port (%6x) is Ready\n", rport->port_id);
5048
5049-/*
5050- * Handle exchange reject or retry exhaustion in various states.
5051- */
5052-static void fc_rport_reject(struct fc_rport *rport)
5053-{
5054- struct fc_rport_libfc_priv *rp = rport->dd_data;
5055- struct fc_lport *lp = rp->local_port;
5056- switch (rp->rp_state) {
5057- case RPORT_ST_PLOGI:
5058- case RPORT_ST_PRLI:
5059- fc_rport_state_enter(rport, RPORT_ST_ERROR);
5060- if (rport == lp->dns_rp &&
5061- lp->state != LPORT_ST_RESET) {
5062- fc_lport_lock(lp);
5063- del_timer(&lp->state_timer);
5064- lp->dns_rp = NULL;
5065- if (lp->state == LPORT_ST_DNS_STOP) {
5066- fc_lport_unlock(lp);
5067- lp->tt.lport_logout(lp);
5068- } else {
5069- lp->tt.lport_login(lp);
5070- fc_lport_unlock(lp);
5071- }
5072- fc_remote_port_delete(rport);
5073- }
5074- break;
5075- case RPORT_ST_RTV:
5076- fc_rport_state_enter(rport, RPORT_ST_READY);
5077- if (fc_rp_debug)
5078- FC_DBG("remote %6x ready\n", rport->port_id);
5079- if (rport == lp->dns_rp &&
5080- lp->state == LPORT_ST_DNS) {
5081- fc_lport_lock(lp);
5082- del_timer(&lp->state_timer);
5083- lp->tt.dns_register(lp);
5084- fc_lport_unlock(lp);
5085- }
5086- break;
5087- case RPORT_ST_LOGO:
5088- fc_rport_state_enter(rport, RPORT_ST_INIT);
5089- if (fc_rp_debug)
5090- FC_DBG("remote %6x closed\n", rport->port_id);
5091- if (rport == lp->dns_rp &&
5092- lp->state != LPORT_ST_RESET) {
5093- fc_lport_lock(lp);
5094- del_timer(&lp->state_timer);
5095- lp->dns_rp = NULL;
5096- if (lp->state == LPORT_ST_DNS_STOP) {
5097- fc_lport_unlock(lp);
5098- lp->tt.lport_logout(lp);
5099- } else {
5100- lp->tt.lport_login(lp);
5101- fc_lport_unlock(lp);
5102- }
5103- fc_remote_port_delete(rport);
5104- }
5105- break;
5106- case RPORT_ST_NONE:
5107- case RPORT_ST_READY:
5108- case RPORT_ST_ERROR:
5109- case RPORT_ST_PLOGI_RECV:
5110- case RPORT_ST_STARTED:
5111- case RPORT_ST_INIT:
5112- BUG();
5113- break;
5114- }
5115- return;
5116+ rdata->event = LPORT_EV_RPORT_CREATED;
5117 }
5118
5119-/*
5120- * Timeout handler for retrying after allocation failures or exchange timeout.
5121+/**
5122+ * fc_rport_timeout - Handler for the retry_work timer.
5123+ * @work: The work struct of the fc_rport_libfc_priv
5124+ *
5125+ * Locking Note: Called without the rport lock held. This
5126+ * function will hold the rport lock, call an _enter_*
5127+ * function and then unlock the rport.
5128 */
5129 static void fc_rport_timeout(struct work_struct *work)
5130 {
5131- struct fc_rport_libfc_priv *rp =
5132+ struct fc_rport_libfc_priv *rdata =
5133 container_of(work, struct fc_rport_libfc_priv, retry_work.work);
5134- struct fc_rport *rport = (((void *)rp) - sizeof(struct fc_rport));
5135+ struct fc_rport *rport = PRIV_TO_RPORT(rdata);
5136
5137- switch (rp->rp_state) {
5138+ mutex_lock(&rdata->rp_mutex);
5139+
5140+ switch (rdata->rp_state) {
5141 case RPORT_ST_PLOGI:
5142 fc_rport_enter_plogi(rport);
5143 break;
5144@@ -436,149 +439,178 @@ static void fc_rport_timeout(struct work_struct *work)
5145 fc_rport_enter_logo(rport);
5146 break;
5147 case RPORT_ST_READY:
5148- case RPORT_ST_ERROR:
5149 case RPORT_ST_INIT:
5150 break;
5151 case RPORT_ST_NONE:
5152- case RPORT_ST_PLOGI_RECV:
5153- case RPORT_ST_STARTED:
5154 BUG();
5155 break;
5156 }
5157 put_device(&rport->dev);
5158-}
5159-
5160-/*
5161- * Handle retry for allocation failure via timeout.
5162- */
5163-static void fc_rport_retry(struct fc_rport *rport)
5164-{
5165- struct fc_rport_libfc_priv *rp = rport->dd_data;
5166- struct fc_lport *lp = rp->local_port;
5167
5168- if (rp->retries < lp->max_retry_count) {
5169- rp->retries++;
5170- get_device(&rport->dev);
5171- schedule_delayed_work(&rp->retry_work,
5172- msecs_to_jiffies(rp->e_d_tov));
5173- } else {
5174- FC_DBG("sess %6x alloc failure in state %d, "
5175- "retries exhausted\n",
5176- rport->port_id, rp->rp_state);
5177- fc_rport_reject(rport);
5178- }
5179+ fc_rport_unlock(rport);
5180 }
5181
5182-/*
5183- * Handle error from a sequence issued by the rport state machine.
5184+/**
5185+ * fc_rport_error - Handler for any errors
5186+ * @rport: The fc_rport object
5187+ * @fp: The frame pointer
5188+ *
5189+ * If the error was caused by a resource allocation failure
5190+ * then wait for half a second and retry, otherwise retry
5191+ * immediately.
5192+ *
5193+ * Locking Note: The rport lock is expected to be held before
5194+ * calling this routine
5195 */
5196 static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
5197 {
5198- struct fc_rport_libfc_priv *rp = rport->dd_data;
5199- fc_rport_lock(rport);
5200+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5201+ unsigned long delay = 0;
5202+
5203 if (fc_rp_debug)
5204- FC_DBG("state %d error %ld retries %d\n",
5205- rp->rp_state, PTR_ERR(fp), rp->retries);
5206+ FC_DBG("Error %ld in state %s, retries %d\n",
5207+ PTR_ERR(fp), fc_rport_state(rport), rdata->retries);
5208
5209- if (PTR_ERR(fp) == -FC_EX_TIMEOUT &&
5210- rp->retries++ >= rp->local_port->max_retry_count) {
5211+ if (rdata->retries < rdata->local_port->max_retry_count) {
5212+ rdata->retries++;
5213+ if (!fp)
5214+ delay = msecs_to_jiffies(500);
5215 get_device(&rport->dev);
5216- schedule_delayed_work(&rp->retry_work, 0);
5217- } else
5218- fc_rport_reject(rport);
5219+ schedule_delayed_work(&rdata->retry_work, delay);
5220+ } else {
5221+ switch (rdata->rp_state) {
5222+ case RPORT_ST_PLOGI:
5223+ case RPORT_ST_PRLI:
5224+ case RPORT_ST_LOGO:
5225+ if (fc_rp_debug)
5226+ FC_DBG("Remote port (%6x) closed.\n",
5227+ rport->port_id);
5228
5229- fc_rport_unlock(rport);
5230+ fc_remote_port_delete(rport);
5231+
5232+ rdata->event = LPORT_EV_RPORT_FAILED;
5233+ break;
5234+ case RPORT_ST_RTV:
5235+ fc_rport_enter_ready(rport);
5236+ break;
5237+ case RPORT_ST_NONE:
5238+ case RPORT_ST_READY:
5239+ case RPORT_ST_INIT:
5240+ BUG();
5241+ break;
5242+ }
5243+ }
5244 }
5245
5246 /**
5247- * fc_rport_plpogi_recv_resp - Handle incoming ELS PLOGI response
5248+ * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response
5249 * @sp: current sequence in the PLOGI exchange
5250 * @fp: response frame
5251 * @rp_arg: Fibre Channel remote port
5252+ *
5253+ * Locking Note: This function will be called without the rport lock
5254+ * held, but it will lock, call an _enter_* function or fc_rport_error
5255+ * and then unlock the rport.
5256 */
5257 static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
5258 void *rp_arg)
5259 {
5260- struct fc_els_ls_rjt *rjp;
5261+ struct fc_rport *rport = rp_arg;
5262+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5263+ struct fc_lport *lport = rdata->local_port;
5264 struct fc_els_flogi *plp;
5265- u64 wwpn, wwnn;
5266 unsigned int tov;
5267 u16 csp_seq;
5268 u16 cssp_seq;
5269 u8 op;
5270- struct fc_rport *rport = rp_arg;
5271- struct fc_rport_libfc_priv *rp = rport->dd_data;
5272
5273- if (!IS_ERR(fp)) {
5274- op = fc_frame_payload_op(fp);
5275- fc_rport_lock(rport);
5276- if (op == ELS_LS_ACC &&
5277- (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
5278- wwpn = get_unaligned_be64(&plp->fl_wwpn);
5279- wwnn = get_unaligned_be64(&plp->fl_wwnn);
5280+ mutex_lock(&rdata->rp_mutex);
5281
5282- fc_rport_set_name(rport, wwpn, wwnn);
5283- tov = ntohl(plp->fl_csp.sp_e_d_tov);
5284- if (ntohs(plp->fl_csp.sp_features) & FC_SP_FT_EDTR)
5285- tov /= 1000;
5286- if (tov > rp->e_d_tov)
5287- rp->e_d_tov = tov;
5288- csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
5289- cssp_seq = ntohs(plp->fl_cssp[3 - 1].cp_con_seq);
5290- if (cssp_seq < csp_seq)
5291- csp_seq = cssp_seq;
5292- rp->max_seq = csp_seq;
5293- rport->maxframe_size =
5294- fc_plogi_get_maxframe(plp, rp->local_port->mfs);
5295- if (rp->rp_state == RPORT_ST_PLOGI)
5296- fc_rport_enter_prli(rport);
5297- } else {
5298- if (fc_rp_debug)
5299- FC_DBG("bad PLOGI response\n");
5300-
5301- rjp = fc_frame_payload_get(fp, sizeof(*rjp));
5302- if (op == ELS_LS_RJT && rjp != NULL &&
5303- rjp->er_reason == ELS_RJT_INPROG)
5304- fc_rport_retry(rport); /* try again */
5305- else
5306- fc_rport_reject(rport); /* error */
5307- }
5308- fc_rport_unlock(rport);
5309- fc_frame_free(fp);
5310- } else {
5311+ if (fc_rp_debug)
5312+ FC_DBG("Received a PLOGI response\n");
5313+
5314+ if (rdata->rp_state != RPORT_ST_PLOGI) {
5315+ FC_DBG("Received a PLOGI response, but in state %s\n",
5316+ fc_rport_state(rport));
5317+ goto out;
5318+ }
5319+
5320+ if (IS_ERR(fp)) {
5321 fc_rport_error(rport, fp);
5322+ goto out;
5323 }
5324+
5325+ op = fc_frame_payload_op(fp);
5326+ if (op == ELS_LS_ACC &&
5327+ (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
5328+ tov = ntohl(plp->fl_csp.sp_e_d_tov);
5329+ if (ntohs(plp->fl_csp.sp_features) & FC_SP_FT_EDTR)
5330+ tov /= 1000;
5331+ if (tov > rdata->e_d_tov)
5332+ rdata->e_d_tov = tov;
5333+ csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
5334+ cssp_seq = ntohs(plp->fl_cssp[3 - 1].cp_con_seq);
5335+ if (cssp_seq < csp_seq)
5336+ csp_seq = cssp_seq;
5337+ rdata->max_seq = csp_seq;
5338+ rport->maxframe_size =
5339+ fc_plogi_get_maxframe(plp, lport->mfs);
5340+
5341+ /*
5342+ * If the rport is one of the well known addresses
5343+ * we skip PRLI and RTV and go straight to READY.
5344+ */
5345+ if (rport->port_id >= FC_FID_DOM_MGR)
5346+ fc_rport_enter_ready(rport);
5347+ else
5348+ fc_rport_enter_prli(rport);
5349+ } else
5350+ fc_rport_error(rport, fp);
5351+
5352+out:
5353+ fc_rport_unlock(rport);
5354+ fc_frame_free(fp);
5355 }
5356
5357 /**
5358 * fc_rport_enter_plogi - Send Port Login (PLOGI) request to peer
5359 * @rport: Fibre Channel remote port to send PLOGI to
5360+ *
5361+ * Locking Note: The rport lock is expected to be held before calling
5362+ * this routine.
5363 */
5364 static void fc_rport_enter_plogi(struct fc_rport *rport)
5365 {
5366+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5367+ struct fc_lport *lport = rdata->local_port;
5368 struct fc_frame *fp;
5369 struct fc_els_flogi *plogi;
5370- struct fc_lport *lp;
5371- struct fc_rport_libfc_priv *rp = rport->dd_data;
5372
5373- lp = rp->local_port;
5374+ if (fc_rp_debug)
5375+ FC_DBG("Port (%6x) entered PLOGI state from %s state\n",
5376+ rport->port_id, fc_rport_state(rport));
5377+
5378 fc_rport_state_enter(rport, RPORT_ST_PLOGI);
5379+
5380 rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
5381- fp = fc_frame_alloc(lp, sizeof(*plogi));
5382- if (!fp)
5383- return fc_rport_retry(rport);
5384+ fp = fc_frame_alloc(lport, sizeof(*plogi));
5385+ if (!fp) {
5386+ fc_rport_error(rport, fp);
5387+ return;
5388+ }
5389+
5390 plogi = fc_frame_payload_get(fp, sizeof(*plogi));
5391- WARN_ON(!plogi);
5392- fc_lport_plogi_fill(rp->local_port, plogi, ELS_PLOGI);
5393- rp->e_d_tov = lp->e_d_tov;
5394+ fc_lport_plogi_fill(rdata->local_port, plogi, ELS_PLOGI);
5395+ rdata->e_d_tov = lport->e_d_tov;
5396 fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
5397- if (!lp->tt.exch_seq_send(lp, fp,
5398- fc_rport_plogi_resp,
5399- rport, lp->e_d_tov,
5400- rp->local_port->fid,
5401- rport->port_id,
5402- FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5403- fc_rport_retry(rport);
5404+
5405+ if (!lport->tt.exch_seq_send(lport, fp,
5406+ fc_rport_plogi_resp, NULL,
5407+ rport, lport->e_d_tov,
5408+ rdata->local_port->fid,
5409+ rport->port_id,
5410+ FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5411+ fc_rport_error(rport, fp);
5412 }
5413
5414 /**
5415@@ -586,13 +618,16 @@ static void fc_rport_enter_plogi(struct fc_rport *rport)
5416 * @sp: current sequence in the PRLI exchange
5417 * @fp: response frame
5418 * @rp_arg: Fibre Channel remote port
5419+ *
5420+ * Locking Note: This function will be called without the rport lock
5421+ * held, but it will lock, call an _enter_* function or fc_rport_error
5422+ * and then unlock the rport.
5423 */
5424 static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
5425 void *rp_arg)
5426 {
5427 struct fc_rport *rport = rp_arg;
5428- struct fc_rport_libfc_priv *rp = rport->dd_data;
5429- struct fc_lport *lp = rp->local_port;
5430+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5431 struct {
5432 struct fc_els_prli prli;
5433 struct fc_els_spp spp;
5434@@ -601,19 +636,29 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
5435 u32 fcp_parm = 0;
5436 u8 op;
5437
5438+ mutex_lock(&rdata->rp_mutex);
5439+
5440+ if (fc_rp_debug)
5441+ FC_DBG("Received a PRLI response\n");
5442+
5443+ if (rdata->rp_state != RPORT_ST_PRLI) {
5444+ FC_DBG("Received a PRLI response, but in state %s\n",
5445+ fc_rport_state(rport));
5446+ goto out;
5447+ }
5448+
5449 if (IS_ERR(fp)) {
5450 fc_rport_error(rport, fp);
5451- return;
5452+ goto out;
5453 }
5454
5455- fc_rport_lock(rport);
5456 op = fc_frame_payload_op(fp);
5457 if (op == ELS_LS_ACC) {
5458 pp = fc_frame_payload_get(fp, sizeof(*pp));
5459 if (pp && pp->prli.prli_spp_len >= sizeof(pp->spp)) {
5460 fcp_parm = ntohl(pp->spp.spp_params);
5461 if (fcp_parm & FCP_SPPF_RETRY)
5462- rp->flags |= FC_RP_FLAGS_RETRY;
5463+ rdata->flags |= FC_RP_FLAGS_RETRY;
5464 }
5465
5466 rport->supported_classes = FC_COS_CLASS3;
5467@@ -622,28 +667,17 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
5468 if (fcp_parm & FCP_SPPF_TARG_FCN)
5469 roles |= FC_RPORT_ROLE_FCP_TARGET;
5470
5471+ rdata->roles = roles;
5472 fc_rport_enter_rtv(rport);
5473- fc_rport_unlock(rport);
5474- fc_remote_port_rolechg(rport, roles);
5475+
5476 } else {
5477- FC_DBG("bad ELS response\n");
5478- fc_rport_state_enter(rport, RPORT_ST_ERROR);
5479- fc_rport_unlock(rport);
5480- if (rport == lp->dns_rp && lp->state != LPORT_ST_RESET) {
5481- fc_lport_lock(lp);
5482- del_timer(&lp->state_timer);
5483- lp->dns_rp = NULL;
5484- if (lp->state == LPORT_ST_DNS_STOP) {
5485- fc_lport_unlock(lp);
5486- lp->tt.lport_logout(lp);
5487- } else {
5488- lp->tt.lport_login(lp);
5489- fc_lport_unlock(lp);
5490- }
5491- fc_remote_port_delete(rport);
5492- }
5493+ FC_DBG("Bad ELS response\n");
5494+ rdata->event = LPORT_EV_RPORT_FAILED;
5495+ fc_remote_port_delete(rport);
5496 }
5497
5498+out:
5499+ fc_rport_unlock(rport);
5500 fc_frame_free(fp);
5501 }
5502
5503@@ -652,101 +686,94 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
5504 * @sp: current sequence in the LOGO exchange
5505 * @fp: response frame
5506 * @rp_arg: Fibre Channel remote port
5507+ *
5508+ * Locking Note: This function will be called without the rport lock
5509+ * held, but it will lock, call an _enter_* function or fc_rport_error
5510+ * and then unlock the rport.
5511 */
5512 static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
5513 void *rp_arg)
5514 {
5515 struct fc_rport *rport = rp_arg;
5516- struct fc_rport_libfc_priv *rp = rport->dd_data;
5517- struct fc_lport *lp = rp->local_port;
5518+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5519 u8 op;
5520
5521+ mutex_lock(&rdata->rp_mutex);
5522+
5523+ if (fc_rp_debug)
5524+ FC_DBG("Received a LOGO response\n");
5525+
5526+ if (rdata->rp_state != RPORT_ST_LOGO) {
5527+ FC_DBG("Received a LOGO response, but in state %s\n",
5528+ fc_rport_state(rport));
5529+ goto out;
5530+ }
5531+
5532 if (IS_ERR(fp)) {
5533 fc_rport_error(rport, fp);
5534- return;
5535+ goto out;
5536 }
5537
5538- fc_rport_lock(rport);
5539 op = fc_frame_payload_op(fp);
5540 if (op == ELS_LS_ACC) {
5541 fc_rport_enter_rtv(rport);
5542- fc_rport_unlock(rport);
5543+
5544 } else {
5545- FC_DBG("bad ELS response\n");
5546- fc_rport_state_enter(rport, RPORT_ST_ERROR);
5547- fc_rport_unlock(rport);
5548- if (rport == lp->dns_rp && lp->state != LPORT_ST_RESET) {
5549- fc_lport_lock(lp);
5550- del_timer(&lp->state_timer);
5551- lp->dns_rp = NULL;
5552- if (lp->state == LPORT_ST_DNS_STOP) {
5553- fc_lport_unlock(lp);
5554- lp->tt.lport_logout(lp);
5555- } else {
5556- lp->tt.lport_login(lp);
5557- fc_lport_unlock(lp);
5558- }
5559- fc_remote_port_delete(rport);
5560- }
5561+ FC_DBG("Bad ELS response\n");
5562+ rdata->event = LPORT_EV_RPORT_LOGO;
5563+ fc_remote_port_delete(rport);
5564 }
5565
5566+out:
5567+ fc_rport_unlock(rport);
5568 fc_frame_free(fp);
5569 }
5570
5571 /**
5572 * fc_rport_enter_prli - Send Process Login (PRLI) request to peer
5573 * @rport: Fibre Channel remote port to send PRLI to
5574+ *
5575+ * Locking Note: The rport lock is expected to be held before calling
5576+ * this routine.
5577 */
5578 static void fc_rport_enter_prli(struct fc_rport *rport)
5579 {
5580+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5581+ struct fc_lport *lport = rdata->local_port;
5582 struct {
5583 struct fc_els_prli prli;
5584 struct fc_els_spp spp;
5585 } *pp;
5586 struct fc_frame *fp;
5587- struct fc_rport_libfc_priv *rp = rport->dd_data;
5588- struct fc_lport *lp = rp->local_port;
5589+
5590+ if (fc_rp_debug)
5591+ FC_DBG("Port (%6x) entered PRLI state from %s state\n",
5592+ rport->port_id, fc_rport_state(rport));
5593
5594 fc_rport_state_enter(rport, RPORT_ST_PRLI);
5595
5596- /*
5597- * Special case if session is for name server or any other
5598- * well-known address: Skip the PRLI step.
5599- * This should be made more general, possibly moved to the FCP layer.
5600- */
5601- if (rport->port_id >= FC_FID_DOM_MGR) {
5602- fc_rport_state_enter(rport, RPORT_ST_READY);
5603- if (fc_rp_debug)
5604- FC_DBG("remote %6x ready\n", rport->port_id);
5605- if (rport == lp->dns_rp &&
5606- lp->state == LPORT_ST_DNS) {
5607- fc_lport_lock(lp);
5608- del_timer(&lp->state_timer);
5609- lp->tt.dns_register(lp);
5610- fc_lport_unlock(lp);
5611- }
5612+ fp = fc_frame_alloc(lport, sizeof(*pp));
5613+ if (!fp) {
5614+ fc_rport_error(rport, fp);
5615 return;
5616 }
5617- fp = fc_frame_alloc(lp, sizeof(*pp));
5618- if (!fp)
5619- return fc_rport_retry(rport);
5620+
5621 pp = fc_frame_payload_get(fp, sizeof(*pp));
5622- WARN_ON(!pp);
5623 memset(pp, 0, sizeof(*pp));
5624 pp->prli.prli_cmd = ELS_PRLI;
5625 pp->prli.prli_spp_len = sizeof(struct fc_els_spp);
5626 pp->prli.prli_len = htons(sizeof(*pp));
5627 pp->spp.spp_type = FC_TYPE_FCP;
5628 pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR;
5629- pp->spp.spp_params = htonl(rp->local_port->service_params);
5630+ pp->spp.spp_params = htonl(lport->service_params);
5631 fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
5632- if (!lp->tt.exch_seq_send(lp, fp,
5633- fc_rport_prli_resp,
5634- rport, lp->e_d_tov,
5635- rp->local_port->fid,
5636- rport->port_id,
5637- FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5638- fc_rport_retry(rport);
5639+
5640+ if (!lport->tt.exch_seq_send(lport, fp,
5641+ fc_rport_prli_resp, NULL,
5642+ rport, lport->e_d_tov,
5643+ lport->fid, rport->port_id,
5644+ FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5645+ fc_rport_error(rport, fp);
5646 }
5647
5648 /**
5649@@ -756,21 +783,34 @@ static void fc_rport_enter_prli(struct fc_rport *rport)
5650 * @rp_arg: Fibre Channel remote port
5651 *
5652 * Many targets don't seem to support this.
5653+ *
5654+ * Locking Note: This function will be called without the rport lock
5655+ * held, but it will lock, call an _enter_* function or fc_rport_error
5656+ * and then unlock the rport.
5657 */
5658 static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
5659 void *rp_arg)
5660 {
5661 struct fc_rport *rport = rp_arg;
5662- struct fc_rport_libfc_priv *rp = rport->dd_data;
5663- struct fc_lport *lp = rp->local_port;
5664+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5665 u8 op;
5666
5667+ mutex_lock(&rdata->rp_mutex);
5668+
5669+ if (fc_rp_debug)
5670+ FC_DBG("Received a RTV response\n");
5671+
5672+ if (rdata->rp_state != RPORT_ST_RTV) {
5673+ FC_DBG("Received a RTV response, but in state %s\n",
5674+ fc_rport_state(rport));
5675+ goto out;
5676+ }
5677+
5678 if (IS_ERR(fp)) {
5679 fc_rport_error(rport, fp);
5680- return;
5681+ goto out;
5682 }
5683
5684- fc_rport_lock(rport);
5685 op = fc_frame_payload_op(fp);
5686 if (op == ELS_LS_ACC) {
5687 struct fc_els_rtv_acc *rtv;
5688@@ -783,107 +823,126 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
5689 tov = ntohl(rtv->rtv_r_a_tov);
5690 if (tov == 0)
5691 tov = 1;
5692- rp->r_a_tov = tov;
5693+ rdata->r_a_tov = tov;
5694 tov = ntohl(rtv->rtv_e_d_tov);
5695 if (toq & FC_ELS_RTV_EDRES)
5696 tov /= 1000000;
5697 if (tov == 0)
5698 tov = 1;
5699- rp->e_d_tov = tov;
5700+ rdata->e_d_tov = tov;
5701 }
5702 }
5703- fc_rport_state_enter(rport, RPORT_ST_READY);
5704+
5705+ fc_rport_enter_ready(rport);
5706+
5707+out:
5708 fc_rport_unlock(rport);
5709- if (fc_rp_debug)
5710- FC_DBG("remote %6x ready\n", rport->port_id);
5711- if (rport == lp->dns_rp &&
5712- lp->state == LPORT_ST_DNS) {
5713- fc_lport_lock(lp);
5714- del_timer(&lp->state_timer);
5715- lp->tt.dns_register(lp);
5716- fc_lport_unlock(lp);
5717- }
5718 fc_frame_free(fp);
5719 }
5720
5721 /**
5722 * fc_rport_enter_rtv - Send Request Timeout Value (RTV) request to peer
5723 * @rport: Fibre Channel remote port to send RTV to
5724+ *
5725+ * Locking Note: The rport lock is expected to be held before calling
5726+ * this routine.
5727 */
5728 static void fc_rport_enter_rtv(struct fc_rport *rport)
5729 {
5730 struct fc_els_rtv *rtv;
5731 struct fc_frame *fp;
5732- struct fc_lport *lp;
5733- struct fc_rport_libfc_priv *rp = rport->dd_data;
5734+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5735+ struct fc_lport *lport = rdata->local_port;
5736+
5737+ if (fc_rp_debug)
5738+ FC_DBG("Port (%6x) entered RTV state from %s state\n",
5739+ rport->port_id, fc_rport_state(rport));
5740
5741- lp = rp->local_port;
5742 fc_rport_state_enter(rport, RPORT_ST_RTV);
5743
5744- fp = fc_frame_alloc(lp, sizeof(*rtv));
5745- if (!fp)
5746- return fc_rport_retry(rport);
5747+ fp = fc_frame_alloc(lport, sizeof(*rtv));
5748+ if (!fp) {
5749+ fc_rport_error(rport, fp);
5750+ return;
5751+ }
5752+
5753 rtv = fc_frame_payload_get(fp, sizeof(*rtv));
5754- WARN_ON(!rtv);
5755 memset(rtv, 0, sizeof(*rtv));
5756 rtv->rtv_cmd = ELS_RTV;
5757 fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
5758- if (!lp->tt.exch_seq_send(lp, fp,
5759- fc_rport_rtv_resp,
5760- rport, lp->e_d_tov,
5761- rp->local_port->fid,
5762- rport->port_id,
5763- FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5764- fc_rport_retry(rport);
5765+
5766+ if (!lport->tt.exch_seq_send(lport, fp,
5767+ fc_rport_rtv_resp, NULL,
5768+ rport, lport->e_d_tov,
5769+ lport->fid, rport->port_id,
5770+ FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5771+ fc_rport_error(rport, fp);
5772 }
5773
5774 /**
5775 * fc_rport_enter_logo - Send Logout (LOGO) request to peer
5776 * @rport: Fibre Channel remote port to send LOGO to
5777+ *
5778+ * Locking Note: The rport lock is expected to be held before calling
5779+ * this routine.
5780 */
5781 static void fc_rport_enter_logo(struct fc_rport *rport)
5782 {
5783+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5784+ struct fc_lport *lport = rdata->local_port;
5785 struct fc_frame *fp;
5786 struct fc_els_logo *logo;
5787- struct fc_lport *lp;
5788- struct fc_rport_libfc_priv *rp = rport->dd_data;
5789+
5790+ if (fc_rp_debug)
5791+ FC_DBG("Port (%6x) entered LOGO state from %s state\n",
5792+ rport->port_id, fc_rport_state(rport));
5793
5794 fc_rport_state_enter(rport, RPORT_ST_LOGO);
5795
5796- lp = rp->local_port;
5797- fp = fc_frame_alloc(lp, sizeof(*logo));
5798- if (!fp)
5799- return fc_rport_retry(rport);
5800+ fp = fc_frame_alloc(lport, sizeof(*logo));
5801+ if (!fp) {
5802+ fc_rport_error(rport, fp);
5803+ return;
5804+ }
5805+
5806 logo = fc_frame_payload_get(fp, sizeof(*logo));
5807 memset(logo, 0, sizeof(*logo));
5808 logo->fl_cmd = ELS_LOGO;
5809- hton24(logo->fl_n_port_id, lp->fid);
5810- logo->fl_n_port_wwn = htonll(lp->wwpn);
5811-
5812+ hton24(logo->fl_n_port_id, lport->fid);
5813+ logo->fl_n_port_wwn = htonll(lport->wwpn);
5814 fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
5815- if (!lp->tt.exch_seq_send(lp, fp,
5816- fc_rport_logo_resp,
5817- rport, lp->e_d_tov,
5818- rp->local_port->fid,
5819- rport->port_id,
5820- FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5821- fc_rport_retry(rport);
5822+
5823+ if (!lport->tt.exch_seq_send(lport, fp,
5824+ fc_rport_logo_resp, NULL,
5825+ rport, lport->e_d_tov,
5826+ lport->fid, rport->port_id,
5827+ FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5828+ fc_rport_error(rport, fp);
5829 }
5830
5831-/*
5832- * Handle a request received by the exchange manager for the session.
5833- * This may be an entirely new session, or a PLOGI or LOGO for an existing one.
5834- * This will free the frame.
5835+
5836+/**
5837+ * fc_rport_recv_req - Receive a request from a rport
5838+ * @sp: current sequence in the PLOGI exchange
5839+ * @fp: response frame
5840+ * @rp_arg: Fibre Channel remote port
5841+ *
5842+ * Locking Note: Called without the rport lock held. This
5843+ * function will hold the rport lock, call an _enter_*
5844+ * function and then unlock the rport.
5845 */
5846 void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
5847 struct fc_rport *rport)
5848 {
5849- struct fc_rport_libfc_priv *rp = rport->dd_data;
5850+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5851+ struct fc_lport *lport = rdata->local_port;
5852+
5853 struct fc_frame_header *fh;
5854- struct fc_lport *lp = rp->local_port;
5855 struct fc_seq_els_data els_data;
5856 u8 op;
5857
5858+ mutex_lock(&rdata->rp_mutex);
5859+
5860 els_data.fp = NULL;
5861 els_data.explan = ELS_EXPL_NONE;
5862 els_data.reason = ELS_RJT_NONE;
5863@@ -907,21 +966,21 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
5864 break;
5865 case ELS_RRQ:
5866 els_data.fp = fp;
5867- lp->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
5868+ lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
5869 break;
5870 case ELS_REC:
5871 els_data.fp = fp;
5872- lp->tt.seq_els_rsp_send(sp, ELS_REC, &els_data);
5873+ lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data);
5874 break;
5875 default:
5876 els_data.reason = ELS_RJT_UNSUP;
5877- lp->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
5878- fc_frame_free(fp);
5879+ lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
5880 break;
5881 }
5882- } else {
5883- fc_frame_free(fp);
5884 }
5885+
5886+ fc_rport_unlock(rport);
5887+ fc_frame_free(fp);
5888 }
5889
5890 /**
5891@@ -929,14 +988,18 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
5892 * @rport: Fibre Channel remote port that initiated PLOGI
5893 * @sp: current sequence in the PLOGI exchange
5894 * @fp: PLOGI request frame
5895+ *
5896+ * Locking Note: The rport lock is exected to be held before calling
5897+ * this function.
5898 */
5899 static void fc_rport_recv_plogi_req(struct fc_rport *rport,
5900 struct fc_seq *sp, struct fc_frame *rx_fp)
5901 {
5902- struct fc_rport_libfc_priv *rp = rport->dd_data;
5903+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
5904+ struct fc_lport *lport = rdata->local_port;
5905 struct fc_frame *fp = rx_fp;
5906+
5907 struct fc_frame_header *fh;
5908- struct fc_lport *lp;
5909 struct fc_els_flogi *pl;
5910 struct fc_seq_els_data rjt_data;
5911 u32 sid;
5912@@ -944,9 +1007,15 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
5913 u64 wwnn;
5914 enum fc_els_rjt_reason reject = 0;
5915 u32 f_ctl;
5916-
5917 rjt_data.fp = NULL;
5918+
5919 fh = fc_frame_header_get(fp);
5920+
5921+ if (fc_rp_debug)
5922+ FC_DBG("Received PLOGI request from port (%6x) "
5923+ "while in state %s\n", ntoh24(fh->fh_s_id),
5924+ fc_rport_state(rport));
5925+
5926 sid = ntoh24(fh->fh_s_id);
5927 pl = fc_frame_payload_get(fp, sizeof(*pl));
5928 if (!pl) {
5929@@ -958,8 +1027,6 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
5930 }
5931 wwpn = get_unaligned_be64(&pl->fl_wwpn);
5932 wwnn = get_unaligned_be64(&pl->fl_wwnn);
5933- fc_rport_lock(rport);
5934- lp = rp->local_port;
5935
5936 /*
5937 * If the session was just created, possibly due to the incoming PLOGI,
5938@@ -972,63 +1039,50 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
5939 * XXX TBD: If the session was ready before, the PLOGI should result in
5940 * all outstanding exchanges being reset.
5941 */
5942- switch (rp->rp_state) {
5943+ switch (rdata->rp_state) {
5944 case RPORT_ST_INIT:
5945 if (fc_rp_debug)
5946 FC_DBG("incoming PLOGI from %6x wwpn %llx state INIT "
5947 "- reject\n", sid, wwpn);
5948 reject = ELS_RJT_UNSUP;
5949 break;
5950- case RPORT_ST_STARTED:
5951- /*
5952- * we'll only accept a login if the port name
5953- * matches or was unknown.
5954- */
5955- if (rport->port_name != -1 &&
5956- rport->port_name != wwpn) {
5957- FC_DBG("incoming PLOGI from name %llx expected %llx\n",
5958- wwpn, rport->port_name);
5959- reject = ELS_RJT_UNAB;
5960- }
5961- break;
5962 case RPORT_ST_PLOGI:
5963 if (fc_rp_debug)
5964 FC_DBG("incoming PLOGI from %x in PLOGI state %d\n",
5965- sid, rp->rp_state);
5966- if (wwpn < lp->wwpn)
5967+ sid, rdata->rp_state);
5968+ if (wwpn < lport->wwpn)
5969 reject = ELS_RJT_INPROG;
5970 break;
5971 case RPORT_ST_PRLI:
5972- case RPORT_ST_ERROR:
5973 case RPORT_ST_READY:
5974 if (fc_rp_debug)
5975 FC_DBG("incoming PLOGI from %x in logged-in state %d "
5976- "- ignored for now\n", sid, rp->rp_state);
5977+ "- ignored for now\n", sid, rdata->rp_state);
5978 /* XXX TBD - should reset */
5979 break;
5980 case RPORT_ST_NONE:
5981 default:
5982 if (fc_rp_debug)
5983 FC_DBG("incoming PLOGI from %x in unexpected "
5984- "state %d\n", sid, rp->rp_state);
5985+ "state %d\n", sid, rdata->rp_state);
5986 break;
5987 }
5988
5989 if (reject) {
5990 rjt_data.reason = reject;
5991 rjt_data.explan = ELS_EXPL_NONE;
5992- lp->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
5993+ lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
5994 fc_frame_free(fp);
5995 } else {
5996- fp = fc_frame_alloc(lp, sizeof(*pl));
5997+ fp = fc_frame_alloc(lport, sizeof(*pl));
5998 if (fp == NULL) {
5999 fp = rx_fp;
6000 rjt_data.reason = ELS_RJT_UNAB;
6001 rjt_data.explan = ELS_EXPL_NONE;
6002- lp->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
6003+ lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
6004 fc_frame_free(fp);
6005 } else {
6006- sp = lp->tt.seq_start_next(sp);
6007+ sp = lport->tt.seq_start_next(sp);
6008 WARN_ON(!sp);
6009 fc_rport_set_name(rport, wwpn, wwnn);
6010
6011@@ -1036,11 +1090,11 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
6012 * Get session payload size from incoming PLOGI.
6013 */
6014 rport->maxframe_size =
6015- fc_plogi_get_maxframe(pl, lp->mfs);
6016+ fc_plogi_get_maxframe(pl, lport->mfs);
6017 fc_frame_free(rx_fp);
6018 pl = fc_frame_payload_get(fp, sizeof(*pl));
6019 WARN_ON(!pl);
6020- fc_lport_plogi_fill(lp, pl, ELS_LS_ACC);
6021+ fc_lport_plogi_fill(lport, pl, ELS_LS_ACC);
6022
6023 /*
6024 * Send LS_ACC. If this fails,
6025@@ -1048,15 +1102,11 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
6026 */
6027 f_ctl = FC_FC_SEQ_INIT | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
6028 fc_frame_setup(fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
6029- lp->tt.seq_send(lp, sp, fp, f_ctl);
6030- if (rp->rp_state == RPORT_ST_PLOGI)
6031+ lport->tt.seq_send(lport, sp, fp, f_ctl);
6032+ if (rdata->rp_state == RPORT_ST_PLOGI)
6033 fc_rport_enter_prli(rport);
6034- else
6035- fc_rport_state_enter(rport,
6036- RPORT_ST_PLOGI_RECV);
6037 }
6038 }
6039- fc_rport_unlock(rport);
6040 }
6041
6042 /**
6043@@ -1064,14 +1114,18 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
6044 * @rport: Fibre Channel remote port that initiated PRLI
6045 * @sp: current sequence in the PRLI exchange
6046 * @fp: PRLI request frame
6047+ *
6048+ * Locking Note: The rport lock is exected to be held before calling
6049+ * this function.
6050 */
6051 static void fc_rport_recv_prli_req(struct fc_rport *rport,
6052 struct fc_seq *sp, struct fc_frame *rx_fp)
6053 {
6054- struct fc_rport_libfc_priv *rp = rport->dd_data;
6055+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
6056+ struct fc_lport *lport = rdata->local_port;
6057+
6058 struct fc_frame *fp;
6059 struct fc_frame_header *fh;
6060- struct fc_lport *lp;
6061 struct {
6062 struct fc_els_prli prli;
6063 struct fc_els_spp spp;
6064@@ -1087,12 +1141,16 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
6065 u32 f_ctl;
6066 u32 fcp_parm;
6067 u32 roles = FC_RPORT_ROLE_UNKNOWN;
6068-
6069 rjt_data.fp = NULL;
6070+
6071 fh = fc_frame_header_get(rx_fp);
6072- lp = rp->local_port;
6073- switch (rp->rp_state) {
6074- case RPORT_ST_PLOGI_RECV:
6075+
6076+ if (fc_rp_debug)
6077+ FC_DBG("Received PRLI request from port (%6x) "
6078+ "while in state %s\n", ntoh24(fh->fh_s_id),
6079+ fc_rport_state(rport));
6080+
6081+ switch (rdata->rp_state) {
6082 case RPORT_ST_PRLI:
6083 case RPORT_ST_READY:
6084 reason = ELS_RJT_NONE;
6085@@ -1122,12 +1180,12 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
6086 rspp = &pp->spp;
6087 }
6088 if (reason != ELS_RJT_NONE ||
6089- (fp = fc_frame_alloc(lp, len)) == NULL) {
6090+ (fp = fc_frame_alloc(lport, len)) == NULL) {
6091 rjt_data.reason = reason;
6092 rjt_data.explan = explan;
6093- lp->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
6094+ lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
6095 } else {
6096- sp = lp->tt.seq_start_next(sp);
6097+ sp = lport->tt.seq_start_next(sp);
6098 WARN_ON(!sp);
6099 pp = fc_frame_payload_get(fp, len);
6100 WARN_ON(!pp);
6101@@ -1156,15 +1214,16 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
6102 case FC_TYPE_FCP:
6103 fcp_parm = ntohl(rspp->spp_params);
6104 if (fcp_parm * FCP_SPPF_RETRY)
6105- rp->flags |= FC_RP_FLAGS_RETRY;
6106+ rdata->flags |= FC_RP_FLAGS_RETRY;
6107 rport->supported_classes = FC_COS_CLASS3;
6108 if (fcp_parm & FCP_SPPF_INIT_FCN)
6109 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
6110 if (fcp_parm & FCP_SPPF_TARG_FCN)
6111 roles |= FC_RPORT_ROLE_FCP_TARGET;
6112- fc_remote_port_rolechg(rport, roles);
6113+ rdata->roles = roles;
6114+
6115 spp->spp_params =
6116- htonl(rp->local_port->service_params);
6117+ htonl(lport->service_params);
6118 break;
6119 default:
6120 resp = FC_SPP_RESP_INVL;
6121@@ -1181,32 +1240,20 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
6122 */
6123 f_ctl = FC_FC_SEQ_INIT | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
6124 fc_frame_setup(fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
6125- lp->tt.seq_send(lp, sp, fp, f_ctl);
6126+ lport->tt.seq_send(lport, sp, fp, f_ctl);
6127
6128 /*
6129 * Get lock and re-check state.
6130 */
6131- fc_rport_lock(rport);
6132- switch (rp->rp_state) {
6133- case RPORT_ST_PLOGI_RECV:
6134+ switch (rdata->rp_state) {
6135 case RPORT_ST_PRLI:
6136- fc_rport_state_enter(rport, RPORT_ST_READY);
6137- if (fc_rp_debug)
6138- FC_DBG("remote %6x ready\n", rport->port_id);
6139- if (rport == lp->dns_rp &&
6140- lp->state == LPORT_ST_DNS) {
6141- fc_lport_lock(lp);
6142- del_timer(&lp->state_timer);
6143- lp->tt.dns_register(lp);
6144- fc_lport_unlock(lp);
6145- }
6146+ fc_rport_enter_ready(rport);
6147 break;
6148 case RPORT_ST_READY:
6149 break;
6150 default:
6151 break;
6152 }
6153- fc_rport_unlock(rport);
6154 }
6155 fc_frame_free(rx_fp);
6156 }
6157@@ -1216,22 +1263,30 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
6158 * @rport: Fibre Channel remote port that initiated PRLO
6159 * @sp: current sequence in the PRLO exchange
6160 * @fp: PRLO request frame
6161+ *
6162+ * Locking Note: The rport lock is exected to be held before calling
6163+ * this function.
6164 */
6165 static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
6166 struct fc_frame *fp)
6167 {
6168- struct fc_rport_libfc_priv *rp = rport->dd_data;
6169+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
6170+ struct fc_lport *lport = rdata->local_port;
6171+
6172 struct fc_frame_header *fh;
6173- struct fc_lport *lp = rp->local_port;
6174 struct fc_seq_els_data rjt_data;
6175
6176 fh = fc_frame_header_get(fp);
6177- FC_DBG("incoming PRLO from %x state %d\n",
6178- ntoh24(fh->fh_s_id), rp->rp_state);
6179+
6180+ if (fc_rp_debug)
6181+ FC_DBG("Received PRLO request from port (%6x) "
6182+ "while in state %s\n", ntoh24(fh->fh_s_id),
6183+ fc_rport_state(rport));
6184+
6185 rjt_data.fp = NULL;
6186 rjt_data.reason = ELS_RJT_UNAB;
6187 rjt_data.explan = ELS_EXPL_NONE;
6188- lp->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
6189+ lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
6190 fc_frame_free(fp);
6191 }
6192
6193@@ -1240,62 +1295,95 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
6194 * @rport: Fibre Channel remote port that initiated LOGO
6195 * @sp: current sequence in the LOGO exchange
6196 * @fp: LOGO request frame
6197+ *
6198+ * Locking Note: The rport lock is exected to be held before calling
6199+ * this function.
6200 */
6201 static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp,
6202 struct fc_frame *fp)
6203 {
6204 struct fc_frame_header *fh;
6205- struct fc_rport_libfc_priv *rp = rport->dd_data;
6206- struct fc_lport *lp = rp->local_port;
6207+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
6208+ struct fc_lport *lport = rdata->local_port;
6209
6210 fh = fc_frame_header_get(fp);
6211- fc_rport_lock(rport);
6212- fc_rport_state_enter(rport, RPORT_ST_INIT);
6213- fc_rport_unlock(rport);
6214+
6215 if (fc_rp_debug)
6216- FC_DBG("remote %6x closed\n", rport->port_id);
6217- if (rport == lp->dns_rp &&
6218- lp->state != LPORT_ST_RESET) {
6219- fc_lport_lock(lp);
6220- del_timer(&lp->state_timer);
6221- lp->dns_rp = NULL;
6222- if (lp->state == LPORT_ST_DNS_STOP) {
6223- fc_lport_unlock(lp);
6224- lp->tt.lport_logout(lp);
6225- } else {
6226- lp->tt.lport_login(lp);
6227- fc_lport_unlock(lp);
6228- }
6229- fc_remote_port_delete(rport);
6230- }
6231- lp->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
6232+ FC_DBG("Received LOGO request from port (%6x) "
6233+ "while in state %s\n", ntoh24(fh->fh_s_id),
6234+ fc_rport_state(rport));
6235+
6236+ rdata->event = LPORT_EV_RPORT_LOGO;
6237+
6238+ lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
6239 fc_frame_free(fp);
6240 }
6241
6242-int fc_rport_init(struct fc_lport *lp)
6243+int fc_rport_init(struct fc_lport *lport)
6244 {
6245- if (!lp->tt.rport_login)
6246- lp->tt.rport_login = fc_rport_login;
6247-
6248- if (!lp->tt.rport_logout)
6249- lp->tt.rport_logout = fc_rport_logout;
6250+ if (!lport->tt.rport_login)
6251+ lport->tt.rport_login = fc_rport_login;
6252
6253- if (!lp->tt.rport_recv_req)
6254- lp->tt.rport_recv_req = fc_rport_recv_req;
6255+ if (!lport->tt.rport_logout)
6256+ lport->tt.rport_logout = fc_rport_logout;
6257
6258- if (!lp->tt.rport_create)
6259- lp->tt.rport_create = fc_remote_port_create;
6260+ if (!lport->tt.rport_recv_req)
6261+ lport->tt.rport_recv_req = fc_rport_recv_req;
6262
6263- if (!lp->tt.rport_lookup)
6264- lp->tt.rport_lookup = fc_rport_lookup;
6265+ if (!lport->tt.rport_lookup)
6266+ lport->tt.rport_lookup = fc_rport_lookup;
6267
6268- if (!lp->tt.rport_reset)
6269- lp->tt.rport_reset = fc_rport_reset;
6270+ if (!lport->tt.rport_reset)
6271+ lport->tt.rport_reset = fc_rport_reset;
6272
6273- if (!lp->tt.rport_reset_list)
6274- lp->tt.rport_reset_list = fc_rport_reset_list;
6275+ if (!lport->tt.rport_reset_list)
6276+ lport->tt.rport_reset_list = fc_rport_reset_list;
6277
6278 return 0;
6279 }
6280 EXPORT_SYMBOL(fc_rport_init);
6281
6282+/**
6283+ * fc_block_rports - delete all the remote ports, on reset or link down
6284+ * @lp: libfc local port instance
6285+ *
6286+ * This routine temporarily removes any online remote ports from the fc_host
6287+ * rport list, then drops the host lock in order to call fc_remote_port_delete()
6288+ * on each rport in turn, and finally splices the list back onto the fc_host.
6289+ */
6290+void fc_block_rports(struct fc_lport *lp)
6291+{
6292+ struct Scsi_Host *shost = lp->host;
6293+ struct fc_rport *rport, *next;
6294+ unsigned long flags;
6295+ LIST_HEAD(rports);
6296+
6297+ spin_lock_irqsave(shost->host_lock, flags);
6298+ list_for_each_entry_safe(rport, next, &fc_host_rports(shost), peers) {
6299+ /* protect the name service remote port */
6300+ if (rport->port_id == FC_FID_DIR_SERV)
6301+ continue;
6302+ if (rport->port_state != FC_PORTSTATE_ONLINE)
6303+ continue;
6304+ list_move_tail(&rport->peers, &rports);
6305+ }
6306+ spin_unlock_irqrestore(shost->host_lock, flags);
6307+
6308+ list_for_each_entry(rport, &rports, peers) {
6309+ fc_remote_port_delete(rport);
6310+ }
6311+
6312+ spin_lock_irqsave(shost->host_lock, flags);
6313+ list_splice(&rports, &fc_host_rports(shost));
6314+ spin_unlock_irqrestore(shost->host_lock, flags);
6315+}
6316+
6317+void fc_rport_terminate_io(struct fc_rport *rport)
6318+{
6319+ struct fc_rport_libfc_priv *rp = rport->dd_data;
6320+ struct fc_lport *lp = rp->local_port;
6321+
6322+ lp->tt.exch_mgr_reset(lp->emp, 0, rport->port_id);
6323+ lp->tt.exch_mgr_reset(lp->emp, rport->port_id, 0);
6324+}
6325+EXPORT_SYMBOL(fc_rport_terminate_io);
6326diff --git a/include/scsi/fc/fc_fcoe.h b/include/scsi/fc/fc_fcoe.h
6327index b2e07ec..59c9d0c 100644
6328--- a/include/scsi/fc/fc_fcoe.h
6329+++ b/include/scsi/fc/fc_fcoe.h
6330@@ -93,14 +93,6 @@ static inline void fc_fcoe_set_mac(u8 *mac, u8 *did)
6331 mac[5] = did[2];
6332 }
6333
6334-/*
6335- * VLAN header. This is also defined in linux/if_vlan.h, but for kernels only.
6336- */
6337-struct fcoe_vlan_hdr {
6338- __be16 vlan_tag; /* VLAN tag including priority */
6339- __be16 vlan_ethertype; /* encapsulated ethertype ETH_P_FCOE */
6340-};
6341-
6342 #ifndef ETH_P_8021Q
6343 #define ETH_P_8021Q 0x8100
6344 #endif
6345diff --git a/include/scsi/fc/fc_fs.h b/include/scsi/fc/fc_fs.h
6346index ba6df64..3897c6c 100644
6347--- a/include/scsi/fc/fc_fs.h
6348+++ b/include/scsi/fc/fc_fs.h
6349@@ -329,16 +329,4 @@ enum fc_pf_rjt_reason {
6350 FC_RJT_VENDOR = 0xff, /* vendor specific reject */
6351 };
6352
6353-/*
6354- * Data descriptor format (R_CTL == FC_RCTL_DD_DATA_DESC).
6355- * This is used for FCP SCSI transfer ready.
6356- */
6357-struct fc_data_desc {
6358- __be32 dd_offset; /* data relative offset in bytes */
6359- __be32 dd_len; /* transfer buffer size in bytes */
6360- __u8 _dd_resvd[4];
6361-};
6362-
6363-#define FC_DATA_DESC_LEN 12 /* expected length of structure */
6364-
6365 #endif /* _FC_FS_H_ */
6366diff --git a/include/scsi/libfc/libfc.h b/include/scsi/libfc/libfc.h
6367index b139aed..24d3fcb 100644
6368--- a/include/scsi/libfc/libfc.h
6369+++ b/include/scsi/libfc/libfc.h
6370@@ -29,6 +29,7 @@
6371 #include <scsi/fc/fc_fcp.h>
6372 #include <scsi/fc/fc_ns.h>
6373 #include <scsi/fc/fc_els.h>
6374+#include <scsi/fc/fc_gs.h>
6375
6376 #include <scsi/libfc/fc_frame.h>
6377
6378@@ -91,28 +92,50 @@ enum fc_lport_state {
6379 LPORT_ST_NONE = 0,
6380 LPORT_ST_FLOGI,
6381 LPORT_ST_DNS,
6382- LPORT_ST_REG_PN,
6383- LPORT_ST_REG_FT,
6384+ LPORT_ST_RPN_ID,
6385+ LPORT_ST_RFT_ID,
6386 LPORT_ST_SCR,
6387 LPORT_ST_READY,
6388- LPORT_ST_DNS_STOP,
6389 LPORT_ST_LOGO,
6390 LPORT_ST_RESET
6391 };
6392
6393+enum fc_lport_event {
6394+ LPORT_EV_RPORT_NONE = 0,
6395+ LPORT_EV_RPORT_CREATED,
6396+ LPORT_EV_RPORT_FAILED,
6397+ LPORT_EV_RPORT_LOGO
6398+};
6399+
6400 enum fc_rport_state {
6401 RPORT_ST_NONE = 0,
6402 RPORT_ST_INIT, /* initialized */
6403- RPORT_ST_STARTED, /* started */
6404 RPORT_ST_PLOGI, /* waiting for PLOGI completion */
6405- RPORT_ST_PLOGI_RECV, /* received PLOGI (as target) */
6406 RPORT_ST_PRLI, /* waiting for PRLI completion */
6407 RPORT_ST_RTV, /* waiting for RTV completion */
6408- RPORT_ST_ERROR, /* error */
6409 RPORT_ST_READY, /* ready for use */
6410 RPORT_ST_LOGO, /* port logout sent */
6411 };
6412
6413+enum fc_rport_trans_state {
6414+ FC_PORTSTATE_ROGUE,
6415+ FC_PORTSTATE_REAL,
6416+};
6417+
6418+/**
6419+ * struct fc_disc_port - temporary discovery port to hold rport identifiers
6420+ * @lp: Fibre Channel host port instance
6421+ * @peers: node for list management during discovery and RSCN processing
6422+ * @ids: identifiers structure to pass to fc_remote_port_add()
6423+ * @rport_work: work struct for starting the rport state machine
6424+ */
6425+struct fc_disc_port {
6426+ struct fc_lport *lp;
6427+ struct list_head peers;
6428+ struct fc_rport_identifiers ids;
6429+ struct work_struct rport_work;
6430+};
6431+
6432 /**
6433 * struct fc_rport_libfc_priv - libfc internal information about a remote port
6434 * @local_port: Fibre Channel host port instance
6435@@ -122,8 +145,9 @@ enum fc_rport_state {
6436 * @retries: retry count in current state
6437 * @e_d_tov: error detect timeout value (in msec)
6438 * @r_a_tov: resource allocation timeout value (in msec)
6439- * @rp_lock: lock protects state
6440+ * @rp_mutex: mutex protects rport
6441 * @retry_work:
6442+ * @event_callback: Callback for rport READY, FAILED or LOGO
6443 */
6444 struct fc_rport_libfc_priv {
6445 struct fc_lport *local_port;
6446@@ -135,10 +159,23 @@ struct fc_rport_libfc_priv {
6447 unsigned int retries;
6448 unsigned int e_d_tov;
6449 unsigned int r_a_tov;
6450- spinlock_t rp_lock;
6451+ enum fc_rport_trans_state trans_state;
6452+ struct mutex rp_mutex;
6453 struct delayed_work retry_work;
6454+ enum fc_lport_event event;
6455+ void (*event_callback)(struct fc_lport *, u32,
6456+ enum fc_lport_event);
6457+ u32 roles;
6458 };
6459
6460+#define PRIV_TO_RPORT(x) \
6461+ (struct fc_rport*)((void *)x - sizeof(struct fc_rport));
6462+#define RPORT_TO_PRIV(x) \
6463+ (struct fc_rport_libfc_priv*)((void *)x + sizeof(struct fc_rport));
6464+
6465+struct fc_rport *fc_rport_dummy_create(struct fc_disc_port *);
6466+void fc_rport_dummy_destroy(struct fc_rport *);
6467+
6468 static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64 wwnn)
6469 {
6470 rport->node_name = wwnn;
6471@@ -219,9 +256,12 @@ struct libfc_function_template {
6472 * fc_frame pointer in response handler will also indicate timeout
6473 * as error using IS_ERR related macros.
6474 *
6475- * The response handler argumemt resp_arg is passed back to resp
6476- * handler when it is invoked by EM layer in above mentioned
6477- * two scenarios.
6478+ * The exchange destructor handler is also set in this routine.
6479+ * The destructor handler is invoked by EM layer when exchange
6480+ * is about to free, this can be used by caller to free its
6481+ * resources along with exchange free.
6482+ *
6483+ * The arg is passed back to resp and destructor handler.
6484 *
6485 * The timeout value (in msec) for an exchange is set if non zero
6486 * timer_msec argument is specified. The timer is canceled when
6487@@ -232,10 +272,12 @@ struct libfc_function_template {
6488 */
6489 struct fc_seq *(*exch_seq_send)(struct fc_lport *lp,
6490 struct fc_frame *fp,
6491- void (*resp)(struct fc_seq *,
6492+ void (*resp)(struct fc_seq *sp,
6493 struct fc_frame *fp,
6494 void *arg),
6495- void *resp_arg, unsigned int timer_msec,
6496+ void (*destructor)(struct fc_seq *sp,
6497+ void *arg),
6498+ void *arg, unsigned int timer_msec,
6499 u32 sid, u32 did, u32 f_ctl);
6500
6501 /*
6502@@ -316,9 +358,10 @@ struct libfc_function_template {
6503 void (*lport_recv)(struct fc_lport *lp, struct fc_seq *sp,
6504 struct fc_frame *fp);
6505
6506- int (*lport_login)(struct fc_lport *);
6507 int (*lport_reset)(struct fc_lport *);
6508- int (*lport_logout)(struct fc_lport *);
6509+
6510+ void (*event_callback)(struct fc_lport *, u32,
6511+ enum fc_lport_event);
6512
6513 /**
6514 * Remote Port interfaces
6515@@ -346,9 +389,6 @@ struct libfc_function_template {
6516
6517 struct fc_rport *(*rport_lookup)(const struct fc_lport *, u32);
6518
6519- struct fc_rport *(*rport_create)(struct fc_lport *,
6520- struct fc_rport_identifiers *);
6521-
6522 void (*rport_reset)(struct fc_rport *);
6523
6524 void (*rport_reset_list)(struct fc_lport *);
6525@@ -378,9 +418,6 @@ struct libfc_function_template {
6526 * Start discovery for a local port.
6527 */
6528 int (*disc_start)(struct fc_lport *);
6529-
6530- void (*dns_register)(struct fc_lport *);
6531- void (*disc_stop)(struct fc_lport *);
6532 };
6533
6534 struct fc_lport {
6535@@ -396,7 +433,7 @@ struct fc_lport {
6536 /* Operational Information */
6537 struct libfc_function_template tt;
6538 u16 link_status;
6539- u8 ns_disc_done;
6540+ u8 disc_done;
6541 enum fc_lport_state state;
6542 unsigned long boot_time;
6543
6544@@ -407,12 +444,12 @@ struct fc_lport {
6545 u64 wwnn;
6546 u32 fid;
6547 u8 retry_count;
6548- unsigned char ns_disc_retry_count;
6549- unsigned char ns_disc_delay;
6550- unsigned char ns_disc_pending;
6551- unsigned char ns_disc_requested;
6552- unsigned short ns_disc_seq_count;
6553- unsigned char ns_disc_buf_len;
6554+ unsigned char disc_retry_count;
6555+ unsigned char disc_delay;
6556+ unsigned char disc_pending;
6557+ unsigned char disc_requested;
6558+ unsigned short disc_seq_count;
6559+ unsigned char disc_buf_len;
6560
6561 /* Capabilities */
6562 char ifname[IFNAMSIZ];
6563@@ -427,13 +464,13 @@ struct fc_lport {
6564 struct fc_ns_fts fcts; /* FC-4 type masks */
6565 struct fc_els_rnid_gen rnid_gen; /* RNID information */
6566
6567- /* Locks */
6568- spinlock_t state_lock; /* serializes state changes */
6569+ /* Semaphores */
6570+ struct mutex lp_mutex;
6571
6572 /* Miscellaneous */
6573- struct fc_gpn_ft_resp ns_disc_buf; /* partial name buffer */
6574- struct timer_list state_timer; /* timer for state events */
6575- struct delayed_work ns_disc_work;
6576+ struct fc_gpn_ft_resp disc_buf; /* partial name buffer */
6577+ struct delayed_work retry_work;
6578+ struct delayed_work disc_work;
6579
6580 void *drv_priv;
6581 };
6582@@ -462,33 +499,26 @@ static inline void fc_set_wwpn(struct fc_lport *lp, u64 wwnn)
6583 lp->wwpn = wwnn;
6584 }
6585
6586-static inline int fc_lport_locked(struct fc_lport *lp)
6587-{
6588-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
6589- return spin_is_locked(&lp->state_lock);
6590-#else
6591- return 1;
6592-#endif /* CONFIG_SMP || CONFIG_DEBUG_SPINLOCK */
6593-}
6594-
6595-/*
6596- * Locking code.
6597- */
6598-static inline void fc_lport_lock(struct fc_lport *lp)
6599-{
6600- spin_lock_bh(&lp->state_lock);
6601-}
6602-
6603-static inline void fc_lport_unlock(struct fc_lport *lp)
6604+/**
6605+ * fc_fill_dns_hdr - Fill in a name service request header
6606+ * @lp: Fibre Channel host port instance
6607+ * @ct: Common Transport (CT) header structure
6608+ * @op: Name Service request code
6609+ * @req_size: Full size of Name Service request
6610+ */
6611+static inline void fc_fill_dns_hdr(struct fc_lport *lp, struct fc_ct_hdr *ct,
6612+ unsigned int op, unsigned int req_size)
6613 {
6614- spin_unlock_bh(&lp->state_lock);
6615+ memset(ct, 0, sizeof(*ct) + req_size);
6616+ ct->ct_rev = FC_CT_REV;
6617+ ct->ct_fs_type = FC_FST_DIR;
6618+ ct->ct_fs_subtype = FC_NS_SUBTYPE;
6619+ ct->ct_cmd = htons((u16) op);
6620 }
6621
6622 static inline void fc_lport_state_enter(struct fc_lport *lp,
6623 enum fc_lport_state state)
6624 {
6625- WARN_ON(!fc_lport_locked(lp));
6626- del_timer(&lp->state_timer);
6627 if (state != lp->state)
6628 lp->retry_count = 0;
6629 lp->state = state;
6630@@ -543,7 +573,7 @@ int fc_lport_config(struct fc_lport *);
6631 /*
6632 * Reset the local port.
6633 */
6634-int fc_lport_enter_reset(struct fc_lport *);
6635+int fc_lport_reset(struct fc_lport *);
6636
6637 /*
6638 * Set the mfs or reset
6639@@ -555,12 +585,14 @@ int fc_set_mfs(struct fc_lport *lp, u32 mfs);
6640 * REMOTE PORT LAYER
6641 *****************************/
6642 int fc_rport_init(struct fc_lport *lp);
6643+void fc_rport_terminate_io(struct fc_rport *rp);
6644+void fc_block_rports(struct fc_lport *lp);
6645
6646
6647 /**
6648 * DISCOVERY LAYER
6649 *****************************/
6650-int fc_ns_init(struct fc_lport *lp);
6651+int fc_disc_init(struct fc_lport *lp);
6652
6653
6654 /**
6655@@ -670,10 +702,12 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
6656 */
6657 struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
6658 struct fc_frame *fp,
6659- void (*resp)(struct fc_seq *,
6660+ void (*resp)(struct fc_seq *sp,
6661 struct fc_frame *fp,
6662 void *arg),
6663- void *resp_arg, u32 timer_msec,
6664+ void (*destructor)(struct fc_seq *sp,
6665+ void *arg),
6666+ void *arg, u32 timer_msec,
6667 u32 sid, u32 did, u32 f_ctl);
6668
6669 /*
6670@@ -738,15 +772,11 @@ void fc_seq_get_xids(struct fc_seq *sp, u16 *oxid, u16 *rxid);
6671 */
6672 void fc_seq_set_rec_data(struct fc_seq *sp, u32 rec_data);
6673
6674-/**
6675- * fc_functions_template
6676- *****************************/
6677-void fc_attr_init(struct fc_lport *);
6678-void fc_get_host_port_id(struct Scsi_Host *shost);
6679+/*
6680+ * Functions for fc_functions_template
6681+ */
6682 void fc_get_host_speed(struct Scsi_Host *shost);
6683-void fc_get_host_port_type(struct Scsi_Host *shost);
6684 void fc_get_host_port_state(struct Scsi_Host *shost);
6685-void fc_get_host_fabric_name(struct Scsi_Host *shost);
6686 void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout);
6687 struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *);
6688