drivers/ata/libata-sff.c: comment spelling fixes
[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_logo_req() - Handle received fabric LOGO request
456  * @lport: Fibre Channel local port recieving the LOGO
457  * @sp: current sequence in the LOGO exchange
458  * @fp: LOGO request frame
459  *
460  * Locking Note: The lport lock is exected to be held before calling
461  * this function.
462  */
463 static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp,
464                                    struct fc_lport *lport)
465 {
466         lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
467         fc_lport_enter_reset(lport);
468         fc_frame_free(fp);
469 }
470
471 /**
472  * fc_fabric_login() - Start the lport state machine
473  * @lport: The lport that should log into the fabric
474  *
475  * Locking Note: This function should not be called
476  *               with the lport lock held.
477  */
478 int fc_fabric_login(struct fc_lport *lport)
479 {
480         int rc = -1;
481
482         mutex_lock(&lport->lp_mutex);
483         if (lport->state == LPORT_ST_DISABLED) {
484                 fc_lport_enter_reset(lport);
485                 rc = 0;
486         }
487         mutex_unlock(&lport->lp_mutex);
488
489         return rc;
490 }
491 EXPORT_SYMBOL(fc_fabric_login);
492
493 /**
494  * fc_linkup() - Handler for transport linkup events
495  * @lport: The lport whose link is up
496  */
497 void fc_linkup(struct fc_lport *lport)
498 {
499         printk(KERN_INFO "libfc: Link up on port (%6x)\n",
500                fc_host_port_id(lport->host));
501
502         mutex_lock(&lport->lp_mutex);
503         if (!lport->link_up) {
504                 lport->link_up = 1;
505
506                 if (lport->state == LPORT_ST_RESET)
507                         fc_lport_enter_flogi(lport);
508         }
509         mutex_unlock(&lport->lp_mutex);
510 }
511 EXPORT_SYMBOL(fc_linkup);
512
513 /**
514  * fc_linkdown() - Handler for transport linkdown events
515  * @lport: The lport whose link is down
516  */
517 void fc_linkdown(struct fc_lport *lport)
518 {
519         mutex_lock(&lport->lp_mutex);
520         printk(KERN_INFO "libfc: Link down on port (%6x)\n",
521                fc_host_port_id(lport->host));
522
523         if (lport->link_up) {
524                 lport->link_up = 0;
525                 fc_lport_enter_reset(lport);
526                 lport->tt.fcp_cleanup(lport);
527         }
528         mutex_unlock(&lport->lp_mutex);
529 }
530 EXPORT_SYMBOL(fc_linkdown);
531
532 /**
533  * fc_fabric_logoff() - Logout of the fabric
534  * @lport:            fc_lport pointer to logoff the fabric
535  *
536  * Return value:
537  *      0 for success, -1 for failure
538  */
539 int fc_fabric_logoff(struct fc_lport *lport)
540 {
541         lport->tt.disc_stop_final(lport);
542         mutex_lock(&lport->lp_mutex);
543         if (lport->dns_rp)
544                 lport->tt.rport_logoff(lport->dns_rp);
545         mutex_unlock(&lport->lp_mutex);
546         lport->tt.rport_flush_queue();
547         mutex_lock(&lport->lp_mutex);
548         fc_lport_enter_logo(lport);
549         mutex_unlock(&lport->lp_mutex);
550         cancel_delayed_work_sync(&lport->retry_work);
551         return 0;
552 }
553 EXPORT_SYMBOL(fc_fabric_logoff);
554
555 /**
556  * fc_lport_destroy() - unregister a fc_lport
557  * @lport:            fc_lport pointer to unregister
558  *
559  * Return value:
560  *      None
561  * Note:
562  * exit routine for fc_lport instance
563  * clean-up all the allocated memory
564  * and free up other system resources.
565  *
566  */
567 int fc_lport_destroy(struct fc_lport *lport)
568 {
569         mutex_lock(&lport->lp_mutex);
570         lport->state = LPORT_ST_DISABLED;
571         lport->link_up = 0;
572         lport->tt.frame_send = fc_frame_drop;
573         mutex_unlock(&lport->lp_mutex);
574
575         lport->tt.fcp_abort_io(lport);
576         lport->tt.disc_stop_final(lport);
577         lport->tt.exch_mgr_reset(lport, 0, 0);
578         return 0;
579 }
580 EXPORT_SYMBOL(fc_lport_destroy);
581
582 /**
583  * fc_set_mfs() - sets up the mfs for the corresponding fc_lport
584  * @lport: fc_lport pointer to unregister
585  * @mfs: the new mfs for fc_lport
586  *
587  * Set mfs for the given fc_lport to the new mfs.
588  *
589  * Return: 0 for success
590  */
591 int fc_set_mfs(struct fc_lport *lport, u32 mfs)
592 {
593         unsigned int old_mfs;
594         int rc = -EINVAL;
595
596         mutex_lock(&lport->lp_mutex);
597
598         old_mfs = lport->mfs;
599
600         if (mfs >= FC_MIN_MAX_FRAME) {
601                 mfs &= ~3;
602                 if (mfs > FC_MAX_FRAME)
603                         mfs = FC_MAX_FRAME;
604                 mfs -= sizeof(struct fc_frame_header);
605                 lport->mfs = mfs;
606                 rc = 0;
607         }
608
609         if (!rc && mfs < old_mfs)
610                 fc_lport_enter_reset(lport);
611
612         mutex_unlock(&lport->lp_mutex);
613
614         return rc;
615 }
616 EXPORT_SYMBOL(fc_set_mfs);
617
618 /**
619  * fc_lport_disc_callback() - Callback for discovery events
620  * @lport: FC local port
621  * @event: The discovery event
622  */
623 void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
624 {
625         switch (event) {
626         case DISC_EV_SUCCESS:
627                 FC_LPORT_DBG(lport, "Discovery succeeded\n");
628                 break;
629         case DISC_EV_FAILED:
630                 printk(KERN_ERR "libfc: Discovery failed for port (%6x)\n",
631                        fc_host_port_id(lport->host));
632                 mutex_lock(&lport->lp_mutex);
633                 fc_lport_enter_reset(lport);
634                 mutex_unlock(&lport->lp_mutex);
635                 break;
636         case DISC_EV_NONE:
637                 WARN_ON(1);
638                 break;
639         }
640 }
641
642 /**
643  * fc_rport_enter_ready() - Enter the ready state and start discovery
644  * @lport: Fibre Channel local port that is ready
645  *
646  * Locking Note: The lport lock is expected to be held before calling
647  * this routine.
648  */
649 static void fc_lport_enter_ready(struct fc_lport *lport)
650 {
651         FC_LPORT_DBG(lport, "Entered READY from state %s\n",
652                      fc_lport_state(lport));
653
654         fc_lport_state_enter(lport, LPORT_ST_READY);
655
656         if (!lport->ptp_rp)
657                 lport->tt.disc_start(fc_lport_disc_callback, lport);
658 }
659
660 /**
661  * fc_lport_recv_flogi_req() - Receive a FLOGI request
662  * @sp_in: The sequence the FLOGI is on
663  * @rx_fp: The frame the FLOGI is in
664  * @lport: The lport that recieved the request
665  *
666  * A received FLOGI request indicates a point-to-point connection.
667  * Accept it with the common service parameters indicating our N port.
668  * Set up to do a PLOGI if we have the higher-number WWPN.
669  *
670  * Locking Note: The lport lock is exected to be held before calling
671  * this function.
672  */
673 static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
674                                     struct fc_frame *rx_fp,
675                                     struct fc_lport *lport)
676 {
677         struct fc_frame *fp;
678         struct fc_frame_header *fh;
679         struct fc_seq *sp;
680         struct fc_exch *ep;
681         struct fc_els_flogi *flp;
682         struct fc_els_flogi *new_flp;
683         u64 remote_wwpn;
684         u32 remote_fid;
685         u32 local_fid;
686         u32 f_ctl;
687
688         FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n",
689                      fc_lport_state(lport));
690
691         fh = fc_frame_header_get(rx_fp);
692         remote_fid = ntoh24(fh->fh_s_id);
693         flp = fc_frame_payload_get(rx_fp, sizeof(*flp));
694         if (!flp)
695                 goto out;
696         remote_wwpn = get_unaligned_be64(&flp->fl_wwpn);
697         if (remote_wwpn == lport->wwpn) {
698                 printk(KERN_WARNING "libfc: Received FLOGI from port "
699                        "with same WWPN %llx\n", remote_wwpn);
700                 goto out;
701         }
702         FC_LPORT_DBG(lport, "FLOGI from port WWPN %llx\n", remote_wwpn);
703
704         /*
705          * XXX what is the right thing to do for FIDs?
706          * The originator might expect our S_ID to be 0xfffffe.
707          * But if so, both of us could end up with the same FID.
708          */
709         local_fid = FC_LOCAL_PTP_FID_LO;
710         if (remote_wwpn < lport->wwpn) {
711                 local_fid = FC_LOCAL_PTP_FID_HI;
712                 if (!remote_fid || remote_fid == local_fid)
713                         remote_fid = FC_LOCAL_PTP_FID_LO;
714         } else if (!remote_fid) {
715                 remote_fid = FC_LOCAL_PTP_FID_HI;
716         }
717
718         fc_host_port_id(lport->host) = local_fid;
719
720         fp = fc_frame_alloc(lport, sizeof(*flp));
721         if (fp) {
722                 sp = lport->tt.seq_start_next(fr_seq(rx_fp));
723                 new_flp = fc_frame_payload_get(fp, sizeof(*flp));
724                 fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI);
725                 new_flp->fl_cmd = (u8) ELS_LS_ACC;
726
727                 /*
728                  * Send the response.  If this fails, the originator should
729                  * repeat the sequence.
730                  */
731                 f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
732                 ep = fc_seq_exch(sp);
733                 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
734                                FC_TYPE_ELS, f_ctl, 0);
735                 lport->tt.seq_send(lport, sp, fp);
736
737         } else {
738                 fc_lport_error(lport, fp);
739         }
740         fc_lport_ptp_setup(lport, remote_fid, remote_wwpn,
741                            get_unaligned_be64(&flp->fl_wwnn));
742
743 out:
744         sp = fr_seq(rx_fp);
745         fc_frame_free(rx_fp);
746 }
747
748 /**
749  * fc_lport_recv_req() - The generic lport request handler
750  * @lport: The lport that received the request
751  * @sp: The sequence the request is on
752  * @fp: The frame the request is in
753  *
754  * This function will see if the lport handles the request or
755  * if an rport should handle the request.
756  *
757  * Locking Note: This function should not be called with the lport
758  *               lock held becuase it will grab the lock.
759  */
760 static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
761                               struct fc_frame *fp)
762 {
763         struct fc_frame_header *fh = fc_frame_header_get(fp);
764         void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *);
765
766         mutex_lock(&lport->lp_mutex);
767
768         /*
769          * Handle special ELS cases like FLOGI, LOGO, and
770          * RSCN here.  These don't require a session.
771          * Even if we had a session, it might not be ready.
772          */
773         if (!lport->link_up)
774                 fc_frame_free(fp);
775         else if (fh->fh_type == FC_TYPE_ELS &&
776                  fh->fh_r_ctl == FC_RCTL_ELS_REQ) {
777                 /*
778                  * Check opcode.
779                  */
780                 recv = lport->tt.rport_recv_req;
781                 switch (fc_frame_payload_op(fp)) {
782                 case ELS_FLOGI:
783                         recv = fc_lport_recv_flogi_req;
784                         break;
785                 case ELS_LOGO:
786                         fh = fc_frame_header_get(fp);
787                         if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI)
788                                 recv = fc_lport_recv_logo_req;
789                         break;
790                 case ELS_RSCN:
791                         recv = lport->tt.disc_recv_req;
792                         break;
793                 case ELS_ECHO:
794                         recv = fc_lport_recv_echo_req;
795                         break;
796                 case ELS_RLIR:
797                         recv = fc_lport_recv_rlir_req;
798                         break;
799                 case ELS_RNID:
800                         recv = fc_lport_recv_rnid_req;
801                         break;
802                 }
803
804                 recv(sp, fp, lport);
805         } else {
806                 FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n",
807                              fr_eof(fp));
808                 fc_frame_free(fp);
809         }
810         mutex_unlock(&lport->lp_mutex);
811
812         /*
813          *  The common exch_done for all request may not be good
814          *  if any request requires longer hold on exhange. XXX
815          */
816         lport->tt.exch_done(sp);
817 }
818
819 /**
820  * fc_lport_reset() - Reset an lport
821  * @lport: The lport which should be reset
822  *
823  * Locking Note: This functions should not be called with the
824  *               lport lock held.
825  */
826 int fc_lport_reset(struct fc_lport *lport)
827 {
828         cancel_delayed_work_sync(&lport->retry_work);
829         mutex_lock(&lport->lp_mutex);
830         fc_lport_enter_reset(lport);
831         mutex_unlock(&lport->lp_mutex);
832         return 0;
833 }
834 EXPORT_SYMBOL(fc_lport_reset);
835
836 /**
837  * fc_lport_reset_locked() - Reset the local port
838  * @lport: Fibre Channel local port to be reset
839  *
840  * Locking Note: The lport lock is expected to be held before calling
841  * this routine.
842  */
843 static void fc_lport_reset_locked(struct fc_lport *lport)
844 {
845         if (lport->dns_rp)
846                 lport->tt.rport_logoff(lport->dns_rp);
847
848         lport->ptp_rp = NULL;
849
850         lport->tt.disc_stop(lport);
851
852         lport->tt.exch_mgr_reset(lport, 0, 0);
853         fc_host_fabric_name(lport->host) = 0;
854         fc_host_port_id(lport->host) = 0;
855 }
856
857 /**
858  * fc_lport_enter_reset() - Reset the local port
859  * @lport: Fibre Channel local port to be reset
860  *
861  * Locking Note: The lport lock is expected to be held before calling
862  * this routine.
863  */
864 static void fc_lport_enter_reset(struct fc_lport *lport)
865 {
866         FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
867                      fc_lport_state(lport));
868
869         fc_lport_state_enter(lport, LPORT_ST_RESET);
870         fc_lport_reset_locked(lport);
871         if (lport->link_up)
872                 fc_lport_enter_flogi(lport);
873 }
874
875 /**
876  * fc_lport_enter_disabled() - disable 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_enter_disabled(struct fc_lport *lport)
883 {
884         FC_LPORT_DBG(lport, "Entered disabled state from %s state\n",
885                      fc_lport_state(lport));
886
887         fc_lport_state_enter(lport, LPORT_ST_DISABLED);
888         fc_lport_reset_locked(lport);
889 }
890
891 /**
892  * fc_lport_error() - Handler for any errors
893  * @lport: The fc_lport object
894  * @fp: The frame pointer
895  *
896  * If the error was caused by a resource allocation failure
897  * then wait for half a second and retry, otherwise retry
898  * after the e_d_tov time.
899  */
900 static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
901 {
902         unsigned long delay = 0;
903         FC_LPORT_DBG(lport, "Error %ld in state %s, retries %d\n",
904                      PTR_ERR(fp), fc_lport_state(lport),
905                      lport->retry_count);
906
907         if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
908                 /*
909                  * Memory allocation failure, or the exchange timed out.
910                  *  Retry after delay
911                  */
912                 if (lport->retry_count < lport->max_retry_count) {
913                         lport->retry_count++;
914                         if (!fp)
915                                 delay = msecs_to_jiffies(500);
916                         else
917                                 delay = msecs_to_jiffies(lport->e_d_tov);
918
919                         schedule_delayed_work(&lport->retry_work, delay);
920                 } else {
921                         switch (lport->state) {
922                         case LPORT_ST_DISABLED:
923                         case LPORT_ST_READY:
924                         case LPORT_ST_RESET:
925                         case LPORT_ST_RPN_ID:
926                         case LPORT_ST_RFT_ID:
927                         case LPORT_ST_SCR:
928                         case LPORT_ST_DNS:
929                         case LPORT_ST_FLOGI:
930                         case LPORT_ST_LOGO:
931                                 fc_lport_enter_reset(lport);
932                                 break;
933                         }
934                 }
935         }
936 }
937
938 /**
939  * fc_lport_rft_id_resp() - Handle response to Register Fibre
940  *                          Channel Types by ID (RPN_ID) request
941  * @sp: current sequence in RPN_ID exchange
942  * @fp: response frame
943  * @lp_arg: Fibre Channel host port instance
944  *
945  * Locking Note: This function will be called without the lport lock
946  * held, but it will lock, call an _enter_* function or fc_lport_error
947  * and then unlock the lport.
948  */
949 static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
950                                  void *lp_arg)
951 {
952         struct fc_lport *lport = lp_arg;
953         struct fc_frame_header *fh;
954         struct fc_ct_hdr *ct;
955
956         FC_LPORT_DBG(lport, "Received a RFT_ID %s\n", fc_els_resp_type(fp));
957
958         if (fp == ERR_PTR(-FC_EX_CLOSED))
959                 return;
960
961         mutex_lock(&lport->lp_mutex);
962
963         if (lport->state != LPORT_ST_RFT_ID) {
964                 FC_LPORT_DBG(lport, "Received a RFT_ID response, but in state "
965                              "%s\n", fc_lport_state(lport));
966                 if (IS_ERR(fp))
967                         goto err;
968                 goto out;
969         }
970
971         if (IS_ERR(fp)) {
972                 fc_lport_error(lport, fp);
973                 goto err;
974         }
975
976         fh = fc_frame_header_get(fp);
977         ct = fc_frame_payload_get(fp, sizeof(*ct));
978
979         if (fh && ct && fh->fh_type == FC_TYPE_CT &&
980             ct->ct_fs_type == FC_FST_DIR &&
981             ct->ct_fs_subtype == FC_NS_SUBTYPE &&
982             ntohs(ct->ct_cmd) == FC_FS_ACC)
983                 fc_lport_enter_scr(lport);
984         else
985                 fc_lport_error(lport, fp);
986 out:
987         fc_frame_free(fp);
988 err:
989         mutex_unlock(&lport->lp_mutex);
990 }
991
992 /**
993  * fc_lport_rpn_id_resp() - Handle response to Register Port
994  *                          Name by ID (RPN_ID) request
995  * @sp: current sequence in RPN_ID exchange
996  * @fp: response frame
997  * @lp_arg: Fibre Channel host port instance
998  *
999  * Locking Note: This function will be called without the lport lock
1000  * held, but it will lock, call an _enter_* function or fc_lport_error
1001  * and then unlock the lport.
1002  */
1003 static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
1004                                  void *lp_arg)
1005 {
1006         struct fc_lport *lport = lp_arg;
1007         struct fc_frame_header *fh;
1008         struct fc_ct_hdr *ct;
1009
1010         FC_LPORT_DBG(lport, "Received a RPN_ID %s\n", fc_els_resp_type(fp));
1011
1012         if (fp == ERR_PTR(-FC_EX_CLOSED))
1013                 return;
1014
1015         mutex_lock(&lport->lp_mutex);
1016
1017         if (lport->state != LPORT_ST_RPN_ID) {
1018                 FC_LPORT_DBG(lport, "Received a RPN_ID response, but in state "
1019                              "%s\n", fc_lport_state(lport));
1020                 if (IS_ERR(fp))
1021                         goto err;
1022                 goto out;
1023         }
1024
1025         if (IS_ERR(fp)) {
1026                 fc_lport_error(lport, fp);
1027                 goto err;
1028         }
1029
1030         fh = fc_frame_header_get(fp);
1031         ct = fc_frame_payload_get(fp, sizeof(*ct));
1032         if (fh && ct && fh->fh_type == FC_TYPE_CT &&
1033             ct->ct_fs_type == FC_FST_DIR &&
1034             ct->ct_fs_subtype == FC_NS_SUBTYPE &&
1035             ntohs(ct->ct_cmd) == FC_FS_ACC)
1036                 fc_lport_enter_rft_id(lport);
1037         else
1038                 fc_lport_error(lport, fp);
1039
1040 out:
1041         fc_frame_free(fp);
1042 err:
1043         mutex_unlock(&lport->lp_mutex);
1044 }
1045
1046 /**
1047  * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request
1048  * @sp: current sequence in SCR exchange
1049  * @fp: response frame
1050  * @lp_arg: Fibre Channel lport port instance that sent the registration request
1051  *
1052  * Locking Note: This function will be called without the lport lock
1053  * held, but it will lock, call an _enter_* function or fc_lport_error
1054  * and then unlock the lport.
1055  */
1056 static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
1057                               void *lp_arg)
1058 {
1059         struct fc_lport *lport = lp_arg;
1060         u8 op;
1061
1062         FC_LPORT_DBG(lport, "Received a SCR %s\n", fc_els_resp_type(fp));
1063
1064         if (fp == ERR_PTR(-FC_EX_CLOSED))
1065                 return;
1066
1067         mutex_lock(&lport->lp_mutex);
1068
1069         if (lport->state != LPORT_ST_SCR) {
1070                 FC_LPORT_DBG(lport, "Received a SCR response, but in state "
1071                              "%s\n", fc_lport_state(lport));
1072                 if (IS_ERR(fp))
1073                         goto err;
1074                 goto out;
1075         }
1076
1077         if (IS_ERR(fp)) {
1078                 fc_lport_error(lport, fp);
1079                 goto err;
1080         }
1081
1082         op = fc_frame_payload_op(fp);
1083         if (op == ELS_LS_ACC)
1084                 fc_lport_enter_ready(lport);
1085         else
1086                 fc_lport_error(lport, fp);
1087
1088 out:
1089         fc_frame_free(fp);
1090 err:
1091         mutex_unlock(&lport->lp_mutex);
1092 }
1093
1094 /**
1095  * fc_lport_enter_scr() - Send a State Change Register (SCR) request
1096  * @lport: Fibre Channel local port to register for state changes
1097  *
1098  * Locking Note: The lport lock is expected to be held before calling
1099  * this routine.
1100  */
1101 static void fc_lport_enter_scr(struct fc_lport *lport)
1102 {
1103         struct fc_frame *fp;
1104
1105         FC_LPORT_DBG(lport, "Entered SCR state from %s state\n",
1106                      fc_lport_state(lport));
1107
1108         fc_lport_state_enter(lport, LPORT_ST_SCR);
1109
1110         fp = fc_frame_alloc(lport, sizeof(struct fc_els_scr));
1111         if (!fp) {
1112                 fc_lport_error(lport, fp);
1113                 return;
1114         }
1115
1116         if (!lport->tt.elsct_send(lport, FC_FID_FCTRL, fp, ELS_SCR,
1117                                   fc_lport_scr_resp, lport, lport->e_d_tov))
1118                 fc_lport_error(lport, fp);
1119 }
1120
1121 /**
1122  * fc_lport_enter_rft_id() - Register FC4-types with the name server
1123  * @lport: Fibre Channel local port to register
1124  *
1125  * Locking Note: The lport lock is expected to be held before calling
1126  * this routine.
1127  */
1128 static void fc_lport_enter_rft_id(struct fc_lport *lport)
1129 {
1130         struct fc_frame *fp;
1131         struct fc_ns_fts *lps;
1132         int i;
1133
1134         FC_LPORT_DBG(lport, "Entered RFT_ID state from %s state\n",
1135                      fc_lport_state(lport));
1136
1137         fc_lport_state_enter(lport, LPORT_ST_RFT_ID);
1138
1139         lps = &lport->fcts;
1140         i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
1141         while (--i >= 0)
1142                 if (ntohl(lps->ff_type_map[i]) != 0)
1143                         break;
1144         if (i < 0) {
1145                 /* nothing to register, move on to SCR */
1146                 fc_lport_enter_scr(lport);
1147                 return;
1148         }
1149
1150         fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
1151                             sizeof(struct fc_ns_rft));
1152         if (!fp) {
1153                 fc_lport_error(lport, fp);
1154                 return;
1155         }
1156
1157         if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RFT_ID,
1158                                   fc_lport_rft_id_resp,
1159                                   lport, lport->e_d_tov))
1160                 fc_lport_error(lport, fp);
1161 }
1162
1163 /**
1164  * fc_rport_enter_rft_id() - Register port name with the name server
1165  * @lport: Fibre Channel local port to register
1166  *
1167  * Locking Note: The lport lock is expected to be held before calling
1168  * this routine.
1169  */
1170 static void fc_lport_enter_rpn_id(struct fc_lport *lport)
1171 {
1172         struct fc_frame *fp;
1173
1174         FC_LPORT_DBG(lport, "Entered RPN_ID state from %s state\n",
1175                      fc_lport_state(lport));
1176
1177         fc_lport_state_enter(lport, LPORT_ST_RPN_ID);
1178
1179         fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
1180                             sizeof(struct fc_ns_rn_id));
1181         if (!fp) {
1182                 fc_lport_error(lport, fp);
1183                 return;
1184         }
1185
1186         if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RPN_ID,
1187                                   fc_lport_rpn_id_resp,
1188                                   lport, lport->e_d_tov))
1189                 fc_lport_error(lport, fp);
1190 }
1191
1192 static struct fc_rport_operations fc_lport_rport_ops = {
1193         .event_callback = fc_lport_rport_callback,
1194 };
1195
1196 /**
1197  * fc_rport_enter_dns() - Create a rport to the name server
1198  * @lport: Fibre Channel local port requesting a rport for the name server
1199  *
1200  * Locking Note: The lport lock is expected to be held before calling
1201  * this routine.
1202  */
1203 static void fc_lport_enter_dns(struct fc_lport *lport)
1204 {
1205         struct fc_rport_priv *rdata;
1206
1207         FC_LPORT_DBG(lport, "Entered DNS state from %s state\n",
1208                      fc_lport_state(lport));
1209
1210         fc_lport_state_enter(lport, LPORT_ST_DNS);
1211
1212         mutex_lock(&lport->disc.disc_mutex);
1213         rdata = lport->tt.rport_create(lport, FC_FID_DIR_SERV);
1214         mutex_unlock(&lport->disc.disc_mutex);
1215         if (!rdata)
1216                 goto err;
1217
1218         rdata->ops = &fc_lport_rport_ops;
1219         lport->tt.rport_login(rdata);
1220         return;
1221
1222 err:
1223         fc_lport_error(lport, NULL);
1224 }
1225
1226 /**
1227  * fc_lport_timeout() - Handler for the retry_work timer.
1228  * @work: The work struct of the fc_lport
1229  */
1230 static void fc_lport_timeout(struct work_struct *work)
1231 {
1232         struct fc_lport *lport =
1233                 container_of(work, struct fc_lport,
1234                              retry_work.work);
1235
1236         mutex_lock(&lport->lp_mutex);
1237
1238         switch (lport->state) {
1239         case LPORT_ST_DISABLED:
1240         case LPORT_ST_READY:
1241         case LPORT_ST_RESET:
1242                 WARN_ON(1);
1243                 break;
1244         case LPORT_ST_FLOGI:
1245                 fc_lport_enter_flogi(lport);
1246                 break;
1247         case LPORT_ST_DNS:
1248                 fc_lport_enter_dns(lport);
1249                 break;
1250         case LPORT_ST_RPN_ID:
1251                 fc_lport_enter_rpn_id(lport);
1252                 break;
1253         case LPORT_ST_RFT_ID:
1254                 fc_lport_enter_rft_id(lport);
1255                 break;
1256         case LPORT_ST_SCR:
1257                 fc_lport_enter_scr(lport);
1258                 break;
1259         case LPORT_ST_LOGO:
1260                 fc_lport_enter_logo(lport);
1261                 break;
1262         }
1263
1264         mutex_unlock(&lport->lp_mutex);
1265 }
1266
1267 /**
1268  * fc_lport_logo_resp() - Handle response to LOGO request
1269  * @sp: current sequence in LOGO exchange
1270  * @fp: response frame
1271  * @lp_arg: Fibre Channel lport port instance that sent the LOGO request
1272  *
1273  * Locking Note: This function will be called without the lport lock
1274  * held, but it will lock, call an _enter_* function or fc_lport_error
1275  * and then unlock the lport.
1276  */
1277 static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
1278                                void *lp_arg)
1279 {
1280         struct fc_lport *lport = lp_arg;
1281         u8 op;
1282
1283         FC_LPORT_DBG(lport, "Received a LOGO %s\n", fc_els_resp_type(fp));
1284
1285         if (fp == ERR_PTR(-FC_EX_CLOSED))
1286                 return;
1287
1288         mutex_lock(&lport->lp_mutex);
1289
1290         if (lport->state != LPORT_ST_LOGO) {
1291                 FC_LPORT_DBG(lport, "Received a LOGO response, but in state "
1292                              "%s\n", fc_lport_state(lport));
1293                 if (IS_ERR(fp))
1294                         goto err;
1295                 goto out;
1296         }
1297
1298         if (IS_ERR(fp)) {
1299                 fc_lport_error(lport, fp);
1300                 goto err;
1301         }
1302
1303         op = fc_frame_payload_op(fp);
1304         if (op == ELS_LS_ACC)
1305                 fc_lport_enter_disabled(lport);
1306         else
1307                 fc_lport_error(lport, fp);
1308
1309 out:
1310         fc_frame_free(fp);
1311 err:
1312         mutex_unlock(&lport->lp_mutex);
1313 }
1314
1315 /**
1316  * fc_rport_enter_logo() - Logout of the fabric
1317  * @lport: Fibre Channel local port to be logged out
1318  *
1319  * Locking Note: The lport lock is expected to be held before calling
1320  * this routine.
1321  */
1322 static void fc_lport_enter_logo(struct fc_lport *lport)
1323 {
1324         struct fc_frame *fp;
1325         struct fc_els_logo *logo;
1326
1327         FC_LPORT_DBG(lport, "Entered LOGO state from %s state\n",
1328                      fc_lport_state(lport));
1329
1330         fc_lport_state_enter(lport, LPORT_ST_LOGO);
1331
1332         fp = fc_frame_alloc(lport, sizeof(*logo));
1333         if (!fp) {
1334                 fc_lport_error(lport, fp);
1335                 return;
1336         }
1337
1338         if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_LOGO,
1339                                   fc_lport_logo_resp, lport, lport->e_d_tov))
1340                 fc_lport_error(lport, fp);
1341 }
1342
1343 /**
1344  * fc_lport_flogi_resp() - Handle response to FLOGI request
1345  * @sp: current sequence in FLOGI exchange
1346  * @fp: response frame
1347  * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request
1348  *
1349  * Locking Note: This function will be called without the lport lock
1350  * held, but it will lock, call an _enter_* function or fc_lport_error
1351  * and then unlock the lport.
1352  */
1353 static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
1354                                 void *lp_arg)
1355 {
1356         struct fc_lport *lport = lp_arg;
1357         struct fc_frame_header *fh;
1358         struct fc_els_flogi *flp;
1359         u32 did;
1360         u16 csp_flags;
1361         unsigned int r_a_tov;
1362         unsigned int e_d_tov;
1363         u16 mfs;
1364
1365         FC_LPORT_DBG(lport, "Received a FLOGI %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_FLOGI) {
1373                 FC_LPORT_DBG(lport, "Received a FLOGI 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         fh = fc_frame_header_get(fp);
1386         did = ntoh24(fh->fh_d_id);
1387         if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
1388
1389                 printk(KERN_INFO "libfc: Assigned FID (%6x) in FLOGI response\n",
1390                        did);
1391                 fc_host_port_id(lport->host) = did;
1392
1393                 flp = fc_frame_payload_get(fp, sizeof(*flp));
1394                 if (flp) {
1395                         mfs = ntohs(flp->fl_csp.sp_bb_data) &
1396                                 FC_SP_BB_DATA_MASK;
1397                         if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
1398                             mfs < lport->mfs)
1399                                 lport->mfs = mfs;
1400                         csp_flags = ntohs(flp->fl_csp.sp_features);
1401                         r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
1402                         e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
1403                         if (csp_flags & FC_SP_FT_EDTR)
1404                                 e_d_tov /= 1000000;
1405                         if ((csp_flags & FC_SP_FT_FPORT) == 0) {
1406                                 if (e_d_tov > lport->e_d_tov)
1407                                         lport->e_d_tov = e_d_tov;
1408                                 lport->r_a_tov = 2 * e_d_tov;
1409                                 printk(KERN_INFO "libfc: Port (%6x) entered "
1410                                        "point to point mode\n", did);
1411                                 fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id),
1412                                                    get_unaligned_be64(
1413                                                            &flp->fl_wwpn),
1414                                                    get_unaligned_be64(
1415                                                            &flp->fl_wwnn));
1416                         } else {
1417                                 lport->e_d_tov = e_d_tov;
1418                                 lport->r_a_tov = r_a_tov;
1419                                 fc_host_fabric_name(lport->host) =
1420                                         get_unaligned_be64(&flp->fl_wwnn);
1421                                 fc_lport_enter_dns(lport);
1422                         }
1423                 }
1424         } else {
1425                 FC_LPORT_DBG(lport, "Bad FLOGI response\n");
1426         }
1427
1428 out:
1429         fc_frame_free(fp);
1430 err:
1431         mutex_unlock(&lport->lp_mutex);
1432 }
1433
1434 /**
1435  * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager
1436  * @lport: Fibre Channel local port to be logged in to the fabric
1437  *
1438  * Locking Note: The lport lock is expected to be held before calling
1439  * this routine.
1440  */
1441 void fc_lport_enter_flogi(struct fc_lport *lport)
1442 {
1443         struct fc_frame *fp;
1444
1445         FC_LPORT_DBG(lport, "Entered FLOGI state from %s state\n",
1446                      fc_lport_state(lport));
1447
1448         fc_lport_state_enter(lport, LPORT_ST_FLOGI);
1449
1450         fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
1451         if (!fp)
1452                 return fc_lport_error(lport, fp);
1453
1454         if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_FLOGI,
1455                                   fc_lport_flogi_resp, lport, lport->e_d_tov))
1456                 fc_lport_error(lport, fp);
1457 }
1458
1459 /* Configure a fc_lport */
1460 int fc_lport_config(struct fc_lport *lport)
1461 {
1462         INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
1463         mutex_init(&lport->lp_mutex);
1464
1465         fc_lport_state_enter(lport, LPORT_ST_DISABLED);
1466
1467         fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
1468         fc_lport_add_fc4_type(lport, FC_TYPE_CT);
1469
1470         return 0;
1471 }
1472 EXPORT_SYMBOL(fc_lport_config);
1473
1474 int fc_lport_init(struct fc_lport *lport)
1475 {
1476         if (!lport->tt.lport_recv)
1477                 lport->tt.lport_recv = fc_lport_recv_req;
1478
1479         if (!lport->tt.lport_reset)
1480                 lport->tt.lport_reset = fc_lport_reset;
1481
1482         fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
1483         fc_host_node_name(lport->host) = lport->wwnn;
1484         fc_host_port_name(lport->host) = lport->wwpn;
1485         fc_host_supported_classes(lport->host) = FC_COS_CLASS3;
1486         memset(fc_host_supported_fc4s(lport->host), 0,
1487                sizeof(fc_host_supported_fc4s(lport->host)));
1488         fc_host_supported_fc4s(lport->host)[2] = 1;
1489         fc_host_supported_fc4s(lport->host)[7] = 1;
1490
1491         /* This value is also unchanging */
1492         memset(fc_host_active_fc4s(lport->host), 0,
1493                sizeof(fc_host_active_fc4s(lport->host)));
1494         fc_host_active_fc4s(lport->host)[2] = 1;
1495         fc_host_active_fc4s(lport->host)[7] = 1;
1496         fc_host_maxframe_size(lport->host) = lport->mfs;
1497         fc_host_supported_speeds(lport->host) = 0;
1498         if (lport->link_supported_speeds & FC_PORTSPEED_1GBIT)
1499                 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT;
1500         if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
1501                 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
1502
1503         INIT_LIST_HEAD(&lport->ema_list);
1504         return 0;
1505 }
1506 EXPORT_SYMBOL(fc_lport_init);