blob: ad06f6189092b59833a3d0de039c5195d1badd55 [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 Gudipatia046bf02010-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 Gudipatia046bf02010-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 }
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800102 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");
Jing Huang7725ccf2009-09-23 17:46:15 -0700108 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
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800118 case BFA_LPS_SM_RX_CVL:
Jing Huang7725ccf2009-09-23 17:46:15 -0700119 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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800130 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700131 }
132}
133
134/**
135 * login is in progress -- awaiting response from firmware
136 */
137static void
138bfa_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:
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800145 if (lps->status == BFA_STATUS_OK) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700146 bfa_sm_set_state(lps, bfa_lps_sm_online);
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800147 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 {
Jing Huang7725ccf2009-09-23 17:46:15 -0700154 bfa_sm_set_state(lps, bfa_lps_sm_init);
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800155 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 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700164 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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800172 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700173 }
174}
175
176/**
177 * login pending - awaiting space in request queue
178 */
179static void
180bfa_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
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800195 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
Jing Huang7725ccf2009-09-23 17:46:15 -0700203 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800204 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700205 }
206}
207
208/**
209 * login complete
210 */
211static void
212bfa_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 }
Krishna Gudipatif58e9eb2010-03-05 19:37:45 -0800226 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
227 BFA_PL_EID_LOGO, 0, "Logout");
Jing Huang7725ccf2009-09-23 17:46:15 -0700228 break;
229
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800230 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
Jing Huang7725ccf2009-09-23 17:46:15 -0700239 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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800245 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700246 }
247}
248
249/**
250 * logout in progress - awaiting firmware response
251 */
252static void
253bfa_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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800269 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700270 }
271}
272
273/**
274 * logout pending -- awaiting space in request queue
275 */
276static void
277bfa_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:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800294 bfa_sm_fault(lps->bfa, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700295 }
296}
297
298
299
300/**
301 * lps_pvt BFA LPS private functions
302 */
303
304/**
305 * return memory requirement
306 */
307static void
308bfa_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 */
319static void
320bfa_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
349static void
350bfa_lps_initdone(struct bfa_s *bfa)
351{
352}
353
354static void
355bfa_lps_detach(struct bfa_s *bfa)
356{
357}
358
359static void
360bfa_lps_start(struct bfa_s *bfa)
361{
362}
363
364static void
365bfa_lps_stop(struct bfa_s *bfa)
366{
367}
368
369/**
370 * IOC in disabled state -- consider all lps offline
371 */
372static void
373bfa_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 */
388static void
389bfa_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 */
435static void
436bfa_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/**
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800448 * Firmware received a Clear virtual link request (for FCoE)
449 */
450static void
451bfa_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/**
Jing Huang7725ccf2009-09-23 17:46:15 -0700462 * Space is available in request queue, resume queueing request to firmware.
463 */
464static void
465bfa_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 */
475static void
476bfa_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 */
487static void
488bfa_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 */
512static void
513bfa_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 */
531static void
532bfa_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 */
548static void
549bfa_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 */
566static void
567bfa_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 */
583static void
584bfa_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
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800597/**
598 * Clear virtual link completion handler for non-fcs
599 */
600static void
601bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
602{
603 struct bfa_lps_s *lps = arg;
Jing Huang7725ccf2009-09-23 17:46:15 -0700604
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800605 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 */
617static void
618bfa_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}
Jing Huang7725ccf2009-09-23 17:46:15 -0700630
Krishna Gudipatia046bf02010-03-03 17:43:45 -0800631u32
632bfa_lps_get_max_vport(struct bfa_s *bfa)
633{
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -0800634 if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800635 return BFA_LPS_MAX_VPORTS_SUPP_CT;
Krishna Gudipatia046bf02010-03-03 17:43:45 -0800636 else
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800637 return BFA_LPS_MAX_VPORTS_SUPP_CB;
Krishna Gudipatia046bf02010-03-03 17:43:45 -0800638}
639
Jing Huang7725ccf2009-09-23 17:46:15 -0700640/**
641 * lps_public BFA LPS public functions
642 */
643
644/**
645 * Allocate a lport srvice tag.
646 */
647struct bfa_lps_s *
648bfa_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 */
668void
669bfa_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 */
677void
678bfa_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 */
694void
695bfa_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 */
711void
712bfa_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 */
720void
721bfa_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 */
730void
731bfa_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 */
739u8
740bfa_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 */
748u8
749bfa_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 */
767bfa_boolean_t
768bfa_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 */
776bfa_boolean_t
777bfa_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 */
785bfa_boolean_t
786bfa_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 */
793bfa_boolean_t
794bfa_lps_is_authreq(struct bfa_lps_s *lps)
795{
796 return lps->auth_req;
797}
798
799bfa_eproto_status_t
800bfa_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 */
808u32
809bfa_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 */
817u16
818bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
819{
820 return lps->pr_bbcred;
821}
822
823/**
824 * Return peer port name
825 */
826wwn_t
827bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
828{
829 return lps->pr_pwwn;
830}
831
832/**
833 * Return peer node name
834 */
835wwn_t
836bfa_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 */
844u8
845bfa_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 */
853u8
854bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
855{
856 return lps->lsrjt_expl;
857}
858
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800859/**
860 * Return fpma/spma MAC for lport
861 */
862struct mac_s
863bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
864{
865 return lps->lp_mac;
866}
Jing Huang7725ccf2009-09-23 17:46:15 -0700867
868/**
869 * LPS firmware message class handler.
870 */
871void
872bfa_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
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800888 case BFI_LPS_H2I_CVL_EVENT:
889 bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
890 break;
891
Jing Huang7725ccf2009-09-23 17:46:15 -0700892 default:
893 bfa_trc(bfa, m->mhdr.msg_id);
894 bfa_assert(0);
895 }
896}
897
898