1 Subject: Open-FCoE update for Beta3
2 From: John Fastabend <john.r.fastabend@intel.com>
3 Date: Thu Nov 6 13:01:32 2008 +0100:
4 Git: 2d8ac46f55c5f06ac3fe9830c899386789aa8900
7 Incremental Open-FCoE update for Beta3.
9 Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
10 Acked-by: Hannes Reinecke <hare@suse.de>
12 diff --git a/drivers/scsi/fcoe/fcoe_if.c b/drivers/scsi/fcoe/fcoe_if.c
13 index 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)
18 write_unlock_bh(&fci->fcoe_hostlist_lock);
20 - /* Cleanup the fc_lport */
21 - fc_lport_destroy(lp);
24 - fc_exch_mgr_free(lp->emp);
25 + /* Don't listen for Ethernet packets anymore */
26 + dev_remove_pack(&fc->fcoe_packet_type);
28 /* Detach from the scsi-ml */
29 fc_remove_host(lp->host);
30 scsi_remove_host(lp->host);
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);
38 + fc_exch_mgr_free(lp->emp);
40 /* Delete secondary MAC addresses */
42 @@ -388,8 +388,7 @@ static int libfc_config(struct fc_lport *lp)
52 diff --git a/drivers/scsi/fcoe/fcoeinit.c b/drivers/scsi/fcoe/fcoeinit.c
53 index 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;
58 static int fcoe_reset(struct Scsi_Host *shost)
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);
67 @@ -66,11 +66,10 @@ struct fc_function_template fcoe_transport_function = {
68 .show_host_active_fc4s = 1,
69 .show_host_maxframe_size = 1,
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,
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,
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,
93 + .terminate_rport_io = fc_rport_terminate_io,
96 struct fcoe_percpu_s *fcoe_percpu[NR_CPUS];
97 diff --git a/drivers/scsi/libfc/Makefile b/drivers/scsi/libfc/Makefile
98 index 0a31ca2..e6d4086 100644
99 --- a/drivers/scsi/libfc/Makefile
100 +++ b/drivers/scsi/libfc/Makefile
102 obj-$(CONFIG_LIBFC) += libfc.o
113 diff --git a/drivers/scsi/libfc/fc_attr.c b/drivers/scsi/libfc/fc_attr.c
114 deleted file mode 100644
115 index d73f39e..0000000
116 --- a/drivers/scsi/libfc/fc_attr.c
120 - * Copyright(c) 2007 Intel Corporation. All rights reserved.
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.
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
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.
135 - * Maintained at www.Open-FCoE.org
138 -#include <linux/kernel.h>
139 -#include <linux/types.h>
141 -#include <scsi/scsi_host.h>
143 -#include <scsi/libfc/libfc.h>
145 -MODULE_AUTHOR("Open-FCoE.org");
146 -MODULE_DESCRIPTION("libfc");
147 -MODULE_LICENSE("GPL");
149 -void fc_get_host_port_id(struct Scsi_Host *shost)
151 - struct fc_lport *lp = shost_priv(shost);
153 - fc_host_port_id(shost) = fc_lport_get_fid(lp);
155 -EXPORT_SYMBOL(fc_get_host_port_id);
157 -void fc_get_host_speed(struct Scsi_Host *shost)
160 - * should be obtain from DEC or Enet Driver
162 - fc_host_speed(shost) = 1; /* for now it is 1g */
164 -EXPORT_SYMBOL(fc_get_host_speed);
166 -void fc_get_host_port_type(struct Scsi_Host *shost)
168 - fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
170 -EXPORT_SYMBOL(fc_get_host_port_type);
172 -void fc_get_host_fabric_name(struct Scsi_Host *shost)
174 - struct fc_lport *lp = shost_priv(shost);
176 - fc_host_fabric_name(shost) = lp->wwnn;
178 -EXPORT_SYMBOL(fc_get_host_fabric_name);
180 -void fc_attr_init(struct fc_lport *lp)
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;
196 -EXPORT_SYMBOL(fc_attr_init);
198 -void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
201 - rport->dev_loss_tmo = timeout + 5;
203 - rport->dev_loss_tmo = 30;
206 -EXPORT_SYMBOL(fc_set_rport_loss_tmo);
208 -struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
211 - struct fc_host_statistics *fcoe_stats;
212 - struct fc_lport *lp = shost_priv(shost);
213 - struct timespec v0, v1;
215 - fcoe_stats = &lp->host_stats;
216 - memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
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);
222 - for_each_online_cpu(i) {
223 - struct fcoe_dev_stats *stats = lp->dev_stats[i];
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;
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;
247 -EXPORT_SYMBOL(fc_get_host_stats);
248 diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
250 index 0000000..30403aa
252 +++ b/drivers/scsi/libfc/fc_disc.c
255 + * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
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.
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
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.
270 + * Maintained at www.Open-FCoE.org
275 + * Actually, this discovers all FC-4 remote ports, including FCP initiators.
278 +#include <linux/timer.h>
279 +#include <linux/err.h>
280 +#include <asm/unaligned.h>
282 +#include <scsi/fc/fc_gs.h>
284 +#include <scsi/libfc/libfc.h>
286 +#define FC_DISC_RETRY_LIMIT 3 /* max retries */
287 +#define FC_DISC_RETRY_DELAY 500UL /* (msecs) delay */
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 *);
303 + * fc_disc_rscn_req - Handle Registered State Change Notification (RSCN)
304 + * @sp: Current sequence of the RSCN exchange
306 + * @lp: Fibre Channel host port instance
308 +static void fc_disc_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
309 + struct fc_lport *lp)
311 + struct fc_els_rscn *rp;
312 + struct fc_els_rscn_page *pp;
313 + struct fc_seq_els_data rjt_data;
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;
321 + rp = fc_frame_payload_get(fp, sizeof(*rp));
323 + if (!rp || rp->rscn_page_len != sizeof(*pp))
326 + len = ntohs(rp->rscn_plen);
327 + if (len < sizeof(*rp))
329 + len -= sizeof(*rp);
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;
337 + * if we get an address format other than port
338 + * (area, domain, fabric), then do a full discovery
341 + case ELS_ADDR_FMT_PORT:
342 + dp = kzalloc(sizeof(*dp), GFP_KERNEL);
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);
354 + case ELS_ADDR_FMT_AREA:
355 + case ELS_ADDR_FMT_DOM:
356 + case ELS_ADDR_FMT_FAB:
362 + lp->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
365 + FC_DBG("RSCN received: rediscovering\n");
366 + list_for_each_entry_safe(dp, next, &disc_list, peers) {
367 + list_del(&dp->peers);
370 + fc_disc_restart(lp);
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);
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);
391 +static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
392 + struct fc_lport *lp)
394 + switch (fc_frame_payload_op(fp)) {
396 + fc_disc_rscn_req(sp, fp, lp);
399 + FC_DBG("fc_disc recieved an unexpected request\n");
405 + * Refresh target discovery, perhaps due to an RSCN.
406 + * A configurable delay is introduced to collect any subsequent RSCNs.
408 +static int fc_disc_restart(struct fc_lport *lp)
410 + if (!lp->disc_requested && !lp->disc_pending) {
411 + schedule_delayed_work(&lp->disc_work,
412 + msecs_to_jiffies(lp->disc_delay * 1000));
414 + lp->disc_requested = 1;
419 + * Fibre Channel Target discovery.
421 + * Returns non-zero if discovery cannot be started.
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.
428 +int fc_disc_start(struct fc_lport *lp)
430 + struct fc_rport *rport;
432 + struct fc_rport_identifiers ids;
435 + * If not ready, or already running discovery, just set request flag.
437 + if (!fc_lport_test_ready(lp) || lp->disc_pending) {
438 + lp->disc_requested = 1;
442 + lp->disc_pending = 1;
443 + lp->disc_requested = 0;
444 + lp->disc_retry_count = 0;
447 + * Handle point-to-point mode as a simple discovery
448 + * of the remote port.
450 + rport = lp->ptp_rp;
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);
458 + error = fc_disc_new_target(lp, rport, &ids);
459 + put_device(&rport->dev);
463 + fc_block_rports(lp);
464 + fc_disc_gpn_ft_req(lp); /* get ports by FC-4 type */
471 + * Restart discovery after a delay due to resource shortages.
472 + * If the error persists, the discovery will be abandoned.
474 +static void fc_disc_retry(struct fc_lport *lp)
476 + unsigned long delay = FC_DISC_RETRY_DELAY;
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));
488 + * Handle new target found by discovery.
489 + * Create remote port and session if needed.
490 + * Ignore returns of our own FID & WWPN.
492 + * If a non-NULL rp is passed in, it is held for the caller, but not for us.
494 + * Events delivered are:
495 + * FC_EV_READY, when remote port is rediscovered.
497 +static int fc_disc_new_target(struct fc_lport *lp,
498 + struct fc_rport *rport,
499 + struct fc_rport_identifiers *ids)
501 + struct fc_rport_libfc_priv *rp;
504 + if (rport && ids->port_name) {
505 + if (rport->port_name == -1) {
507 + * Set WWN and fall through to notify of create.
509 + fc_rport_set_name(rport, ids->port_name,
511 + } else if (rport->port_name != ids->port_name) {
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.
519 + fc_disc_del_target(lp, rport);
523 + if (((ids->port_name != -1) || (ids->port_id != -1)) &&
524 + ids->port_id != lp->fid && ids->port_name != lp->wwpn) {
526 + rport = lp->tt.rport_lookup(lp, ids->port_id);
528 + struct fc_disc_port dp;
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);
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);
550 + * Delete the remote port.
552 +static void fc_disc_del_target(struct fc_lport *lp, struct fc_rport *rport)
554 + lp->tt.rport_reset(rport);
555 + fc_remote_port_delete(rport); /* release hold from create */
559 + * Done with discovery
561 +static void fc_disc_done(struct fc_lport *lp)
564 + lp->disc_pending = 0;
565 + if (lp->disc_requested)
566 + lp->tt.disc_start(lp);
570 + * fc_disc_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request
571 + * @lp: Fibre Channel host port instance
573 +static void fc_disc_gpn_ft_req(struct fc_lport *lp)
575 + struct fc_frame *fp;
576 + struct fc_seq *sp = NULL;
578 + struct fc_ct_hdr ct;
579 + struct fc_ns_gid_ft gid;
583 + lp->disc_buf_len = 0;
584 + lp->disc_seq_count = 0;
585 + fp = fc_frame_alloc(lp, sizeof(*rp));
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;
593 + WARN_ON(!fc_lport_test_ready(lp));
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,
601 + FC_FC_SEQ_INIT | FC_FC_END_SEQ);
603 + if (error || sp == NULL)
608 + * Handle error on dNS request.
610 +static void fc_disc_error(struct fc_lport *lp, struct fc_frame *fp)
612 + int err = PTR_ERR(fp);
615 + case -FC_EX_TIMEOUT:
616 + if (lp->disc_retry_count++ < FC_DISC_RETRY_LIMIT) {
617 + fc_disc_gpn_ft_req(lp);
619 + FC_DBG("err %d - ending\n", err);
624 + FC_DBG("err %d - ending\n", err);
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
636 +static int fc_disc_gpn_ft_parse(struct fc_lport *lp, void *buf, size_t len)
638 + struct fc_gpn_ft_resp *np;
643 + struct fc_disc_port dp;
644 + struct fc_rport *rp;
645 + struct fc_rport_libfc_priv *rpp;
648 + * Handle partial name record left over from previous call.
652 + np = (struct fc_gpn_ft_resp *)bp;
653 + tlen = lp->disc_buf_len;
655 + WARN_ON(tlen >= sizeof(*np));
656 + plen = sizeof(*np) - tlen;
657 + WARN_ON(plen <= 0);
658 + WARN_ON(plen >= sizeof(*np));
661 + np = &lp->disc_buf;
662 + memcpy((char *)np + tlen, bp, plen);
665 + * Set bp so that the loop below will advance it to the
666 + * first valid full name element.
671 + lp->disc_buf_len = (unsigned char) plen;
672 + if (plen == sizeof(*np))
673 + lp->disc_buf_len = 0;
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".
683 + while (plen >= sizeof(*np)) {
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;
690 + if ((dp.ids.port_id != lp->fid) &&
691 + (dp.ids.port_name != lp->wwpn)) {
692 + rp = fc_rport_dummy_create(&dp);
695 + rpp->local_port = lp;
696 + lp->tt.rport_login(rp);
698 + FC_DBG("Failed to allocate memory for "
699 + "the newly discovered port (%6x)\n",
703 + if (np->fp_flags & FC_NS_FID_LAST) {
708 + len -= sizeof(*np);
710 + np = (struct fc_gpn_ft_resp *)bp;
715 + * Save any partial record at the end of the buffer for next time.
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;
722 + lp->disc_buf_len = 0;
728 + * Handle retry of memory allocation for remote ports.
730 +static void fc_disc_timeout(struct work_struct *work)
732 + struct fc_lport *lp;
734 + lp = container_of(work, struct fc_lport, disc_work.work);
736 + if (lp->disc_pending)
737 + fc_disc_gpn_ft_req(lp);
739 + lp->tt.disc_start(lp);
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
748 + * The response may be in multiple frames
750 +static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
753 + struct fc_lport *lp = lp_arg;
754 + struct fc_ct_hdr *cp;
755 + struct fc_frame_header *fh;
756 + unsigned int seq_cnt;
762 + fc_disc_error(lp, fp);
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));
774 + FC_DBG("GPN_FT response too short, len %d\n",
776 + } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
779 + * Accepted. Parse response.
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,
789 + FC_DBG("GPN_FT unexpected response code %x\n",
790 + ntohs(cp->ct_cmd));
792 + } else if (fr_sof(fp) == FC_SOF_N3 &&
793 + seq_cnt == lp->disc_seq_count) {
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));
801 + error = fc_disc_gpn_ft_parse(lp, buf, len);
805 + lp->disc_seq_count++;
811 + * Discover the directory information for a single target.
812 + * This could be from an RSCN that reported a change for the target.
814 +static void fc_disc_single(struct fc_lport *lp, struct fc_disc_port *dp)
816 + struct fc_rport *rport;
817 + struct fc_rport *rp;
818 + struct fc_rport_libfc_priv *rpp;
820 + if (dp->ids.port_id == lp->fid)
823 + rport = lp->tt.rport_lookup(lp, dp->ids.port_id);
825 + fc_disc_del_target(lp, rport);
826 + put_device(&rport->dev); /* hold from lookup */
829 + rp = fc_rport_dummy_create(dp);
833 + lp->tt.rport_login(rp);
840 +int fc_disc_init(struct fc_lport *lp)
842 + INIT_DELAYED_WORK(&lp->disc_work, fc_disc_timeout);
844 + if (!lp->tt.disc_start)
845 + lp->tt.disc_start = fc_disc_start;
847 + if (!lp->tt.disc_recv_req)
848 + lp->tt.disc_recv_req = fc_disc_recv_req;
852 +EXPORT_SYMBOL(fc_disc_init);
853 diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
854 index 11a03bd..ed74d95 100644
855 --- a/drivers/scsi/libfc/fc_exch.c
856 +++ b/drivers/scsi/libfc/fc_exch.c
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
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.
868 * sequence allocation
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.
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 */
882 * Handler for responses to this current exchange.
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 *);
888 + * arg is passed as void pointer to exchange
889 + * resp and destructor handlers
895 @@ -297,6 +305,8 @@ static void fc_exch_release(struct fc_exch *ep)
897 if (atomic_dec_and_test(&ep->ex_refcnt)) {
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 */
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 */
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)
927 + spin_unlock_bh(&ep->ex_lock);
931 - arg = ep->resp_arg;
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)
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.
942 struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, u16 xid)
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);
948 - if (likely(mp->exches[xid - min_xid] == NULL)) {
949 - mp->last_xid = xid;
951 - spin_unlock_bh(&mp->em_lock);
952 - atomic_inc(&mp->stats.no_free_exch_xid);
953 - mempool_free(ep, mp->ep_pool);
956 + if (unlikely(mp->exches[xid - min_xid] != NULL))
958 + mp->last_xid = xid;
962 + if (mp->lp->state == LPORT_ST_RESET)
963 + goto err; /* don't add new ep during local port reset */
965 + fc_exch_hold(ep); /* hold for exch in mp */
966 + spin_lock_init(&ep->ex_lock);
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.
972 + spin_lock_bh(&ep->ex_lock);
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;
982 - spin_lock_init(&ep->ex_lock);
983 setup_timer(&ep->ex_timer, fc_exch_timeout, (unsigned long)ep);
985 - fc_exch_hold(ep); /* hold for caller */
989 + spin_unlock_bh(&mp->em_lock);
990 + atomic_inc(&mp->stats.no_free_exch_xid);
991 + mempool_free(ep, mp->ep_pool);
994 EXPORT_SYMBOL(fc_exch_alloc);
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);
1000 + fc_exch_hold(ep); /* hold for caller */
1001 + spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */
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)
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;
1014 @@ -717,12 +739,11 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp)
1015 reject = FC_RJT_RX_ID;
1018 - new_ep = ep = fc_exch_resp(mp, fp);
1019 + ep = fc_exch_resp(mp, fp);
1021 reject = FC_RJT_EXCH_EST; /* XXX */
1024 - fc_exch_hold(ep); /* Additional hold for caller */
1025 xid = ep->xid; /* get our XID */
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)
1032 - fc_exch_release(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 */
1040 @@ -1160,7 +1180,7 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
1044 - ep->resp(sp, fp, ep->resp_arg);
1045 + ep->resp(sp, fp, ep->arg);
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);
1053 - ex_resp_arg = ep->resp_arg;
1054 + ex_resp_arg = ep->arg;
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)
1062 - ex_resp_arg = ep->resp_arg;
1063 + ex_resp_arg = ep->arg;
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)
1069 * do we want to check END_SEQ as well as LAST_SEQ here?
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;
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);
1089 fc_exch_mgr_delete_ep(ep);
1090 @@ -1640,9 +1658,7 @@ reject:
1092 static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1094 - struct fc_exch *ep = fc_seq_exch(sp);
1095 - struct fc_exch *aborted_ep;
1097 + struct fc_exch *aborted_ep = arg;
1101 @@ -1669,16 +1685,9 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
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);
1111 - fc_exch_done(&aborted_ep->seq);
1112 - /* drop hold for rec qual */
1113 - fc_exch_release(aborted_ep);
1115 + fc_exch_done(&aborted_ep->seq);
1116 + /* drop hold for rec qual */
1117 + fc_exch_release(aborted_ep);
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;
1129 @@ -1711,18 +1719,14 @@ static void fc_exch_rrq(struct fc_exch *ep)
1131 if (ep->esb_stat & ESB_ST_RESP)
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);
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);
1146 - rrq_ep = fc_seq_exch(rrq_sp);
1147 - rrq_ep->aborted_ep = ep;
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,
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)
1161 struct fc_seq *sp = NULL;
1162 struct fc_frame_header *fh;
1166 ep = lp->tt.exch_get(lp, fp);
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);
1172 - ep->resp_arg = resp_arg;
1173 + ep->destructor = destructor;
1175 ep->r_a_tov = FC_DEF_R_A_TOV;
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)))
1182 - spin_lock_bh(&ep->ex_lock);
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);
1191 + rc = fc_exch_done_locked(ep);
1192 + spin_unlock_bh(&ep->ex_lock);
1194 + fc_exch_mgr_delete_ep(ep);
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);
1202 + /* lport lock ? */
1203 if (!lp || !mp || (lp->state == LPORT_ST_NONE)) {
1204 FC_DBG("fc_lport or EM is not allocated and configured");
1206 diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
1207 index 97da731..2566eed 100644
1208 --- a/drivers/scsi/libfc/fc_fcp.c
1209 +++ b/drivers/scsi/libfc/fc_fcp.c
1212 #include <scsi/libfc/libfc.h>
1214 +MODULE_AUTHOR("Open-FCoE.org");
1215 +MODULE_DESCRIPTION("libfc");
1216 +MODULE_LICENSE("GPL");
1219 static struct kmem_cache *scsi_pkt_cachep;
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);
1229 @@ -233,6 +238,22 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *sp)
1233 + * fc_fcp_pkt_destory - release hold on scsi_pkt packet
1235 + * @sp: exchange sequence
1236 + * @fsp: fcp packet struct
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
1243 +static void fc_fcp_pkt_destroy(struct fc_seq *sp, void *arg)
1245 + fc_fcp_pkt_release(arg);
1249 * fc_fcp_lock_pkt - lock a packet and get a ref to it.
1252 @@ -604,13 +625,31 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *sp,
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)
1260 - * we will let the command timeout and scsi-ml escalate if
1261 - * the abort was rejected
1263 - if (fh->fh_r_ctl == FC_RCTL_BA_ACC) {
1265 + struct fc_ba_rjt *brp;
1266 + struct fc_frame_header *fh;
1268 + fh = fc_frame_header_get(fp);
1269 + switch (fh->fh_r_ctl) {
1270 + case FC_RCTL_BA_ACC:
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)
1279 + * we will let the command timeout
1280 + * and scsi-ml recover in this case,
1281 + * therefore cleared the ba_done flag.
1287 fsp->state |= FC_SRB_ABORTED;
1288 fsp->state &= ~FC_SRB_ABORT_PENDING;
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;
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;
1302 if (fh->fh_type == FC_TYPE_BLS) {
1303 - fc_fcp_abts_resp(fsp, fh);
1304 + fc_fcp_abts_resp(fsp, fp);
1308 @@ -701,8 +740,8 @@ static void fc_fcp_recv(struct fc_seq *sp, struct fc_frame *fp, void *arg)
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);
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,
1323 + fc_fcp_pkt_destroy,
1325 rp->local_port->fid,
1327 @@ -1034,7 +1074,9 @@ static int fc_fcp_send_cmd(struct fc_fcp_pkt *fsp)
1331 + fsp->last_pkt_time = jiffies;
1333 + fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
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,
1341 + fc_fcp_pkt_destroy,
1343 rp->local_port->fid,
1345 @@ -1138,6 +1181,7 @@ static void fc_lun_reset_send(unsigned long data)
1349 + fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
1353 @@ -1183,12 +1227,6 @@ static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
1355 spin_lock_bh(&fsp->scsi_pkt_lock);
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
1363 lp->tt.exch_done(fsp->seq_ptr);
1364 fsp->seq_ptr = NULL;
1366 @@ -1231,9 +1269,6 @@ static void fc_tm_done(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1369 * raced with eh timeout handler.
1371 - * TODO: If this happens we could be freeing the fsp right now and
1372 - * would oops. Next patches will fix this race.
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)
1378 if (rp->flags & FC_RP_FLAGS_REC_SUPPORTED)
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),
1384 fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
1385 else if (fsp->state & FC_SRB_RCV_STATUS)
1386 fc_fcp_complete(fsp);
1388 fc_timeout_error(fsp);
1390 fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;
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,
1398 + fc_fcp_rec_resp, NULL,
1399 fsp, jiffies_to_msecs(FC_SCSI_REC_TOV),
1400 rp->local_port->fid,
1402 @@ -1402,9 +1436,14 @@ static void fc_fcp_rec_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1404 FC_DBG("device does not support REC\n");
1405 rp = fsp->rport->dd_data;
1407 + * if we do not spport RECs or got some bogus
1408 + * reason then resetup timer so we check for
1409 + * making progress.
1411 rp->flags &= ~FC_RP_FLAGS_REC_SUPPORTED;
1412 - /* fall through */
1414 + fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
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,
1424 + fc_fcp_srr_resp, NULL,
1425 fsp, jiffies_to_msecs(FC_SCSI_REC_TOV),
1426 rp->local_port->fid,
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");
1432 - shost_printk(KERN_INFO, shost, "Host reset succeeded failed."
1433 + shost_printk(KERN_INFO, shost, "Host reset failed. "
1434 "lport not ready.\n");
1437 diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
1438 index b390a32..b1854b9 100644
1439 --- a/drivers/scsi/libfc/fc_lport.c
1440 +++ b/drivers/scsi/libfc/fc_lport.c
1441 @@ -36,76 +36,130 @@
1443 static int fc_lport_debug;
1445 +static void fc_lport_error(struct fc_lport *, struct fc_frame *);
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 *);
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",
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)
1479 -static const char *fc_lport_state(struct fc_lport *lp)
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
1486 + * Locking Note: The rport lock should not be held when calling
1489 +static void fc_lport_rport_event(struct fc_lport *lport, u32 port_id,
1490 + enum fc_lport_event event)
1492 + struct fc_rport *rport = lport->tt.rport_lookup(lport, port_id);
1494 + if (fc_lport_debug)
1495 + FC_DBG("Received a %d event for port (%6x)\n", event, port_id);
1497 + if (port_id == FC_FID_DIR_SERV) {
1498 + mutex_lock(&lport->lp_mutex);
1500 + case LPORT_EV_RPORT_CREATED:
1502 + lport->dns_rp = rport;
1503 + fc_lport_enter_rpn_id(lport);
1506 + case LPORT_EV_RPORT_LOGO:
1507 + case LPORT_EV_RPORT_FAILED:
1508 + lport->dns_rp = NULL;
1509 + fc_lport_enter_dns(lport);
1511 + case LPORT_EV_RPORT_NONE:
1514 + mutex_unlock(&lport->lp_mutex);
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
1522 +static const char *fc_lport_state(struct fc_lport *lport)
1526 - cp = fc_lport_state_names[lp->state];
1527 + cp = fc_lport_state_names[lport->state];
1533 -static void fc_lport_ptp_setup(struct fc_lport *lp,
1534 - u32 remote_fid, u64 remote_wwpn,
1537 + * fc_lport_ptp_clear - Delete the ptp rport
1538 + * @lport: The lport whose ptp rport should be removed
1540 +static void fc_lport_ptp_clear(struct fc_lport *lport)
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,
1550 - * if we have to create a rport the fc class can sleep so we must
1551 - * drop the lock here
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);
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;
1569 -static void fc_lport_ptp_clear(struct fc_lport *lp)
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
1577 +static void fc_lport_ptp_setup(struct fc_lport *lport,
1578 + u32 remote_fid, u64 remote_wwpn,
1582 - fc_remote_port_delete(lp->ptp_rp);
1583 - lp->ptp_rp = NULL;
1585 + struct fc_disc_port dp;
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;
1593 + fc_lport_ptp_clear(lport);
1595 + lport->ptp_rp = fc_rport_dummy_create(&dp);
1597 + lport->tt.rport_login(lport->ptp_rp);
1599 + fc_lport_enter_ready(lport);
1603 - * Routines to support struct fc_function_template
1605 + * fc_get_host_port_state - supports fc_function_template
1606 + * @shost: The host whose port state should be returned
1608 void fc_get_host_port_state(struct Scsi_Host *shost)
1610 @@ -118,82 +172,130 @@ void fc_get_host_port_state(struct Scsi_Host *shost)
1612 EXPORT_SYMBOL(fc_get_host_port_state);
1614 +void fc_get_host_speed(struct Scsi_Host *shost)
1616 + struct fc_lport *lport = shost_priv(shost);
1618 + fc_host_speed(shost) = lport->link_speed;
1620 +EXPORT_SYMBOL(fc_get_host_speed);
1622 +struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
1625 + struct fc_host_statistics *fcoe_stats;
1626 + struct fc_lport *lp = shost_priv(shost);
1627 + struct timespec v0, v1;
1629 + fcoe_stats = &lp->host_stats;
1630 + memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
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);
1636 + for_each_online_cpu(i) {
1637 + struct fcoe_dev_stats *stats = lp->dev_stats[i];
1638 + if (stats == NULL)
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;
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;
1661 +EXPORT_SYMBOL(fc_get_host_stats);
1664 * Fill in FLOGI command for request.
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,
1672 struct fc_els_csp *sp;
1673 struct fc_els_cssp *cp;
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);
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;
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.
1708 -static void fc_lport_set_fid(struct fc_lport *lp, u32 fid)
1710 - if (fid != 0 && lp->fid == fid)
1713 - if (fc_lport_debug)
1714 - FC_DBG("changing local port fid from %x to %x\n",
1717 - lp->tt.rport_reset_list(lp);
1721 * Add a supported FC-4 type.
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)
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));
1734 - * Handle received RLIR - registered link incident report.
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
1741 + * Locking Note: The lport lock is exected to be held before calling
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)
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));
1754 + lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
1759 - * Handle received ECHO.
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
1766 + * Locking Note: The lport lock is exected to be held before calling
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)
1774 struct fc_frame *fp;
1776 @@ -201,29 +303,40 @@ static void fc_lport_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
1780 + if (fc_lport_debug)
1781 + FC_DBG("Received RLIR request while in state %s\n",
1782 + fc_lport_state(lport));
1784 len = fr_len(in_fp) - sizeof(struct fc_frame_header);
1785 pp = fc_frame_payload_get(in_fp, len);
1787 if (len < sizeof(__be32))
1788 len = sizeof(__be32);
1789 - fp = fc_frame_alloc(lp, len);
1791 + fp = fc_frame_alloc(lport, len);
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);
1803 fc_frame_free(in_fp);
1807 - * Handle received RNID.
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
1814 + * Locking Note: The lport lock is exected to be held before calling
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)
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,
1828 + if (fc_lport_debug)
1829 + FC_DBG("Received RNID request while in state %s\n",
1830 + fc_lport_state(lport));
1832 req = fc_frame_payload_get(in_fp, sizeof(*req));
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);
1840 fmt = req->rnid_fmt;
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);
1848 - fp = fc_frame_alloc(lp, len);
1849 + fp = fc_frame_alloc(lport, len);
1851 rp = fc_frame_payload_get(fp, 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,
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);
1874 fc_frame_free(in_fp);
1878 - * Handle received fabric logout request.
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
1885 + * Locking Note: The lport lock is exected to be held before calling
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)
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);
1900 - * Receive request frame
1902 + * fc_fabric_login - Start the lport state machine
1903 + * @lport: The lport that should log into the fabric
1905 + * Locking Note: This function should not be called
1906 + * with the lport lock held.
1909 -int fc_fabric_login(struct fc_lport *lp)
1910 +int fc_fabric_login(struct fc_lport *lport)
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);
1923 + mutex_unlock(&lport->lp_mutex);
1927 EXPORT_SYMBOL(fc_fabric_login);
1930 - * fc_linkup - link up notification
1931 - * @dev: Pointer to fc_lport .
1933 -void fc_linkup(struct fc_lport *lp)
1934 + * fc_linkup - Handler for transport linkup events
1935 + * @lport: The lport whose link is up
1937 +void fc_linkup(struct fc_lport *lport)
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;
1949 + if (lport->state == LPORT_ST_RESET)
1950 + fc_lport_enter_flogi(lport);
1952 + mutex_unlock(&lport->lp_mutex);
1954 EXPORT_SYMBOL(fc_linkup);
1957 - * fc_linkdown - link down notification
1958 - * @dev: Pointer to fc_lport .
1960 -void fc_linkdown(struct fc_lport *lp)
1961 + * fc_linkdown - Handler for transport linkdown events
1962 + * @lport: The lport whose link is down
1964 +void fc_linkdown(struct fc_lport *lport)
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);
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);
1978 + mutex_unlock(&lport->lp_mutex);
1980 EXPORT_SYMBOL(fc_linkdown);
1982 -void fc_pause(struct fc_lport *lp)
1984 + * fc_pause - Pause the flow of frames
1985 + * @lport: The lport to be paused
1987 +void fc_pause(struct fc_lport *lport)
1989 - lp->link_status |= FC_PAUSE;
1990 + mutex_lock(&lport->lp_mutex);
1991 + lport->link_status |= FC_PAUSE;
1992 + mutex_unlock(&lport->lp_mutex);
1994 EXPORT_SYMBOL(fc_pause);
1996 -void fc_unpause(struct fc_lport *lp)
1998 + * fc_unpause - Unpause the flow of frames
1999 + * @lport: The lport to be unpaused
2001 +void fc_unpause(struct fc_lport *lport)
2003 - lp->link_status &= ~(FC_PAUSE);
2004 + mutex_lock(&lport->lp_mutex);
2005 + lport->link_status &= ~(FC_PAUSE);
2006 + mutex_unlock(&lport->lp_mutex);
2008 EXPORT_SYMBOL(fc_unpause);
2010 -int fc_fabric_logoff(struct fc_lport *lp)
2012 + * fc_fabric_logoff - Logout of the fabric
2013 + * @lport: fc_lport pointer to logoff the fabric
2016 + * 0 for success, -1 for failure
2018 +int fc_fabric_logoff(struct fc_lport *lport)
2020 - fc_lport_lock(lp);
2021 - switch (lp->state) {
2022 - case LPORT_ST_NONE:
2024 - case LPORT_ST_FLOGI:
2025 - case LPORT_ST_LOGO:
2026 - case LPORT_ST_RESET:
2027 - fc_lport_enter_reset(lp);
2029 - case LPORT_ST_DNS:
2030 - case LPORT_ST_DNS_STOP:
2031 - fc_lport_enter_logo(lp);
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);
2040 - fc_lport_unlock(lp);
2041 - lp->tt.scsi_cleanup(lp);
2043 + mutex_lock(&lport->lp_mutex);
2044 + fc_lport_enter_logo(lport);
2045 + lport->tt.scsi_cleanup(lport);
2046 + mutex_unlock(&lport->lp_mutex);
2049 EXPORT_SYMBOL(fc_fabric_logoff);
2052 * fc_lport_destroy - unregister a fc_lport
2053 - * @lp: fc_lport pointer to unregister
2054 + * @lport: fc_lport pointer to unregister
2058 @@ -386,30 +518,26 @@ EXPORT_SYMBOL(fc_fabric_logoff);
2059 * and free up other system resources.
2062 -int fc_lport_destroy(struct fc_lport *lp)
2063 +int fc_lport_destroy(struct fc_lport *lport)
2065 - fc_lport_lock(lp);
2066 - fc_lport_state_enter(lp, LPORT_ST_LOGO);
2067 - fc_lport_unlock(lp);
2069 - cancel_delayed_work_sync(&lp->ns_disc_work);
2071 - lp->tt.scsi_abort_io(lp);
2073 - lp->tt.frame_send = fc_frame_drop;
2075 - lp->tt.exch_mgr_reset(lp->emp, 0, 0);
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);
2085 EXPORT_SYMBOL(fc_lport_destroy);
2087 -int fc_set_mfs(struct fc_lport *lp, u32 mfs)
2088 +int fc_set_mfs(struct fc_lport *lport, u32 mfs)
2090 unsigned int old_mfs;
2093 - old_mfs = lp->mfs;
2094 + mutex_lock(&lport->lp_mutex);
2096 + old_mfs = lport->mfs;
2098 if (mfs >= FC_MIN_MAX_FRAME) {
2100 @@ -417,97 +545,55 @@ int fc_set_mfs(struct fc_lport *lp, u32 mfs)
2101 if (mfs > FC_MAX_FRAME)
2103 mfs -= sizeof(struct fc_frame_header);
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);
2116 + mutex_unlock(&lport->lp_mutex);
2120 EXPORT_SYMBOL(fc_set_mfs);
2123 - * re-enter state for retrying a request after a timeout or alloc failure.
2125 + * fc_rport_enter_ready - Enter the ready state and start discovery
2126 + * @lport: Fibre Channel local port that is ready
2128 + * Locking Note: The lport lock is expected to be held before calling
2131 -static void fc_lport_enter_retry(struct fc_lport *lp)
2132 +static void fc_lport_enter_ready(struct fc_lport *lport)
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:
2145 - case LPORT_ST_FLOGI:
2146 - fc_lport_enter_flogi(lp);
2148 - case LPORT_ST_LOGO:
2149 - fc_lport_enter_logo(lp);
2153 + if (fc_lport_debug)
2154 + FC_DBG("Port (%6x) entered Ready from state %s\n",
2155 + lport->fid, fc_lport_state(lport));
2158 - * enter next state for handling an exchange reject or retry exhaustion
2159 - * in the current state.
2161 -static void fc_lport_enter_reject(struct fc_lport *lp)
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:
2174 - case LPORT_ST_FLOGI:
2175 - fc_lport_enter_flogi(lp);
2177 - case LPORT_ST_LOGO:
2178 - fc_lport_enter_reset(lp);
2182 + fc_lport_state_enter(lport, LPORT_ST_READY);
2185 - * Handle resource allocation problem by retrying in a bit.
2187 -static void fc_lport_retry(struct fc_lport *lp)
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));
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);
2202 + lport->tt.disc_start(lport);
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
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.
2216 + * Locking Note: The lport lock is exected to be held before calling
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)
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,
2230 + if (fc_lport_debug)
2231 + FC_DBG("Received FLOGI request while in state %s\n",
2232 + fc_lport_state(lport));
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));
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);
2246 FC_DBG("FLOGI from port WWPN %llx\n", remote_wwpn);
2247 - fc_lport_lock(lp);
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.
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;
2263 - fc_lport_set_fid(lp, local_fid);
2265 - fp = fc_frame_alloc(lp, sizeof(*flp));
2266 + lport->fid = local_fid;
2268 + fp = fc_frame_alloc(lport, sizeof(*flp));
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;
2278 @@ -561,23 +651,35 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
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);
2286 - fc_lport_retry(lp);
2287 + fc_lport_error(lport, fp);
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))
2295 + if (lport->tt.disc_start(lport))
2296 FC_DBG("target discovery start error\n");
2299 fc_frame_free(rx_fp);
2302 -static void fc_lport_recv(struct fc_lport *lp, struct fc_seq *sp,
2303 - struct fc_frame *fp)
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
2310 + * This function will see if the lport handles the request or
2311 + * if an rport should handle the request.
2313 + * Locking Note: This function should not be called with the lport
2314 + * lock held becuase it will grab the lock.
2316 +static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
2317 + struct fc_frame *fp)
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,
2323 struct fc_seq_els_data rjt_data;
2325 + mutex_lock(&lport->lp_mutex);
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;
2334 - recv = lp->tt.disc_recv_req;
2335 + recv = lport->tt.disc_recv_req;
2338 - recv = fc_lport_echo_req;
2339 + recv = fc_lport_recv_echo_req;
2342 - recv = fc_lport_rlir_req;
2343 + recv = fc_lport_recv_rlir_req;
2346 - recv = fc_lport_rnid_req;
2347 + recv = fc_lport_recv_rnid_req;
2353 + recv(sp, fp, lport);
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);
2361 - rport = lp->tt.rport_lookup(lp, s_id);
2362 + rport = lport->tt.rport_lookup(lport, s_id);
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 */
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,
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));
2383 + mutex_unlock(&lport->lp_mutex);
2387 - * The common exch_done for all request may not be good
2388 - * if any request requires longer hold on exhange. XXX
2390 - lp->tt.exch_done(sp);
2392 + * fc_lport_reset - Reset an lport
2393 + * @lport: The lport which should be reset
2395 + * Locking Note: This functions should not be called with the
2396 + * lport lock held.
2398 +int fc_lport_reset(struct fc_lport *lport)
2400 + mutex_lock(&lport->lp_mutex);
2401 + fc_lport_enter_reset(lport);
2402 + mutex_unlock(&lport->lp_mutex);
2405 +EXPORT_SYMBOL(fc_lport_reset);
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.
2412 + * fc_rport_enter_reset - Reset the local port
2413 + * @lport: Fibre Channel local port to be reset
2415 + * Locking Note: The lport lock is expected to be held before calling
2418 -int fc_lport_enter_reset(struct fc_lport *lp)
2419 +static void fc_lport_enter_reset(struct fc_lport *lport)
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));
2426 + fc_lport_state_enter(lport, LPORT_ST_RESET);
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;
2435 - fc_lport_ptp_clear(lp);
2436 + fc_lport_ptp_clear(lport);
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.
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);
2450 + fc_block_rports(lport);
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;
2457 + if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP)
2458 + fc_lport_enter_flogi(lport);
2460 -EXPORT_SYMBOL(fc_lport_enter_reset);
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).
2467 + * fc_lport_error - Handler for any errors
2468 + * @lport: The fc_lport object
2469 + * @fp: The frame pointer
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.
2475 +static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
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);
2483 + if (lport->retry_count < lport->max_retry_count) {
2484 + lport->retry_count++;
2486 + delay = msecs_to_jiffies(500);
2489 + msecs_to_jiffies(lport->e_d_tov);
2491 + schedule_delayed_work(&lport->retry_work, delay);
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);
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
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.
2520 +static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
2523 + struct fc_lport *lport = lp_arg;
2524 + struct fc_frame_header *fh;
2525 + struct fc_ct_hdr *ct;
2527 + mutex_lock(&lport->lp_mutex);
2529 + if (fc_lport_debug)
2530 + FC_DBG("Received a RFT_ID response\n");
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));
2539 + fc_lport_error(lport, fp);
2543 + fh = fc_frame_header_get(fp);
2544 + ct = fc_frame_payload_get(fp, sizeof(*ct));
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);
2552 + fc_lport_error(lport, fp);
2554 + mutex_unlock(&lport->lp_mutex);
2555 + fc_frame_free(fp);
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
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.
2569 +static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
2572 + struct fc_lport *lport = lp_arg;
2573 + struct fc_frame_header *fh;
2574 + struct fc_ct_hdr *ct;
2576 + mutex_lock(&lport->lp_mutex);
2578 + if (fc_lport_debug)
2579 + FC_DBG("Received a RPN_ID response\n");
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));
2588 + fc_lport_error(lport, fp);
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);
2600 + fc_lport_error(lport, fp);
2603 + mutex_unlock(&lport->lp_mutex);
2604 + fc_frame_free(fp);
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
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.
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,
2621 - if (lp->state == LPORT_ST_RESET)
2622 + struct fc_lport *lport = lp_arg;
2625 + mutex_lock(&lport->lp_mutex);
2627 + if (fc_lport_debug)
2628 + FC_DBG("Received a SCR response\n");
2630 + if (lport->state != LPORT_ST_SCR) {
2631 + FC_DBG("Received a SCR response, but in state %s\n",
2632 + fc_lport_state(lport));
2637 + fc_lport_error(lport, fp);
2641 + op = fc_frame_payload_op(fp);
2642 + if (op == ELS_LS_ACC)
2643 + fc_lport_enter_ready(lport);
2645 + fc_lport_error(lport, fp);
2648 + mutex_unlock(&lport->lp_mutex);
2649 + fc_frame_free(fp);
2653 + * fc_lport_enter_scr - Send a State Change Register (SCR) request
2654 + * @lport: Fibre Channel local port to register for state changes
2656 + * Locking Note: The lport lock is expected to be held before calling
2659 +static void fc_lport_enter_scr(struct fc_lport *lport)
2661 + struct fc_frame *fp;
2662 + struct fc_els_scr *scr;
2664 + if (fc_lport_debug)
2665 + FC_DBG("Port (%6x) entered SCR state from %s state\n",
2666 + lport->fid, fc_lport_state(lport));
2668 + fc_lport_state_enter(lport, LPORT_ST_SCR);
2670 + fp = fc_frame_alloc(lport, sizeof(*scr));
2672 + fc_lport_error(lport, fp);
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);
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);
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);
2699 + * fc_lport_enter_rft_id - Register FC4-types with the name server
2700 + * @lport: Fibre Channel local port to register
2702 + * Locking Note: The lport lock is expected to be held before calling
2705 +static void fc_lport_enter_rft_id(struct fc_lport *lport)
2707 + struct fc_frame *fp;
2709 + struct fc_ct_hdr ct;
2710 + struct fc_ns_fid fid; /* port ID object */
2711 + struct fc_ns_fts fts; /* FC4-types object */
2713 + struct fc_ns_fts *lps;
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));
2720 + fc_lport_state_enter(lport, LPORT_ST_RFT_ID);
2722 + lps = &lport->fcts;
2723 + i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
2725 + if (ntohl(lps->ff_type_map[i]) != 0)
2728 + /* nothing to register, move on to SCR */
2729 + fc_lport_enter_scr(lport);
2731 + fp = fc_frame_alloc(lport, sizeof(*req));
2733 + fc_lport_error(lport, fp);
2737 + req = fc_frame_payload_get(fp, sizeof(*req));
2738 + fc_fill_dns_hdr(lport, &req->ct,
2741 + sizeof(struct fc_ct_hdr));
2742 + hton24(req->fid.fp_fid, lport->fid);
2744 + fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
2746 + if (!lport->tt.exch_seq_send(lport, fp,
2747 + fc_lport_rft_id_resp, NULL,
2748 + lport, lport->e_d_tov,
2753 + fc_lport_error(lport, fp);
2758 + * fc_rport_enter_rft_id - Register port name with the name server
2759 + * @lport: Fibre Channel local port to register
2761 + * Locking Note: The lport lock is expected to be held before calling
2764 +static void fc_lport_enter_rpn_id(struct fc_lport *lport)
2766 + struct fc_frame *fp;
2768 + struct fc_ct_hdr ct;
2769 + struct fc_ns_rn_id rn;
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));
2776 + fc_lport_state_enter(lport, LPORT_ST_RPN_ID);
2778 + fp = fc_frame_alloc(lport, sizeof(*req));
2780 + fc_lport_error(lport, fp);
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);
2791 + if (!lport->tt.exch_seq_send(lport, fp,
2792 + fc_lport_rpn_id_resp, NULL,
2793 + lport, lport->e_d_tov,
2796 + FC_FC_SEQ_INIT | FC_FC_END_SEQ))
2797 + fc_lport_error(lport, fp);
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
2805 + * Locking Note: The lport lock is expected to be held before calling
2808 +static void fc_lport_enter_dns(struct fc_lport *lport)
2810 + struct fc_rport *rport;
2811 + struct fc_rport_libfc_priv *rdata;
2812 + struct fc_disc_port dp;
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;
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));
2827 + fc_lport_state_enter(lport, LPORT_ST_DNS);
2829 + if (!lport->dns_rp) {
2830 + /* Set up a dummy rport to directory server */
2831 + rport = fc_rport_dummy_create(&dp);
2835 + lport->dns_rp = rport;
2836 + FC_DBG("created an rport for the NS\n");
2839 + rport = lport->dns_rp;
2840 + rdata = rport->dd_data;
2841 + rdata->event_callback = fc_lport_rport_event;
2842 + lport->tt.rport_login(rport);
2846 + fc_lport_error(lport, NULL);
2849 -static void fc_lport_timeout(unsigned long lp_arg)
2851 + * fc_lport_timeout - Handler for the retry_work timer.
2852 + * @work: The work struct of the fc_lport
2854 +static void fc_lport_timeout(struct work_struct *work)
2856 - struct fc_lport *lp = (struct fc_lport *)lp_arg;
2857 + struct fc_lport *lport =
2858 + container_of(work, struct fc_lport,
2861 - fc_lport_lock(lp);
2862 - fc_lport_enter_retry(lp);
2863 - fc_lport_unlock(lp);
2864 + mutex_lock(&lport->lp_mutex);
2866 + switch (lport->state) {
2867 + case LPORT_ST_NONE:
2868 + case LPORT_ST_READY:
2869 + case LPORT_ST_RESET:
2872 + case LPORT_ST_FLOGI:
2873 + fc_lport_enter_flogi(lport);
2875 + case LPORT_ST_DNS:
2876 + fc_lport_enter_dns(lport);
2878 + case LPORT_ST_RPN_ID:
2879 + fc_lport_enter_rpn_id(lport);
2881 + case LPORT_ST_RFT_ID:
2882 + fc_lport_enter_rft_id(lport);
2884 + case LPORT_ST_SCR:
2885 + fc_lport_enter_scr(lport);
2887 + case LPORT_ST_LOGO:
2888 + fc_lport_enter_logo(lport);
2892 + mutex_unlock(&lport->lp_mutex);
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
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.
2905 static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
2908 - struct fc_lport *lp = lp_arg;
2909 + struct fc_lport *lport = lp_arg;
2913 - fc_lport_error(lp, fp);
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);
2921 + if (fc_lport_debug)
2922 + FC_DBG("Received a LOGO response\n");
2924 + if (lport->state != LPORT_ST_LOGO) {
2925 + FC_DBG("Received a LOGO response, but in state %s\n",
2926 + fc_lport_state(lport));
2931 + fc_lport_error(lport, fp);
2935 + op = fc_frame_payload_op(fp);
2936 + if (op == ELS_LS_ACC)
2937 + fc_lport_enter_reset(lport);
2939 + fc_lport_error(lport, fp);
2942 + mutex_unlock(&lport->lp_mutex);
2943 + fc_frame_free(fp);
2946 -/* Logout of the FC fabric */
2947 -static void fc_lport_enter_logo(struct fc_lport *lp)
2949 + * fc_rport_enter_logo - Logout of the fabric
2950 + * @lport: Fibre Channel local port to be logged out
2952 + * Locking Note: The lport lock is expected to be held before calling
2955 +static void fc_lport_enter_logo(struct fc_lport *lport)
2957 struct fc_frame *fp;
2958 struct fc_els_logo *logo;
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));
2965 - fc_lport_state_enter(lp, LPORT_ST_LOGO);
2966 + fc_lport_state_enter(lport, LPORT_ST_LOGO);
2968 /* DNS session should be closed so we can release it here */
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;
2977 - fp = fc_frame_alloc(lp, sizeof(*logo));
2978 + fp = fc_frame_alloc(lport, sizeof(*logo));
2980 - FC_DBG("failed to allocate frame\n");
2981 + fc_lport_error(lport, fp);
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);
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);
2996 - lp->tt.exch_seq_send(lp, fp,
2997 - fc_lport_logo_resp,
2999 - lp->fid, FC_FID_FLOGI,
3000 - FC_FC_SEQ_INIT | FC_FC_END_SEQ);
3003 -static int fc_lport_logout(struct fc_lport *lp)
3005 - fc_lport_lock(lp);
3006 - if (lp->state != LPORT_ST_LOGO)
3007 - fc_lport_enter_logo(lp);
3008 - fc_lport_unlock(lp);
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);
3019 - * Handle incoming ELS FLOGI response.
3020 - * Save parameters of remote switch. Finish exchange.
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
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.
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,
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;
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;
3045 + mutex_lock(&lport->lp_mutex);
3047 + if (fc_lport_debug)
3048 + FC_DBG("Received a FLOGI response\n");
3050 + if (lport->state != LPORT_ST_FLOGI) {
3051 + FC_DBG("Received a FLOGI response, but in state %s\n",
3052 + fc_lport_state(lport));
3057 - fc_lport_error(lp, fp);
3059 + fc_lport_error(lport, fp);
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) {
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);
3073 flp = fc_frame_payload_get(fp, sizeof(*flp));
3075 mfs = ntohs(flp->fl_csp.sp_bb_data) &
3077 if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
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)
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),
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);
3113 - fc_lport_unlock(lp);
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");
3125 FC_DBG("bad FLOGI response\n");
3129 + mutex_unlock(&lport->lp_mutex);
3134 - * Send ELS (extended link service) FLOGI request to peer.
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
3139 + * Locking Note: The lport lock is expected to be held before calling
3142 -static void fc_lport_flogi_send(struct fc_lport *lp)
3143 +void fc_lport_enter_flogi(struct fc_lport *lport)
3145 struct fc_frame *fp;
3146 struct fc_els_flogi *flp;
3148 - fp = fc_frame_alloc(lp, sizeof(*flp));
3149 + if (fc_lport_debug)
3150 + FC_DBG("Processing FLOGI state\n");
3152 + fc_lport_state_enter(lport, LPORT_ST_FLOGI);
3154 + fp = fc_frame_alloc(lport, sizeof(*flp));
3156 - return fc_lport_retry(lp);
3157 + return fc_lport_error(lport, fp);
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);
3163 fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
3164 fc_frame_set_offset(fp, 0);
3166 - if (!lp->tt.exch_seq_send(lp, fp,
3167 - fc_lport_flogi_resp,
3170 - FC_FC_SEQ_INIT | FC_FC_END_SEQ))
3171 - fc_lport_retry(lp);
3174 + if (!lport->tt.exch_seq_send(lport, fp,
3175 + fc_lport_flogi_resp, NULL,
3176 + lport, lport->e_d_tov,
3178 + FC_FC_SEQ_INIT | FC_FC_END_SEQ))
3179 + fc_lport_error(lport, fp);
3181 -void fc_lport_enter_flogi(struct fc_lport *lp)
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);
3189 /* Configure a fc_lport */
3190 -int fc_lport_config(struct fc_lport *lp)
3191 +int fc_lport_config(struct fc_lport *lport)
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);
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);
3203 - lp->ns_disc_delay = DNS_DELAY;
3204 + lport->disc_delay = DNS_DELAY;
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);
3213 EXPORT_SYMBOL(fc_lport_config);
3215 -int fc_lport_init(struct fc_lport *lp)
3216 +int fc_lport_init(struct fc_lport *lport)
3218 - if (!lp->tt.lport_recv)
3219 - lp->tt.lport_recv = fc_lport_recv;
3221 - if (!lp->tt.lport_login)
3222 - lp->tt.lport_login = fc_lport_enter_reset;
3224 - if (!lp->tt.lport_reset)
3225 - lp->tt.lport_reset = fc_lport_enter_reset;
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;
3232 + if (!lport->tt.lport_reset)
3233 + lport->tt.lport_reset = fc_lport_reset;
3235 + if (!lport->tt.event_callback)
3236 + lport->tt.event_callback = fc_lport_rport_event;
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;
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;
3261 diff --git a/drivers/scsi/libfc/fc_ns.c b/drivers/scsi/libfc/fc_ns.c
3262 deleted file mode 100644
3263 index 5c9272c..0000000
3264 --- a/drivers/scsi/libfc/fc_ns.c
3268 - * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
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.
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
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.
3283 - * Maintained at www.Open-FCoE.org
3287 - * Target Discovery
3288 - * Actually, this discovers all FC-4 remote ports, including FCP initiators.
3291 -#include <linux/timer.h>
3292 -#include <linux/err.h>
3293 -#include <asm/unaligned.h>
3295 -#include <scsi/fc/fc_gs.h>
3297 -#include <scsi/libfc/libfc.h>
3299 -#define FC_NS_RETRY_LIMIT 3 /* max retries */
3300 -#define FC_NS_RETRY_DELAY 500UL /* (msecs) delay */
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 *);
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()
3319 -struct fc_ns_port {
3320 - struct fc_lport *lp;
3321 - struct list_head peers;
3322 - struct fc_rport_identifiers ids;
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);
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,
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 *);
3344 - * fc_ns_rscn_req - Handle Registered State Change Notification (RSCN)
3345 - * @sp: Current sequence of the RSCN exchange
3347 - * @lp: Fibre Channel host port instance
3349 -static void fc_ns_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
3350 - struct fc_lport *lp)
3352 - struct fc_els_rscn *rp;
3353 - struct fc_els_rscn_page *pp;
3354 - struct fc_seq_els_data rjt_data;
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;
3362 - rp = fc_frame_payload_get(fp, sizeof(*rp));
3364 - if (!rp || rp->rscn_page_len != sizeof(*pp))
3367 - len = ntohs(rp->rscn_plen);
3368 - if (len < sizeof(*rp))
3370 - len -= sizeof(*rp);
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;
3378 - * if we get an address format other than port
3379 - * (area, domain, fabric), then do a full discovery
3382 - case ELS_ADDR_FMT_PORT:
3383 - dp = kzalloc(sizeof(*dp), GFP_KERNEL);
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);
3395 - case ELS_ADDR_FMT_AREA:
3396 - case ELS_ADDR_FMT_DOM:
3397 - case ELS_ADDR_FMT_FAB:
3403 - lp->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
3406 - FC_DBG("RSCN received: rediscovering\n");
3407 - list_for_each_entry_safe(dp, next, &disc_list, peers) {
3408 - list_del(&dp->peers);
3411 - fc_ns_restart(lp);
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);
3422 - fc_frame_free(fp);
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);
3432 -static void fc_ns_recv_req(struct fc_seq *sp, struct fc_frame *fp,
3433 - struct fc_lport *lp)
3435 - switch (fc_frame_payload_op(fp)) {
3437 - fc_ns_rscn_req(sp, fp, lp);
3440 - FC_DBG("fc_ns recieved an unexpected request\n");
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
3451 -static void fc_ns_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
3454 - struct fc_lport *lp = lp_arg;
3458 - fc_ns_error(lp, fp);
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);
3465 - FC_DBG("target discovery start error\n");
3466 - fc_frame_free(fp);
3471 - * fc_ns_enter scr - Send a State Change Register (SCR) request
3472 - * @lp: Fibre Channel host port instance
3474 -static void fc_ns_enter_scr(struct fc_lport *lp)
3476 - struct fc_frame *fp;
3477 - struct fc_els_scr *scr;
3480 - FC_DBG("Processing SCR state\n");
3482 - fc_lport_state_enter(lp, LPORT_ST_SCR);
3484 - fp = fc_frame_alloc(lp, sizeof(*scr));
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;
3491 - fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
3492 - fc_frame_set_offset(fp, 0);
3494 - lp->tt.exch_seq_send(lp, fp,
3497 - lp->fid, FC_FID_FCTRL,
3498 - FC_FC_SEQ_INIT | FC_FC_END_SEQ);
3502 - * fc_ns_enter_reg_ft - Register FC4-types with the name server
3503 - * @lp: Fibre Channel host port instance
3505 -static void fc_ns_enter_reg_ft(struct fc_lport *lp)
3507 - struct fc_frame *fp;
3509 - struct fc_ct_hdr ct;
3510 - struct fc_ns_fid fid; /* port ID object */
3511 - struct fc_ns_fts fts; /* FC4-types object */
3513 - struct fc_ns_fts *lps;
3517 - FC_DBG("Processing REG_FT state\n");
3519 - fc_lport_state_enter(lp, LPORT_ST_REG_FT);
3522 - i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
3524 - if (ntohl(lps->ff_type_map[i]) != 0)
3527 - fp = fc_frame_alloc(lp, sizeof(*req));
3529 - req = fc_frame_payload_get(fp, sizeof(*req));
3530 - fc_lport_fill_dns_hdr(lp, &req->ct,
3533 - sizeof(struct fc_ct_hdr));
3534 - hton24(req->fid.fp_fid, lp->fid);
3536 - fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
3537 - if (!lp->tt.exch_seq_send(lp, fp,
3541 - lp->dns_rp->port_id,
3549 - fc_ns_enter_scr(lp);
3554 - * enter next state for handling an exchange reject or retry exhaustion
3555 - * in the current state.
3557 -static void fc_ns_enter_reject(struct fc_lport *lp)
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:
3567 - case LPORT_ST_REG_PN:
3568 - fc_ns_enter_reg_ft(lp);
3570 - case LPORT_ST_REG_FT:
3571 - fc_ns_enter_scr(lp);
3573 - case LPORT_ST_SCR:
3574 - case LPORT_ST_DNS_STOP:
3575 - lp->tt.disc_stop(lp);
3577 - case LPORT_ST_DNS:
3578 - lp->tt.lport_reset(lp);
3583 -static void fc_ns_enter_retry(struct fc_lport *lp)
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:
3593 - case LPORT_ST_DNS:
3594 - lp->tt.dns_register(lp);
3596 - case LPORT_ST_DNS_STOP:
3597 - lp->tt.disc_stop(lp);
3599 - case LPORT_ST_REG_PN:
3600 - fc_ns_enter_reg_pn(lp);
3602 - case LPORT_ST_REG_FT:
3603 - fc_ns_enter_reg_ft(lp);
3605 - case LPORT_ST_SCR:
3606 - fc_ns_enter_scr(lp);
3612 - * Refresh target discovery, perhaps due to an RSCN.
3613 - * A configurable delay is introduced to collect any subsequent RSCNs.
3615 -static int fc_ns_restart(struct fc_lport *lp)
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));
3622 - lp->ns_disc_requested = 1;
3623 - fc_lport_unlock(lp);
3627 -/* unlocked varient of scsi_target_block from scsi_lib.c */
3628 -#include "../scsi_priv.h"
3630 -static void __device_block(struct scsi_device *sdev, void *data)
3632 - scsi_internal_device_block(sdev);
3635 -static int __target_block(struct device *dev, void *data)
3637 - if (scsi_is_target_device(dev))
3638 - __starget_for_each_device(to_scsi_target(dev),
3639 - NULL, __device_block);
3643 -static void __scsi_target_block(struct device *dev)
3645 - if (scsi_is_target_device(dev))
3646 - __starget_for_each_device(to_scsi_target(dev),
3647 - NULL, __device_block);
3649 - device_for_each_child(dev, NULL, __target_block);
3652 -static void fc_block_rports(struct fc_lport *lp)
3654 - struct Scsi_Host *shost = lp->host;
3655 - struct fc_rport *rport;
3656 - unsigned long flags;
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)
3663 - if (rport->port_state != FC_PORTSTATE_ONLINE)
3665 - rport->port_state = FC_PORTSTATE_BLOCKED;
3666 - rport->flags |= FC_RPORT_DEVLOSS_PENDING;
3667 - __scsi_target_block(&rport->dev);
3669 - spin_unlock_irqrestore(shost->host_lock, flags);
3673 - * Fibre Channel Target discovery.
3675 - * Returns non-zero if discovery cannot be started.
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.
3682 -int fc_ns_disc_start(struct fc_lport *lp)
3684 - struct fc_rport *rport;
3686 - struct fc_rport_identifiers ids;
3688 - fc_lport_lock(lp);
3691 - * If not ready, or already running discovery, just set request flag.
3693 - if (!fc_lport_test_ready(lp) || lp->ns_disc_pending) {
3694 - lp->ns_disc_requested = 1;
3695 - fc_lport_unlock(lp);
3698 - lp->ns_disc_pending = 1;
3699 - lp->ns_disc_requested = 0;
3700 - lp->ns_disc_retry_count = 0;
3703 - * Handle point-to-point mode as a simple discovery
3704 - * of the remote port.
3706 - rport = lp->ptp_rp;
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);
3717 - fc_ns_disc_done(lp);
3719 - fc_lport_unlock(lp);
3720 - fc_block_rports(lp);
3721 - fc_ns_gpn_ft_req(lp); /* get ports by FC-4 type */
3728 - * Handle resource allocation problem by retrying in a bit.
3730 -static void fc_ns_retry(struct fc_lport *lp)
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));
3740 - FC_DBG("local port %6x alloc failure "
3741 - "- retries exhausted\n", lp->fid);
3742 - fc_ns_enter_reject(lp);
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).
3751 -static void fc_ns_error(struct fc_lport *lp, struct fc_frame *fp)
3753 - if (lp->state == LPORT_ST_RESET)
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);
3762 - fc_ns_enter_reject(lp);
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);
3772 - * Restart discovery after a delay due to resource shortages.
3773 - * If the error persists, the discovery will be abandoned.
3775 -static void fcdt_ns_retry(struct fc_lport *lp)
3777 - unsigned long delay = FC_NS_RETRY_DELAY;
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));
3785 - fc_ns_disc_done(lp);
3789 - * Test for dNS accept in response payload.
3791 -static int fc_lport_dns_acc(struct fc_frame *fp)
3793 - struct fc_frame_header *fh;
3794 - struct fc_ct_hdr *ct;
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) {
3809 - * Handle response from name server.
3812 -fc_ns_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg)
3814 - struct fc_lport *lp = lp_arg;
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);
3823 - fc_ns_enter_scr(lp);
3828 - fc_lport_unlock(lp);
3829 - fc_frame_free(fp);
3831 - fc_ns_error(lp, fp);
3835 - * Handle new target found by discovery.
3836 - * Create remote port and session if needed.
3837 - * Ignore returns of our own FID & WWPN.
3839 - * If a non-NULL rp is passed in, it is held for the caller, but not for us.
3841 - * Events delivered are:
3842 - * FC_EV_READY, when remote port is rediscovered.
3844 -static int fc_ns_new_target(struct fc_lport *lp,
3845 - struct fc_rport *rport,
3846 - struct fc_rport_identifiers *ids)
3848 - struct fc_rport_libfc_priv *rp;
3851 - if (rport && ids->port_name) {
3852 - if (rport->port_name == -1) {
3854 - * Set WWN and fall through to notify of create.
3856 - fc_rport_set_name(rport, ids->port_name,
3857 - rport->node_name);
3858 - } else if (rport->port_name != ids->port_name) {
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.
3866 - fc_ns_del_target(lp, rport);
3870 - if (((ids->port_name != -1) || (ids->port_id != -1)) &&
3871 - ids->port_id != lp->fid && ids->port_name != lp->wwpn) {
3873 - rport = lp->tt.rport_lookup(lp, ids->port_id);
3874 - if (rport == NULL)
3875 - rport = lp->tt.rport_create(lp, ids);
3880 - rp = rport->dd_data;
3881 - rp->rp_state = RPORT_ST_INIT;
3882 - lp->tt.rport_login(rport);
3889 - * Delete the remote port.
3891 -static void fc_ns_del_target(struct fc_lport *lp, struct fc_rport *rport)
3893 - lp->tt.rport_reset(rport);
3894 - fc_remote_port_delete(rport); /* release hold from create */
3898 - * Done with discovery
3900 -static void fc_ns_disc_done(struct fc_lport *lp)
3902 - lp->ns_disc_done = 1;
3903 - lp->ns_disc_pending = 0;
3904 - if (lp->ns_disc_requested)
3905 - lp->tt.disc_start(lp);
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
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)
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);
3926 - * fc_ns_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request
3927 - * @lp: Fibre Channel host port instance
3929 -static void fc_ns_gpn_ft_req(struct fc_lport *lp)
3931 - struct fc_frame *fp;
3932 - struct fc_seq *sp = NULL;
3934 - struct fc_ct_hdr ct;
3935 - struct fc_ns_gid_ft gid;
3939 - lp->ns_disc_buf_len = 0;
3940 - lp->ns_disc_seq_count = 0;
3941 - fp = fc_frame_alloc(lp, sizeof(*rp));
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;
3949 - WARN_ON(!fc_lport_test_ready(lp));
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,
3956 - lp->dns_rp->port_id,
3957 - FC_FC_SEQ_INIT | FC_FC_END_SEQ);
3959 - if (error || sp == NULL)
3960 - fcdt_ns_retry(lp);
3964 - * Handle error on dNS request.
3966 -static void fcdt_ns_error(struct fc_lport *lp, struct fc_frame *fp)
3968 - int err = PTR_ERR(fp);
3971 - case -FC_EX_TIMEOUT:
3972 - if (lp->ns_disc_retry_count++ < FC_NS_RETRY_LIMIT) {
3973 - fc_ns_gpn_ft_req(lp);
3975 - FC_DBG("err %d - ending\n", err);
3976 - fc_ns_disc_done(lp);
3980 - FC_DBG("err %d - ending\n", err);
3981 - fc_ns_disc_done(lp);
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
3992 -static int fc_ns_gpn_ft_parse(struct fc_lport *lp, void *buf, size_t len)
3994 - struct fc_gpn_ft_resp *np;
3999 - struct fc_ns_port *dp;
4002 - * Handle partial name record left over from previous call.
4006 - np = (struct fc_gpn_ft_resp *)bp;
4007 - tlen = lp->ns_disc_buf_len;
4009 - WARN_ON(tlen >= sizeof(*np));
4010 - plen = sizeof(*np) - tlen;
4011 - WARN_ON(plen <= 0);
4012 - WARN_ON(plen >= sizeof(*np));
4015 - np = &lp->ns_disc_buf;
4016 - memcpy((char *)np + tlen, bp, plen);
4019 - * Set bp so that the loop below will advance it to the
4020 - * first valid full name element.
4025 - lp->ns_disc_buf_len = (unsigned char) plen;
4026 - if (plen == sizeof(*np))
4027 - lp->ns_disc_buf_len = 0;
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".
4037 - while (plen >= sizeof(*np)) {
4038 - dp = kzalloc(sizeof(*dp), GFP_KERNEL);
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);
4049 - if (np->fp_flags & FC_NS_FID_LAST) {
4050 - fc_ns_disc_done(lp);
4054 - len -= sizeof(*np);
4055 - bp += sizeof(*np);
4056 - np = (struct fc_gpn_ft_resp *)bp;
4061 - * Save any partial record at the end of the buffer for next time.
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;
4068 - lp->ns_disc_buf_len = 0;
4074 - * Handle retry of memory allocation for remote ports.
4076 -static void fc_ns_timeout(struct work_struct *work)
4078 - struct fc_lport *lp;
4080 - lp = container_of(work, struct fc_lport, ns_disc_work.work);
4082 - if (lp->ns_disc_pending)
4083 - fc_ns_gpn_ft_req(lp);
4085 - lp->tt.disc_start(lp);
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
4094 - * The response may be in multiple frames
4096 -static void fc_ns_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
4099 - struct fc_lport *lp = lp_arg;
4100 - struct fc_ct_hdr *cp;
4101 - struct fc_frame_header *fh;
4102 - unsigned int seq_cnt;
4108 - fcdt_ns_error(lp, fp);
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));
4120 - FC_DBG("GPN_FT response too short, len %d\n",
4122 - } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
4125 - * Accepted. Parse response.
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,
4133 - fc_ns_disc_done(lp);
4135 - FC_DBG("GPN_FT unexpected response code %x\n",
4136 - ntohs(cp->ct_cmd));
4138 - } else if (fr_sof(fp) == FC_SOF_N3 &&
4139 - seq_cnt == lp->ns_disc_seq_count) {
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));
4147 - error = fc_ns_gpn_ft_parse(lp, buf, len);
4149 - fcdt_ns_retry(lp);
4151 - lp->ns_disc_seq_count++;
4153 - fc_frame_free(fp);
4157 - * Discover the directory information for a single target.
4158 - * This could be from an RSCN that reported a change for the target.
4160 -static void fc_ns_single(struct fc_lport *lp, struct fc_ns_port *dp)
4162 - struct fc_rport *rport;
4164 - if (dp->ids.port_id == lp->fid)
4167 - rport = lp->tt.rport_lookup(lp, dp->ids.port_id);
4169 - fc_ns_del_target(lp, rport);
4170 - put_device(&rport->dev); /* hold from lookup */
4173 - if (fc_ns_gpn_id_req(lp, dp) != 0)
4177 - fc_ns_restart(lp);
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
4187 - * The remote port is held by the caller for us.
4189 -static int fc_ns_gpn_id_req(struct fc_lport *lp, struct fc_ns_port *dp)
4191 - struct fc_frame *fp;
4193 - struct fc_ct_hdr ct;
4194 - struct fc_ns_fid fid;
4198 - fp = fc_frame_alloc(lp, sizeof(*cp));
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);
4206 - WARN_ON(!fc_lport_test_ready(lp));
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,
4213 - lp->dns_rp->port_id,
4214 - FC_FC_SEQ_INIT | FC_FC_END_SEQ))
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
4226 -static void fc_ns_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
4229 - struct fc_ns_port *dp = dp_arg;
4230 - struct fc_lport *lp;
4232 - struct fc_ct_hdr ct;
4238 - fc_ns_gpn_id_error(dp, fp);
4243 - WARN_ON(!fc_frame_is_linear(fp)); /* buffer must be contiguous */
4245 - cp = fc_frame_payload_get(fp, sizeof(cp->ct));
4247 - FC_DBG("GPN_ID response too short, len %d\n", fr_len(fp));
4250 - cmd = ntohs(cp->ct.ct_cmd);
4253 - cp = fc_frame_payload_get(fp, sizeof(*cp));
4255 - FC_DBG("GPN_ID response payload too short, len %d\n",
4259 - dp->ids.port_name = ntohll(cp->wwn);
4260 - fc_ns_gnn_id_req(lp, dp);
4263 - fc_ns_restart(lp);
4266 - FC_DBG("GPN_ID unexpected CT response cmd %x\n", cmd);
4269 - fc_frame_free(fp);
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
4277 -static void fc_ns_gpn_id_error(struct fc_ns_port *dp, struct fc_frame *fp)
4279 - struct fc_lport *lp = dp->lp;
4281 - switch (PTR_ERR(fp)) {
4282 - case -FC_EX_TIMEOUT:
4283 - fc_ns_restart(lp);
4285 - case -FC_EX_CLOSED:
4293 - * Setup session to dNS if not already set up.
4295 -static void fc_ns_enter_dns(struct fc_lport *lp)
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,
4303 - .roles = FC_RPORT_ROLE_UNKNOWN,
4307 - FC_DBG("Processing DNS state\n");
4309 - fc_lport_state_enter(lp, LPORT_ST_DNS);
4311 - if (!lp->dns_rp) {
4313 - * Set up remote port to directory server.
4317 - * we are called with the state_lock, but if rport_lookup_create
4318 - * needs to create a rport then it will sleep.
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);
4327 - lp->dns_rp = rport;
4330 - rport = lp->dns_rp;
4331 - rp = rport->dd_data;
4334 - * If dNS session isn't ready, start its logon.
4336 - if (rp->rp_state != RPORT_ST_READY) {
4337 - lp->tt.rport_login(rport);
4339 - del_timer(&lp->state_timer);
4340 - fc_ns_enter_reg_pn(lp);
4345 - * Resource allocation problem (malloc). Try again in 500 mS.
4352 - * Logoff DNS session.
4353 - * We should get an event call when the session has been logged out.
4355 -static void fc_ns_enter_dns_stop(struct fc_lport *lp)
4357 - struct fc_rport *rport = lp->dns_rp;
4360 - FC_DBG("Processing DNS_STOP state\n");
4362 - fc_lport_state_enter(lp, LPORT_ST_DNS_STOP);
4365 - lp->tt.rport_logout(rport);
4367 - lp->tt.lport_logout(lp);
4371 - * Fill in dNS request header.
4374 -fc_lport_fill_dns_hdr(struct fc_lport *lp, struct fc_ct_hdr *ct,
4375 - unsigned int op, unsigned int req_size)
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);
4385 - * Register port name with name server.
4387 -static void fc_ns_enter_reg_pn(struct fc_lport *lp)
4389 - struct fc_frame *fp;
4391 - struct fc_ct_hdr ct;
4392 - struct fc_ns_rn_id rn;
4396 - FC_DBG("Processing REG_PN state\n");
4398 - fc_lport_state_enter(lp, LPORT_ST_REG_PN);
4399 - fp = fc_frame_alloc(lp, sizeof(*req));
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,
4414 - lp->dns_rp->port_id,
4415 - FC_FC_SEQ_INIT | FC_FC_END_SEQ))
4419 -int fc_ns_init(struct fc_lport *lp)
4421 - INIT_DELAYED_WORK(&lp->ns_disc_work, fc_ns_timeout);
4423 - if (!lp->tt.disc_start)
4424 - lp->tt.disc_start = fc_ns_disc_start;
4426 - if (!lp->tt.disc_recv_req)
4427 - lp->tt.disc_recv_req = fc_ns_recv_req;
4429 - if (!lp->tt.dns_register)
4430 - lp->tt.dns_register = fc_ns_enter_dns;
4432 - if (!lp->tt.disc_stop)
4433 - lp->tt.disc_stop = fc_ns_enter_dns_stop;
4437 -EXPORT_SYMBOL(fc_ns_init);
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
4444 - * The remote port is held by the caller for us.
4446 -static int fc_ns_gnn_id_req(struct fc_lport *lp, struct fc_ns_port *dp)
4448 - struct fc_frame *fp;
4450 - struct fc_ct_hdr ct;
4451 - struct fc_ns_fid fid;
4455 - fp = fc_frame_alloc(lp, sizeof(*cp));
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);
4463 - WARN_ON(!fc_lport_test_ready(lp));
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,
4470 - lp->dns_rp->port_id,
4471 - FC_FC_SEQ_INIT | FC_FC_END_SEQ))
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
4483 -static void fc_ns_gnn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
4486 - struct fc_ns_port *dp = dp_arg;
4487 - struct fc_lport *lp;
4489 - struct fc_ct_hdr ct;
4495 - fc_ns_gnn_id_error(dp, fp);
4500 - WARN_ON(!fc_frame_is_linear(fp)); /* buffer must be contiguous */
4502 - cp = fc_frame_payload_get(fp, sizeof(cp->ct));
4504 - FC_DBG("GNN_ID response too short, len %d\n", fr_len(fp));
4507 - cmd = ntohs(cp->ct.ct_cmd);
4510 - cp = fc_frame_payload_get(fp, sizeof(*cp));
4512 - FC_DBG("GNN_ID response payload too short, len %d\n",
4516 - dp->ids.node_name = ntohll(cp->wwn);
4517 - fc_ns_new_target(lp, NULL, &dp->ids);
4520 - fc_ns_restart(lp);
4523 - FC_DBG("GNN_ID unexpected CT response cmd %x\n", cmd);
4527 - fc_frame_free(fp);
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
4535 -static void fc_ns_gnn_id_error(struct fc_ns_port *dp, struct fc_frame *fp)
4537 - struct fc_lport *lp = dp->lp;
4539 - switch (PTR_ERR(fp)) {
4540 - case -FC_EX_TIMEOUT:
4541 - fc_ns_restart(lp);
4543 - case -FC_EX_CLOSED:
4550 diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
4551 index 6d0c970..107b304 100644
4552 --- a/drivers/scsi/libfc/fc_rport.c
4553 +++ b/drivers/scsi/libfc/fc_rport.c
4556 static int fc_rp_debug;
4559 - * static functions.
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 *);
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 *);
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",
4587 +struct fc_rport *fc_rport_dummy_create(struct fc_disc_port *dp)
4589 + struct fc_rport *rport;
4590 + struct fc_rport_libfc_priv *rdata;
4591 + rport = kzalloc(sizeof(*rport) + sizeof(*rdata), GFP_KERNEL);
4593 -static struct fc_rport *fc_remote_port_create(struct fc_lport *,
4594 - struct fc_rport_identifiers *);
4598 + rdata = RPORT_TO_PRIV(rport);
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;
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);
4621 +void fc_rport_dummy_destroy(struct fc_rport *rport)
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
4630 +static const char *fc_rport_state(struct fc_rport *rport)
4633 + struct fc_rport_libfc_priv *rdata = rport->dd_data;
4635 + cp = fc_rport_state_names[rdata->rp_state];
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)
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
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)
4658 - struct fc_rport_libfc_priv *rp;
4659 - struct fc_rport *rport;
4661 - rport = fc_remote_port_add(lp->host, 0, ids);
4665 - rp = rport->dd_data;
4666 - rp->local_port = lp;
4668 - /* default value until service parameters are exchanged in PLOGI */
4669 - rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
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);
4682 -static inline void fc_rport_lock(struct fc_rport *rport)
4684 - struct fc_rport_libfc_priv *rp = rport->dd_data;
4685 - spin_lock_bh(&rp->rp_lock);
4688 -static inline void fc_rport_unlock(struct fc_rport *rport)
4690 - struct fc_rport_libfc_priv *rp = rport->dd_data;
4691 - spin_unlock_bh(&rp->rp_lock);
4693 + rport->dev_loss_tmo = timeout + 5;
4695 + rport->dev_loss_tmo = 30;
4697 +EXPORT_SYMBOL(fc_set_rport_loss_tmo);
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)
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
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)
4715 struct fc_els_csp *sp;
4716 @@ -163,266 +191,241 @@ fc_lport_plogi_fill(struct fc_lport *lp,
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);
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);
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;
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
4752 + * Locking Note: Called with the rport lock held
4754 static void fc_rport_state_enter(struct fc_rport *rport,
4755 enum fc_rport_state new)
4757 - struct fc_rport_libfc_priv *rp = rport->dd_data;
4758 - if (rp->rp_state != new)
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;
4767 +static void fc_rport_unlock(struct fc_rport *rport)
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;
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;
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;
4787 + new_rport = fc_remote_port_add(lport->host, 0, &ids);
4790 + * Switch from the dummy rport to the rport
4791 + * returned by the FC class.
4793 + new_rport->maxframe_size = rport->maxframe_size;
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);
4806 + fc_rport_state_enter(new_rport, RPORT_ST_READY);
4807 + fc_remote_port_rolechg(new_rport, rdata->roles);
4809 + FC_DBG("Failed to create the rport for port "
4810 + "(%6x).\n", ids.port_id);
4811 + event = LPORT_EV_RPORT_FAILED;
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);
4824 + mutex_unlock(&rdata->rp_mutex);
4825 + fc_remote_port_delete(rport);
4828 + mutex_unlock(&rdata->rp_mutex);
4831 + if (event != LPORT_EV_RPORT_NONE && event_callback) {
4832 + event_callback(lport, fid, event);
4833 + rdata->event = LPORT_EV_RPORT_NONE;
4838 * fc_rport_login - Start the remote port login state machine
4839 * @rport: Fibre Channel remote port
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.
4845 int fc_rport_login(struct fc_rport *rport)
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;
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);
4859 - FC_DBG("remote %6x closed\n", rport->port_id);
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;
4867 - if (lp->state == LPORT_ST_DNS_STOP) {
4868 - fc_lport_unlock(lp);
4869 - lp->tt.lport_logout(lp);
4871 - lp->tt.lport_login(lp);
4872 - fc_lport_unlock(lp);
4874 - fc_remote_port_delete(rport);
4877 - fc_rport_unlock(rport);
4878 + mutex_lock(&rdata->rp_mutex);
4881 + FC_DBG("Login to port (%6x)\n", rport->port_id);
4883 + fc_rport_enter_plogi(rport);
4885 + fc_rport_unlock(rport);
4891 - * Stop the session - log it off.
4893 + * fc_rport_logout - Logout of the remote port and delete it
4894 + * @rport: Fibre Channel remote port
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.
4900 int fc_rport_logout(struct fc_rport *rport)
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;
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);
4915 - fc_rport_state_enter(rport, RPORT_ST_INIT);
4916 - fc_rport_unlock(rport);
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;
4925 - if (lp->state == LPORT_ST_DNS_STOP) {
4926 - fc_lport_unlock(lp);
4927 - lp->tt.lport_logout(lp);
4929 - lp->tt.lport_login(lp);
4930 - fc_lport_unlock(lp);
4932 + mutex_lock(&rdata->rp_mutex);
4934 - fc_remote_port_delete(rport);
4939 + FC_DBG("Logout of port (%6x)\n", rport->port_id);
4941 + fc_rport_enter_logo(rport);
4942 + fc_rport_unlock(rport);
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.
4951 + * fc_rport_reset - Reset the remote port
4952 + * @rport: Fibre Channel remote port
4954 + * XXX - This functionality is currently broken
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.
4960 void fc_rport_reset(struct fc_rport *rport)
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;
4966 + mutex_lock(&rdata->rp_mutex);
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);
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);
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);
4989 - lp->tt.lport_login(lp);
4990 - fc_lport_unlock(lp);
4992 - fc_remote_port_delete(rport);
4994 + fc_rport_unlock(rport);
4998 - * Reset all sessions for a local port session list.
5000 + * fc_rport_reset_list - Reset all sessions for a local port session list.
5001 + * @lport: The lport whose rports should be reset
5003 + * Locking Note: TBD
5005 -void fc_rport_reset_list(struct fc_lport *lp)
5006 +void fc_rport_reset_list(struct fc_lport *lport)
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;
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);
5019 spin_unlock_irqrestore(shost->host_lock, flags);
5022 -static void fc_rport_enter_start(struct fc_rport *rport)
5024 + * fc_rport_enter_ready - The rport is ready
5025 + * @rport: Fibre Channel remote port that is ready
5027 + * Locking Note: The rport lock is expected to be held before calling
5030 +static void fc_rport_enter_ready(struct fc_rport *rport)
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;
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().
5040 - fc_rport_state_enter(rport, RPORT_ST_STARTED);
5041 + fc_rport_state_enter(rport, RPORT_ST_READY);
5043 - if (rport == lp->dns_rp || fc_lport_test_ready(lp))
5044 - fc_rport_enter_plogi(rport);
5047 + FC_DBG("Port (%6x) is Ready\n", rport->port_id);
5050 - * Handle exchange reject or retry exhaustion in various states.
5052 -static void fc_rport_reject(struct fc_rport *rport)
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);
5069 - lp->tt.lport_login(lp);
5070 - fc_lport_unlock(lp);
5072 - fc_remote_port_delete(rport);
5075 - case RPORT_ST_RTV:
5076 - fc_rport_state_enter(rport, RPORT_ST_READY);
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);
5087 - case RPORT_ST_LOGO:
5088 - fc_rport_state_enter(rport, RPORT_ST_INIT);
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);
5100 - lp->tt.lport_login(lp);
5101 - fc_lport_unlock(lp);
5103 - fc_remote_port_delete(rport);
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:
5116 + rdata->event = LPORT_EV_RPORT_CREATED;
5120 - * Timeout handler for retrying after allocation failures or exchange timeout.
5122 + * fc_rport_timeout - Handler for the retry_work timer.
5123 + * @work: The work struct of the fc_rport_libfc_priv
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.
5129 static void fc_rport_timeout(struct work_struct *work)
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);
5137 - switch (rp->rp_state) {
5138 + mutex_lock(&rdata->rp_mutex);
5140 + switch (rdata->rp_state) {
5141 case RPORT_ST_PLOGI:
5142 fc_rport_enter_plogi(rport);
5144 @@ -436,149 +439,178 @@ static void fc_rport_timeout(struct work_struct *work)
5145 fc_rport_enter_logo(rport);
5147 case RPORT_ST_READY:
5148 - case RPORT_ST_ERROR:
5152 - case RPORT_ST_PLOGI_RECV:
5153 - case RPORT_ST_STARTED:
5157 put_device(&rport->dev);
5161 - * Handle retry for allocation failure via timeout.
5163 -static void fc_rport_retry(struct fc_rport *rport)
5165 - struct fc_rport_libfc_priv *rp = rport->dd_data;
5166 - struct fc_lport *lp = rp->local_port;
5168 - if (rp->retries < lp->max_retry_count) {
5170 - get_device(&rport->dev);
5171 - schedule_delayed_work(&rp->retry_work,
5172 - msecs_to_jiffies(rp->e_d_tov));
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);
5179 + fc_rport_unlock(rport);
5183 - * Handle error from a sequence issued by the rport state machine.
5185 + * fc_rport_error - Handler for any errors
5186 + * @rport: The fc_rport object
5187 + * @fp: The frame pointer
5189 + * If the error was caused by a resource allocation failure
5190 + * then wait for half a second and retry, otherwise retry
5193 + * Locking Note: The rport lock is expected to be held before
5194 + * calling this routine
5196 static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
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;
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);
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) {
5214 + delay = msecs_to_jiffies(500);
5215 get_device(&rport->dev);
5216 - schedule_delayed_work(&rp->retry_work, 0);
5218 - fc_rport_reject(rport);
5219 + schedule_delayed_work(&rdata->retry_work, delay);
5221 + switch (rdata->rp_state) {
5222 + case RPORT_ST_PLOGI:
5223 + case RPORT_ST_PRLI:
5224 + case RPORT_ST_LOGO:
5226 + FC_DBG("Remote port (%6x) closed.\n",
5229 - fc_rport_unlock(rport);
5230 + fc_remote_port_delete(rport);
5232 + rdata->event = LPORT_EV_RPORT_FAILED;
5234 + case RPORT_ST_RTV:
5235 + fc_rport_enter_ready(rport);
5237 + case RPORT_ST_NONE:
5238 + case RPORT_ST_READY:
5239 + case RPORT_ST_INIT:
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
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.
5257 static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
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;
5270 - struct fc_rport *rport = rp_arg;
5271 - struct fc_rport_libfc_priv *rp = rport->dd_data;
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);
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)
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);
5299 - FC_DBG("bad PLOGI response\n");
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 */
5306 - fc_rport_reject(rport); /* error */
5308 - fc_rport_unlock(rport);
5309 - fc_frame_free(fp);
5312 + FC_DBG("Received a PLOGI response\n");
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));
5321 fc_rport_error(rport, fp);
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)
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);
5342 + * If the rport is one of the well known addresses
5343 + * we skip PRLI and RTV and go straight to READY.
5345 + if (rport->port_id >= FC_FID_DOM_MGR)
5346 + fc_rport_enter_ready(rport);
5348 + fc_rport_enter_prli(rport);
5350 + fc_rport_error(rport, fp);
5353 + fc_rport_unlock(rport);
5354 + fc_frame_free(fp);
5358 * fc_rport_enter_plogi - Send Port Login (PLOGI) request to peer
5359 * @rport: Fibre Channel remote port to send PLOGI to
5361 + * Locking Note: The rport lock is expected to be held before calling
5364 static void fc_rport_enter_plogi(struct fc_rport *rport)
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;
5373 - lp = rp->local_port;
5375 + FC_DBG("Port (%6x) entered PLOGI state from %s state\n",
5376 + rport->port_id, fc_rport_state(rport));
5378 fc_rport_state_enter(rport, RPORT_ST_PLOGI);
5380 rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
5381 - fp = fc_frame_alloc(lp, sizeof(*plogi));
5383 - return fc_rport_retry(rport);
5384 + fp = fc_frame_alloc(lport, sizeof(*plogi));
5386 + fc_rport_error(rport, fp);
5390 plogi = fc_frame_payload_get(fp, sizeof(*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,
5402 - FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5403 - fc_rport_retry(rport);
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,
5410 + FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5411 + fc_rport_error(rport, fp);
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
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.
5424 static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
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;
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,
5438 + mutex_lock(&rdata->rp_mutex);
5441 + FC_DBG("Received a PRLI response\n");
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));
5450 fc_rport_error(rport, fp);
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;
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;
5471 + rdata->roles = roles;
5472 fc_rport_enter_rtv(rport);
5473 - fc_rport_unlock(rport);
5474 - fc_remote_port_rolechg(rport, roles);
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);
5488 - lp->tt.lport_login(lp);
5489 - fc_lport_unlock(lp);
5491 - fc_remote_port_delete(rport);
5493 + FC_DBG("Bad ELS response\n");
5494 + rdata->event = LPORT_EV_RPORT_FAILED;
5495 + fc_remote_port_delete(rport);
5499 + fc_rport_unlock(rport);
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
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.
5512 static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
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;
5521 + mutex_lock(&rdata->rp_mutex);
5524 + FC_DBG("Received a LOGO response\n");
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));
5533 fc_rport_error(rport, fp);
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);
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);
5556 - lp->tt.lport_login(lp);
5557 - fc_lport_unlock(lp);
5559 - fc_remote_port_delete(rport);
5561 + FC_DBG("Bad ELS response\n");
5562 + rdata->event = LPORT_EV_RPORT_LOGO;
5563 + fc_remote_port_delete(rport);
5567 + fc_rport_unlock(rport);
5572 * fc_rport_enter_prli - Send Process Login (PRLI) request to peer
5573 * @rport: Fibre Channel remote port to send PRLI to
5575 + * Locking Note: The rport lock is expected to be held before calling
5578 static void fc_rport_enter_prli(struct fc_rport *rport)
5580 + struct fc_rport_libfc_priv *rdata = rport->dd_data;
5581 + struct fc_lport *lport = rdata->local_port;
5583 struct fc_els_prli prli;
5584 struct fc_els_spp spp;
5586 struct fc_frame *fp;
5587 - struct fc_rport_libfc_priv *rp = rport->dd_data;
5588 - struct fc_lport *lp = rp->local_port;
5591 + FC_DBG("Port (%6x) entered PRLI state from %s state\n",
5592 + rport->port_id, fc_rport_state(rport));
5594 fc_rport_state_enter(rport, RPORT_ST_PRLI);
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.
5601 - if (rport->port_id >= FC_FID_DOM_MGR) {
5602 - fc_rport_state_enter(rport, RPORT_ST_READY);
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);
5612 + fp = fc_frame_alloc(lport, sizeof(*pp));
5614 + fc_rport_error(rport, fp);
5617 - fp = fc_frame_alloc(lp, sizeof(*pp));
5619 - return fc_rport_retry(rport);
5621 pp = fc_frame_payload_get(fp, sizeof(*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,
5637 - FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5638 - fc_rport_retry(rport);
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);
5649 @@ -756,21 +783,34 @@ static void fc_rport_enter_prli(struct fc_rport *rport)
5650 * @rp_arg: Fibre Channel remote port
5652 * Many targets don't seem to support this.
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.
5658 static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
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;
5667 + mutex_lock(&rdata->rp_mutex);
5670 + FC_DBG("Received a RTV response\n");
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));
5679 fc_rport_error(rport, fp);
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);
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)
5699 - rp->e_d_tov = tov;
5700 + rdata->e_d_tov = tov;
5703 - fc_rport_state_enter(rport, RPORT_ST_READY);
5705 + fc_rport_enter_ready(rport);
5708 fc_rport_unlock(rport);
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);
5722 * fc_rport_enter_rtv - Send Request Timeout Value (RTV) request to peer
5723 * @rport: Fibre Channel remote port to send RTV to
5725 + * Locking Note: The rport lock is expected to be held before calling
5728 static void fc_rport_enter_rtv(struct fc_rport *rport)
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;
5738 + FC_DBG("Port (%6x) entered RTV state from %s state\n",
5739 + rport->port_id, fc_rport_state(rport));
5741 - lp = rp->local_port;
5742 fc_rport_state_enter(rport, RPORT_ST_RTV);
5744 - fp = fc_frame_alloc(lp, sizeof(*rtv));
5746 - return fc_rport_retry(rport);
5747 + fp = fc_frame_alloc(lport, sizeof(*rtv));
5749 + fc_rport_error(rport, fp);
5753 rtv = fc_frame_payload_get(fp, sizeof(*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,
5763 - FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5764 - fc_rport_retry(rport);
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);
5775 * fc_rport_enter_logo - Send Logout (LOGO) request to peer
5776 * @rport: Fibre Channel remote port to send LOGO to
5778 + * Locking Note: The rport lock is expected to be held before calling
5781 static void fc_rport_enter_logo(struct fc_rport *rport)
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;
5791 + FC_DBG("Port (%6x) entered LOGO state from %s state\n",
5792 + rport->port_id, fc_rport_state(rport));
5794 fc_rport_state_enter(rport, RPORT_ST_LOGO);
5796 - lp = rp->local_port;
5797 - fp = fc_frame_alloc(lp, sizeof(*logo));
5799 - return fc_rport_retry(rport);
5800 + fp = fc_frame_alloc(lport, sizeof(*logo));
5802 + fc_rport_error(rport, fp);
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);
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,
5820 - FC_FC_SEQ_INIT | FC_FC_END_SEQ))
5821 - fc_rport_retry(rport);
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);
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.
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
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.
5846 void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
5847 struct fc_rport *rport)
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;
5853 struct fc_frame_header *fh;
5854 - struct fc_lport *lp = rp->local_port;
5855 struct fc_seq_els_data els_data;
5858 + mutex_lock(&rdata->rp_mutex);
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,
5867 - lp->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
5868 + lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
5872 - lp->tt.seq_els_rsp_send(sp, ELS_REC, &els_data);
5873 + lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data);
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);
5883 - fc_frame_free(fp);
5886 + fc_rport_unlock(rport);
5887 + fc_frame_free(fp);
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
5896 + * Locking Note: The rport lock is exected to be held before calling
5899 static void fc_rport_recv_plogi_req(struct fc_rport *rport,
5900 struct fc_seq *sp, struct fc_frame *rx_fp)
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;
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;
5912 @@ -944,9 +1007,15 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
5914 enum fc_els_rjt_reason reject = 0;
5919 fh = fc_frame_header_get(fp);
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));
5926 sid = ntoh24(fh->fh_s_id);
5927 pl = fc_frame_payload_get(fp, sizeof(*pl));
5929 @@ -958,8 +1027,6 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
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;
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.
5942 - switch (rp->rp_state) {
5943 + switch (rdata->rp_state) {
5946 FC_DBG("incoming PLOGI from %6x wwpn %llx state INIT "
5947 "- reject\n", sid, wwpn);
5948 reject = ELS_RJT_UNSUP;
5950 - case RPORT_ST_STARTED:
5952 - * we'll only accept a login if the port name
5953 - * matches or was unknown.
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;
5962 case RPORT_ST_PLOGI:
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;
5972 - case RPORT_ST_ERROR:
5973 case RPORT_ST_READY:
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 */
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);
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);
5996 - fp = fc_frame_alloc(lp, sizeof(*pl));
5997 + fp = fc_frame_alloc(lport, sizeof(*pl));
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);
6006 - sp = lp->tt.seq_start_next(sp);
6007 + sp = lport->tt.seq_start_next(sp);
6009 fc_rport_set_name(rport, wwpn, wwnn);
6011 @@ -1036,11 +1090,11 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
6012 * Get session payload size from incoming PLOGI.
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));
6020 - fc_lport_plogi_fill(lp, pl, ELS_LS_ACC);
6021 + fc_lport_plogi_fill(lport, pl, ELS_LS_ACC);
6024 * Send LS_ACC. If this fails,
6025 @@ -1048,15 +1102,11 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
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);
6035 - fc_rport_state_enter(rport,
6036 - RPORT_ST_PLOGI_RECV);
6039 - fc_rport_unlock(rport);
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
6048 + * Locking Note: The rport lock is exected to be held before calling
6051 static void fc_rport_recv_prli_req(struct fc_rport *rport,
6052 struct fc_seq *sp, struct fc_frame *rx_fp)
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;
6058 struct fc_frame *fp;
6059 struct fc_frame_header *fh;
6060 - struct fc_lport *lp;
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,
6067 u32 roles = FC_RPORT_ROLE_UNKNOWN;
6071 fh = fc_frame_header_get(rx_fp);
6072 - lp = rp->local_port;
6073 - switch (rp->rp_state) {
6074 - case RPORT_ST_PLOGI_RECV:
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));
6081 + switch (rdata->rp_state) {
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,
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);
6096 - sp = lp->tt.seq_start_next(sp);
6097 + sp = lport->tt.seq_start_next(sp);
6099 pp = fc_frame_payload_get(fp, len);
6101 @@ -1156,15 +1214,16 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
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;
6116 - htonl(rp->local_port->service_params);
6117 + htonl(lport->service_params);
6120 resp = FC_SPP_RESP_INVL;
6121 @@ -1181,32 +1240,20 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
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);
6129 * Get lock and re-check state.
6131 - fc_rport_lock(rport);
6132 - switch (rp->rp_state) {
6133 - case RPORT_ST_PLOGI_RECV:
6134 + switch (rdata->rp_state) {
6136 - fc_rport_state_enter(rport, RPORT_ST_READY);
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);
6146 + fc_rport_enter_ready(rport);
6148 case RPORT_ST_READY:
6153 - fc_rport_unlock(rport);
6155 fc_frame_free(rx_fp);
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
6162 + * Locking Note: The rport lock is exected to be held before calling
6165 static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
6166 struct fc_frame *fp)
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;
6172 struct fc_frame_header *fh;
6173 - struct fc_lport *lp = rp->local_port;
6174 struct fc_seq_els_data rjt_data;
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);
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));
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);
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
6198 + * Locking Note: The rport lock is exected to be held before calling
6201 static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp,
6202 struct fc_frame *fp)
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;
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);
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);
6226 - lp->tt.lport_login(lp);
6227 - fc_lport_unlock(lp);
6229 - fc_remote_port_delete(rport);
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));
6236 + rdata->event = LPORT_EV_RPORT_LOGO;
6238 + lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
6242 -int fc_rport_init(struct fc_lport *lp)
6243 +int fc_rport_init(struct fc_lport *lport)
6245 - if (!lp->tt.rport_login)
6246 - lp->tt.rport_login = fc_rport_login;
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;
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;
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;
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;
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;
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;
6280 EXPORT_SYMBOL(fc_rport_init);
6283 + * fc_block_rports - delete all the remote ports, on reset or link down
6284 + * @lp: libfc local port instance
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.
6290 +void fc_block_rports(struct fc_lport *lp)
6292 + struct Scsi_Host *shost = lp->host;
6293 + struct fc_rport *rport, *next;
6294 + unsigned long flags;
6295 + LIST_HEAD(rports);
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)
6302 + if (rport->port_state != FC_PORTSTATE_ONLINE)
6304 + list_move_tail(&rport->peers, &rports);
6306 + spin_unlock_irqrestore(shost->host_lock, flags);
6308 + list_for_each_entry(rport, &rports, peers) {
6309 + fc_remote_port_delete(rport);
6312 + spin_lock_irqsave(shost->host_lock, flags);
6313 + list_splice(&rports, &fc_host_rports(shost));
6314 + spin_unlock_irqrestore(shost->host_lock, flags);
6317 +void fc_rport_terminate_io(struct fc_rport *rport)
6319 + struct fc_rport_libfc_priv *rp = rport->dd_data;
6320 + struct fc_lport *lp = rp->local_port;
6322 + lp->tt.exch_mgr_reset(lp->emp, 0, rport->port_id);
6323 + lp->tt.exch_mgr_reset(lp->emp, rport->port_id, 0);
6325 +EXPORT_SYMBOL(fc_rport_terminate_io);
6326 diff --git a/include/scsi/fc/fc_fcoe.h b/include/scsi/fc/fc_fcoe.h
6327 index 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)
6335 - * VLAN header. This is also defined in linux/if_vlan.h, but for kernels only.
6337 -struct fcoe_vlan_hdr {
6338 - __be16 vlan_tag; /* VLAN tag including priority */
6339 - __be16 vlan_ethertype; /* encapsulated ethertype ETH_P_FCOE */
6343 #define ETH_P_8021Q 0x8100
6345 diff --git a/include/scsi/fc/fc_fs.h b/include/scsi/fc/fc_fs.h
6346 index 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 */
6354 - * Data descriptor format (R_CTL == FC_RCTL_DD_DATA_DESC).
6355 - * This is used for FCP SCSI transfer ready.
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];
6363 -#define FC_DATA_DESC_LEN 12 /* expected length of structure */
6365 #endif /* _FC_FS_H_ */
6366 diff --git a/include/scsi/libfc/libfc.h b/include/scsi/libfc/libfc.h
6367 index b139aed..24d3fcb 100644
6368 --- a/include/scsi/libfc/libfc.h
6369 +++ b/include/scsi/libfc/libfc.h
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>
6376 #include <scsi/libfc/fc_frame.h>
6378 @@ -91,28 +92,50 @@ enum fc_lport_state {
6388 - LPORT_ST_DNS_STOP,
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
6400 enum fc_rport_state {
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 */
6413 +enum fc_rport_trans_state {
6414 + FC_PORTSTATE_ROGUE,
6415 + FC_PORTSTATE_REAL,
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
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;
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
6442 + * @event_callback: Callback for rport READY, FAILED or LOGO
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);
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));
6465 +struct fc_rport *fc_rport_dummy_create(struct fc_disc_port *);
6466 +void fc_rport_dummy_destroy(struct fc_rport *);
6468 static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64 wwnn)
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.
6475 - * The response handler argumemt resp_arg is passed back to resp
6476 - * handler when it is invoked by EM layer in above mentioned
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.
6483 + * The arg is passed back to resp and destructor handler.
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 {
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,
6495 - void *resp_arg, unsigned int timer_msec,
6496 + void (*destructor)(struct fc_seq *sp,
6498 + void *arg, unsigned int timer_msec,
6499 u32 sid, u32 did, u32 f_ctl);
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);
6506 - int (*lport_login)(struct fc_lport *);
6507 int (*lport_reset)(struct fc_lport *);
6508 - int (*lport_logout)(struct fc_lport *);
6510 + void (*event_callback)(struct fc_lport *, u32,
6511 + enum fc_lport_event);
6514 * Remote Port interfaces
6515 @@ -346,9 +389,6 @@ struct libfc_function_template {
6517 struct fc_rport *(*rport_lookup)(const struct fc_lport *, u32);
6519 - struct fc_rport *(*rport_create)(struct fc_lport *,
6520 - struct fc_rport_identifiers *);
6522 void (*rport_reset)(struct fc_rport *);
6524 void (*rport_reset_list)(struct fc_lport *);
6525 @@ -378,9 +418,6 @@ struct libfc_function_template {
6526 * Start discovery for a local port.
6528 int (*disc_start)(struct fc_lport *);
6530 - void (*dns_register)(struct fc_lport *);
6531 - void (*disc_stop)(struct fc_lport *);
6535 @@ -396,7 +433,7 @@ struct fc_lport {
6536 /* Operational Information */
6537 struct libfc_function_template tt;
6541 enum fc_lport_state state;
6542 unsigned long boot_time;
6544 @@ -407,12 +444,12 @@ struct fc_lport {
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;
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 */
6568 - spinlock_t state_lock; /* serializes state changes */
6570 + struct mutex lp_mutex;
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;
6582 @@ -462,33 +499,26 @@ static inline void fc_set_wwpn(struct fc_lport *lp, u64 wwnn)
6586 -static inline int fc_lport_locked(struct fc_lport *lp)
6588 -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
6589 - return spin_is_locked(&lp->state_lock);
6592 -#endif /* CONFIG_SMP || CONFIG_DEBUG_SPINLOCK */
6598 -static inline void fc_lport_lock(struct fc_lport *lp)
6600 - spin_lock_bh(&lp->state_lock);
6603 -static inline void fc_lport_unlock(struct fc_lport *lp)
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
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)
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);
6622 static inline void fc_lport_state_enter(struct fc_lport *lp,
6623 enum fc_lport_state state)
6625 - WARN_ON(!fc_lport_locked(lp));
6626 - del_timer(&lp->state_timer);
6627 if (state != lp->state)
6628 lp->retry_count = 0;
6630 @@ -543,7 +573,7 @@ int fc_lport_config(struct fc_lport *);
6632 * Reset the local port.
6634 -int fc_lport_enter_reset(struct fc_lport *);
6635 +int fc_lport_reset(struct fc_lport *);
6638 * Set the mfs or reset
6639 @@ -555,12 +585,14 @@ int fc_set_mfs(struct fc_lport *lp, u32 mfs);
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);
6649 *****************************/
6650 -int fc_ns_init(struct fc_lport *lp);
6651 +int fc_disc_init(struct fc_lport *lp);
6655 @@ -670,10 +702,12 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
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,
6663 - void *resp_arg, u32 timer_msec,
6664 + void (*destructor)(struct fc_seq *sp,
6666 + void *arg, u32 timer_msec,
6667 u32 sid, u32 did, u32 f_ctl);
6670 @@ -738,15 +772,11 @@ void fc_seq_get_xids(struct fc_seq *sp, u16 *oxid, u16 *rxid);
6672 void fc_seq_set_rec_data(struct fc_seq *sp, u32 rec_data);
6675 - * fc_functions_template
6676 - *****************************/
6677 -void fc_attr_init(struct fc_lport *);
6678 -void fc_get_host_port_id(struct Scsi_Host *shost);
6680 + * Functions for fc_functions_template
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 *);