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