blob: acabb44f092fa4c55019b83cff3242b2b5c44a20 [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);
Jing Huang7725ccf2009-09-23 17:46:15 -070044static void bfa_lps_detach(struct bfa_s *bfa);
45static void bfa_lps_start(struct bfa_s *bfa);
46static void bfa_lps_stop(struct bfa_s *bfa);
47static void bfa_lps_iocdisable(struct bfa_s *bfa);
48static void bfa_lps_login_rsp(struct bfa_s *bfa,
49 struct bfi_lps_login_rsp_s *rsp);
50static void bfa_lps_logout_rsp(struct bfa_s *bfa,
51 struct bfi_lps_logout_rsp_s *rsp);
52static void bfa_lps_reqq_resume(void *lps_arg);
53static void bfa_lps_free(struct bfa_lps_s *lps);
54static void bfa_lps_send_login(struct bfa_lps_s *lps);
55static void bfa_lps_send_logout(struct bfa_lps_s *lps);
56static void bfa_lps_login_comp(struct bfa_lps_s *lps);
57static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -080058static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
Jing Huang7725ccf2009-09-23 17:46:15 -070059
60/**
61 * lps_pvt BFA LPS private functions
62 */
63
64enum 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 */
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -080071 BFA_LPS_SM_RX_CVL = 7, /* Rx clear virtual link */
Jing Huang7725ccf2009-09-23 17:46:15 -070072};
73
74static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
75static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
76static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps,
77 enum bfa_lps_event event);
78static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
79static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
80static void bfa_lps_sm_logowait(struct bfa_lps_s *lps,
81 enum bfa_lps_event event);
82
83/**
84 * Init state -- no login
85 */
86static void
87bfa_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 }
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800101 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");
Jing Huang7725ccf2009-09-23 17:46:15 -0700107 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
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800117 case BFA_LPS_SM_RX_CVL:
Jing Huang7725ccf2009-09-23 17:46:15 -0700118 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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800129 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700130 }
131}
132
133/**
134 * login is in progress -- awaiting response from firmware
135 */
136static void
137bfa_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:
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800144 if (lps->status == BFA_STATUS_OK) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700145 bfa_sm_set_state(lps, bfa_lps_sm_online);
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800146 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 {
Jing Huang7725ccf2009-09-23 17:46:15 -0700153 bfa_sm_set_state(lps, bfa_lps_sm_init);
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800154 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 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700163 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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800171 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700172 }
173}
174
175/**
176 * login pending - awaiting space in request queue
177 */
178static void
179bfa_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
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800194 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
Jing Huang7725ccf2009-09-23 17:46:15 -0700202 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800203 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700204 }
205}
206
207/**
208 * login complete
209 */
210static void
211bfa_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 }
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800225 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
226 BFA_PL_EID_LOGO, 0, "Logout");
Jing Huang7725ccf2009-09-23 17:46:15 -0700227 break;
228
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800229 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
Jing Huang7725ccf2009-09-23 17:46:15 -0700238 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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800244 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700245 }
246}
247
248/**
249 * logout in progress - awaiting firmware response
250 */
251static void
252bfa_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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800268 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700269 }
270}
271
272/**
273 * logout pending -- awaiting space in request queue
274 */
275static void
276bfa_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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800293 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700294 }
295}
296
297
298
299/**
300 * lps_pvt BFA LPS private functions
301 */
302
303/**
304 * return memory requirement
305 */
306static void
307bfa_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 */
318static void
319bfa_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
348static void
Jing Huang7725ccf2009-09-23 17:46:15 -0700349bfa_lps_detach(struct bfa_s *bfa)
350{
351}
352
353static void
354bfa_lps_start(struct bfa_s *bfa)
355{
356}
357
358static void
359bfa_lps_stop(struct bfa_s *bfa)
360{
361}
362
363/**
364 * IOC in disabled state -- consider all lps offline
365 */
366static void
367bfa_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 */
382static void
383bfa_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 */
429static void
430bfa_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/**
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800442 * Firmware received a Clear virtual link request (for FCoE)
443 */
444static void
445bfa_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/**
Jing Huang7725ccf2009-09-23 17:46:15 -0700456 * Space is available in request queue, resume queueing request to firmware.
457 */
458static void
459bfa_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 */
469static void
470bfa_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 */
481static void
482bfa_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 */
506static void
507bfa_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 */
525static void
526bfa_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 */
542static void
543bfa_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 */
560static void
561bfa_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 */
577static void
578bfa_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
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800591/**
592 * Clear virtual link completion handler for non-fcs
593 */
594static void
595bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
596{
597 struct bfa_lps_s *lps = arg;
Jing Huang7725ccf2009-09-23 17:46:15 -0700598
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800599 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 */
611static void
612bfa_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}
Jing Huang7725ccf2009-09-23 17:46:15 -0700624
Krishna Gudipatia046bf052010-03-03 17:43:45 -0800625u32
626bfa_lps_get_max_vport(struct bfa_s *bfa)
627{
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -0800628 if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800629 return BFA_LPS_MAX_VPORTS_SUPP_CT;
Krishna Gudipatia046bf052010-03-03 17:43:45 -0800630 else
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800631 return BFA_LPS_MAX_VPORTS_SUPP_CB;
Krishna Gudipatia046bf052010-03-03 17:43:45 -0800632}
633
Jing Huang7725ccf2009-09-23 17:46:15 -0700634/**
635 * lps_public BFA LPS public functions
636 */
637
638/**
639 * Allocate a lport srvice tag.
640 */
641struct bfa_lps_s *
642bfa_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 */
662void
663bfa_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 */
671void
672bfa_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 */
688void
689bfa_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 */
705void
706bfa_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 */
714void
715bfa_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 */
724void
725bfa_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 */
733u8
734bfa_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 */
742u8
743bfa_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 */
761bfa_boolean_t
762bfa_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 */
770bfa_boolean_t
771bfa_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 */
779bfa_boolean_t
780bfa_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 */
787bfa_boolean_t
788bfa_lps_is_authreq(struct bfa_lps_s *lps)
789{
790 return lps->auth_req;
791}
792
793bfa_eproto_status_t
794bfa_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 */
802u32
803bfa_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 */
811u16
812bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
813{
814 return lps->pr_bbcred;
815}
816
817/**
818 * Return peer port name
819 */
820wwn_t
821bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
822{
823 return lps->pr_pwwn;
824}
825
826/**
827 * Return peer node name
828 */
829wwn_t
830bfa_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 */
838u8
839bfa_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 */
847u8
848bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
849{
850 return lps->lsrjt_expl;
851}
852
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800853/**
854 * Return fpma/spma MAC for lport
855 */
856struct mac_s
857bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
858{
859 return lps->lp_mac;
860}
Jing Huang7725ccf2009-09-23 17:46:15 -0700861
862/**
863 * LPS firmware message class handler.
864 */
865void
866bfa_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
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800882 case BFI_LPS_H2I_CVL_EVENT:
883 bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
884 break;
885
Jing Huang7725ccf2009-09-23 17:46:15 -0700886 default:
887 bfa_trc(bfa, m->mhdr.msg_id);
888 bfa_assert(0);
889 }
890}
891
892