diff options
Diffstat (limited to 'drivers/scsi/bfa/bfa_lps.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_lps.c | 782 |
1 files changed, 782 insertions, 0 deletions
diff --git a/drivers/scsi/bfa/bfa_lps.c b/drivers/scsi/bfa/bfa_lps.c new file mode 100644 index 00000000000..9844b45412b --- /dev/null +++ b/drivers/scsi/bfa/bfa_lps.c | |||
@@ -0,0 +1,782 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. | ||
3 | * All rights reserved | ||
4 | * www.brocade.com | ||
5 | * | ||
6 | * Linux driver for Brocade Fibre Channel Host Bus Adapter. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License (GPL) Version 2 as | ||
10 | * published by the Free Software Foundation | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <bfa.h> | ||
19 | #include <bfi/bfi_lps.h> | ||
20 | #include <cs/bfa_debug.h> | ||
21 | |||
22 | BFA_TRC_FILE(HAL, LPS); | ||
23 | BFA_MODULE(lps); | ||
24 | |||
25 | #define BFA_LPS_MIN_LPORTS (1) | ||
26 | #define BFA_LPS_MAX_LPORTS (256) | ||
27 | |||
28 | /** | ||
29 | * forward declarations | ||
30 | */ | ||
31 | static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, | ||
32 | u32 *dm_len); | ||
33 | static void bfa_lps_attach(struct bfa_s *bfa, void *bfad, | ||
34 | struct bfa_iocfc_cfg_s *cfg, | ||
35 | struct bfa_meminfo_s *meminfo, | ||
36 | struct bfa_pcidev_s *pcidev); | ||
37 | static void bfa_lps_initdone(struct bfa_s *bfa); | ||
38 | static void bfa_lps_detach(struct bfa_s *bfa); | ||
39 | static void bfa_lps_start(struct bfa_s *bfa); | ||
40 | static void bfa_lps_stop(struct bfa_s *bfa); | ||
41 | static void bfa_lps_iocdisable(struct bfa_s *bfa); | ||
42 | static void bfa_lps_login_rsp(struct bfa_s *bfa, | ||
43 | struct bfi_lps_login_rsp_s *rsp); | ||
44 | static void bfa_lps_logout_rsp(struct bfa_s *bfa, | ||
45 | struct bfi_lps_logout_rsp_s *rsp); | ||
46 | static void bfa_lps_reqq_resume(void *lps_arg); | ||
47 | static void bfa_lps_free(struct bfa_lps_s *lps); | ||
48 | static void bfa_lps_send_login(struct bfa_lps_s *lps); | ||
49 | static void bfa_lps_send_logout(struct bfa_lps_s *lps); | ||
50 | static void bfa_lps_login_comp(struct bfa_lps_s *lps); | ||
51 | static void bfa_lps_logout_comp(struct bfa_lps_s *lps); | ||
52 | |||
53 | |||
54 | /** | ||
55 | * lps_pvt BFA LPS private functions | ||
56 | */ | ||
57 | |||
58 | enum bfa_lps_event { | ||
59 | BFA_LPS_SM_LOGIN = 1, /* login request from user */ | ||
60 | BFA_LPS_SM_LOGOUT = 2, /* logout request from user */ | ||
61 | BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */ | ||
62 | BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */ | ||
63 | BFA_LPS_SM_DELETE = 5, /* lps delete from user */ | ||
64 | BFA_LPS_SM_OFFLINE = 6, /* Link is offline */ | ||
65 | }; | ||
66 | |||
67 | static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event); | ||
68 | static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event); | ||
69 | static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, | ||
70 | enum bfa_lps_event event); | ||
71 | static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event); | ||
72 | static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event); | ||
73 | static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, | ||
74 | enum bfa_lps_event event); | ||
75 | |||
76 | /** | ||
77 | * Init state -- no login | ||
78 | */ | ||
79 | static void | ||
80 | bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
81 | { | ||
82 | bfa_trc(lps->bfa, lps->lp_tag); | ||
83 | bfa_trc(lps->bfa, event); | ||
84 | |||
85 | switch (event) { | ||
86 | case BFA_LPS_SM_LOGIN: | ||
87 | if (bfa_reqq_full(lps->bfa, lps->reqq)) { | ||
88 | bfa_sm_set_state(lps, bfa_lps_sm_loginwait); | ||
89 | bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe); | ||
90 | } else { | ||
91 | bfa_sm_set_state(lps, bfa_lps_sm_login); | ||
92 | bfa_lps_send_login(lps); | ||
93 | } | ||
94 | break; | ||
95 | |||
96 | case BFA_LPS_SM_LOGOUT: | ||
97 | bfa_lps_logout_comp(lps); | ||
98 | break; | ||
99 | |||
100 | case BFA_LPS_SM_DELETE: | ||
101 | bfa_lps_free(lps); | ||
102 | break; | ||
103 | |||
104 | case BFA_LPS_SM_OFFLINE: | ||
105 | break; | ||
106 | |||
107 | case BFA_LPS_SM_FWRSP: | ||
108 | /* Could happen when fabric detects loopback and discards | ||
109 | * the lps request. Fw will eventually sent out the timeout | ||
110 | * Just ignore | ||
111 | */ | ||
112 | break; | ||
113 | |||
114 | default: | ||
115 | bfa_assert(0); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * login is in progress -- awaiting response from firmware | ||
121 | */ | ||
122 | static void | ||
123 | bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
124 | { | ||
125 | bfa_trc(lps->bfa, lps->lp_tag); | ||
126 | bfa_trc(lps->bfa, event); | ||
127 | |||
128 | switch (event) { | ||
129 | case BFA_LPS_SM_FWRSP: | ||
130 | if (lps->status == BFA_STATUS_OK) | ||
131 | bfa_sm_set_state(lps, bfa_lps_sm_online); | ||
132 | else | ||
133 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
134 | bfa_lps_login_comp(lps); | ||
135 | break; | ||
136 | |||
137 | case BFA_LPS_SM_OFFLINE: | ||
138 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
139 | break; | ||
140 | |||
141 | default: | ||
142 | bfa_assert(0); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * login pending - awaiting space in request queue | ||
148 | */ | ||
149 | static void | ||
150 | bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
151 | { | ||
152 | bfa_trc(lps->bfa, lps->lp_tag); | ||
153 | bfa_trc(lps->bfa, event); | ||
154 | |||
155 | switch (event) { | ||
156 | case BFA_LPS_SM_RESUME: | ||
157 | bfa_sm_set_state(lps, bfa_lps_sm_login); | ||
158 | break; | ||
159 | |||
160 | case BFA_LPS_SM_OFFLINE: | ||
161 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
162 | bfa_reqq_wcancel(&lps->wqe); | ||
163 | break; | ||
164 | |||
165 | default: | ||
166 | bfa_assert(0); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * login complete | ||
172 | */ | ||
173 | static void | ||
174 | bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
175 | { | ||
176 | bfa_trc(lps->bfa, lps->lp_tag); | ||
177 | bfa_trc(lps->bfa, event); | ||
178 | |||
179 | switch (event) { | ||
180 | case BFA_LPS_SM_LOGOUT: | ||
181 | if (bfa_reqq_full(lps->bfa, lps->reqq)) { | ||
182 | bfa_sm_set_state(lps, bfa_lps_sm_logowait); | ||
183 | bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe); | ||
184 | } else { | ||
185 | bfa_sm_set_state(lps, bfa_lps_sm_logout); | ||
186 | bfa_lps_send_logout(lps); | ||
187 | } | ||
188 | break; | ||
189 | |||
190 | case BFA_LPS_SM_OFFLINE: | ||
191 | case BFA_LPS_SM_DELETE: | ||
192 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
193 | break; | ||
194 | |||
195 | default: | ||
196 | bfa_assert(0); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * logout in progress - awaiting firmware response | ||
202 | */ | ||
203 | static void | ||
204 | bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
205 | { | ||
206 | bfa_trc(lps->bfa, lps->lp_tag); | ||
207 | bfa_trc(lps->bfa, event); | ||
208 | |||
209 | switch (event) { | ||
210 | case BFA_LPS_SM_FWRSP: | ||
211 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
212 | bfa_lps_logout_comp(lps); | ||
213 | break; | ||
214 | |||
215 | case BFA_LPS_SM_OFFLINE: | ||
216 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
217 | break; | ||
218 | |||
219 | default: | ||
220 | bfa_assert(0); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * logout pending -- awaiting space in request queue | ||
226 | */ | ||
227 | static void | ||
228 | bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
229 | { | ||
230 | bfa_trc(lps->bfa, lps->lp_tag); | ||
231 | bfa_trc(lps->bfa, event); | ||
232 | |||
233 | switch (event) { | ||
234 | case BFA_LPS_SM_RESUME: | ||
235 | bfa_sm_set_state(lps, bfa_lps_sm_logout); | ||
236 | bfa_lps_send_logout(lps); | ||
237 | break; | ||
238 | |||
239 | case BFA_LPS_SM_OFFLINE: | ||
240 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
241 | bfa_reqq_wcancel(&lps->wqe); | ||
242 | break; | ||
243 | |||
244 | default: | ||
245 | bfa_assert(0); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | |||
250 | |||
251 | /** | ||
252 | * lps_pvt BFA LPS private functions | ||
253 | */ | ||
254 | |||
255 | /** | ||
256 | * return memory requirement | ||
257 | */ | ||
258 | static void | ||
259 | bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len) | ||
260 | { | ||
261 | if (cfg->drvcfg.min_cfg) | ||
262 | *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS; | ||
263 | else | ||
264 | *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS; | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * bfa module attach at initialization time | ||
269 | */ | ||
270 | static void | ||
271 | bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
272 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
273 | { | ||
274 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
275 | struct bfa_lps_s *lps; | ||
276 | int i; | ||
277 | |||
278 | bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s)); | ||
279 | mod->num_lps = BFA_LPS_MAX_LPORTS; | ||
280 | if (cfg->drvcfg.min_cfg) | ||
281 | mod->num_lps = BFA_LPS_MIN_LPORTS; | ||
282 | else | ||
283 | mod->num_lps = BFA_LPS_MAX_LPORTS; | ||
284 | mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo); | ||
285 | |||
286 | bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s); | ||
287 | |||
288 | INIT_LIST_HEAD(&mod->lps_free_q); | ||
289 | INIT_LIST_HEAD(&mod->lps_active_q); | ||
290 | |||
291 | for (i = 0; i < mod->num_lps; i++, lps++) { | ||
292 | lps->bfa = bfa; | ||
293 | lps->lp_tag = (u8) i; | ||
294 | lps->reqq = BFA_REQQ_LPS; | ||
295 | bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps); | ||
296 | list_add_tail(&lps->qe, &mod->lps_free_q); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static void | ||
301 | bfa_lps_initdone(struct bfa_s *bfa) | ||
302 | { | ||
303 | } | ||
304 | |||
305 | static void | ||
306 | bfa_lps_detach(struct bfa_s *bfa) | ||
307 | { | ||
308 | } | ||
309 | |||
310 | static void | ||
311 | bfa_lps_start(struct bfa_s *bfa) | ||
312 | { | ||
313 | } | ||
314 | |||
315 | static void | ||
316 | bfa_lps_stop(struct bfa_s *bfa) | ||
317 | { | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * IOC in disabled state -- consider all lps offline | ||
322 | */ | ||
323 | static void | ||
324 | bfa_lps_iocdisable(struct bfa_s *bfa) | ||
325 | { | ||
326 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
327 | struct bfa_lps_s *lps; | ||
328 | struct list_head *qe, *qen; | ||
329 | |||
330 | list_for_each_safe(qe, qen, &mod->lps_active_q) { | ||
331 | lps = (struct bfa_lps_s *) qe; | ||
332 | bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * Firmware login response | ||
338 | */ | ||
339 | static void | ||
340 | bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp) | ||
341 | { | ||
342 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
343 | struct bfa_lps_s *lps; | ||
344 | |||
345 | bfa_assert(rsp->lp_tag < mod->num_lps); | ||
346 | lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag); | ||
347 | |||
348 | lps->status = rsp->status; | ||
349 | switch (rsp->status) { | ||
350 | case BFA_STATUS_OK: | ||
351 | lps->fport = rsp->f_port; | ||
352 | lps->npiv_en = rsp->npiv_en; | ||
353 | lps->lp_pid = rsp->lp_pid; | ||
354 | lps->pr_bbcred = bfa_os_ntohs(rsp->bb_credit); | ||
355 | lps->pr_pwwn = rsp->port_name; | ||
356 | lps->pr_nwwn = rsp->node_name; | ||
357 | lps->auth_req = rsp->auth_req; | ||
358 | lps->lp_mac = rsp->lp_mac; | ||
359 | lps->brcd_switch = rsp->brcd_switch; | ||
360 | lps->fcf_mac = rsp->fcf_mac; | ||
361 | |||
362 | break; | ||
363 | |||
364 | case BFA_STATUS_FABRIC_RJT: | ||
365 | lps->lsrjt_rsn = rsp->lsrjt_rsn; | ||
366 | lps->lsrjt_expl = rsp->lsrjt_expl; | ||
367 | |||
368 | break; | ||
369 | |||
370 | case BFA_STATUS_EPROTOCOL: | ||
371 | lps->ext_status = rsp->ext_status; | ||
372 | |||
373 | break; | ||
374 | |||
375 | default: | ||
376 | /* Nothing to do with other status */ | ||
377 | break; | ||
378 | } | ||
379 | |||
380 | bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP); | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * Firmware logout response | ||
385 | */ | ||
386 | static void | ||
387 | bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp) | ||
388 | { | ||
389 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
390 | struct bfa_lps_s *lps; | ||
391 | |||
392 | bfa_assert(rsp->lp_tag < mod->num_lps); | ||
393 | lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag); | ||
394 | |||
395 | bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP); | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * Space is available in request queue, resume queueing request to firmware. | ||
400 | */ | ||
401 | static void | ||
402 | bfa_lps_reqq_resume(void *lps_arg) | ||
403 | { | ||
404 | struct bfa_lps_s *lps = lps_arg; | ||
405 | |||
406 | bfa_sm_send_event(lps, BFA_LPS_SM_RESUME); | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * lps is freed -- triggered by vport delete | ||
411 | */ | ||
412 | static void | ||
413 | bfa_lps_free(struct bfa_lps_s *lps) | ||
414 | { | ||
415 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(lps->bfa); | ||
416 | |||
417 | list_del(&lps->qe); | ||
418 | list_add_tail(&lps->qe, &mod->lps_free_q); | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * send login request to firmware | ||
423 | */ | ||
424 | static void | ||
425 | bfa_lps_send_login(struct bfa_lps_s *lps) | ||
426 | { | ||
427 | struct bfi_lps_login_req_s *m; | ||
428 | |||
429 | m = bfa_reqq_next(lps->bfa, lps->reqq); | ||
430 | bfa_assert(m); | ||
431 | |||
432 | bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ, | ||
433 | bfa_lpuid(lps->bfa)); | ||
434 | |||
435 | m->lp_tag = lps->lp_tag; | ||
436 | m->alpa = lps->alpa; | ||
437 | m->pdu_size = bfa_os_htons(lps->pdusz); | ||
438 | m->pwwn = lps->pwwn; | ||
439 | m->nwwn = lps->nwwn; | ||
440 | m->fdisc = lps->fdisc; | ||
441 | m->auth_en = lps->auth_en; | ||
442 | |||
443 | bfa_reqq_produce(lps->bfa, lps->reqq); | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * send logout request to firmware | ||
448 | */ | ||
449 | static void | ||
450 | bfa_lps_send_logout(struct bfa_lps_s *lps) | ||
451 | { | ||
452 | struct bfi_lps_logout_req_s *m; | ||
453 | |||
454 | m = bfa_reqq_next(lps->bfa, lps->reqq); | ||
455 | bfa_assert(m); | ||
456 | |||
457 | bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ, | ||
458 | bfa_lpuid(lps->bfa)); | ||
459 | |||
460 | m->lp_tag = lps->lp_tag; | ||
461 | m->port_name = lps->pwwn; | ||
462 | bfa_reqq_produce(lps->bfa, lps->reqq); | ||
463 | } | ||
464 | |||
465 | /** | ||
466 | * Indirect login completion handler for non-fcs | ||
467 | */ | ||
468 | static void | ||
469 | bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete) | ||
470 | { | ||
471 | struct bfa_lps_s *lps = arg; | ||
472 | |||
473 | if (!complete) | ||
474 | return; | ||
475 | |||
476 | if (lps->fdisc) | ||
477 | bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status); | ||
478 | else | ||
479 | bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status); | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * Login completion handler -- direct call for fcs, queue for others | ||
484 | */ | ||
485 | static void | ||
486 | bfa_lps_login_comp(struct bfa_lps_s *lps) | ||
487 | { | ||
488 | if (!lps->bfa->fcs) { | ||
489 | bfa_cb_queue(lps->bfa, &lps->hcb_qe, | ||
490 | bfa_lps_login_comp_cb, lps); | ||
491 | return; | ||
492 | } | ||
493 | |||
494 | if (lps->fdisc) | ||
495 | bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status); | ||
496 | else | ||
497 | bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status); | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * Indirect logout completion handler for non-fcs | ||
502 | */ | ||
503 | static void | ||
504 | bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete) | ||
505 | { | ||
506 | struct bfa_lps_s *lps = arg; | ||
507 | |||
508 | if (!complete) | ||
509 | return; | ||
510 | |||
511 | if (lps->fdisc) | ||
512 | bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg); | ||
513 | else | ||
514 | bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg); | ||
515 | } | ||
516 | |||
517 | /** | ||
518 | * Logout completion handler -- direct call for fcs, queue for others | ||
519 | */ | ||
520 | static void | ||
521 | bfa_lps_logout_comp(struct bfa_lps_s *lps) | ||
522 | { | ||
523 | if (!lps->bfa->fcs) { | ||
524 | bfa_cb_queue(lps->bfa, &lps->hcb_qe, | ||
525 | bfa_lps_logout_comp_cb, lps); | ||
526 | return; | ||
527 | } | ||
528 | if (lps->fdisc) | ||
529 | bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg); | ||
530 | else | ||
531 | bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg); | ||
532 | } | ||
533 | |||
534 | |||
535 | |||
536 | /** | ||
537 | * lps_public BFA LPS public functions | ||
538 | */ | ||
539 | |||
540 | /** | ||
541 | * Allocate a lport srvice tag. | ||
542 | */ | ||
543 | struct bfa_lps_s * | ||
544 | bfa_lps_alloc(struct bfa_s *bfa) | ||
545 | { | ||
546 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
547 | struct bfa_lps_s *lps = NULL; | ||
548 | |||
549 | bfa_q_deq(&mod->lps_free_q, &lps); | ||
550 | |||
551 | if (lps == NULL) | ||
552 | return NULL; | ||
553 | |||
554 | list_add_tail(&lps->qe, &mod->lps_active_q); | ||
555 | |||
556 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
557 | return lps; | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * Free lport service tag. This can be called anytime after an alloc. | ||
562 | * No need to wait for any pending login/logout completions. | ||
563 | */ | ||
564 | void | ||
565 | bfa_lps_delete(struct bfa_lps_s *lps) | ||
566 | { | ||
567 | bfa_sm_send_event(lps, BFA_LPS_SM_DELETE); | ||
568 | } | ||
569 | |||
570 | /** | ||
571 | * Initiate a lport login. | ||
572 | */ | ||
573 | void | ||
574 | bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz, | ||
575 | wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en) | ||
576 | { | ||
577 | lps->uarg = uarg; | ||
578 | lps->alpa = alpa; | ||
579 | lps->pdusz = pdusz; | ||
580 | lps->pwwn = pwwn; | ||
581 | lps->nwwn = nwwn; | ||
582 | lps->fdisc = BFA_FALSE; | ||
583 | lps->auth_en = auth_en; | ||
584 | bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN); | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * Initiate a lport fdisc login. | ||
589 | */ | ||
590 | void | ||
591 | bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn, | ||
592 | wwn_t nwwn) | ||
593 | { | ||
594 | lps->uarg = uarg; | ||
595 | lps->alpa = 0; | ||
596 | lps->pdusz = pdusz; | ||
597 | lps->pwwn = pwwn; | ||
598 | lps->nwwn = nwwn; | ||
599 | lps->fdisc = BFA_TRUE; | ||
600 | lps->auth_en = BFA_FALSE; | ||
601 | bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN); | ||
602 | } | ||
603 | |||
604 | /** | ||
605 | * Initiate a lport logout (flogi). | ||
606 | */ | ||
607 | void | ||
608 | bfa_lps_flogo(struct bfa_lps_s *lps) | ||
609 | { | ||
610 | bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT); | ||
611 | } | ||
612 | |||
613 | /** | ||
614 | * Initiate a lport FDSIC logout. | ||
615 | */ | ||
616 | void | ||
617 | bfa_lps_fdisclogo(struct bfa_lps_s *lps) | ||
618 | { | ||
619 | bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT); | ||
620 | } | ||
621 | |||
622 | /** | ||
623 | * Discard a pending login request -- should be called only for | ||
624 | * link down handling. | ||
625 | */ | ||
626 | void | ||
627 | bfa_lps_discard(struct bfa_lps_s *lps) | ||
628 | { | ||
629 | bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE); | ||
630 | } | ||
631 | |||
632 | /** | ||
633 | * Return lport services tag | ||
634 | */ | ||
635 | u8 | ||
636 | bfa_lps_get_tag(struct bfa_lps_s *lps) | ||
637 | { | ||
638 | return lps->lp_tag; | ||
639 | } | ||
640 | |||
641 | /** | ||
642 | * Return lport services tag given the pid | ||
643 | */ | ||
644 | u8 | ||
645 | bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid) | ||
646 | { | ||
647 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
648 | struct bfa_lps_s *lps; | ||
649 | int i; | ||
650 | |||
651 | for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) { | ||
652 | if (lps->lp_pid == pid) | ||
653 | return lps->lp_tag; | ||
654 | } | ||
655 | |||
656 | /* Return base port tag anyway */ | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | /** | ||
661 | * return if fabric login indicates support for NPIV | ||
662 | */ | ||
663 | bfa_boolean_t | ||
664 | bfa_lps_is_npiv_en(struct bfa_lps_s *lps) | ||
665 | { | ||
666 | return lps->npiv_en; | ||
667 | } | ||
668 | |||
669 | /** | ||
670 | * Return TRUE if attached to F-Port, else return FALSE | ||
671 | */ | ||
672 | bfa_boolean_t | ||
673 | bfa_lps_is_fport(struct bfa_lps_s *lps) | ||
674 | { | ||
675 | return lps->fport; | ||
676 | } | ||
677 | |||
678 | /** | ||
679 | * Return TRUE if attached to a Brocade Fabric | ||
680 | */ | ||
681 | bfa_boolean_t | ||
682 | bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps) | ||
683 | { | ||
684 | return lps->brcd_switch; | ||
685 | } | ||
686 | /** | ||
687 | * return TRUE if authentication is required | ||
688 | */ | ||
689 | bfa_boolean_t | ||
690 | bfa_lps_is_authreq(struct bfa_lps_s *lps) | ||
691 | { | ||
692 | return lps->auth_req; | ||
693 | } | ||
694 | |||
695 | bfa_eproto_status_t | ||
696 | bfa_lps_get_extstatus(struct bfa_lps_s *lps) | ||
697 | { | ||
698 | return lps->ext_status; | ||
699 | } | ||
700 | |||
701 | /** | ||
702 | * return port id assigned to the lport | ||
703 | */ | ||
704 | u32 | ||
705 | bfa_lps_get_pid(struct bfa_lps_s *lps) | ||
706 | { | ||
707 | return lps->lp_pid; | ||
708 | } | ||
709 | |||
710 | /** | ||
711 | * Return bb_credit assigned in FLOGI response | ||
712 | */ | ||
713 | u16 | ||
714 | bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps) | ||
715 | { | ||
716 | return lps->pr_bbcred; | ||
717 | } | ||
718 | |||
719 | /** | ||
720 | * Return peer port name | ||
721 | */ | ||
722 | wwn_t | ||
723 | bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps) | ||
724 | { | ||
725 | return lps->pr_pwwn; | ||
726 | } | ||
727 | |||
728 | /** | ||
729 | * Return peer node name | ||
730 | */ | ||
731 | wwn_t | ||
732 | bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps) | ||
733 | { | ||
734 | return lps->pr_nwwn; | ||
735 | } | ||
736 | |||
737 | /** | ||
738 | * return reason code if login request is rejected | ||
739 | */ | ||
740 | u8 | ||
741 | bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps) | ||
742 | { | ||
743 | return lps->lsrjt_rsn; | ||
744 | } | ||
745 | |||
746 | /** | ||
747 | * return explanation code if login request is rejected | ||
748 | */ | ||
749 | u8 | ||
750 | bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps) | ||
751 | { | ||
752 | return lps->lsrjt_expl; | ||
753 | } | ||
754 | |||
755 | |||
756 | /** | ||
757 | * LPS firmware message class handler. | ||
758 | */ | ||
759 | void | ||
760 | bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | ||
761 | { | ||
762 | union bfi_lps_i2h_msg_u msg; | ||
763 | |||
764 | bfa_trc(bfa, m->mhdr.msg_id); | ||
765 | msg.msg = m; | ||
766 | |||
767 | switch (m->mhdr.msg_id) { | ||
768 | case BFI_LPS_H2I_LOGIN_RSP: | ||
769 | bfa_lps_login_rsp(bfa, msg.login_rsp); | ||
770 | break; | ||
771 | |||
772 | case BFI_LPS_H2I_LOGOUT_RSP: | ||
773 | bfa_lps_logout_rsp(bfa, msg.logout_rsp); | ||
774 | break; | ||
775 | |||
776 | default: | ||
777 | bfa_trc(bfa, m->mhdr.msg_id); | ||
778 | bfa_assert(0); | ||
779 | } | ||
780 | } | ||
781 | |||
782 | |||