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