blob: d2d48a619c30973a14a30388c15146394abd29de [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{
634 struct bfa_ioc_attr_s ioc_attr;
635
636 bfa_get_attr(bfa, &ioc_attr);
637
638 if (ioc_attr.pci_attr.device_id == BFA_PCI_DEVICE_ID_CT)
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800639 return BFA_LPS_MAX_VPORTS_SUPP_CT;
Krishna Gudipatia046bf02010-03-03 17:43:45 -0800640 else
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800641 return BFA_LPS_MAX_VPORTS_SUPP_CB;
Krishna Gudipatia046bf02010-03-03 17:43:45 -0800642}
643
Jing Huang7725ccf2009-09-23 17:46:15 -0700644/**
645 * lps_public BFA LPS public functions
646 */
647
648/**
649 * Allocate a lport srvice tag.
650 */
651struct bfa_lps_s *
652bfa_lps_alloc(struct bfa_s *bfa)
653{
654 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
655 struct bfa_lps_s *lps = NULL;
656
657 bfa_q_deq(&mod->lps_free_q, &lps);
658
659 if (lps == NULL)
660 return NULL;
661
662 list_add_tail(&lps->qe, &mod->lps_active_q);
663
664 bfa_sm_set_state(lps, bfa_lps_sm_init);
665 return lps;
666}
667
668/**
669 * Free lport service tag. This can be called anytime after an alloc.
670 * No need to wait for any pending login/logout completions.
671 */
672void
673bfa_lps_delete(struct bfa_lps_s *lps)
674{
675 bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
676}
677
678/**
679 * Initiate a lport login.
680 */
681void
682bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
683 wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
684{
685 lps->uarg = uarg;
686 lps->alpa = alpa;
687 lps->pdusz = pdusz;
688 lps->pwwn = pwwn;
689 lps->nwwn = nwwn;
690 lps->fdisc = BFA_FALSE;
691 lps->auth_en = auth_en;
692 bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
693}
694
695/**
696 * Initiate a lport fdisc login.
697 */
698void
699bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
700 wwn_t nwwn)
701{
702 lps->uarg = uarg;
703 lps->alpa = 0;
704 lps->pdusz = pdusz;
705 lps->pwwn = pwwn;
706 lps->nwwn = nwwn;
707 lps->fdisc = BFA_TRUE;
708 lps->auth_en = BFA_FALSE;
709 bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
710}
711
712/**
713 * Initiate a lport logout (flogi).
714 */
715void
716bfa_lps_flogo(struct bfa_lps_s *lps)
717{
718 bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
719}
720
721/**
722 * Initiate a lport FDSIC logout.
723 */
724void
725bfa_lps_fdisclogo(struct bfa_lps_s *lps)
726{
727 bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
728}
729
730/**
731 * Discard a pending login request -- should be called only for
732 * link down handling.
733 */
734void
735bfa_lps_discard(struct bfa_lps_s *lps)
736{
737 bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
738}
739
740/**
741 * Return lport services tag
742 */
743u8
744bfa_lps_get_tag(struct bfa_lps_s *lps)
745{
746 return lps->lp_tag;
747}
748
749/**
750 * Return lport services tag given the pid
751 */
752u8
753bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
754{
755 struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
756 struct bfa_lps_s *lps;
757 int i;
758
759 for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
760 if (lps->lp_pid == pid)
761 return lps->lp_tag;
762 }
763
764 /* Return base port tag anyway */
765 return 0;
766}
767
768/**
769 * return if fabric login indicates support for NPIV
770 */
771bfa_boolean_t
772bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
773{
774 return lps->npiv_en;
775}
776
777/**
778 * Return TRUE if attached to F-Port, else return FALSE
779 */
780bfa_boolean_t
781bfa_lps_is_fport(struct bfa_lps_s *lps)
782{
783 return lps->fport;
784}
785
786/**
787 * Return TRUE if attached to a Brocade Fabric
788 */
789bfa_boolean_t
790bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
791{
792 return lps->brcd_switch;
793}
794/**
795 * return TRUE if authentication is required
796 */
797bfa_boolean_t
798bfa_lps_is_authreq(struct bfa_lps_s *lps)
799{
800 return lps->auth_req;
801}
802
803bfa_eproto_status_t
804bfa_lps_get_extstatus(struct bfa_lps_s *lps)
805{
806 return lps->ext_status;
807}
808
809/**
810 * return port id assigned to the lport
811 */
812u32
813bfa_lps_get_pid(struct bfa_lps_s *lps)
814{
815 return lps->lp_pid;
816}
817
818/**
819 * Return bb_credit assigned in FLOGI response
820 */
821u16
822bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
823{
824 return lps->pr_bbcred;
825}
826
827/**
828 * Return peer port name
829 */
830wwn_t
831bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
832{
833 return lps->pr_pwwn;
834}
835
836/**
837 * Return peer node name
838 */
839wwn_t
840bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
841{
842 return lps->pr_nwwn;
843}
844
845/**
846 * return reason code if login request is rejected
847 */
848u8
849bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
850{
851 return lps->lsrjt_rsn;
852}
853
854/**
855 * return explanation code if login request is rejected
856 */
857u8
858bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
859{
860 return lps->lsrjt_expl;
861}
862
Krishna Gudipati86e32da2010-03-05 19:35:33 -0800863/**
864 * Return fpma/spma MAC for lport
865 */
866struct mac_s
867bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
868{
869 return lps->lp_mac;
870}
Jing Huang7725ccf2009-09-23 17:46:15 -0700871
872/**
873 * LPS firmware message class handler.
874 */
875void
876bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
877{
878 union bfi_lps_i2h_msg_u msg;
879
880 bfa_trc(bfa, m->mhdr.msg_id);
881 msg.msg = m;
882
883 switch (m->mhdr.msg_id) {
884 case BFI_LPS_H2I_LOGIN_RSP:
885 bfa_lps_login_rsp(bfa, msg.login_rsp);
886 break;
887
888 case BFI_LPS_H2I_LOGOUT_RSP:
889 bfa_lps_logout_rsp(bfa, msg.logout_rsp);
890 break;
891
Krishna Gudipati5c1fb1d2010-03-03 17:42:39 -0800892 case BFI_LPS_H2I_CVL_EVENT:
893 bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
894 break;
895
Jing Huang7725ccf2009-09-23 17:46:15 -0700896 default:
897 bfa_trc(bfa, m->mhdr.msg_id);
898 bfa_assert(0);
899 }
900}
901
902