upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / scsi / bfa / bfa_lps.c
1 /*
2  * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 #include <bfa.h>
19 #include <bfi/bfi_lps.h>
20 #include <cs/bfa_debug.h>
21 #include <defs/bfa_defs_pci.h>
22
23 BFA_TRC_FILE(HAL, LPS);
24 BFA_MODULE(lps);
25
26 #define BFA_LPS_MIN_LPORTS      (1)
27 #define BFA_LPS_MAX_LPORTS      (256)
28
29 /*
30  * Maximum Vports supported per physical port or vf.
31  */
32 #define BFA_LPS_MAX_VPORTS_SUPP_CB  255
33 #define BFA_LPS_MAX_VPORTS_SUPP_CT  190
34
35 /**
36  * forward declarations
37  */
38 static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
39                             u32 *dm_len);
40 static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
41                            struct bfa_iocfc_cfg_s *cfg,
42                            struct bfa_meminfo_s *meminfo,
43                            struct bfa_pcidev_s *pcidev);
44 static void bfa_lps_detach(struct bfa_s *bfa);
45 static void bfa_lps_start(struct bfa_s *bfa);
46 static void bfa_lps_stop(struct bfa_s *bfa);
47 static void bfa_lps_iocdisable(struct bfa_s *bfa);
48 static void bfa_lps_login_rsp(struct bfa_s *bfa,
49                               struct bfi_lps_login_rsp_s *rsp);
50 static void bfa_lps_logout_rsp(struct bfa_s *bfa,
51                                struct bfi_lps_logout_rsp_s *rsp);
52 static void bfa_lps_reqq_resume(void *lps_arg);
53 static void bfa_lps_free(struct bfa_lps_s *lps);
54 static void bfa_lps_send_login(struct bfa_lps_s *lps);
55 static void bfa_lps_send_logout(struct bfa_lps_s *lps);
56 static void bfa_lps_login_comp(struct bfa_lps_s *lps);
57 static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
58 static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
59
60 /**
61  *  lps_pvt BFA LPS private functions
62  */
63
64 enum bfa_lps_event {
65         BFA_LPS_SM_LOGIN        = 1,    /* login request from user      */
66         BFA_LPS_SM_LOGOUT       = 2,    /* logout request from user     */
67         BFA_LPS_SM_FWRSP        = 3,    /* f/w response to login/logout */
68         BFA_LPS_SM_RESUME       = 4,    /* space present in reqq queue  */
69         BFA_LPS_SM_DELETE       = 5,    /* lps delete from user         */
70         BFA_LPS_SM_OFFLINE      = 6,    /* Link is offline              */
71         BFA_LPS_SM_RX_CVL       = 7,    /* Rx clear virtual link        */
72 };
73
74 static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
75 static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
76 static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps,
77                         enum bfa_lps_event event);
78 static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
79 static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
80 static void bfa_lps_sm_logowait(struct bfa_lps_s *lps,
81                         enum bfa_lps_event event);
82
83 /**
84  * Init state -- no login
85  */
86 static void
87 bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
88 {
89         bfa_trc(lps->bfa, lps->lp_tag);
90         bfa_trc(lps->bfa, event);
91
92         switch (event) {
93         case BFA_LPS_SM_LOGIN:
94                 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
95                         bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
96                         bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
97                 } else {
98                         bfa_sm_set_state(lps, bfa_lps_sm_login);
99                         bfa_lps_send_login(lps);
100                 }
101                 if (lps->fdisc)
102                         bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
103                         BFA_PL_EID_LOGIN, 0, "FDISC Request");
104                 else
105                         bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
106                         BFA_PL_EID_LOGIN, 0, "FLOGI Request");
107                 break;
108
109         case BFA_LPS_SM_LOGOUT:
110                 bfa_lps_logout_comp(lps);
111                 break;
112
113         case BFA_LPS_SM_DELETE:
114                 bfa_lps_free(lps);
115                 break;
116
117         case BFA_LPS_SM_RX_CVL:
118         case BFA_LPS_SM_OFFLINE:
119                 break;
120
121         case BFA_LPS_SM_FWRSP:
122                 /* Could happen when fabric detects loopback and discards
123                  * the lps request. Fw will eventually sent out the timeout
124                  * Just ignore
125                  */
126                 break;
127
128         default:
129                 bfa_sm_fault(lps->bfa, event);
130         }
131 }
132
133 /**
134  * login is in progress -- awaiting response from firmware
135  */
136 static void
137 bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
138 {
139         bfa_trc(lps->bfa, lps->lp_tag);
140         bfa_trc(lps->bfa, event);
141
142         switch (event) {
143         case BFA_LPS_SM_FWRSP:
144                 if (lps->status == BFA_STATUS_OK) {
145                         bfa_sm_set_state(lps, bfa_lps_sm_online);
146                         if (lps->fdisc)
147                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
148                                 BFA_PL_EID_LOGIN, 0, "FDISC Accept");
149                         else
150                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
151                                 BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
152                 } else {
153                         bfa_sm_set_state(lps, bfa_lps_sm_init);
154                         if (lps->fdisc)
155                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
156                                 BFA_PL_EID_LOGIN, 0,
157                                 "FDISC Fail (RJT or timeout)");
158                         else
159                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
160                                 BFA_PL_EID_LOGIN, 0,
161                                 "FLOGI Fail (RJT or timeout)");
162                 }
163                 bfa_lps_login_comp(lps);
164                 break;
165
166         case BFA_LPS_SM_OFFLINE:
167                 bfa_sm_set_state(lps, bfa_lps_sm_init);
168                 break;
169
170         default:
171                 bfa_sm_fault(lps->bfa, event);
172         }
173 }
174
175 /**
176  * login pending - awaiting space in request queue
177  */
178 static void
179 bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
180 {
181         bfa_trc(lps->bfa, lps->lp_tag);
182         bfa_trc(lps->bfa, event);
183
184         switch (event) {
185         case BFA_LPS_SM_RESUME:
186                 bfa_sm_set_state(lps, bfa_lps_sm_login);
187                 break;
188
189         case BFA_LPS_SM_OFFLINE:
190                 bfa_sm_set_state(lps, bfa_lps_sm_init);
191                 bfa_reqq_wcancel(&lps->wqe);
192                 break;
193
194         case BFA_LPS_SM_RX_CVL:
195                 /*
196                  * Login was not even sent out; so when getting out
197                  * of this state, it will appear like a login retry
198                  * after Clear virtual link
199                  */
200                 break;
201
202         default:
203                 bfa_sm_fault(lps->bfa, event);
204         }
205 }
206
207 /**
208  * login complete
209  */
210 static void
211 bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
212 {
213         bfa_trc(lps->bfa, lps->lp_tag);
214         bfa_trc(lps->bfa, event);
215
216         switch (event) {
217         case BFA_LPS_SM_LOGOUT:
218                 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
219                         bfa_sm_set_state(lps, bfa_lps_sm_logowait);
220                         bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
221                 } else {
222                         bfa_sm_set_state(lps, bfa_lps_sm_logout);
223                         bfa_lps_send_logout(lps);
224                 }
225                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
226                         BFA_PL_EID_LOGO, 0, "Logout");
227                 break;
228
229         case BFA_LPS_SM_RX_CVL:
230                 bfa_sm_set_state(lps, bfa_lps_sm_init);
231
232                 /* Let the vport module know about this event */
233                 bfa_lps_cvl_event(lps);
234                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
235                         BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
236                 break;
237
238         case BFA_LPS_SM_OFFLINE:
239         case BFA_LPS_SM_DELETE:
240                 bfa_sm_set_state(lps, bfa_lps_sm_init);
241                 break;
242
243         default:
244                 bfa_sm_fault(lps->bfa, event);
245         }
246 }
247
248 /**
249  * logout in progress - awaiting firmware response
250  */
251 static void
252 bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
253 {
254         bfa_trc(lps->bfa, lps->lp_tag);
255         bfa_trc(lps->bfa, event);
256
257         switch (event) {
258         case BFA_LPS_SM_FWRSP:
259                 bfa_sm_set_state(lps, bfa_lps_sm_init);
260                 bfa_lps_logout_comp(lps);
261                 break;
262
263         case BFA_LPS_SM_OFFLINE:
264                 bfa_sm_set_state(lps, bfa_lps_sm_init);
265                 break;
266
267         default:
268                 bfa_sm_fault(lps->bfa, event);
269         }
270 }
271
272 /**
273  * logout pending -- awaiting space in request queue
274  */
275 static void
276 bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
277 {
278         bfa_trc(lps->bfa, lps->lp_tag);
279         bfa_trc(lps->bfa, event);
280
281         switch (event) {
282         case BFA_LPS_SM_RESUME:
283                 bfa_sm_set_state(lps, bfa_lps_sm_logout);
284                 bfa_lps_send_logout(lps);
285                 break;
286
287         case BFA_LPS_SM_OFFLINE:
288                 bfa_sm_set_state(lps, bfa_lps_sm_init);
289                 bfa_reqq_wcancel(&lps->wqe);
290                 break;
291
292         default:
293                 bfa_sm_fault(lps->bfa, event);
294         }
295 }
296
297
298
299 /**
300  *  lps_pvt BFA LPS private functions
301  */
302
303 /**
304  * return memory requirement
305  */
306 static void
307 bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
308 {
309         if (cfg->drvcfg.min_cfg)
310                 *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
311         else
312                 *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
313 }
314
315 /**
316  * bfa module attach at initialization time
317  */
318 static void
319 bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
320                 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
321 {
322         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
323         struct bfa_lps_s        *lps;
324         int                     i;
325
326         bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
327         mod->num_lps = BFA_LPS_MAX_LPORTS;
328         if (cfg->drvcfg.min_cfg)
329                 mod->num_lps = BFA_LPS_MIN_LPORTS;
330         else
331                 mod->num_lps = BFA_LPS_MAX_LPORTS;
332         mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
333
334         bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
335
336         INIT_LIST_HEAD(&mod->lps_free_q);
337         INIT_LIST_HEAD(&mod->lps_active_q);
338
339         for (i = 0; i < mod->num_lps; i++, lps++) {
340                 lps->bfa        = bfa;
341                 lps->lp_tag     = (u8) i;
342                 lps->reqq       = BFA_REQQ_LPS;
343                 bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
344                 list_add_tail(&lps->qe, &mod->lps_free_q);
345         }
346 }
347
348 static void
349 bfa_lps_detach(struct bfa_s *bfa)
350 {
351 }
352
353 static void
354 bfa_lps_start(struct bfa_s *bfa)
355 {
356 }
357
358 static void
359 bfa_lps_stop(struct bfa_s *bfa)
360 {
361 }
362
363 /**
364  * IOC in disabled state -- consider all lps offline
365  */
366 static void
367 bfa_lps_iocdisable(struct bfa_s *bfa)
368 {
369         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
370         struct bfa_lps_s        *lps;
371         struct list_head                *qe, *qen;
372
373         list_for_each_safe(qe, qen, &mod->lps_active_q) {
374                 lps = (struct bfa_lps_s *) qe;
375                 bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
376         }
377 }
378
379 /**
380  * Firmware login response
381  */
382 static void
383 bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
384 {
385         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
386         struct bfa_lps_s        *lps;
387
388         bfa_assert(rsp->lp_tag < mod->num_lps);
389         lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
390
391         lps->status = rsp->status;
392         switch (rsp->status) {
393         case BFA_STATUS_OK:
394                 lps->fport      = rsp->f_port;
395                 lps->npiv_en    = rsp->npiv_en;
396                 lps->lp_pid     = rsp->lp_pid;
397                 lps->pr_bbcred  = bfa_os_ntohs(rsp->bb_credit);
398                 lps->pr_pwwn    = rsp->port_name;
399                 lps->pr_nwwn    = rsp->node_name;
400                 lps->auth_req   = rsp->auth_req;
401                 lps->lp_mac     = rsp->lp_mac;
402                 lps->brcd_switch = rsp->brcd_switch;
403                 lps->fcf_mac    = rsp->fcf_mac;
404
405                 break;
406
407         case BFA_STATUS_FABRIC_RJT:
408                 lps->lsrjt_rsn = rsp->lsrjt_rsn;
409                 lps->lsrjt_expl = rsp->lsrjt_expl;
410
411                 break;
412
413         case BFA_STATUS_EPROTOCOL:
414                 lps->ext_status = rsp->ext_status;
415
416                 break;
417
418         default:
419                 /* Nothing to do with other status */
420                 break;
421         }
422
423         bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
424 }
425
426 /**
427  * Firmware logout response
428  */
429 static void
430 bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
431 {
432         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
433         struct bfa_lps_s        *lps;
434
435         bfa_assert(rsp->lp_tag < mod->num_lps);
436         lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
437
438         bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
439 }
440
441 /**
442  * Firmware received a Clear virtual link request (for FCoE)
443  */
444 static void
445 bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
446 {
447         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
448         struct bfa_lps_s        *lps;
449
450         lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
451
452         bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
453 }
454
455 /**
456  * Space is available in request queue, resume queueing request to firmware.
457  */
458 static void
459 bfa_lps_reqq_resume(void *lps_arg)
460 {
461         struct bfa_lps_s        *lps = lps_arg;
462
463         bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
464 }
465
466 /**
467  * lps is freed -- triggered by vport delete
468  */
469 static void
470 bfa_lps_free(struct bfa_lps_s *lps)
471 {
472         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
473
474         list_del(&lps->qe);
475         list_add_tail(&lps->qe, &mod->lps_free_q);
476 }
477
478 /**
479  * send login request to firmware
480  */
481 static void
482 bfa_lps_send_login(struct bfa_lps_s *lps)
483 {
484         struct bfi_lps_login_req_s      *m;
485
486         m = bfa_reqq_next(lps->bfa, lps->reqq);
487         bfa_assert(m);
488
489         bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
490                         bfa_lpuid(lps->bfa));
491
492         m->lp_tag       = lps->lp_tag;
493         m->alpa         = lps->alpa;
494         m->pdu_size     = bfa_os_htons(lps->pdusz);
495         m->pwwn         = lps->pwwn;
496         m->nwwn         = lps->nwwn;
497         m->fdisc        = lps->fdisc;
498         m->auth_en      = lps->auth_en;
499
500         bfa_reqq_produce(lps->bfa, lps->reqq);
501 }
502
503 /**
504  * send logout request to firmware
505  */
506 static void
507 bfa_lps_send_logout(struct bfa_lps_s *lps)
508 {
509         struct bfi_lps_logout_req_s *m;
510
511         m = bfa_reqq_next(lps->bfa, lps->reqq);
512         bfa_assert(m);
513
514         bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
515                         bfa_lpuid(lps->bfa));
516
517         m->lp_tag    = lps->lp_tag;
518         m->port_name = lps->pwwn;
519         bfa_reqq_produce(lps->bfa, lps->reqq);
520 }
521
522 /**
523  * Indirect login completion handler for non-fcs
524  */
525 static void
526 bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
527 {
528         struct bfa_lps_s *lps   = arg;
529
530         if (!complete)
531                 return;
532
533         if (lps->fdisc)
534                 bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
535         else
536                 bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
537 }
538
539 /**
540  * Login completion handler -- direct call for fcs, queue for others
541  */
542 static void
543 bfa_lps_login_comp(struct bfa_lps_s *lps)
544 {
545         if (!lps->bfa->fcs) {
546                 bfa_cb_queue(lps->bfa, &lps->hcb_qe,
547                                 bfa_lps_login_comp_cb, lps);
548                 return;
549         }
550
551         if (lps->fdisc)
552                 bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
553         else
554                 bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
555 }
556
557 /**
558  * Indirect logout completion handler for non-fcs
559  */
560 static void
561 bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
562 {
563         struct bfa_lps_s *lps   = arg;
564
565         if (!complete)
566                 return;
567
568         if (lps->fdisc)
569                 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
570         else
571                 bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
572 }
573
574 /**
575  * Logout completion handler -- direct call for fcs, queue for others
576  */
577 static void
578 bfa_lps_logout_comp(struct bfa_lps_s *lps)
579 {
580         if (!lps->bfa->fcs) {
581                 bfa_cb_queue(lps->bfa, &lps->hcb_qe,
582                                 bfa_lps_logout_comp_cb, lps);
583                 return;
584         }
585         if (lps->fdisc)
586                 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
587         else
588                 bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
589 }
590
591 /**
592  * Clear virtual link completion handler for non-fcs
593  */
594 static void
595 bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
596 {
597         struct bfa_lps_s *lps   = arg;
598
599         if (!complete)
600                 return;
601
602         /* Clear virtual link to base port will result in link down */
603         if (lps->fdisc)
604                 bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
605 }
606
607 /**
608  * Received Clear virtual link event --direct call for fcs,
609  * queue for others
610  */
611 static void
612 bfa_lps_cvl_event(struct bfa_lps_s *lps)
613 {
614         if (!lps->bfa->fcs) {
615                 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
616                                 lps);
617                 return;
618         }
619
620         /* Clear virtual link to base port will result in link down */
621         if (lps->fdisc)
622                 bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
623 }
624
625 u32
626 bfa_lps_get_max_vport(struct bfa_s *bfa)
627 {
628         if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
629                 return BFA_LPS_MAX_VPORTS_SUPP_CT;
630         else
631                 return BFA_LPS_MAX_VPORTS_SUPP_CB;
632 }
633
634 /**
635  *  lps_public BFA LPS public functions
636  */
637
638 /**
639  * Allocate a lport srvice tag.
640  */
641 struct bfa_lps_s  *
642 bfa_lps_alloc(struct bfa_s *bfa)
643 {
644         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
645         struct bfa_lps_s        *lps = NULL;
646
647         bfa_q_deq(&mod->lps_free_q, &lps);
648
649         if (lps == NULL)
650                 return NULL;
651
652         list_add_tail(&lps->qe, &mod->lps_active_q);
653
654         bfa_sm_set_state(lps, bfa_lps_sm_init);
655         return lps;
656 }
657
658 /**
659  * Free lport service tag. This can be called anytime after an alloc.
660  * No need to wait for any pending login/logout completions.
661  */
662 void
663 bfa_lps_delete(struct bfa_lps_s *lps)
664 {
665         bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
666 }
667
668 /**
669  * Initiate a lport login.
670  */
671 void
672 bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
673         wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
674 {
675         lps->uarg       = uarg;
676         lps->alpa       = alpa;
677         lps->pdusz      = pdusz;
678         lps->pwwn       = pwwn;
679         lps->nwwn       = nwwn;
680         lps->fdisc      = BFA_FALSE;
681         lps->auth_en    = auth_en;
682         bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
683 }
684
685 /**
686  * Initiate a lport fdisc login.
687  */
688 void
689 bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
690         wwn_t nwwn)
691 {
692         lps->uarg       = uarg;
693         lps->alpa       = 0;
694         lps->pdusz      = pdusz;
695         lps->pwwn       = pwwn;
696         lps->nwwn       = nwwn;
697         lps->fdisc      = BFA_TRUE;
698         lps->auth_en    = BFA_FALSE;
699         bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
700 }
701
702 /**
703  * Initiate a lport logout (flogi).
704  */
705 void
706 bfa_lps_flogo(struct bfa_lps_s *lps)
707 {
708         bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
709 }
710
711 /**
712  * Initiate a lport FDSIC logout.
713  */
714 void
715 bfa_lps_fdisclogo(struct bfa_lps_s *lps)
716 {
717         bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
718 }
719
720 /**
721  * Discard a pending login request -- should be called only for
722  * link down handling.
723  */
724 void
725 bfa_lps_discard(struct bfa_lps_s *lps)
726 {
727         bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
728 }
729
730 /**
731  * Return lport services tag
732  */
733 u8
734 bfa_lps_get_tag(struct bfa_lps_s *lps)
735 {
736         return lps->lp_tag;
737 }
738
739 /**
740  * Return lport services tag given the pid
741  */
742 u8
743 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
744 {
745         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
746         struct bfa_lps_s        *lps;
747         int                     i;
748
749         for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
750                 if (lps->lp_pid == pid)
751                         return lps->lp_tag;
752         }
753
754         /* Return base port tag anyway */
755         return 0;
756 }
757
758 /**
759  * return if fabric login indicates support for NPIV
760  */
761 bfa_boolean_t
762 bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
763 {
764         return lps->npiv_en;
765 }
766
767 /**
768  * Return TRUE if attached to F-Port, else return FALSE
769  */
770 bfa_boolean_t
771 bfa_lps_is_fport(struct bfa_lps_s *lps)
772 {
773         return lps->fport;
774 }
775
776 /**
777  * Return TRUE if attached to a Brocade Fabric
778  */
779 bfa_boolean_t
780 bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
781 {
782         return lps->brcd_switch;
783 }
784 /**
785  * return TRUE if authentication is required
786  */
787 bfa_boolean_t
788 bfa_lps_is_authreq(struct bfa_lps_s *lps)
789 {
790         return lps->auth_req;
791 }
792
793 bfa_eproto_status_t
794 bfa_lps_get_extstatus(struct bfa_lps_s *lps)
795 {
796         return lps->ext_status;
797 }
798
799 /**
800  * return port id assigned to the lport
801  */
802 u32
803 bfa_lps_get_pid(struct bfa_lps_s *lps)
804 {
805         return lps->lp_pid;
806 }
807
808 /**
809  * Return bb_credit assigned in FLOGI response
810  */
811 u16
812 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
813 {
814         return lps->pr_bbcred;
815 }
816
817 /**
818  * Return peer port name
819  */
820 wwn_t
821 bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
822 {
823         return lps->pr_pwwn;
824 }
825
826 /**
827  * Return peer node name
828  */
829 wwn_t
830 bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
831 {
832         return lps->pr_nwwn;
833 }
834
835 /**
836  * return reason code if login request is rejected
837  */
838 u8
839 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
840 {
841         return lps->lsrjt_rsn;
842 }
843
844 /**
845  * return explanation code if login request is rejected
846  */
847 u8
848 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
849 {
850         return lps->lsrjt_expl;
851 }
852
853 /**
854  * Return fpma/spma MAC for lport
855  */
856 struct mac_s
857 bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
858 {
859         return lps->lp_mac;
860 }
861
862 /**
863  * LPS firmware message class handler.
864  */
865 void
866 bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
867 {
868         union bfi_lps_i2h_msg_u msg;
869
870         bfa_trc(bfa, m->mhdr.msg_id);
871         msg.msg = m;
872
873         switch (m->mhdr.msg_id) {
874         case BFI_LPS_H2I_LOGIN_RSP:
875                 bfa_lps_login_rsp(bfa, msg.login_rsp);
876                 break;
877
878         case BFI_LPS_H2I_LOGOUT_RSP:
879                 bfa_lps_logout_rsp(bfa, msg.logout_rsp);
880                 break;
881
882         case BFI_LPS_H2I_CVL_EVENT:
883                 bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
884                 break;
885
886         default:
887                 bfa_trc(bfa, m->mhdr.msg_id);
888                 bfa_assert(0);
889         }
890 }
891
892