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