[SCSI] libfc: make fc_rport_priv the primary rport interface.
[safe/jmp/linux-2.6] / drivers / scsi / libfc / fc_lport.c
1 /*
2  * Copyright(c) 2007 Intel Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16  *
17  * Maintained at www.Open-FCoE.org
18  */
19
20 /*
21  * PORT LOCKING NOTES
22  *
23  * These comments only apply to the 'port code' which consists of the lport,
24  * disc and rport blocks.
25  *
26  * MOTIVATION
27  *
28  * The lport, disc and rport blocks all have mutexes that are used to protect
29  * those objects. The main motivation for these locks is to prevent from
30  * having an lport reset just before we send a frame. In that scenario the
31  * lport's FID would get set to zero and then we'd send a frame with an
32  * invalid SID. We also need to ensure that states don't change unexpectedly
33  * while processing another state.
34  *
35  * HEIRARCHY
36  *
37  * The following heirarchy defines the locking rules. A greater lock
38  * may be held before acquiring a lesser lock, but a lesser lock should never
39  * be held while attempting to acquire a greater lock. Here is the heirarchy-
40  *
41  * lport > disc, lport > rport, disc > rport
42  *
43  * CALLBACKS
44  *
45  * The callbacks cause complications with this scheme. There is a callback
46  * from the rport (to either lport or disc) and a callback from disc
47  * (to the lport).
48  *
49  * As rports exit the rport state machine a callback is made to the owner of
50  * the rport to notify success or failure. Since the callback is likely to
51  * cause the lport or disc to grab its lock we cannot hold the rport lock
52  * while making the callback. To ensure that the rport is not free'd while
53  * processing the callback the rport callbacks are serialized through a
54  * single-threaded workqueue. An rport would never be free'd while in a
55  * callback handler becuase no other rport work in this queue can be executed
56  * at the same time.
57  *
58  * When discovery succeeds or fails a callback is made to the lport as
59  * notification. Currently, succesful discovery causes the lport to take no
60  * action. A failure will cause the lport to reset. There is likely a circular
61  * locking problem with this implementation.
62  */
63
64 /*
65  * LPORT LOCKING
66  *
67  * The critical sections protected by the lport's mutex are quite broad and
68  * may be improved upon in the future. The lport code and its locking doesn't
69  * influence the I/O path, so excessive locking doesn't penalize I/O
70  * performance.
71  *
72  * The strategy is to lock whenever processing a request or response. Note
73  * that every _enter_* function corresponds to a state change. They generally
74  * change the lports state and then send a request out on the wire. We lock
75  * before calling any of these functions to protect that state change. This
76  * means that the entry points into the lport block manage the locks while
77  * the state machine can transition between states (i.e. _enter_* functions)
78  * while always staying protected.
79  *
80  * When handling responses we also hold the lport mutex broadly. When the
81  * lport receives the response frame it locks the mutex and then calls the
82  * appropriate handler for the particuar response. Generally a response will
83  * trigger a state change and so the lock must already be held.
84  *
85  * Retries also have to consider the locking. The retries occur from a work
86  * context and the work function will lock the lport and then retry the state
87  * (i.e. _enter_* function).
88  */
89
90 #include <linux/timer.h>
91 #include <asm/unaligned.h>
92
93 #include <scsi/fc/fc_gs.h>
94
95 #include <scsi/libfc.h>
96 #include <scsi/fc_encode.h>
97
98 /* Fabric IDs to use for point-to-point mode, chosen on whims. */
99 #define FC_LOCAL_PTP_FID_LO   0x010101
100 #define FC_LOCAL_PTP_FID_HI   0x010102
101
102 #define DNS_DELAY             3 /* Discovery delay after RSCN (in seconds)*/
103
104 static void fc_lport_error(struct fc_lport *, struct fc_frame *);
105
106 static void fc_lport_enter_reset(struct fc_lport *);
107 static void fc_lport_enter_flogi(struct fc_lport *);
108 static void fc_lport_enter_dns(struct fc_lport *);
109 static void fc_lport_enter_rpn_id(struct fc_lport *);
110 static void fc_lport_enter_rft_id(struct fc_lport *);
111 static void fc_lport_enter_scr(struct fc_lport *);
112 static void fc_lport_enter_ready(struct fc_lport *);
113 static void fc_lport_enter_logo(struct fc_lport *);
114
115 static const char *fc_lport_state_names[] = {
116         [LPORT_ST_DISABLED] = "disabled",
117         [LPORT_ST_FLOGI] =    "FLOGI",
118         [LPORT_ST_DNS] =      "dNS",
119         [LPORT_ST_RPN_ID] =   "RPN_ID",
120         [LPORT_ST_RFT_ID] =   "RFT_ID",
121         [LPORT_ST_SCR] =      "SCR",
122         [LPORT_ST_READY] =    "Ready",
123         [LPORT_ST_LOGO] =     "LOGO",
124         [LPORT_ST_RESET] =    "reset",
125 };
126
127 static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
128 {
129         fc_frame_free(fp);
130         return 0;
131 }
132
133 /**
134  * fc_lport_rport_callback() - Event handler for rport events
135  * @lport: The lport which is receiving the event
136  * @rdata: private remote port data
137  * @event: The event that occured
138  *
139  * Locking Note: The rport lock should not be held when calling
140  *               this function.
141  */
142 static void fc_lport_rport_callback(struct fc_lport *lport,
143                                     struct fc_rport_priv *rdata,
144                                     enum fc_rport_event event)
145 {
146         struct fc_rport *rport = PRIV_TO_RPORT(rdata);
147
148         FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event,
149                      rport->port_id);
150
151         switch (event) {
152         case RPORT_EV_CREATED:
153                 if (rport->port_id == FC_FID_DIR_SERV) {
154                         mutex_lock(&lport->lp_mutex);
155                         if (lport->state == LPORT_ST_DNS) {
156                                 lport->dns_rp = rdata;
157                                 fc_lport_enter_rpn_id(lport);
158                         } else {
159                                 FC_LPORT_DBG(lport, "Received an CREATED event "
160                                              "on port (%6x) for the directory "
161                                              "server, but the lport is not "
162                                              "in the DNS state, it's in the "
163                                              "%d state", rport->port_id,
164                                              lport->state);
165                                 lport->tt.rport_logoff(rdata);
166                         }
167                         mutex_unlock(&lport->lp_mutex);
168                 } else
169                         FC_LPORT_DBG(lport, "Received an event for port (%6x) "
170                                      "which is not the directory server\n",
171                                      rport->port_id);
172                 break;
173         case RPORT_EV_LOGO:
174         case RPORT_EV_FAILED:
175         case RPORT_EV_STOP:
176                 if (rport->port_id == FC_FID_DIR_SERV) {
177                         mutex_lock(&lport->lp_mutex);
178                         lport->dns_rp = NULL;
179                         mutex_unlock(&lport->lp_mutex);
180
181                 } else
182                         FC_LPORT_DBG(lport, "Received an event for port (%6x) "
183                                      "which is not the directory server\n",
184                                      rport->port_id);
185                 break;
186         case RPORT_EV_NONE:
187                 break;
188         }
189 }
190
191 /**
192  * fc_lport_state() - Return a string which represents the lport's state
193  * @lport: The lport whose state is to converted to a string
194  */
195 static const char *fc_lport_state(struct fc_lport *lport)
196 {
197         const char *cp;
198
199         cp = fc_lport_state_names[lport->state];
200         if (!cp)
201                 cp = "unknown";
202         return cp;
203 }
204
205 /**
206  * fc_lport_ptp_setup() - Create an rport for point-to-point mode
207  * @lport: The lport to attach the ptp rport to
208  * @fid: The FID of the ptp rport
209  * @remote_wwpn: The WWPN of the ptp rport
210  * @remote_wwnn: The WWNN of the ptp rport
211  */
212 static void fc_lport_ptp_setup(struct fc_lport *lport,
213                                u32 remote_fid, u64 remote_wwpn,
214                                u64 remote_wwnn)
215 {
216         struct fc_rport_identifiers ids;
217
218         ids.port_id = remote_fid;
219         ids.port_name = remote_wwpn;
220         ids.node_name = remote_wwnn;
221         ids.roles = FC_RPORT_ROLE_UNKNOWN;
222
223         if (lport->ptp_rp) {
224                 lport->tt.rport_logoff(lport->ptp_rp);
225                 lport->ptp_rp = NULL;
226         }
227
228         lport->ptp_rp = lport->tt.rport_create(lport, &ids);
229
230         lport->tt.rport_login(lport->ptp_rp);
231
232         fc_lport_enter_ready(lport);
233 }
234
235 void fc_get_host_port_type(struct Scsi_Host *shost)
236 {
237         /* TODO - currently just NPORT */
238         fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
239 }
240 EXPORT_SYMBOL(fc_get_host_port_type);
241
242 void fc_get_host_port_state(struct Scsi_Host *shost)
243 {
244         struct fc_lport *lp = shost_priv(shost);
245
246         if (lp->link_up)
247                 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
248         else
249                 fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
250 }
251 EXPORT_SYMBOL(fc_get_host_port_state);
252
253 void fc_get_host_speed(struct Scsi_Host *shost)
254 {
255         struct fc_lport *lport = shost_priv(shost);
256
257         fc_host_speed(shost) = lport->link_speed;
258 }
259 EXPORT_SYMBOL(fc_get_host_speed);
260
261 struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
262 {
263         struct fc_host_statistics *fcoe_stats;
264         struct fc_lport *lp = shost_priv(shost);
265         struct timespec v0, v1;
266         unsigned int cpu;
267
268         fcoe_stats = &lp->host_stats;
269         memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
270
271         jiffies_to_timespec(jiffies, &v0);
272         jiffies_to_timespec(lp->boot_time, &v1);
273         fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec);
274
275         for_each_possible_cpu(cpu) {
276                 struct fcoe_dev_stats *stats;
277
278                 stats = per_cpu_ptr(lp->dev_stats, cpu);
279
280                 fcoe_stats->tx_frames += stats->TxFrames;
281                 fcoe_stats->tx_words += stats->TxWords;
282                 fcoe_stats->rx_frames += stats->RxFrames;
283                 fcoe_stats->rx_words += stats->RxWords;
284                 fcoe_stats->error_frames += stats->ErrorFrames;
285                 fcoe_stats->invalid_crc_count += stats->InvalidCRCCount;
286                 fcoe_stats->fcp_input_requests += stats->InputRequests;
287                 fcoe_stats->fcp_output_requests += stats->OutputRequests;
288                 fcoe_stats->fcp_control_requests += stats->ControlRequests;
289                 fcoe_stats->fcp_input_megabytes += stats->InputMegabytes;
290                 fcoe_stats->fcp_output_megabytes += stats->OutputMegabytes;
291                 fcoe_stats->link_failure_count += stats->LinkFailureCount;
292         }
293         fcoe_stats->lip_count = -1;
294         fcoe_stats->nos_count = -1;
295         fcoe_stats->loss_of_sync_count = -1;
296         fcoe_stats->loss_of_signal_count = -1;
297         fcoe_stats->prim_seq_protocol_err_count = -1;
298         fcoe_stats->dumped_frames = -1;
299         return fcoe_stats;
300 }
301 EXPORT_SYMBOL(fc_get_host_stats);
302
303 /*
304  * Fill in FLOGI command for request.
305  */
306 static void
307 fc_lport_flogi_fill(struct fc_lport *lport, struct fc_els_flogi *flogi,
308                     unsigned int op)
309 {
310         struct fc_els_csp *sp;
311         struct fc_els_cssp *cp;
312
313         memset(flogi, 0, sizeof(*flogi));
314         flogi->fl_cmd = (u8) op;
315         put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
316         put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
317         sp = &flogi->fl_csp;
318         sp->sp_hi_ver = 0x20;
319         sp->sp_lo_ver = 0x20;
320         sp->sp_bb_cred = htons(10);     /* this gets set by gateway */
321         sp->sp_bb_data = htons((u16) lport->mfs);
322         cp = &flogi->fl_cssp[3 - 1];    /* class 3 parameters */
323         cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
324         if (op != ELS_FLOGI) {
325                 sp->sp_features = htons(FC_SP_FT_CIRO);
326                 sp->sp_tot_seq = htons(255);    /* seq. we accept */
327                 sp->sp_rel_off = htons(0x1f);
328                 sp->sp_e_d_tov = htonl(lport->e_d_tov);
329
330                 cp->cp_rdfs = htons((u16) lport->mfs);
331                 cp->cp_con_seq = htons(255);
332                 cp->cp_open_seq = 1;
333         }
334 }
335
336 /*
337  * Add a supported FC-4 type.
338  */
339 static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type)
340 {
341         __be32 *mp;
342
343         mp = &lport->fcts.ff_type_map[type / FC_NS_BPW];
344         *mp = htonl(ntohl(*mp) | 1UL << (type % FC_NS_BPW));
345 }
346
347 /**
348  * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report.
349  * @lport: Fibre Channel local port recieving the RLIR
350  * @sp: current sequence in the RLIR exchange
351  * @fp: RLIR request frame
352  *
353  * Locking Note: The lport lock is exected to be held before calling
354  * this function.
355  */
356 static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
357                                    struct fc_lport *lport)
358 {
359         FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n",
360                      fc_lport_state(lport));
361
362         lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
363         fc_frame_free(fp);
364 }
365
366 /**
367  * fc_lport_recv_echo_req() - Handle received ECHO request
368  * @lport: Fibre Channel local port recieving the ECHO
369  * @sp: current sequence in the ECHO exchange
370  * @fp: ECHO request frame
371  *
372  * Locking Note: The lport lock is exected to be held before calling
373  * this function.
374  */
375 static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
376                                    struct fc_lport *lport)
377 {
378         struct fc_frame *fp;
379         struct fc_exch *ep = fc_seq_exch(sp);
380         unsigned int len;
381         void *pp;
382         void *dp;
383         u32 f_ctl;
384
385         FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n",
386                      fc_lport_state(lport));
387
388         len = fr_len(in_fp) - sizeof(struct fc_frame_header);
389         pp = fc_frame_payload_get(in_fp, len);
390
391         if (len < sizeof(__be32))
392                 len = sizeof(__be32);
393
394         fp = fc_frame_alloc(lport, len);
395         if (fp) {
396                 dp = fc_frame_payload_get(fp, len);
397                 memcpy(dp, pp, len);
398                 *((u32 *)dp) = htonl(ELS_LS_ACC << 24);
399                 sp = lport->tt.seq_start_next(sp);
400                 f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
401                 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
402                                FC_TYPE_ELS, f_ctl, 0);
403                 lport->tt.seq_send(lport, sp, fp);
404         }
405         fc_frame_free(in_fp);
406 }
407
408 /**
409  * fc_lport_recv_echo_req() - Handle received Request Node ID data request
410  * @lport: Fibre Channel local port recieving the RNID
411  * @sp: current sequence in the RNID exchange
412  * @fp: RNID request frame
413  *
414  * Locking Note: The lport lock is exected to be held before calling
415  * this function.
416  */
417 static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
418                                    struct fc_lport *lport)
419 {
420         struct fc_frame *fp;
421         struct fc_exch *ep = fc_seq_exch(sp);
422         struct fc_els_rnid *req;
423         struct {
424                 struct fc_els_rnid_resp rnid;
425                 struct fc_els_rnid_cid cid;
426                 struct fc_els_rnid_gen gen;
427         } *rp;
428         struct fc_seq_els_data rjt_data;
429         u8 fmt;
430         size_t len;
431         u32 f_ctl;
432
433         FC_LPORT_DBG(lport, "Received RNID request while in state %s\n",
434                      fc_lport_state(lport));
435
436         req = fc_frame_payload_get(in_fp, sizeof(*req));
437         if (!req) {
438                 rjt_data.fp = NULL;
439                 rjt_data.reason = ELS_RJT_LOGIC;
440                 rjt_data.explan = ELS_EXPL_NONE;
441                 lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
442         } else {
443                 fmt = req->rnid_fmt;
444                 len = sizeof(*rp);
445                 if (fmt != ELS_RNIDF_GEN ||
446                     ntohl(lport->rnid_gen.rnid_atype) == 0) {
447                         fmt = ELS_RNIDF_NONE;   /* nothing to provide */
448                         len -= sizeof(rp->gen);
449                 }
450                 fp = fc_frame_alloc(lport, len);
451                 if (fp) {
452                         rp = fc_frame_payload_get(fp, len);
453                         memset(rp, 0, len);
454                         rp->rnid.rnid_cmd = ELS_LS_ACC;
455                         rp->rnid.rnid_fmt = fmt;
456                         rp->rnid.rnid_cid_len = sizeof(rp->cid);
457                         rp->cid.rnid_wwpn = htonll(lport->wwpn);
458                         rp->cid.rnid_wwnn = htonll(lport->wwnn);
459                         if (fmt == ELS_RNIDF_GEN) {
460                                 rp->rnid.rnid_sid_len = sizeof(rp->gen);
461                                 memcpy(&rp->gen, &lport->rnid_gen,
462                                        sizeof(rp->gen));
463                         }
464                         sp = lport->tt.seq_start_next(sp);
465                         f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ;
466                         f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT;
467                         fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
468                                        FC_TYPE_ELS, f_ctl, 0);
469                         lport->tt.seq_send(lport, sp, fp);
470                 }
471         }
472         fc_frame_free(in_fp);
473 }
474
475 /**
476  * fc_lport_recv_adisc_req() - Handle received Address Discovery Request
477  * @lport: Fibre Channel local port recieving the ADISC
478  * @sp: current sequence in the ADISC exchange
479  * @fp: ADISC request frame
480  *
481  * Locking Note: The lport lock is expected to be held before calling
482  * this function.
483  */
484 static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp,
485                                     struct fc_lport *lport)
486 {
487         struct fc_frame *fp;
488         struct fc_exch *ep = fc_seq_exch(sp);
489         struct fc_els_adisc *req, *rp;
490         struct fc_seq_els_data rjt_data;
491         size_t len;
492         u32 f_ctl;
493
494         FC_LPORT_DBG(lport, "Received ADISC request while in state %s\n",
495                      fc_lport_state(lport));
496
497         req = fc_frame_payload_get(in_fp, sizeof(*req));
498         if (!req) {
499                 rjt_data.fp = NULL;
500                 rjt_data.reason = ELS_RJT_LOGIC;
501                 rjt_data.explan = ELS_EXPL_NONE;
502                 lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
503         } else {
504                 len = sizeof(*rp);
505                 fp = fc_frame_alloc(lport, len);
506                 if (fp) {
507                         rp = fc_frame_payload_get(fp, len);
508                         memset(rp, 0, len);
509                         rp->adisc_cmd = ELS_LS_ACC;
510                         rp->adisc_wwpn = htonll(lport->wwpn);
511                         rp->adisc_wwnn = htonll(lport->wwnn);
512                         hton24(rp->adisc_port_id,
513                                fc_host_port_id(lport->host));
514                         sp = lport->tt.seq_start_next(sp);
515                         f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ;
516                         f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT;
517                         fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
518                                        FC_TYPE_ELS, f_ctl, 0);
519                         lport->tt.seq_send(lport, sp, fp);
520                 }
521         }
522         fc_frame_free(in_fp);
523 }
524
525 /**
526  * fc_lport_recv_logo_req() - Handle received fabric LOGO request
527  * @lport: Fibre Channel local port recieving the LOGO
528  * @sp: current sequence in the LOGO exchange
529  * @fp: LOGO request frame
530  *
531  * Locking Note: The lport lock is exected to be held before calling
532  * this function.
533  */
534 static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp,
535                                    struct fc_lport *lport)
536 {
537         lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
538         fc_lport_enter_reset(lport);
539         fc_frame_free(fp);
540 }
541
542 /**
543  * fc_fabric_login() - Start the lport state machine
544  * @lport: The lport that should log into the fabric
545  *
546  * Locking Note: This function should not be called
547  *               with the lport lock held.
548  */
549 int fc_fabric_login(struct fc_lport *lport)
550 {
551         int rc = -1;
552
553         mutex_lock(&lport->lp_mutex);
554         if (lport->state == LPORT_ST_DISABLED) {
555                 fc_lport_enter_reset(lport);
556                 rc = 0;
557         }
558         mutex_unlock(&lport->lp_mutex);
559
560         return rc;
561 }
562 EXPORT_SYMBOL(fc_fabric_login);
563
564 /**
565  * fc_linkup() - Handler for transport linkup events
566  * @lport: The lport whose link is up
567  */
568 void fc_linkup(struct fc_lport *lport)
569 {
570         printk(KERN_INFO "libfc: Link up on port (%6x)\n",
571                fc_host_port_id(lport->host));
572
573         mutex_lock(&lport->lp_mutex);
574         if (!lport->link_up) {
575                 lport->link_up = 1;
576
577                 if (lport->state == LPORT_ST_RESET)
578                         fc_lport_enter_flogi(lport);
579         }
580         mutex_unlock(&lport->lp_mutex);
581 }
582 EXPORT_SYMBOL(fc_linkup);
583
584 /**
585  * fc_linkdown() - Handler for transport linkdown events
586  * @lport: The lport whose link is down
587  */
588 void fc_linkdown(struct fc_lport *lport)
589 {
590         mutex_lock(&lport->lp_mutex);
591         printk(KERN_INFO "libfc: Link down on port (%6x)\n",
592                fc_host_port_id(lport->host));
593
594         if (lport->link_up) {
595                 lport->link_up = 0;
596                 fc_lport_enter_reset(lport);
597                 lport->tt.fcp_cleanup(lport);
598         }
599         mutex_unlock(&lport->lp_mutex);
600 }
601 EXPORT_SYMBOL(fc_linkdown);
602
603 /**
604  * fc_fabric_logoff() - Logout of the fabric
605  * @lport:            fc_lport pointer to logoff the fabric
606  *
607  * Return value:
608  *      0 for success, -1 for failure
609  */
610 int fc_fabric_logoff(struct fc_lport *lport)
611 {
612         lport->tt.disc_stop_final(lport);
613         mutex_lock(&lport->lp_mutex);
614         if (lport->dns_rp)
615                 lport->tt.rport_logoff(lport->dns_rp);
616         mutex_unlock(&lport->lp_mutex);
617         lport->tt.rport_flush_queue();
618         mutex_lock(&lport->lp_mutex);
619         fc_lport_enter_logo(lport);
620         mutex_unlock(&lport->lp_mutex);
621         cancel_delayed_work_sync(&lport->retry_work);
622         return 0;
623 }
624 EXPORT_SYMBOL(fc_fabric_logoff);
625
626 /**
627  * fc_lport_destroy() - unregister a fc_lport
628  * @lport:            fc_lport pointer to unregister
629  *
630  * Return value:
631  *      None
632  * Note:
633  * exit routine for fc_lport instance
634  * clean-up all the allocated memory
635  * and free up other system resources.
636  *
637  */
638 int fc_lport_destroy(struct fc_lport *lport)
639 {
640         mutex_lock(&lport->lp_mutex);
641         lport->state = LPORT_ST_DISABLED;
642         lport->link_up = 0;
643         lport->tt.frame_send = fc_frame_drop;
644         mutex_unlock(&lport->lp_mutex);
645
646         lport->tt.fcp_abort_io(lport);
647         lport->tt.disc_stop_final(lport);
648         lport->tt.exch_mgr_reset(lport, 0, 0);
649         return 0;
650 }
651 EXPORT_SYMBOL(fc_lport_destroy);
652
653 /**
654  * fc_set_mfs() - sets up the mfs for the corresponding fc_lport
655  * @lport: fc_lport pointer to unregister
656  * @mfs: the new mfs for fc_lport
657  *
658  * Set mfs for the given fc_lport to the new mfs.
659  *
660  * Return: 0 for success
661  */
662 int fc_set_mfs(struct fc_lport *lport, u32 mfs)
663 {
664         unsigned int old_mfs;
665         int rc = -EINVAL;
666
667         mutex_lock(&lport->lp_mutex);
668
669         old_mfs = lport->mfs;
670
671         if (mfs >= FC_MIN_MAX_FRAME) {
672                 mfs &= ~3;
673                 if (mfs > FC_MAX_FRAME)
674                         mfs = FC_MAX_FRAME;
675                 mfs -= sizeof(struct fc_frame_header);
676                 lport->mfs = mfs;
677                 rc = 0;
678         }
679
680         if (!rc && mfs < old_mfs)
681                 fc_lport_enter_reset(lport);
682
683         mutex_unlock(&lport->lp_mutex);
684
685         return rc;
686 }
687 EXPORT_SYMBOL(fc_set_mfs);
688
689 /**
690  * fc_lport_disc_callback() - Callback for discovery events
691  * @lport: FC local port
692  * @event: The discovery event
693  */
694 void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
695 {
696         switch (event) {
697         case DISC_EV_SUCCESS:
698                 FC_LPORT_DBG(lport, "Discovery succeeded\n");
699                 break;
700         case DISC_EV_FAILED:
701                 printk(KERN_ERR "libfc: Discovery failed for port (%6x)\n",
702                        fc_host_port_id(lport->host));
703                 mutex_lock(&lport->lp_mutex);
704                 fc_lport_enter_reset(lport);
705                 mutex_unlock(&lport->lp_mutex);
706                 break;
707         case DISC_EV_NONE:
708                 WARN_ON(1);
709                 break;
710         }
711 }
712
713 /**
714  * fc_rport_enter_ready() - Enter the ready state and start discovery
715  * @lport: Fibre Channel local port that is ready
716  *
717  * Locking Note: The lport lock is expected to be held before calling
718  * this routine.
719  */
720 static void fc_lport_enter_ready(struct fc_lport *lport)
721 {
722         FC_LPORT_DBG(lport, "Entered READY from state %s\n",
723                      fc_lport_state(lport));
724
725         fc_lport_state_enter(lport, LPORT_ST_READY);
726
727         lport->tt.disc_start(fc_lport_disc_callback, lport);
728 }
729
730 /**
731  * fc_lport_recv_flogi_req() - Receive a FLOGI request
732  * @sp_in: The sequence the FLOGI is on
733  * @rx_fp: The frame the FLOGI is in
734  * @lport: The lport that recieved the request
735  *
736  * A received FLOGI request indicates a point-to-point connection.
737  * Accept it with the common service parameters indicating our N port.
738  * Set up to do a PLOGI if we have the higher-number WWPN.
739  *
740  * Locking Note: The lport lock is exected to be held before calling
741  * this function.
742  */
743 static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
744                                     struct fc_frame *rx_fp,
745                                     struct fc_lport *lport)
746 {
747         struct fc_frame *fp;
748         struct fc_frame_header *fh;
749         struct fc_seq *sp;
750         struct fc_exch *ep;
751         struct fc_els_flogi *flp;
752         struct fc_els_flogi *new_flp;
753         u64 remote_wwpn;
754         u32 remote_fid;
755         u32 local_fid;
756         u32 f_ctl;
757
758         FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n",
759                      fc_lport_state(lport));
760
761         fh = fc_frame_header_get(rx_fp);
762         remote_fid = ntoh24(fh->fh_s_id);
763         flp = fc_frame_payload_get(rx_fp, sizeof(*flp));
764         if (!flp)
765                 goto out;
766         remote_wwpn = get_unaligned_be64(&flp->fl_wwpn);
767         if (remote_wwpn == lport->wwpn) {
768                 printk(KERN_WARNING "libfc: Received FLOGI from port "
769                        "with same WWPN %llx\n", remote_wwpn);
770                 goto out;
771         }
772         FC_LPORT_DBG(lport, "FLOGI from port WWPN %llx\n", remote_wwpn);
773
774         /*
775          * XXX what is the right thing to do for FIDs?
776          * The originator might expect our S_ID to be 0xfffffe.
777          * But if so, both of us could end up with the same FID.
778          */
779         local_fid = FC_LOCAL_PTP_FID_LO;
780         if (remote_wwpn < lport->wwpn) {
781                 local_fid = FC_LOCAL_PTP_FID_HI;
782                 if (!remote_fid || remote_fid == local_fid)
783                         remote_fid = FC_LOCAL_PTP_FID_LO;
784         } else if (!remote_fid) {
785                 remote_fid = FC_LOCAL_PTP_FID_HI;
786         }
787
788         fc_host_port_id(lport->host) = local_fid;
789
790         fp = fc_frame_alloc(lport, sizeof(*flp));
791         if (fp) {
792                 sp = lport->tt.seq_start_next(fr_seq(rx_fp));
793                 new_flp = fc_frame_payload_get(fp, sizeof(*flp));
794                 fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI);
795                 new_flp->fl_cmd = (u8) ELS_LS_ACC;
796
797                 /*
798                  * Send the response.  If this fails, the originator should
799                  * repeat the sequence.
800                  */
801                 f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
802                 ep = fc_seq_exch(sp);
803                 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
804                                FC_TYPE_ELS, f_ctl, 0);
805                 lport->tt.seq_send(lport, sp, fp);
806
807         } else {
808                 fc_lport_error(lport, fp);
809         }
810         fc_lport_ptp_setup(lport, remote_fid, remote_wwpn,
811                            get_unaligned_be64(&flp->fl_wwnn));
812
813         lport->tt.disc_start(fc_lport_disc_callback, lport);
814
815 out:
816         sp = fr_seq(rx_fp);
817         fc_frame_free(rx_fp);
818 }
819
820 /**
821  * fc_lport_recv_req() - The generic lport request handler
822  * @lport: The lport that received the request
823  * @sp: The sequence the request is on
824  * @fp: The frame the request is in
825  *
826  * This function will see if the lport handles the request or
827  * if an rport should handle the request.
828  *
829  * Locking Note: This function should not be called with the lport
830  *               lock held becuase it will grab the lock.
831  */
832 static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
833                               struct fc_frame *fp)
834 {
835         struct fc_frame_header *fh = fc_frame_header_get(fp);
836         void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *);
837         struct fc_rport_priv *rdata;
838         u32 s_id;
839         u32 d_id;
840         struct fc_seq_els_data rjt_data;
841
842         mutex_lock(&lport->lp_mutex);
843
844         /*
845          * Handle special ELS cases like FLOGI, LOGO, and
846          * RSCN here.  These don't require a session.
847          * Even if we had a session, it might not be ready.
848          */
849         if (!lport->link_up)
850                 fc_frame_free(fp);
851         else if (fh->fh_type == FC_TYPE_ELS &&
852                  fh->fh_r_ctl == FC_RCTL_ELS_REQ) {
853                 /*
854                  * Check opcode.
855                  */
856                 recv = NULL;
857                 switch (fc_frame_payload_op(fp)) {
858                 case ELS_FLOGI:
859                         recv = fc_lport_recv_flogi_req;
860                         break;
861                 case ELS_LOGO:
862                         fh = fc_frame_header_get(fp);
863                         if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI)
864                                 recv = fc_lport_recv_logo_req;
865                         break;
866                 case ELS_RSCN:
867                         recv = lport->tt.disc_recv_req;
868                         break;
869                 case ELS_ECHO:
870                         recv = fc_lport_recv_echo_req;
871                         break;
872                 case ELS_RLIR:
873                         recv = fc_lport_recv_rlir_req;
874                         break;
875                 case ELS_RNID:
876                         recv = fc_lport_recv_rnid_req;
877                         break;
878                 case ELS_ADISC:
879                         recv = fc_lport_recv_adisc_req;
880                         break;
881                 }
882
883                 if (recv)
884                         recv(sp, fp, lport);
885                 else {
886                         /*
887                          * Find session.
888                          * If this is a new incoming PLOGI, we won't find it.
889                          */
890                         s_id = ntoh24(fh->fh_s_id);
891                         d_id = ntoh24(fh->fh_d_id);
892
893                         rdata = lport->tt.rport_lookup(lport, s_id);
894                         if (rdata)
895                                 lport->tt.rport_recv_req(sp, fp, rdata);
896                         else {
897                                 rjt_data.fp = NULL;
898                                 rjt_data.reason = ELS_RJT_UNAB;
899                                 rjt_data.explan = ELS_EXPL_NONE;
900                                 lport->tt.seq_els_rsp_send(sp,
901                                                            ELS_LS_RJT,
902                                                            &rjt_data);
903                                 fc_frame_free(fp);
904                         }
905                 }
906         } else {
907                 FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n",
908                              fr_eof(fp));
909                 fc_frame_free(fp);
910         }
911         mutex_unlock(&lport->lp_mutex);
912
913         /*
914          *  The common exch_done for all request may not be good
915          *  if any request requires longer hold on exhange. XXX
916          */
917         lport->tt.exch_done(sp);
918 }
919
920 /**
921  * fc_lport_reset() - Reset an lport
922  * @lport: The lport which should be reset
923  *
924  * Locking Note: This functions should not be called with the
925  *               lport lock held.
926  */
927 int fc_lport_reset(struct fc_lport *lport)
928 {
929         cancel_delayed_work_sync(&lport->retry_work);
930         mutex_lock(&lport->lp_mutex);
931         fc_lport_enter_reset(lport);
932         mutex_unlock(&lport->lp_mutex);
933         return 0;
934 }
935 EXPORT_SYMBOL(fc_lport_reset);
936
937 /**
938  * fc_lport_reset_locked() - Reset the local port
939  * @lport: Fibre Channel local port to be reset
940  *
941  * Locking Note: The lport lock is expected to be held before calling
942  * this routine.
943  */
944 static void fc_lport_reset_locked(struct fc_lport *lport)
945 {
946         if (lport->dns_rp)
947                 lport->tt.rport_logoff(lport->dns_rp);
948
949         if (lport->ptp_rp) {
950                 lport->tt.rport_logoff(lport->ptp_rp);
951                 lport->ptp_rp = NULL;
952         }
953
954         lport->tt.disc_stop(lport);
955
956         lport->tt.exch_mgr_reset(lport, 0, 0);
957         fc_host_fabric_name(lport->host) = 0;
958         fc_host_port_id(lport->host) = 0;
959 }
960
961 /**
962  * fc_lport_enter_reset() - Reset the local port
963  * @lport: Fibre Channel local port to be reset
964  *
965  * Locking Note: The lport lock is expected to be held before calling
966  * this routine.
967  */
968 static void fc_lport_enter_reset(struct fc_lport *lport)
969 {
970         FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
971                      fc_lport_state(lport));
972
973         fc_lport_state_enter(lport, LPORT_ST_RESET);
974         fc_lport_reset_locked(lport);
975         if (lport->link_up)
976                 fc_lport_enter_flogi(lport);
977 }
978
979 /**
980  * fc_lport_enter_disabled() - disable the local port
981  * @lport: Fibre Channel local port to be reset
982  *
983  * Locking Note: The lport lock is expected to be held before calling
984  * this routine.
985  */
986 static void fc_lport_enter_disabled(struct fc_lport *lport)
987 {
988         FC_LPORT_DBG(lport, "Entered disabled state from %s state\n",
989                      fc_lport_state(lport));
990
991         fc_lport_state_enter(lport, LPORT_ST_DISABLED);
992         fc_lport_reset_locked(lport);
993 }
994
995 /**
996  * fc_lport_error() - Handler for any errors
997  * @lport: The fc_lport object
998  * @fp: The frame pointer
999  *
1000  * If the error was caused by a resource allocation failure
1001  * then wait for half a second and retry, otherwise retry
1002  * after the e_d_tov time.
1003  */
1004 static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
1005 {
1006         unsigned long delay = 0;
1007         FC_LPORT_DBG(lport, "Error %ld in state %s, retries %d\n",
1008                      PTR_ERR(fp), fc_lport_state(lport),
1009                      lport->retry_count);
1010
1011         if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
1012                 /*
1013                  * Memory allocation failure, or the exchange timed out.
1014                  *  Retry after delay
1015                  */
1016                 if (lport->retry_count < lport->max_retry_count) {
1017                         lport->retry_count++;
1018                         if (!fp)
1019                                 delay = msecs_to_jiffies(500);
1020                         else
1021                                 delay = msecs_to_jiffies(lport->e_d_tov);
1022
1023                         schedule_delayed_work(&lport->retry_work, delay);
1024                 } else {
1025                         switch (lport->state) {
1026                         case LPORT_ST_DISABLED:
1027                         case LPORT_ST_READY:
1028                         case LPORT_ST_RESET:
1029                         case LPORT_ST_RPN_ID:
1030                         case LPORT_ST_RFT_ID:
1031                         case LPORT_ST_SCR:
1032                         case LPORT_ST_DNS:
1033                         case LPORT_ST_FLOGI:
1034                         case LPORT_ST_LOGO:
1035                                 fc_lport_enter_reset(lport);
1036                                 break;
1037                         }
1038                 }
1039         }
1040 }
1041
1042 /**
1043  * fc_lport_rft_id_resp() - Handle response to Register Fibre
1044  *                          Channel Types by ID (RPN_ID) request
1045  * @sp: current sequence in RPN_ID exchange
1046  * @fp: response frame
1047  * @lp_arg: Fibre Channel host port instance
1048  *
1049  * Locking Note: This function will be called without the lport lock
1050  * held, but it will lock, call an _enter_* function or fc_lport_error
1051  * and then unlock the lport.
1052  */
1053 static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
1054                                  void *lp_arg)
1055 {
1056         struct fc_lport *lport = lp_arg;
1057         struct fc_frame_header *fh;
1058         struct fc_ct_hdr *ct;
1059
1060         if (fp == ERR_PTR(-FC_EX_CLOSED))
1061                 return;
1062
1063         mutex_lock(&lport->lp_mutex);
1064
1065         FC_LPORT_DBG(lport, "Received a RFT_ID response\n");
1066
1067         if (lport->state != LPORT_ST_RFT_ID) {
1068                 FC_LPORT_DBG(lport, "Received a RFT_ID response, but in state "
1069                              "%s\n", fc_lport_state(lport));
1070                 if (IS_ERR(fp))
1071                         goto err;
1072                 goto out;
1073         }
1074
1075         if (IS_ERR(fp)) {
1076                 fc_lport_error(lport, fp);
1077                 goto err;
1078         }
1079
1080         fh = fc_frame_header_get(fp);
1081         ct = fc_frame_payload_get(fp, sizeof(*ct));
1082
1083         if (fh && ct && fh->fh_type == FC_TYPE_CT &&
1084             ct->ct_fs_type == FC_FST_DIR &&
1085             ct->ct_fs_subtype == FC_NS_SUBTYPE &&
1086             ntohs(ct->ct_cmd) == FC_FS_ACC)
1087                 fc_lport_enter_scr(lport);
1088         else
1089                 fc_lport_error(lport, fp);
1090 out:
1091         fc_frame_free(fp);
1092 err:
1093         mutex_unlock(&lport->lp_mutex);
1094 }
1095
1096 /**
1097  * fc_lport_rpn_id_resp() - Handle response to Register Port
1098  *                          Name by ID (RPN_ID) request
1099  * @sp: current sequence in RPN_ID exchange
1100  * @fp: response frame
1101  * @lp_arg: Fibre Channel host port instance
1102  *
1103  * Locking Note: This function will be called without the lport lock
1104  * held, but it will lock, call an _enter_* function or fc_lport_error
1105  * and then unlock the lport.
1106  */
1107 static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
1108                                  void *lp_arg)
1109 {
1110         struct fc_lport *lport = lp_arg;
1111         struct fc_frame_header *fh;
1112         struct fc_ct_hdr *ct;
1113
1114         if (fp == ERR_PTR(-FC_EX_CLOSED))
1115                 return;
1116
1117         mutex_lock(&lport->lp_mutex);
1118
1119         FC_LPORT_DBG(lport, "Received a RPN_ID response\n");
1120
1121         if (lport->state != LPORT_ST_RPN_ID) {
1122                 FC_LPORT_DBG(lport, "Received a RPN_ID response, but in state "
1123                              "%s\n", fc_lport_state(lport));
1124                 if (IS_ERR(fp))
1125                         goto err;
1126                 goto out;
1127         }
1128
1129         if (IS_ERR(fp)) {
1130                 fc_lport_error(lport, fp);
1131                 goto err;
1132         }
1133
1134         fh = fc_frame_header_get(fp);
1135         ct = fc_frame_payload_get(fp, sizeof(*ct));
1136         if (fh && ct && fh->fh_type == FC_TYPE_CT &&
1137             ct->ct_fs_type == FC_FST_DIR &&
1138             ct->ct_fs_subtype == FC_NS_SUBTYPE &&
1139             ntohs(ct->ct_cmd) == FC_FS_ACC)
1140                 fc_lport_enter_rft_id(lport);
1141         else
1142                 fc_lport_error(lport, fp);
1143
1144 out:
1145         fc_frame_free(fp);
1146 err:
1147         mutex_unlock(&lport->lp_mutex);
1148 }
1149
1150 /**
1151  * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request
1152  * @sp: current sequence in SCR exchange
1153  * @fp: response frame
1154  * @lp_arg: Fibre Channel lport port instance that sent the registration request
1155  *
1156  * Locking Note: This function will be called without the lport lock
1157  * held, but it will lock, call an _enter_* function or fc_lport_error
1158  * and then unlock the lport.
1159  */
1160 static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
1161                               void *lp_arg)
1162 {
1163         struct fc_lport *lport = lp_arg;
1164         u8 op;
1165
1166         if (fp == ERR_PTR(-FC_EX_CLOSED))
1167                 return;
1168
1169         mutex_lock(&lport->lp_mutex);
1170
1171         FC_LPORT_DBG(lport, "Received a SCR response\n");
1172
1173         if (lport->state != LPORT_ST_SCR) {
1174                 FC_LPORT_DBG(lport, "Received a SCR response, but in state "
1175                              "%s\n", fc_lport_state(lport));
1176                 if (IS_ERR(fp))
1177                         goto err;
1178                 goto out;
1179         }
1180
1181         if (IS_ERR(fp)) {
1182                 fc_lport_error(lport, fp);
1183                 goto err;
1184         }
1185
1186         op = fc_frame_payload_op(fp);
1187         if (op == ELS_LS_ACC)
1188                 fc_lport_enter_ready(lport);
1189         else
1190                 fc_lport_error(lport, fp);
1191
1192 out:
1193         fc_frame_free(fp);
1194 err:
1195         mutex_unlock(&lport->lp_mutex);
1196 }
1197
1198 /**
1199  * fc_lport_enter_scr() - Send a State Change Register (SCR) request
1200  * @lport: Fibre Channel local port to register for state changes
1201  *
1202  * Locking Note: The lport lock is expected to be held before calling
1203  * this routine.
1204  */
1205 static void fc_lport_enter_scr(struct fc_lport *lport)
1206 {
1207         struct fc_frame *fp;
1208
1209         FC_LPORT_DBG(lport, "Entered SCR state from %s state\n",
1210                      fc_lport_state(lport));
1211
1212         fc_lport_state_enter(lport, LPORT_ST_SCR);
1213
1214         fp = fc_frame_alloc(lport, sizeof(struct fc_els_scr));
1215         if (!fp) {
1216                 fc_lport_error(lport, fp);
1217                 return;
1218         }
1219
1220         if (!lport->tt.elsct_send(lport, NULL, fp, ELS_SCR,
1221                                   fc_lport_scr_resp, lport, lport->e_d_tov))
1222                 fc_lport_error(lport, fp);
1223 }
1224
1225 /**
1226  * fc_lport_enter_rft_id() - Register FC4-types with the name server
1227  * @lport: Fibre Channel local port to register
1228  *
1229  * Locking Note: The lport lock is expected to be held before calling
1230  * this routine.
1231  */
1232 static void fc_lport_enter_rft_id(struct fc_lport *lport)
1233 {
1234         struct fc_frame *fp;
1235         struct fc_ns_fts *lps;
1236         int i;
1237
1238         FC_LPORT_DBG(lport, "Entered RFT_ID state from %s state\n",
1239                      fc_lport_state(lport));
1240
1241         fc_lport_state_enter(lport, LPORT_ST_RFT_ID);
1242
1243         lps = &lport->fcts;
1244         i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
1245         while (--i >= 0)
1246                 if (ntohl(lps->ff_type_map[i]) != 0)
1247                         break;
1248         if (i < 0) {
1249                 /* nothing to register, move on to SCR */
1250                 fc_lport_enter_scr(lport);
1251                 return;
1252         }
1253
1254         fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
1255                             sizeof(struct fc_ns_rft));
1256         if (!fp) {
1257                 fc_lport_error(lport, fp);
1258                 return;
1259         }
1260
1261         if (!lport->tt.elsct_send(lport, NULL, fp, FC_NS_RFT_ID,
1262                                   fc_lport_rft_id_resp,
1263                                   lport, lport->e_d_tov))
1264                 fc_lport_error(lport, fp);
1265 }
1266
1267 /**
1268  * fc_rport_enter_rft_id() - Register port name with the name server
1269  * @lport: Fibre Channel local port to register
1270  *
1271  * Locking Note: The lport lock is expected to be held before calling
1272  * this routine.
1273  */
1274 static void fc_lport_enter_rpn_id(struct fc_lport *lport)
1275 {
1276         struct fc_frame *fp;
1277
1278         FC_LPORT_DBG(lport, "Entered RPN_ID state from %s state\n",
1279                      fc_lport_state(lport));
1280
1281         fc_lport_state_enter(lport, LPORT_ST_RPN_ID);
1282
1283         fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
1284                             sizeof(struct fc_ns_rn_id));
1285         if (!fp) {
1286                 fc_lport_error(lport, fp);
1287                 return;
1288         }
1289
1290         if (!lport->tt.elsct_send(lport, NULL, fp, FC_NS_RPN_ID,
1291                                   fc_lport_rpn_id_resp,
1292                                   lport, lport->e_d_tov))
1293                 fc_lport_error(lport, fp);
1294 }
1295
1296 static struct fc_rport_operations fc_lport_rport_ops = {
1297         .event_callback = fc_lport_rport_callback,
1298 };
1299
1300 /**
1301  * fc_rport_enter_dns() - Create a rport to the name server
1302  * @lport: Fibre Channel local port requesting a rport for the name server
1303  *
1304  * Locking Note: The lport lock is expected to be held before calling
1305  * this routine.
1306  */
1307 static void fc_lport_enter_dns(struct fc_lport *lport)
1308 {
1309         struct fc_rport_priv *rdata;
1310         struct fc_rport_identifiers ids;
1311
1312         ids.port_id = FC_FID_DIR_SERV;
1313         ids.port_name = -1;
1314         ids.node_name = -1;
1315         ids.roles = FC_RPORT_ROLE_UNKNOWN;
1316
1317         FC_LPORT_DBG(lport, "Entered DNS state from %s state\n",
1318                      fc_lport_state(lport));
1319
1320         fc_lport_state_enter(lport, LPORT_ST_DNS);
1321
1322         rdata = lport->tt.rport_create(lport, &ids);
1323         if (!rdata)
1324                 goto err;
1325
1326         rdata->ops = &fc_lport_rport_ops;
1327         lport->tt.rport_login(rdata);
1328         return;
1329
1330 err:
1331         fc_lport_error(lport, NULL);
1332 }
1333
1334 /**
1335  * fc_lport_timeout() - Handler for the retry_work timer.
1336  * @work: The work struct of the fc_lport
1337  */
1338 static void fc_lport_timeout(struct work_struct *work)
1339 {
1340         struct fc_lport *lport =
1341                 container_of(work, struct fc_lport,
1342                              retry_work.work);
1343
1344         mutex_lock(&lport->lp_mutex);
1345
1346         switch (lport->state) {
1347         case LPORT_ST_DISABLED:
1348         case LPORT_ST_READY:
1349         case LPORT_ST_RESET:
1350                 WARN_ON(1);
1351                 break;
1352         case LPORT_ST_FLOGI:
1353                 fc_lport_enter_flogi(lport);
1354                 break;
1355         case LPORT_ST_DNS:
1356                 fc_lport_enter_dns(lport);
1357                 break;
1358         case LPORT_ST_RPN_ID:
1359                 fc_lport_enter_rpn_id(lport);
1360                 break;
1361         case LPORT_ST_RFT_ID:
1362                 fc_lport_enter_rft_id(lport);
1363                 break;
1364         case LPORT_ST_SCR:
1365                 fc_lport_enter_scr(lport);
1366                 break;
1367         case LPORT_ST_LOGO:
1368                 fc_lport_enter_logo(lport);
1369                 break;
1370         }
1371
1372         mutex_unlock(&lport->lp_mutex);
1373 }
1374
1375 /**
1376  * fc_lport_logo_resp() - Handle response to LOGO request
1377  * @sp: current sequence in LOGO exchange
1378  * @fp: response frame
1379  * @lp_arg: Fibre Channel lport port instance that sent the LOGO request
1380  *
1381  * Locking Note: This function will be called without the lport lock
1382  * held, but it will lock, call an _enter_* function or fc_lport_error
1383  * and then unlock the lport.
1384  */
1385 static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
1386                                void *lp_arg)
1387 {
1388         struct fc_lport *lport = lp_arg;
1389         u8 op;
1390
1391         if (fp == ERR_PTR(-FC_EX_CLOSED))
1392                 return;
1393
1394         mutex_lock(&lport->lp_mutex);
1395
1396         FC_LPORT_DBG(lport, "Received a LOGO response\n");
1397
1398         if (lport->state != LPORT_ST_LOGO) {
1399                 FC_LPORT_DBG(lport, "Received a LOGO response, but in state "
1400                              "%s\n", fc_lport_state(lport));
1401                 if (IS_ERR(fp))
1402                         goto err;
1403                 goto out;
1404         }
1405
1406         if (IS_ERR(fp)) {
1407                 fc_lport_error(lport, fp);
1408                 goto err;
1409         }
1410
1411         op = fc_frame_payload_op(fp);
1412         if (op == ELS_LS_ACC)
1413                 fc_lport_enter_disabled(lport);
1414         else
1415                 fc_lport_error(lport, fp);
1416
1417 out:
1418         fc_frame_free(fp);
1419 err:
1420         mutex_unlock(&lport->lp_mutex);
1421 }
1422
1423 /**
1424  * fc_rport_enter_logo() - Logout of the fabric
1425  * @lport: Fibre Channel local port to be logged out
1426  *
1427  * Locking Note: The lport lock is expected to be held before calling
1428  * this routine.
1429  */
1430 static void fc_lport_enter_logo(struct fc_lport *lport)
1431 {
1432         struct fc_frame *fp;
1433         struct fc_els_logo *logo;
1434
1435         FC_LPORT_DBG(lport, "Entered LOGO state from %s state\n",
1436                      fc_lport_state(lport));
1437
1438         fc_lport_state_enter(lport, LPORT_ST_LOGO);
1439
1440         fp = fc_frame_alloc(lport, sizeof(*logo));
1441         if (!fp) {
1442                 fc_lport_error(lport, fp);
1443                 return;
1444         }
1445
1446         if (!lport->tt.elsct_send(lport, NULL, fp, ELS_LOGO, fc_lport_logo_resp,
1447                                   lport, lport->e_d_tov))
1448                 fc_lport_error(lport, fp);
1449 }
1450
1451 /**
1452  * fc_lport_flogi_resp() - Handle response to FLOGI request
1453  * @sp: current sequence in FLOGI exchange
1454  * @fp: response frame
1455  * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request
1456  *
1457  * Locking Note: This function will be called without the lport lock
1458  * held, but it will lock, call an _enter_* function or fc_lport_error
1459  * and then unlock the lport.
1460  */
1461 static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
1462                                 void *lp_arg)
1463 {
1464         struct fc_lport *lport = lp_arg;
1465         struct fc_frame_header *fh;
1466         struct fc_els_flogi *flp;
1467         u32 did;
1468         u16 csp_flags;
1469         unsigned int r_a_tov;
1470         unsigned int e_d_tov;
1471         u16 mfs;
1472
1473         if (fp == ERR_PTR(-FC_EX_CLOSED))
1474                 return;
1475
1476         mutex_lock(&lport->lp_mutex);
1477
1478         FC_LPORT_DBG(lport, "Received a FLOGI response\n");
1479
1480         if (lport->state != LPORT_ST_FLOGI) {
1481                 FC_LPORT_DBG(lport, "Received a FLOGI response, but in state "
1482                              "%s\n", fc_lport_state(lport));
1483                 if (IS_ERR(fp))
1484                         goto err;
1485                 goto out;
1486         }
1487
1488         if (IS_ERR(fp)) {
1489                 fc_lport_error(lport, fp);
1490                 goto err;
1491         }
1492
1493         fh = fc_frame_header_get(fp);
1494         did = ntoh24(fh->fh_d_id);
1495         if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
1496
1497                 printk(KERN_INFO "libfc: Assigned FID (%6x) in FLOGI response\n",
1498                        did);
1499                 fc_host_port_id(lport->host) = did;
1500
1501                 flp = fc_frame_payload_get(fp, sizeof(*flp));
1502                 if (flp) {
1503                         mfs = ntohs(flp->fl_csp.sp_bb_data) &
1504                                 FC_SP_BB_DATA_MASK;
1505                         if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
1506                             mfs < lport->mfs)
1507                                 lport->mfs = mfs;
1508                         csp_flags = ntohs(flp->fl_csp.sp_features);
1509                         r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
1510                         e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
1511                         if (csp_flags & FC_SP_FT_EDTR)
1512                                 e_d_tov /= 1000000;
1513                         if ((csp_flags & FC_SP_FT_FPORT) == 0) {
1514                                 if (e_d_tov > lport->e_d_tov)
1515                                         lport->e_d_tov = e_d_tov;
1516                                 lport->r_a_tov = 2 * e_d_tov;
1517                                 printk(KERN_INFO "libfc: Port (%6x) entered "
1518                                        "point to point mode\n", did);
1519                                 fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id),
1520                                                    get_unaligned_be64(
1521                                                            &flp->fl_wwpn),
1522                                                    get_unaligned_be64(
1523                                                            &flp->fl_wwnn));
1524                         } else {
1525                                 lport->e_d_tov = e_d_tov;
1526                                 lport->r_a_tov = r_a_tov;
1527                                 fc_host_fabric_name(lport->host) =
1528                                         get_unaligned_be64(&flp->fl_wwnn);
1529                                 fc_lport_enter_dns(lport);
1530                         }
1531                 }
1532
1533                 if (flp) {
1534                         csp_flags = ntohs(flp->fl_csp.sp_features);
1535                         if ((csp_flags & FC_SP_FT_FPORT) == 0) {
1536                                 lport->tt.disc_start(fc_lport_disc_callback,
1537                                                      lport);
1538                         }
1539                 }
1540         } else {
1541                 FC_LPORT_DBG(lport, "Bad FLOGI response\n");
1542         }
1543
1544 out:
1545         fc_frame_free(fp);
1546 err:
1547         mutex_unlock(&lport->lp_mutex);
1548 }
1549
1550 /**
1551  * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager
1552  * @lport: Fibre Channel local port to be logged in to the fabric
1553  *
1554  * Locking Note: The lport lock is expected to be held before calling
1555  * this routine.
1556  */
1557 void fc_lport_enter_flogi(struct fc_lport *lport)
1558 {
1559         struct fc_frame *fp;
1560
1561         FC_LPORT_DBG(lport, "Entered FLOGI state from %s state\n",
1562                      fc_lport_state(lport));
1563
1564         fc_lport_state_enter(lport, LPORT_ST_FLOGI);
1565
1566         fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
1567         if (!fp)
1568                 return fc_lport_error(lport, fp);
1569
1570         if (!lport->tt.elsct_send(lport, NULL, fp, ELS_FLOGI,
1571                                   fc_lport_flogi_resp, lport, lport->e_d_tov))
1572                 fc_lport_error(lport, fp);
1573 }
1574
1575 /* Configure a fc_lport */
1576 int fc_lport_config(struct fc_lport *lport)
1577 {
1578         INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
1579         mutex_init(&lport->lp_mutex);
1580
1581         fc_lport_state_enter(lport, LPORT_ST_DISABLED);
1582
1583         fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
1584         fc_lport_add_fc4_type(lport, FC_TYPE_CT);
1585
1586         return 0;
1587 }
1588 EXPORT_SYMBOL(fc_lport_config);
1589
1590 int fc_lport_init(struct fc_lport *lport)
1591 {
1592         if (!lport->tt.lport_recv)
1593                 lport->tt.lport_recv = fc_lport_recv_req;
1594
1595         if (!lport->tt.lport_reset)
1596                 lport->tt.lport_reset = fc_lport_reset;
1597
1598         fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
1599         fc_host_node_name(lport->host) = lport->wwnn;
1600         fc_host_port_name(lport->host) = lport->wwpn;
1601         fc_host_supported_classes(lport->host) = FC_COS_CLASS3;
1602         memset(fc_host_supported_fc4s(lport->host), 0,
1603                sizeof(fc_host_supported_fc4s(lport->host)));
1604         fc_host_supported_fc4s(lport->host)[2] = 1;
1605         fc_host_supported_fc4s(lport->host)[7] = 1;
1606
1607         /* This value is also unchanging */
1608         memset(fc_host_active_fc4s(lport->host), 0,
1609                sizeof(fc_host_active_fc4s(lport->host)));
1610         fc_host_active_fc4s(lport->host)[2] = 1;
1611         fc_host_active_fc4s(lport->host)[7] = 1;
1612         fc_host_maxframe_size(lport->host) = lport->mfs;
1613         fc_host_supported_speeds(lport->host) = 0;
1614         if (lport->link_supported_speeds & FC_PORTSPEED_1GBIT)
1615                 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT;
1616         if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
1617                 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
1618
1619         INIT_LIST_HEAD(&lport->ema_list);
1620         return 0;
1621 }
1622 EXPORT_SYMBOL(fc_lport_init);