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