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