]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/scsi/bfa/bfa_fcs.c
Fix common misspellings
[mirror_ubuntu-zesty-kernel.git] / drivers / scsi / bfa / bfa_fcs.c
CommitLineData
7725ccfd 1/*
a36c61f9 2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
7725ccfd
JH
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
5fbe25c7 18/*
7725ccfd
JH
19 * bfa_fcs.c BFA FCS main
20 */
21
f16a1750 22#include "bfad_drv.h"
a36c61f9
KG
23#include "bfa_fcs.h"
24#include "bfa_fcbuild.h"
a36c61f9
KG
25
26BFA_TRC_FILE(FCS, FCS);
7725ccfd 27
5fbe25c7 28/*
7725ccfd
JH
29 * FCS sub-modules
30 */
31struct bfa_fcs_mod_s {
82794a2e 32 void (*attach) (struct bfa_fcs_s *fcs);
a36c61f9
KG
33 void (*modinit) (struct bfa_fcs_s *fcs);
34 void (*modexit) (struct bfa_fcs_s *fcs);
7725ccfd
JH
35};
36
37#define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
38
39static struct bfa_fcs_mod_s fcs_modules[] = {
a36c61f9 40 { bfa_fcs_port_attach, NULL, NULL },
82794a2e
KG
41 { bfa_fcs_uf_attach, NULL, NULL },
42 { bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit,
a36c61f9 43 bfa_fcs_fabric_modexit },
7725ccfd
JH
44};
45
5fbe25c7 46/*
7725ccfd
JH
47 * fcs_api BFA FCS API
48 */
49
50static void
51bfa_fcs_exit_comp(void *fcs_cbarg)
52{
a36c61f9
KG
53 struct bfa_fcs_s *fcs = fcs_cbarg;
54 struct bfad_s *bfad = fcs->bfad;
7725ccfd
JH
55
56 complete(&bfad->comp);
57}
58
59
60
5fbe25c7 61/*
7725ccfd
JH
62 * fcs_api BFA FCS API
63 */
64
5fbe25c7 65/*
82794a2e 66 * fcs attach -- called once to initialize data structures at driver attach time
7725ccfd
JH
67 */
68void
82794a2e 69bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
a36c61f9 70 bfa_boolean_t min_cfg)
7725ccfd 71{
a36c61f9 72 int i;
7725ccfd
JH
73 struct bfa_fcs_mod_s *mod;
74
75 fcs->bfa = bfa;
76 fcs->bfad = bfad;
77 fcs->min_cfg = min_cfg;
78
f7f73812 79 bfa->fcs = BFA_TRUE;
7725ccfd
JH
80 fcbuild_init();
81
a36c61f9 82 for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
7725ccfd 83 mod = &fcs_modules[i];
82794a2e
KG
84 if (mod->attach)
85 mod->attach(fcs);
86 }
87}
88
5fbe25c7 89/*
82794a2e
KG
90 * fcs initialization, called once after bfa initialization is complete
91 */
92void
93bfa_fcs_init(struct bfa_fcs_s *fcs)
94{
a36c61f9 95 int i, npbc_vports;
82794a2e 96 struct bfa_fcs_mod_s *mod;
d9883548 97 struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
82794a2e 98
a36c61f9 99 for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
82794a2e
KG
100 mod = &fcs_modules[i];
101 if (mod->modinit)
102 mod->modinit(fcs);
7725ccfd 103 }
d9883548
JH
104 /* Initialize pbc vports */
105 if (!fcs->min_cfg) {
106 npbc_vports =
a36c61f9 107 bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
d9883548
JH
108 for (i = 0; i < npbc_vports; i++)
109 bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
110 }
7725ccfd
JH
111}
112
7725ccfd 113
5fbe25c7 114/*
a36c61f9
KG
115 * brief
116 * FCS driver details initialization.
7725ccfd 117 *
a36c61f9
KG
118 * param[in] fcs FCS instance
119 * param[in] driver_info Driver Details
7725ccfd 120 *
a36c61f9 121 * return None
7725ccfd
JH
122 */
123void
124bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
125 struct bfa_fcs_driver_info_s *driver_info)
126{
127
128 fcs->driver_info = *driver_info;
129
130 bfa_fcs_fabric_psymb_init(&fcs->fabric);
131}
132
5fbe25c7 133/*
a36c61f9
KG
134 * brief
135 * FCS instance cleanup and exit.
7725ccfd 136 *
a36c61f9
KG
137 * param[in] fcs FCS instance
138 * return None
7725ccfd
JH
139 */
140void
141bfa_fcs_exit(struct bfa_fcs_s *fcs)
142{
143 struct bfa_fcs_mod_s *mod;
a36c61f9 144 int nmods, i;
7725ccfd
JH
145
146 bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
147
a36c61f9
KG
148 nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
149
150 for (i = 0; i < nmods; i++) {
7725ccfd
JH
151
152 mod = &fcs_modules[i];
82794a2e
KG
153 if (mod->modexit) {
154 bfa_wc_up(&fcs->wc);
155 mod->modexit(fcs);
156 }
7725ccfd
JH
157 }
158
159 bfa_wc_wait(&fcs->wc);
160}
161
162
5fbe25c7 163/*
a36c61f9
KG
164 * Fabric module implementation.
165 */
166
167#define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */
168#define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */
169
170#define bfa_fcs_fabric_set_opertype(__fabric) do { \
171 if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \
172 == BFA_PORT_TOPOLOGY_P2P) \
173 (__fabric)->oper_type = BFA_PORT_TYPE_NPORT; \
174 else \
175 (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT; \
176} while (0)
177
178/*
179 * forward declarations
180 */
181static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
182static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
183static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
184static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
185static void bfa_fcs_fabric_delay(void *cbarg);
186static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
187static void bfa_fcs_fabric_delete_comp(void *cbarg);
188static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
189 struct fchs_s *fchs, u16 len);
190static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
191 struct fchs_s *fchs, u16 len);
192static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
193static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
194 struct bfa_fcxp_s *fcxp, void *cbarg,
195 bfa_status_t status,
196 u32 rsp_len,
197 u32 resid_len,
198 struct fchs_s *rspfchs);
a36c61f9
KG
199
200static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
201 enum bfa_fcs_fabric_event event);
202static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
203 enum bfa_fcs_fabric_event event);
204static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
205 enum bfa_fcs_fabric_event event);
206static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
207 enum bfa_fcs_fabric_event event);
208static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
209 enum bfa_fcs_fabric_event event);
210static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
211 enum bfa_fcs_fabric_event event);
a36c61f9
KG
212static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
213 enum bfa_fcs_fabric_event event);
a36c61f9
KG
214static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
215 enum bfa_fcs_fabric_event event);
216static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
217 enum bfa_fcs_fabric_event event);
218static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
219 enum bfa_fcs_fabric_event event);
220static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
221 enum bfa_fcs_fabric_event event);
5fbe25c7 222/*
a36c61f9
KG
223 * Beginning state before fabric creation.
224 */
225static void
226bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
227 enum bfa_fcs_fabric_event event)
228{
229 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
230 bfa_trc(fabric->fcs, event);
231
232 switch (event) {
233 case BFA_FCS_FABRIC_SM_CREATE:
234 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
235 bfa_fcs_fabric_init(fabric);
236 bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
237 break;
238
239 case BFA_FCS_FABRIC_SM_LINK_UP:
240 case BFA_FCS_FABRIC_SM_LINK_DOWN:
241 break;
242
243 default:
244 bfa_sm_fault(fabric->fcs, event);
245 }
246}
247
5fbe25c7 248/*
a36c61f9
KG
249 * Beginning state before fabric creation.
250 */
251static void
252bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
253 enum bfa_fcs_fabric_event event)
254{
255 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
256 bfa_trc(fabric->fcs, event);
257
258 switch (event) {
259 case BFA_FCS_FABRIC_SM_START:
260 if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
261 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
262 bfa_fcs_fabric_login(fabric);
263 } else
264 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
265 break;
266
267 case BFA_FCS_FABRIC_SM_LINK_UP:
268 case BFA_FCS_FABRIC_SM_LINK_DOWN:
269 break;
270
271 case BFA_FCS_FABRIC_SM_DELETE:
272 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
f7f73812 273 bfa_wc_down(&fabric->fcs->wc);
a36c61f9
KG
274 break;
275
276 default:
277 bfa_sm_fault(fabric->fcs, event);
278 }
279}
280
5fbe25c7 281/*
a36c61f9
KG
282 * Link is down, awaiting LINK UP event from port. This is also the
283 * first state at fabric creation.
284 */
285static void
286bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
287 enum bfa_fcs_fabric_event event)
288{
289 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
290 bfa_trc(fabric->fcs, event);
291
292 switch (event) {
293 case BFA_FCS_FABRIC_SM_LINK_UP:
294 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
295 bfa_fcs_fabric_login(fabric);
296 break;
297
298 case BFA_FCS_FABRIC_SM_RETRY_OP:
299 break;
300
301 case BFA_FCS_FABRIC_SM_DELETE:
302 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
303 bfa_fcs_fabric_delete(fabric);
304 break;
305
306 default:
307 bfa_sm_fault(fabric->fcs, event);
308 }
309}
310
5fbe25c7 311/*
a36c61f9
KG
312 * FLOGI is in progress, awaiting FLOGI reply.
313 */
314static void
315bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
316 enum bfa_fcs_fabric_event event)
317{
318 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
319 bfa_trc(fabric->fcs, event);
320
321 switch (event) {
322 case BFA_FCS_FABRIC_SM_CONT_OP:
323
324 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
325 fabric->bb_credit);
326 fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
327
328 if (fabric->auth_reqd && fabric->is_auth) {
329 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
330 bfa_trc(fabric->fcs, event);
331 } else {
332 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
333 bfa_fcs_fabric_notify_online(fabric);
334 }
335 break;
336
337 case BFA_FCS_FABRIC_SM_RETRY_OP:
338 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
339 bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
340 bfa_fcs_fabric_delay, fabric,
341 BFA_FCS_FABRIC_RETRY_DELAY);
342 break;
343
344 case BFA_FCS_FABRIC_SM_LOOPBACK:
345 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
f7f73812 346 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
a36c61f9
KG
347 bfa_fcs_fabric_set_opertype(fabric);
348 break;
349
350 case BFA_FCS_FABRIC_SM_NO_FABRIC:
351 fabric->fab_type = BFA_FCS_FABRIC_N2N;
352 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
353 fabric->bb_credit);
354 bfa_fcs_fabric_notify_online(fabric);
355 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
356 break;
357
358 case BFA_FCS_FABRIC_SM_LINK_DOWN:
359 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
f7f73812 360 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
a36c61f9
KG
361 break;
362
363 case BFA_FCS_FABRIC_SM_DELETE:
364 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
f7f73812 365 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
a36c61f9
KG
366 bfa_fcs_fabric_delete(fabric);
367 break;
368
369 default:
370 bfa_sm_fault(fabric->fcs, event);
371 }
372}
373
374
375static void
376bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
377 enum bfa_fcs_fabric_event event)
378{
379 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
380 bfa_trc(fabric->fcs, event);
381
382 switch (event) {
383 case BFA_FCS_FABRIC_SM_DELAYED:
384 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
385 bfa_fcs_fabric_login(fabric);
386 break;
387
388 case BFA_FCS_FABRIC_SM_LINK_DOWN:
389 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
390 bfa_timer_stop(&fabric->delay_timer);
391 break;
392
393 case BFA_FCS_FABRIC_SM_DELETE:
394 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
395 bfa_timer_stop(&fabric->delay_timer);
396 bfa_fcs_fabric_delete(fabric);
397 break;
398
399 default:
400 bfa_sm_fault(fabric->fcs, event);
401 }
402}
403
5fbe25c7 404/*
a36c61f9
KG
405 * Authentication is in progress, awaiting authentication results.
406 */
407static void
408bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
409 enum bfa_fcs_fabric_event event)
410{
411 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
412 bfa_trc(fabric->fcs, event);
413
414 switch (event) {
415 case BFA_FCS_FABRIC_SM_AUTH_FAILED:
416 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
f7f73812 417 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
a36c61f9
KG
418 break;
419
420 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
421 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
422 bfa_fcs_fabric_notify_online(fabric);
423 break;
424
425 case BFA_FCS_FABRIC_SM_PERF_EVFP:
426 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
427 break;
428
429 case BFA_FCS_FABRIC_SM_LINK_DOWN:
430 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
f7f73812 431 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
a36c61f9
KG
432 break;
433
434 case BFA_FCS_FABRIC_SM_DELETE:
435 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
436 bfa_fcs_fabric_delete(fabric);
437 break;
438
439 default:
440 bfa_sm_fault(fabric->fcs, event);
441 }
442}
443
5fbe25c7 444/*
a36c61f9
KG
445 * Authentication failed
446 */
f7f73812 447void
a36c61f9
KG
448bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
449 enum bfa_fcs_fabric_event event)
450{
451 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
452 bfa_trc(fabric->fcs, event);
453
454 switch (event) {
455 case BFA_FCS_FABRIC_SM_LINK_DOWN:
456 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
457 bfa_fcs_fabric_notify_offline(fabric);
458 break;
459
460 case BFA_FCS_FABRIC_SM_DELETE:
461 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
462 bfa_fcs_fabric_delete(fabric);
463 break;
464
465 default:
466 bfa_sm_fault(fabric->fcs, event);
467 }
468}
469
5fbe25c7 470/*
a36c61f9
KG
471 * Port is in loopback mode.
472 */
f7f73812 473void
a36c61f9
KG
474bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
475 enum bfa_fcs_fabric_event event)
476{
477 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
478 bfa_trc(fabric->fcs, event);
479
480 switch (event) {
481 case BFA_FCS_FABRIC_SM_LINK_DOWN:
482 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
483 bfa_fcs_fabric_notify_offline(fabric);
484 break;
485
486 case BFA_FCS_FABRIC_SM_DELETE:
487 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
488 bfa_fcs_fabric_delete(fabric);
489 break;
490
491 default:
492 bfa_sm_fault(fabric->fcs, event);
493 }
494}
495
5fbe25c7 496/*
a36c61f9
KG
497 * There is no attached fabric - private loop or NPort-to-NPort topology.
498 */
499static void
500bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
501 enum bfa_fcs_fabric_event event)
502{
503 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
504 bfa_trc(fabric->fcs, event);
505
506 switch (event) {
507 case BFA_FCS_FABRIC_SM_LINK_DOWN:
508 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
f7f73812 509 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
a36c61f9
KG
510 bfa_fcs_fabric_notify_offline(fabric);
511 break;
512
513 case BFA_FCS_FABRIC_SM_DELETE:
514 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
515 bfa_fcs_fabric_delete(fabric);
516 break;
517
518 case BFA_FCS_FABRIC_SM_NO_FABRIC:
519 bfa_trc(fabric->fcs, fabric->bb_credit);
520 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
521 fabric->bb_credit);
522 break;
523
524 default:
525 bfa_sm_fault(fabric->fcs, event);
526 }
527}
528
5fbe25c7 529/*
a36c61f9
KG
530 * Fabric is online - normal operating state.
531 */
f7f73812 532void
a36c61f9
KG
533bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
534 enum bfa_fcs_fabric_event event)
535{
536 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
537 bfa_trc(fabric->fcs, event);
538
539 switch (event) {
540 case BFA_FCS_FABRIC_SM_LINK_DOWN:
541 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
f7f73812 542 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
a36c61f9
KG
543 bfa_fcs_fabric_notify_offline(fabric);
544 break;
545
546 case BFA_FCS_FABRIC_SM_DELETE:
547 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
548 bfa_fcs_fabric_delete(fabric);
549 break;
550
551 case BFA_FCS_FABRIC_SM_AUTH_FAILED:
552 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
f7f73812 553 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
a36c61f9
KG
554 break;
555
556 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
557 break;
558
559 default:
560 bfa_sm_fault(fabric->fcs, event);
561 }
562}
563
5fbe25c7 564/*
a36c61f9
KG
565 * Exchanging virtual fabric parameters.
566 */
567static void
568bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
569 enum bfa_fcs_fabric_event event)
570{
571 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
572 bfa_trc(fabric->fcs, event);
573
574 switch (event) {
575 case BFA_FCS_FABRIC_SM_CONT_OP:
576 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
577 break;
578
579 case BFA_FCS_FABRIC_SM_ISOLATE:
580 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
581 break;
582
583 default:
584 bfa_sm_fault(fabric->fcs, event);
585 }
586}
587
5fbe25c7 588/*
a36c61f9
KG
589 * EVFP exchange complete and VFT tagging is enabled.
590 */
591static void
592bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
593 enum bfa_fcs_fabric_event event)
594{
595 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
596 bfa_trc(fabric->fcs, event);
597}
598
5fbe25c7 599/*
a36c61f9
KG
600 * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
601 */
602static void
603bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
604 enum bfa_fcs_fabric_event event)
605{
606 struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
607 char pwwn_ptr[BFA_STRING_32];
608
609 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
610 bfa_trc(fabric->fcs, event);
611 wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);
612
88166242 613 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
a36c61f9
KG
614 "Port is isolated due to VF_ID mismatch. "
615 "PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",
616 pwwn_ptr, fabric->fcs->port_vfid,
617 fabric->event_arg.swp_vfid);
618}
619
5fbe25c7 620/*
a36c61f9
KG
621 * Fabric is being deleted, awaiting vport delete completions.
622 */
623static void
624bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
625 enum bfa_fcs_fabric_event event)
7725ccfd 626{
a36c61f9
KG
627 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
628 bfa_trc(fabric->fcs, event);
629
630 switch (event) {
631 case BFA_FCS_FABRIC_SM_DELCOMP:
632 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
f7f73812 633 bfa_wc_down(&fabric->fcs->wc);
a36c61f9
KG
634 break;
635
636 case BFA_FCS_FABRIC_SM_LINK_UP:
637 break;
638
639 case BFA_FCS_FABRIC_SM_LINK_DOWN:
640 bfa_fcs_fabric_notify_offline(fabric);
641 break;
642
643 default:
644 bfa_sm_fault(fabric->fcs, event);
645 }
7725ccfd
JH
646}
647
648
a36c61f9 649
5fbe25c7 650/*
a36c61f9
KG
651 * fcs_fabric_private fabric private functions
652 */
653
654static void
655bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
656{
657 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
658
659 port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;
f7f73812
MZ
660 port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn;
661 port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;
a36c61f9
KG
662}
663
5fbe25c7 664/*
a36c61f9
KG
665 * Port Symbolic Name Creation for base port.
666 */
7725ccfd 667void
a36c61f9 668bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
7725ccfd 669{
a36c61f9
KG
670 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
671 char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
672 struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
673
674 bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
675
676 /* Model name/number */
677 strncpy((char *)&port_cfg->sym_name, model,
678 BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
679 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
680 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
681
682 /* Driver Version */
683 strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
684 BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
685 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
686 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
687
688 /* Host machine name */
689 strncat((char *)&port_cfg->sym_name,
690 (char *)driver_info->host_machine_name,
691 BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
692 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
693 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
694
695 /*
696 * Host OS Info :
697 * If OS Patch Info is not there, do not truncate any bytes from the
698 * OS name string and instead copy the entire OS info string (64 bytes).
699 */
700 if (driver_info->host_os_patch[0] == '\0') {
701 strncat((char *)&port_cfg->sym_name,
702 (char *)driver_info->host_os_name,
703 BFA_FCS_OS_STR_LEN);
704 strncat((char *)&port_cfg->sym_name,
705 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
706 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
707 } else {
708 strncat((char *)&port_cfg->sym_name,
709 (char *)driver_info->host_os_name,
710 BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
711 strncat((char *)&port_cfg->sym_name,
712 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
713 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
714
715 /* Append host OS Patch Info */
716 strncat((char *)&port_cfg->sym_name,
717 (char *)driver_info->host_os_patch,
718 BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
719 }
720
721 /* null terminate */
722 port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
7725ccfd
JH
723}
724
5fbe25c7 725/*
a36c61f9
KG
726 * bfa lps login completion callback
727 */
7725ccfd 728void
a36c61f9 729bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
7725ccfd 730{
a36c61f9
KG
731 struct bfa_fcs_fabric_s *fabric = uarg;
732
733 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
734 bfa_trc(fabric->fcs, status);
735
736 switch (status) {
737 case BFA_STATUS_OK:
738 fabric->stats.flogi_accepts++;
739 break;
740
741 case BFA_STATUS_INVALID_MAC:
742 /* Only for CNA */
743 fabric->stats.flogi_acc_err++;
744 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
745
746 return;
747
748 case BFA_STATUS_EPROTOCOL:
f7f73812 749 switch (fabric->lps->ext_status) {
a36c61f9
KG
750 case BFA_EPROTO_BAD_ACCEPT:
751 fabric->stats.flogi_acc_err++;
752 break;
753
754 case BFA_EPROTO_UNKNOWN_RSP:
755 fabric->stats.flogi_unknown_rsp++;
756 break;
757
758 default:
759 break;
760 }
761 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
762
763 return;
764
765 case BFA_STATUS_FABRIC_RJT:
766 fabric->stats.flogi_rejects++;
767 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
768 return;
769
770 default:
771 fabric->stats.flogi_rsp_err++;
772 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
773 return;
774 }
775
f7f73812 776 fabric->bb_credit = fabric->lps->pr_bbcred;
a36c61f9
KG
777 bfa_trc(fabric->fcs, fabric->bb_credit);
778
f7f73812
MZ
779 if (!(fabric->lps->brcd_switch))
780 fabric->fabric_name = fabric->lps->pr_nwwn;
a36c61f9
KG
781
782 /*
783 * Check port type. It should be 1 = F-port.
784 */
f7f73812
MZ
785 if (fabric->lps->fport) {
786 fabric->bport.pid = fabric->lps->lp_pid;
787 fabric->is_npiv = fabric->lps->npiv_en;
788 fabric->is_auth = fabric->lps->auth_req;
a36c61f9
KG
789 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
790 } else {
791 /*
792 * Nport-2-Nport direct attached
793 */
794 fabric->bport.port_topo.pn2n.rem_port_wwn =
f7f73812 795 fabric->lps->pr_pwwn;
a36c61f9
KG
796 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
797 }
798
799 bfa_trc(fabric->fcs, fabric->bport.pid);
800 bfa_trc(fabric->fcs, fabric->is_npiv);
801 bfa_trc(fabric->fcs, fabric->is_auth);
802}
5fbe25c7 803/*
a36c61f9
KG
804 * Allocate and send FLOGI.
805 */
806static void
807bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
808{
809 struct bfa_s *bfa = fabric->fcs->bfa;
810 struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
811 u8 alpa = 0;
812
813 if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
814 alpa = bfa_fcport_get_myalpa(bfa);
815
816 bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
817 pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
818
819 fabric->stats.flogi_sent++;
820}
821
822static void
823bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
824{
825 struct bfa_fcs_vport_s *vport;
826 struct list_head *qe, *qen;
827
828 bfa_trc(fabric->fcs, fabric->fabric_name);
829
830 bfa_fcs_fabric_set_opertype(fabric);
831 fabric->stats.fabric_onlines++;
832
5fbe25c7 833 /*
a36c61f9
KG
834 * notify online event to base and then virtual ports
835 */
836 bfa_fcs_lport_online(&fabric->bport);
837
838 list_for_each_safe(qe, qen, &fabric->vport_q) {
839 vport = (struct bfa_fcs_vport_s *) qe;
840 bfa_fcs_vport_online(vport);
841 }
842}
843
844static void
845bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
846{
847 struct bfa_fcs_vport_s *vport;
848 struct list_head *qe, *qen;
849
850 bfa_trc(fabric->fcs, fabric->fabric_name);
851 fabric->stats.fabric_offlines++;
852
5fbe25c7 853 /*
a36c61f9
KG
854 * notify offline event first to vports and then base port.
855 */
856 list_for_each_safe(qe, qen, &fabric->vport_q) {
857 vport = (struct bfa_fcs_vport_s *) qe;
858 bfa_fcs_vport_offline(vport);
859 }
860
861 bfa_fcs_lport_offline(&fabric->bport);
862
863 fabric->fabric_name = 0;
864 fabric->fabric_ip_addr[0] = 0;
865}
866
867static void
868bfa_fcs_fabric_delay(void *cbarg)
869{
870 struct bfa_fcs_fabric_s *fabric = cbarg;
871
872 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
873}
874
5fbe25c7 875/*
a36c61f9
KG
876 * Delete all vports and wait for vport delete completions.
877 */
878static void
879bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
880{
881 struct bfa_fcs_vport_s *vport;
882 struct list_head *qe, *qen;
883
884 list_for_each_safe(qe, qen, &fabric->vport_q) {
885 vport = (struct bfa_fcs_vport_s *) qe;
886 bfa_fcs_vport_fcs_delete(vport);
887 }
888
889 bfa_fcs_lport_delete(&fabric->bport);
890 bfa_wc_wait(&fabric->wc);
7725ccfd
JH
891}
892
a36c61f9
KG
893static void
894bfa_fcs_fabric_delete_comp(void *cbarg)
895{
896 struct bfa_fcs_fabric_s *fabric = cbarg;
897
898 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
899}
7725ccfd 900
5fbe25c7 901/*
a36c61f9
KG
902 * fcs_fabric_public fabric public functions
903 */
904
5fbe25c7 905/*
a36c61f9
KG
906 * Attach time initialization.
907 */
908void
909bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
910{
911 struct bfa_fcs_fabric_s *fabric;
912
913 fabric = &fcs->fabric;
6a18b167 914 memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
a36c61f9 915
5fbe25c7 916 /*
a36c61f9
KG
917 * Initialize base fabric.
918 */
919 fabric->fcs = fcs;
920 INIT_LIST_HEAD(&fabric->vport_q);
921 INIT_LIST_HEAD(&fabric->vf_q);
922 fabric->lps = bfa_lps_alloc(fcs->bfa);
d4b671c5 923 WARN_ON(!fabric->lps);
a36c61f9 924
5fbe25c7 925 /*
a36c61f9
KG
926 * Initialize fabric delete completion handler. Fabric deletion is
927 * complete when the last vport delete is complete.
928 */
929 bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
930 bfa_wc_up(&fabric->wc); /* For the base port */
931
932 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
933 bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
934}
935
936void
937bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
938{
939 bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
940 bfa_trc(fcs, 0);
941}
942
5fbe25c7 943/*
a36c61f9
KG
944 * Module cleanup
945 */
946void
947bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
948{
949 struct bfa_fcs_fabric_s *fabric;
950
951 bfa_trc(fcs, 0);
952
5fbe25c7 953 /*
a36c61f9
KG
954 * Cleanup base fabric.
955 */
956 fabric = &fcs->fabric;
957 bfa_lps_delete(fabric->lps);
958 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
959}
960
5fbe25c7 961/*
a36c61f9
KG
962 * Fabric module start -- kick starts FCS actions
963 */
964void
965bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
966{
967 struct bfa_fcs_fabric_s *fabric;
968
969 bfa_trc(fcs, 0);
970 fabric = &fcs->fabric;
971 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
972}
973
a36c61f9 974
5fbe25c7 975/*
a36c61f9
KG
976 * Link up notification from BFA physical port module.
977 */
978void
979bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
980{
981 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
982 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
983}
984
5fbe25c7 985/*
a36c61f9
KG
986 * Link down notification from BFA physical port module.
987 */
988void
989bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
990{
991 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
992 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
993}
994
5fbe25c7 995/*
a36c61f9
KG
996 * A child vport is being created in the fabric.
997 *
998 * Call from vport module at vport creation. A list of base port and vports
999 * belonging to a fabric is maintained to propagate link events.
1000 *
1001 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
1002 * param[in] vport - Vport being created.
1003 *
1004 * @return None (always succeeds)
1005 */
1006void
1007bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
1008 struct bfa_fcs_vport_s *vport)
1009{
5fbe25c7 1010 /*
a36c61f9
KG
1011 * - add vport to fabric's vport_q
1012 */
1013 bfa_trc(fabric->fcs, fabric->vf_id);
1014
1015 list_add_tail(&vport->qe, &fabric->vport_q);
1016 fabric->num_vports++;
1017 bfa_wc_up(&fabric->wc);
1018}
1019
5fbe25c7 1020/*
a36c61f9
KG
1021 * A child vport is being deleted from fabric.
1022 *
1023 * Vport is being deleted.
1024 */
1025void
1026bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
1027 struct bfa_fcs_vport_s *vport)
1028{
1029 list_del(&vport->qe);
1030 fabric->num_vports--;
1031 bfa_wc_down(&fabric->wc);
1032}
1033
a36c61f9 1034
5fbe25c7 1035/*
25985edc 1036 * Lookup for a vport within a fabric given its pwwn
a36c61f9
KG
1037 */
1038struct bfa_fcs_vport_s *
1039bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
1040{
1041 struct bfa_fcs_vport_s *vport;
1042 struct list_head *qe;
1043
1044 list_for_each(qe, &fabric->vport_q) {
1045 vport = (struct bfa_fcs_vport_s *) qe;
1046 if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn)
1047 return vport;
1048 }
1049
1050 return NULL;
1051}
1052
a36c61f9
KG
1053
1054/*
1055 * Get OUI of the attached switch.
1056 *
1057 * Note : Use of this function should be avoided as much as possible.
1058 * This function should be used only if there is any requirement
1059* to check for FOS version below 6.3.
1060 * To check if the attached fabric is a brocade fabric, use
1061 * bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
1062 * or above only.
1063 */
1064
1065u16
1066bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
1067{
1068 wwn_t fab_nwwn;
1069 u8 *tmp;
1070 u16 oui;
1071
f7f73812 1072 fab_nwwn = fabric->lps->pr_nwwn;
a36c61f9
KG
1073
1074 tmp = (u8 *)&fab_nwwn;
1075 oui = (tmp[3] << 8) | tmp[4];
1076
1077 return oui;
1078}
5fbe25c7 1079/*
a36c61f9
KG
1080 * Unsolicited frame receive handling.
1081 */
1082void
1083bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1084 u16 len)
1085{
1086 u32 pid = fchs->d_id;
1087 struct bfa_fcs_vport_s *vport;
1088 struct list_head *qe;
1089 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1090 struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;
1091
1092 bfa_trc(fabric->fcs, len);
1093 bfa_trc(fabric->fcs, pid);
1094
5fbe25c7 1095 /*
a36c61f9
KG
1096 * Look for our own FLOGI frames being looped back. This means an
1097 * external loopback cable is in place. Our own FLOGI frames are
1098 * sometimes looped back when switch port gets temporarily bypassed.
1099 */
f16a1750 1100 if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&
a36c61f9
KG
1101 (els_cmd->els_code == FC_ELS_FLOGI) &&
1102 (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {
1103 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
1104 return;
1105 }
1106
5fbe25c7 1107 /*
a36c61f9
KG
1108 * FLOGI/EVFP exchanges should be consumed by base fabric.
1109 */
f16a1750 1110 if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {
a36c61f9
KG
1111 bfa_trc(fabric->fcs, pid);
1112 bfa_fcs_fabric_process_uf(fabric, fchs, len);
1113 return;
1114 }
1115
1116 if (fabric->bport.pid == pid) {
5fbe25c7 1117 /*
a36c61f9
KG
1118 * All authentication frames should be routed to auth
1119 */
1120 bfa_trc(fabric->fcs, els_cmd->els_code);
1121 if (els_cmd->els_code == FC_ELS_AUTH) {
1122 bfa_trc(fabric->fcs, els_cmd->els_code);
1123 return;
1124 }
1125
1126 bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
1127 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
1128 return;
1129 }
1130
5fbe25c7 1131 /*
a36c61f9
KG
1132 * look for a matching local port ID
1133 */
1134 list_for_each(qe, &fabric->vport_q) {
1135 vport = (struct bfa_fcs_vport_s *) qe;
1136 if (vport->lport.pid == pid) {
1137 bfa_fcs_lport_uf_recv(&vport->lport, fchs, len);
1138 return;
1139 }
1140 }
1141 bfa_trc(fabric->fcs, els_cmd->els_code);
1142 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
1143}
1144
5fbe25c7 1145/*
a36c61f9
KG
1146 * Unsolicited frames to be processed by fabric.
1147 */
1148static void
1149bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1150 u16 len)
1151{
1152 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1153
1154 bfa_trc(fabric->fcs, els_cmd->els_code);
1155
1156 switch (els_cmd->els_code) {
1157 case FC_ELS_FLOGI:
1158 bfa_fcs_fabric_process_flogi(fabric, fchs, len);
1159 break;
1160
1161 default:
1162 /*
1163 * need to generate a LS_RJT
1164 */
1165 break;
1166 }
1167}
1168
5fbe25c7 1169/*
a36c61f9
KG
1170 * Process incoming FLOGI
1171 */
1172static void
1173bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
1174 struct fchs_s *fchs, u16 len)
1175{
1176 struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);
1177 struct bfa_fcs_lport_s *bport = &fabric->bport;
1178
1179 bfa_trc(fabric->fcs, fchs->s_id);
1180
1181 fabric->stats.flogi_rcvd++;
1182 /*
1183 * Check port type. It should be 0 = n-port.
1184 */
1185 if (flogi->csp.port_type) {
1186 /*
1187 * @todo: may need to send a LS_RJT
1188 */
1189 bfa_trc(fabric->fcs, flogi->port_name);
1190 fabric->stats.flogi_rejected++;
1191 return;
1192 }
1193
ba816ea8 1194 fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
a36c61f9
KG
1195 bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
1196 bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
1197
1198 /*
1199 * Send a Flogi Acc
1200 */
1201 bfa_fcs_fabric_send_flogi_acc(fabric);
1202 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
1203}
1204
1205static void
1206bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
1207{
1208 struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
1209 struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
1210 struct bfa_s *bfa = fabric->fcs->bfa;
1211 struct bfa_fcxp_s *fcxp;
1212 u16 reqlen;
1213 struct fchs_s fchs;
1214
1215 fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
5fbe25c7 1216 /*
a36c61f9
KG
1217 * Do not expect this failure -- expect remote node to retry
1218 */
1219 if (!fcxp)
1220 return;
1221
1222 reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
f16a1750 1223 bfa_hton3b(FC_FABRIC_PORT),
a36c61f9
KG
1224 n2n_port->reply_oxid, pcfg->pwwn,
1225 pcfg->nwwn,
1226 bfa_fcport_get_maxfrsize(bfa),
1227 bfa_fcport_get_rx_bbcredit(bfa));
1228
f7f73812 1229 bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
a36c61f9
KG
1230 BFA_FALSE, FC_CLASS_3,
1231 reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
1232 FC_MAX_PDUSZ, 0);
1233}
1234
5fbe25c7 1235/*
a36c61f9
KG
1236 * Flogi Acc completion callback.
1237 */
1238static void
1239bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1240 bfa_status_t status, u32 rsp_len,
1241 u32 resid_len, struct fchs_s *rspfchs)
1242{
1243 struct bfa_fcs_fabric_s *fabric = cbarg;
1244
1245 bfa_trc(fabric->fcs, status);
1246}
1247
1248/*
1249 *
1250 * @param[in] fabric - fabric
1251 * @param[in] wwn_t - new fabric name
1252 *
1253 * @return - none
1254 */
1255void
1256bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
1257 wwn_t fabric_name)
1258{
1259 struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
1260 char pwwn_ptr[BFA_STRING_32];
1261 char fwwn_ptr[BFA_STRING_32];
1262
1263 bfa_trc(fabric->fcs, fabric_name);
1264
1265 if (fabric->fabric_name == 0) {
1266 /*
1267 * With BRCD switches, we don't get Fabric Name in FLOGI.
1268 * Don't generate a fabric name change event in this case.
1269 */
1270 fabric->fabric_name = fabric_name;
1271 } else {
1272 fabric->fabric_name = fabric_name;
1273 wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));
1274 wwn2str(fwwn_ptr,
1275 bfa_fcs_lport_get_fabric_name(&fabric->bport));
88166242 1276 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
a36c61f9
KG
1277 "Base port WWN = %s Fabric WWN = %s\n",
1278 pwwn_ptr, fwwn_ptr);
1279 }
1280}
1281
5fbe25c7 1282/*
a36c61f9
KG
1283 * Returns FCS vf structure for a given vf_id.
1284 *
1285 * param[in] vf_id - VF_ID
1286 *
1287 * return
1288 * If lookup succeeds, retuns fcs vf object, otherwise returns NULL
1289 */
1290bfa_fcs_vf_t *
1291bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
1292{
1293 bfa_trc(fcs, vf_id);
1294 if (vf_id == FC_VF_ID_NULL)
1295 return &fcs->fabric;
1296
1297 return NULL;
1298}
1299
5fbe25c7 1300/*
a36c61f9
KG
1301 * BFA FCS PPORT ( physical port)
1302 */
1303static void
1304bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)
1305{
1306 struct bfa_fcs_s *fcs = cbarg;
1307
1308 bfa_trc(fcs, event);
1309
1310 switch (event) {
1311 case BFA_PORT_LINKUP:
1312 bfa_fcs_fabric_link_up(&fcs->fabric);
1313 break;
1314
1315 case BFA_PORT_LINKDOWN:
1316 bfa_fcs_fabric_link_down(&fcs->fabric);
1317 break;
1318
1319 default:
d4b671c5 1320 WARN_ON(1);
a36c61f9
KG
1321 }
1322}
1323
1324void
1325bfa_fcs_port_attach(struct bfa_fcs_s *fcs)
1326{
1327 bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);
1328}
1329
5fbe25c7 1330/*
a36c61f9
KG
1331 * BFA FCS UF ( Unsolicited Frames)
1332 */
1333
5fbe25c7 1334/*
a36c61f9
KG
1335 * BFA callback for unsolicited frame receive handler.
1336 *
1337 * @param[in] cbarg callback arg for receive handler
1338 * @param[in] uf unsolicited frame descriptor
1339 *
1340 * @return None
1341 */
1342static void
1343bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
1344{
1345 struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg;
1346 struct fchs_s *fchs = bfa_uf_get_frmbuf(uf);
1347 u16 len = bfa_uf_get_frmlen(uf);
1348 struct fc_vft_s *vft;
1349 struct bfa_fcs_fabric_s *fabric;
1350
5fbe25c7 1351 /*
a36c61f9
KG
1352 * check for VFT header
1353 */
1354 if (fchs->routing == FC_RTG_EXT_HDR &&
1355 fchs->cat_info == FC_CAT_VFT_HDR) {
1356 bfa_stats(fcs, uf.tagged);
1357 vft = bfa_uf_get_frmbuf(uf);
1358 if (fcs->port_vfid == vft->vf_id)
1359 fabric = &fcs->fabric;
1360 else
1361 fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
1362
5fbe25c7 1363 /*
a36c61f9
KG
1364 * drop frame if vfid is unknown
1365 */
1366 if (!fabric) {
d4b671c5 1367 WARN_ON(1);
a36c61f9
KG
1368 bfa_stats(fcs, uf.vfid_unknown);
1369 bfa_uf_free(uf);
1370 return;
1371 }
1372
5fbe25c7 1373 /*
a36c61f9
KG
1374 * skip vft header
1375 */
1376 fchs = (struct fchs_s *) (vft + 1);
1377 len -= sizeof(struct fc_vft_s);
1378
1379 bfa_trc(fcs, vft->vf_id);
1380 } else {
1381 bfa_stats(fcs, uf.untagged);
1382 fabric = &fcs->fabric;
1383 }
1384
1385 bfa_trc(fcs, ((u32 *) fchs)[0]);
1386 bfa_trc(fcs, ((u32 *) fchs)[1]);
1387 bfa_trc(fcs, ((u32 *) fchs)[2]);
1388 bfa_trc(fcs, ((u32 *) fchs)[3]);
1389 bfa_trc(fcs, ((u32 *) fchs)[4]);
1390 bfa_trc(fcs, ((u32 *) fchs)[5]);
1391 bfa_trc(fcs, len);
1392
1393 bfa_fcs_fabric_uf_recv(fabric, fchs, len);
1394 bfa_uf_free(uf);
1395}
1396
1397void
1398bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
1399{
1400 bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
1401}