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