blob: a9b22bc48bc307aab341cd42490744be85d34c0a [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
Jing Huang7725ccf2009-09-23 17:46:15 -07003 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -070018/*
Jing Huang7725ccf2009-09-23 17:46:15 -070019 * bfa_fcs.c BFA FCS main
20 */
21
Maggie Zhangf16a1752010-12-09 19:12:32 -080022#include "bfad_drv.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070023#include "bfa_fcs.h"
24#include "bfa_fcbuild.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070025
26BFA_TRC_FILE(FCS, FCS);
Jing Huang7725ccf2009-09-23 17:46:15 -070027
Jing Huang5fbe25c2010-10-18 17:17:23 -070028/*
Jing Huang7725ccf2009-09-23 17:46:15 -070029 * FCS sub-modules
30 */
31struct bfa_fcs_mod_s {
Krishna Gudipati82794a22010-03-03 17:43:30 -080032 void (*attach) (struct bfa_fcs_s *fcs);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070033 void (*modinit) (struct bfa_fcs_s *fcs);
34 void (*modexit) (struct bfa_fcs_s *fcs);
Jing Huang7725ccf2009-09-23 17:46:15 -070035};
36
37#define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
38
39static struct bfa_fcs_mod_s fcs_modules[] = {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070040 { bfa_fcs_port_attach, NULL, NULL },
Krishna Gudipati82794a22010-03-03 17:43:30 -080041 { bfa_fcs_uf_attach, NULL, NULL },
42 { bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070043 bfa_fcs_fabric_modexit },
Jing Huang7725ccf2009-09-23 17:46:15 -070044};
45
Jing Huang5fbe25c2010-10-18 17:17:23 -070046/*
Jing Huang7725ccf2009-09-23 17:46:15 -070047 * fcs_api BFA FCS API
48 */
49
50static void
51bfa_fcs_exit_comp(void *fcs_cbarg)
52{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070053 struct bfa_fcs_s *fcs = fcs_cbarg;
54 struct bfad_s *bfad = fcs->bfad;
Jing Huang7725ccf2009-09-23 17:46:15 -070055
56 complete(&bfad->comp);
57}
58
59
60
Jing Huang5fbe25c2010-10-18 17:17:23 -070061/*
Jing Huang7725ccf2009-09-23 17:46:15 -070062 * fcs_api BFA FCS API
63 */
64
Jing Huang5fbe25c2010-10-18 17:17:23 -070065/*
Krishna Gudipati82794a22010-03-03 17:43:30 -080066 * fcs attach -- called once to initialize data structures at driver attach time
Jing Huang7725ccf2009-09-23 17:46:15 -070067 */
68void
Krishna Gudipati82794a22010-03-03 17:43:30 -080069bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070070 bfa_boolean_t min_cfg)
Jing Huang7725ccf2009-09-23 17:46:15 -070071{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070072 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -070073 struct bfa_fcs_mod_s *mod;
74
75 fcs->bfa = bfa;
76 fcs->bfad = bfad;
77 fcs->min_cfg = min_cfg;
78
Maggie Zhangf7f73812010-12-09 19:08:43 -080079 bfa->fcs = BFA_TRUE;
Jing Huang7725ccf2009-09-23 17:46:15 -070080 fcbuild_init();
81
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070082 for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
Jing Huang7725ccf2009-09-23 17:46:15 -070083 mod = &fcs_modules[i];
Krishna Gudipati82794a22010-03-03 17:43:30 -080084 if (mod->attach)
85 mod->attach(fcs);
86 }
87}
88
Jing Huang5fbe25c2010-10-18 17:17:23 -070089/*
Krishna Gudipati82794a22010-03-03 17:43:30 -080090 * fcs initialization, called once after bfa initialization is complete
91 */
92void
93bfa_fcs_init(struct bfa_fcs_s *fcs)
94{
Krishna Gudipati75332a72011-06-13 15:54:31 -070095 int i;
Krishna Gudipati82794a22010-03-03 17:43:30 -080096 struct bfa_fcs_mod_s *mod;
97
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070098 for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
Krishna Gudipati82794a22010-03-03 17:43:30 -080099 mod = &fcs_modules[i];
100 if (mod->modinit)
101 mod->modinit(fcs);
Jing Huang7725ccf2009-09-23 17:46:15 -0700102 }
Krishna Gudipati75332a72011-06-13 15:54:31 -0700103}
104
105/*
106 * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
107 * with values learned during bfa_init firmware GETATTR REQ.
108 */
109void
110bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)
111{
112 struct bfa_fcs_fabric_s *fabric = &fcs->fabric;
113 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
114 struct bfa_ioc_s *ioc = &fabric->fcs->bfa->ioc;
115
116 port_cfg->nwwn = ioc->attr->nwwn;
117 port_cfg->pwwn = ioc->attr->pwwn;
118}
119
120/*
121 * fcs pbc vport initialization
122 */
123void
124bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs)
125{
126 int i, npbc_vports;
127 struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
128
Jing Huangd9883542010-07-08 19:46:26 -0700129 /* Initialize pbc vports */
130 if (!fcs->min_cfg) {
131 npbc_vports =
Krishna Gudipati75332a72011-06-13 15:54:31 -0700132 bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
Jing Huangd9883542010-07-08 19:46:26 -0700133 for (i = 0; i < npbc_vports; i++)
134 bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
135 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700136}
137
Jing Huang5fbe25c2010-10-18 17:17:23 -0700138/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700139 * brief
140 * FCS driver details initialization.
Jing Huang7725ccf2009-09-23 17:46:15 -0700141 *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700142 * param[in] fcs FCS instance
143 * param[in] driver_info Driver Details
Jing Huang7725ccf2009-09-23 17:46:15 -0700144 *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700145 * return None
Jing Huang7725ccf2009-09-23 17:46:15 -0700146 */
147void
148bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
149 struct bfa_fcs_driver_info_s *driver_info)
150{
151
152 fcs->driver_info = *driver_info;
153
154 bfa_fcs_fabric_psymb_init(&fcs->fabric);
155}
156
Jing Huang5fbe25c2010-10-18 17:17:23 -0700157/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700158 * brief
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700159 * FCS instance cleanup and exit.
Jing Huang7725ccf2009-09-23 17:46:15 -0700160 *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700161 * param[in] fcs FCS instance
162 * return None
Jing Huang7725ccf2009-09-23 17:46:15 -0700163 */
164void
165bfa_fcs_exit(struct bfa_fcs_s *fcs)
166{
167 struct bfa_fcs_mod_s *mod;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700168 int nmods, i;
Jing Huang7725ccf2009-09-23 17:46:15 -0700169
170 bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
171
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700172 nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
173
174 for (i = 0; i < nmods; i++) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700175
176 mod = &fcs_modules[i];
Krishna Gudipati82794a22010-03-03 17:43:30 -0800177 if (mod->modexit) {
178 bfa_wc_up(&fcs->wc);
179 mod->modexit(fcs);
180 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700181 }
182
183 bfa_wc_wait(&fcs->wc);
184}
185
186
Jing Huang5fbe25c2010-10-18 17:17:23 -0700187/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700188 * Fabric module implementation.
189 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700190
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700191#define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */
192#define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */
193
194#define bfa_fcs_fabric_set_opertype(__fabric) do { \
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700195 if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \
196 == BFA_PORT_TOPOLOGY_P2P) { \
197 if (fabric->fab_type == BFA_FCS_FABRIC_SWITCHED) \
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700198 (__fabric)->oper_type = BFA_PORT_TYPE_NPORT; \
199 else \
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700200 (__fabric)->oper_type = BFA_PORT_TYPE_P2P; \
201 } else \
202 (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT; \
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700203} while (0)
204
205/*
206 * forward declarations
207 */
208static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
209static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
210static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
211static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
212static void bfa_fcs_fabric_delay(void *cbarg);
213static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
214static void bfa_fcs_fabric_delete_comp(void *cbarg);
215static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
216 struct fchs_s *fchs, u16 len);
217static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
218 struct fchs_s *fchs, u16 len);
219static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
220static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
221 struct bfa_fcxp_s *fcxp, void *cbarg,
222 bfa_status_t status,
223 u32 rsp_len,
224 u32 resid_len,
225 struct fchs_s *rspfchs);
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700226static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric);
227static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled(
228 struct bfa_fcs_fabric_s *fabric);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700229
230static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
231 enum bfa_fcs_fabric_event event);
232static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
233 enum bfa_fcs_fabric_event event);
234static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
235 enum bfa_fcs_fabric_event event);
236static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
237 enum bfa_fcs_fabric_event event);
238static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
239 enum bfa_fcs_fabric_event event);
240static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
241 enum bfa_fcs_fabric_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700242static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
243 enum bfa_fcs_fabric_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700244static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
245 enum bfa_fcs_fabric_event event);
246static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
247 enum bfa_fcs_fabric_event event);
248static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
249 enum bfa_fcs_fabric_event event);
250static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
251 enum bfa_fcs_fabric_event event);
Jing Huang5fbe25c2010-10-18 17:17:23 -0700252/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700253 * Beginning state before fabric creation.
254 */
255static void
256bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
257 enum bfa_fcs_fabric_event event)
258{
259 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
260 bfa_trc(fabric->fcs, event);
261
262 switch (event) {
263 case BFA_FCS_FABRIC_SM_CREATE:
264 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
265 bfa_fcs_fabric_init(fabric);
266 bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
267 break;
268
269 case BFA_FCS_FABRIC_SM_LINK_UP:
270 case BFA_FCS_FABRIC_SM_LINK_DOWN:
271 break;
272
273 default:
274 bfa_sm_fault(fabric->fcs, event);
275 }
276}
277
Jing Huang5fbe25c2010-10-18 17:17:23 -0700278/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700279 * Beginning state before fabric creation.
280 */
281static void
282bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
283 enum bfa_fcs_fabric_event event)
284{
285 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
286 bfa_trc(fabric->fcs, event);
287
288 switch (event) {
289 case BFA_FCS_FABRIC_SM_START:
290 if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
291 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
292 bfa_fcs_fabric_login(fabric);
293 } else
294 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
295 break;
296
297 case BFA_FCS_FABRIC_SM_LINK_UP:
298 case BFA_FCS_FABRIC_SM_LINK_DOWN:
299 break;
300
301 case BFA_FCS_FABRIC_SM_DELETE:
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -0700302 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
303 bfa_fcs_fabric_delete(fabric);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700304 break;
305
306 default:
307 bfa_sm_fault(fabric->fcs, event);
308 }
309}
310
Jing Huang5fbe25c2010-10-18 17:17:23 -0700311/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700312 * Link is down, awaiting LINK UP event from port. This is also the
313 * first state at fabric creation.
314 */
315static void
316bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
317 enum bfa_fcs_fabric_event event)
318{
319 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
320 bfa_trc(fabric->fcs, event);
321
322 switch (event) {
323 case BFA_FCS_FABRIC_SM_LINK_UP:
324 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
325 bfa_fcs_fabric_login(fabric);
326 break;
327
328 case BFA_FCS_FABRIC_SM_RETRY_OP:
329 break;
330
331 case BFA_FCS_FABRIC_SM_DELETE:
332 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
333 bfa_fcs_fabric_delete(fabric);
334 break;
335
336 default:
337 bfa_sm_fault(fabric->fcs, event);
338 }
339}
340
Jing Huang5fbe25c2010-10-18 17:17:23 -0700341/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700342 * FLOGI is in progress, awaiting FLOGI reply.
343 */
344static void
345bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
346 enum bfa_fcs_fabric_event event)
347{
348 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
349 bfa_trc(fabric->fcs, event);
350
351 switch (event) {
352 case BFA_FCS_FABRIC_SM_CONT_OP:
353
354 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700355 fabric->bb_credit,
356 bfa_fcs_fabric_oper_bbscn(fabric));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700357 fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
358
359 if (fabric->auth_reqd && fabric->is_auth) {
360 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
361 bfa_trc(fabric->fcs, event);
362 } else {
363 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
364 bfa_fcs_fabric_notify_online(fabric);
365 }
366 break;
367
368 case BFA_FCS_FABRIC_SM_RETRY_OP:
369 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
370 bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
371 bfa_fcs_fabric_delay, fabric,
372 BFA_FCS_FABRIC_RETRY_DELAY);
373 break;
374
375 case BFA_FCS_FABRIC_SM_LOOPBACK:
376 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800377 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700378 bfa_fcs_fabric_set_opertype(fabric);
379 break;
380
381 case BFA_FCS_FABRIC_SM_NO_FABRIC:
382 fabric->fab_type = BFA_FCS_FABRIC_N2N;
383 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700384 fabric->bb_credit,
385 bfa_fcs_fabric_oper_bbscn(fabric));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700386 bfa_fcs_fabric_notify_online(fabric);
387 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
388 break;
389
390 case BFA_FCS_FABRIC_SM_LINK_DOWN:
391 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800392 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700393 break;
394
395 case BFA_FCS_FABRIC_SM_DELETE:
396 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800397 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700398 bfa_fcs_fabric_delete(fabric);
399 break;
400
401 default:
402 bfa_sm_fault(fabric->fcs, event);
403 }
404}
405
406
407static void
408bfa_fcs_fabric_sm_flogi_retry(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_DELAYED:
416 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
417 bfa_fcs_fabric_login(fabric);
418 break;
419
420 case BFA_FCS_FABRIC_SM_LINK_DOWN:
421 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
422 bfa_timer_stop(&fabric->delay_timer);
423 break;
424
425 case BFA_FCS_FABRIC_SM_DELETE:
426 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
427 bfa_timer_stop(&fabric->delay_timer);
428 bfa_fcs_fabric_delete(fabric);
429 break;
430
431 default:
432 bfa_sm_fault(fabric->fcs, event);
433 }
434}
435
Jing Huang5fbe25c2010-10-18 17:17:23 -0700436/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700437 * Authentication is in progress, awaiting authentication results.
438 */
439static void
440bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
441 enum bfa_fcs_fabric_event event)
442{
443 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
444 bfa_trc(fabric->fcs, event);
445
446 switch (event) {
447 case BFA_FCS_FABRIC_SM_AUTH_FAILED:
448 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800449 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700450 break;
451
452 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
453 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
454 bfa_fcs_fabric_notify_online(fabric);
455 break;
456
457 case BFA_FCS_FABRIC_SM_PERF_EVFP:
458 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
459 break;
460
461 case BFA_FCS_FABRIC_SM_LINK_DOWN:
462 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800463 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700464 break;
465
466 case BFA_FCS_FABRIC_SM_DELETE:
467 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
468 bfa_fcs_fabric_delete(fabric);
469 break;
470
471 default:
472 bfa_sm_fault(fabric->fcs, event);
473 }
474}
475
Jing Huang5fbe25c2010-10-18 17:17:23 -0700476/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700477 * Authentication failed
478 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800479void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700480bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
481 enum bfa_fcs_fabric_event event)
482{
483 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
484 bfa_trc(fabric->fcs, event);
485
486 switch (event) {
487 case BFA_FCS_FABRIC_SM_LINK_DOWN:
488 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
489 bfa_fcs_fabric_notify_offline(fabric);
490 break;
491
492 case BFA_FCS_FABRIC_SM_DELETE:
493 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
494 bfa_fcs_fabric_delete(fabric);
495 break;
496
497 default:
498 bfa_sm_fault(fabric->fcs, event);
499 }
500}
501
Jing Huang5fbe25c2010-10-18 17:17:23 -0700502/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700503 * Port is in loopback mode.
504 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800505void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700506bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
507 enum bfa_fcs_fabric_event event)
508{
509 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
510 bfa_trc(fabric->fcs, event);
511
512 switch (event) {
513 case BFA_FCS_FABRIC_SM_LINK_DOWN:
514 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
515 bfa_fcs_fabric_notify_offline(fabric);
516 break;
517
518 case BFA_FCS_FABRIC_SM_DELETE:
519 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
520 bfa_fcs_fabric_delete(fabric);
521 break;
522
523 default:
524 bfa_sm_fault(fabric->fcs, event);
525 }
526}
527
Jing Huang5fbe25c2010-10-18 17:17:23 -0700528/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700529 * There is no attached fabric - private loop or NPort-to-NPort topology.
530 */
531static void
532bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
533 enum bfa_fcs_fabric_event event)
534{
535 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
536 bfa_trc(fabric->fcs, event);
537
538 switch (event) {
539 case BFA_FCS_FABRIC_SM_LINK_DOWN:
540 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800541 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700542 bfa_fcs_fabric_notify_offline(fabric);
543 break;
544
545 case BFA_FCS_FABRIC_SM_DELETE:
546 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
547 bfa_fcs_fabric_delete(fabric);
548 break;
549
550 case BFA_FCS_FABRIC_SM_NO_FABRIC:
551 bfa_trc(fabric->fcs, fabric->bb_credit);
552 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700553 fabric->bb_credit,
554 bfa_fcs_fabric_oper_bbscn(fabric));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700555 break;
556
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700557 case BFA_FCS_FABRIC_SM_RETRY_OP:
558 break;
559
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700560 default:
561 bfa_sm_fault(fabric->fcs, event);
562 }
563}
564
Jing Huang5fbe25c2010-10-18 17:17:23 -0700565/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700566 * Fabric is online - normal operating state.
567 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800568void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700569bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
570 enum bfa_fcs_fabric_event event)
571{
572 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
573 bfa_trc(fabric->fcs, event);
574
575 switch (event) {
576 case BFA_FCS_FABRIC_SM_LINK_DOWN:
577 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800578 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700579 bfa_fcs_fabric_notify_offline(fabric);
580 break;
581
582 case BFA_FCS_FABRIC_SM_DELETE:
583 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
584 bfa_fcs_fabric_delete(fabric);
585 break;
586
587 case BFA_FCS_FABRIC_SM_AUTH_FAILED:
588 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800589 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700590 break;
591
592 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
593 break;
594
595 default:
596 bfa_sm_fault(fabric->fcs, event);
597 }
598}
599
Jing Huang5fbe25c2010-10-18 17:17:23 -0700600/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700601 * Exchanging virtual fabric parameters.
602 */
603static void
604bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
605 enum bfa_fcs_fabric_event event)
606{
607 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
608 bfa_trc(fabric->fcs, event);
609
610 switch (event) {
611 case BFA_FCS_FABRIC_SM_CONT_OP:
612 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
613 break;
614
615 case BFA_FCS_FABRIC_SM_ISOLATE:
616 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
617 break;
618
619 default:
620 bfa_sm_fault(fabric->fcs, event);
621 }
622}
623
Jing Huang5fbe25c2010-10-18 17:17:23 -0700624/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700625 * EVFP exchange complete and VFT tagging is enabled.
626 */
627static void
628bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
629 enum bfa_fcs_fabric_event event)
630{
631 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
632 bfa_trc(fabric->fcs, event);
633}
634
Jing Huang5fbe25c2010-10-18 17:17:23 -0700635/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700636 * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
637 */
638static void
639bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
640 enum bfa_fcs_fabric_event event)
641{
642 struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
643 char pwwn_ptr[BFA_STRING_32];
644
645 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
646 bfa_trc(fabric->fcs, event);
647 wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);
648
Jing Huang88166242010-12-09 17:11:53 -0800649 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700650 "Port is isolated due to VF_ID mismatch. "
651 "PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",
652 pwwn_ptr, fabric->fcs->port_vfid,
653 fabric->event_arg.swp_vfid);
654}
655
Jing Huang5fbe25c2010-10-18 17:17:23 -0700656/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700657 * Fabric is being deleted, awaiting vport delete completions.
658 */
659static void
660bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
661 enum bfa_fcs_fabric_event event)
662{
663 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
664 bfa_trc(fabric->fcs, event);
665
666 switch (event) {
667 case BFA_FCS_FABRIC_SM_DELCOMP:
668 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800669 bfa_wc_down(&fabric->fcs->wc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700670 break;
671
672 case BFA_FCS_FABRIC_SM_LINK_UP:
673 break;
674
675 case BFA_FCS_FABRIC_SM_LINK_DOWN:
676 bfa_fcs_fabric_notify_offline(fabric);
677 break;
678
679 default:
680 bfa_sm_fault(fabric->fcs, event);
681 }
682}
683
684
685
Jing Huang5fbe25c2010-10-18 17:17:23 -0700686/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700687 * fcs_fabric_private fabric private functions
688 */
689
690static void
691bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
692{
693 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
694
695 port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;
Maggie Zhangf7f73812010-12-09 19:08:43 -0800696 port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn;
697 port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700698}
699
Jing Huang5fbe25c2010-10-18 17:17:23 -0700700/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700701 * Port Symbolic Name Creation for base port.
702 */
703void
704bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
705{
706 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
707 char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
708 struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
709
710 bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
711
712 /* Model name/number */
713 strncpy((char *)&port_cfg->sym_name, model,
714 BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
715 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
716 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
717
718 /* Driver Version */
719 strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
720 BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
721 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
722 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
723
724 /* Host machine name */
725 strncat((char *)&port_cfg->sym_name,
726 (char *)driver_info->host_machine_name,
727 BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
728 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
729 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
730
731 /*
732 * Host OS Info :
733 * If OS Patch Info is not there, do not truncate any bytes from the
734 * OS name string and instead copy the entire OS info string (64 bytes).
735 */
736 if (driver_info->host_os_patch[0] == '\0') {
737 strncat((char *)&port_cfg->sym_name,
738 (char *)driver_info->host_os_name,
739 BFA_FCS_OS_STR_LEN);
740 strncat((char *)&port_cfg->sym_name,
741 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
742 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
743 } else {
744 strncat((char *)&port_cfg->sym_name,
745 (char *)driver_info->host_os_name,
746 BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
747 strncat((char *)&port_cfg->sym_name,
748 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
749 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
750
751 /* Append host OS Patch Info */
752 strncat((char *)&port_cfg->sym_name,
753 (char *)driver_info->host_os_patch,
754 BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
755 }
756
757 /* null terminate */
758 port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
759}
760
Jing Huang5fbe25c2010-10-18 17:17:23 -0700761/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700762 * bfa lps login completion callback
763 */
764void
765bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
766{
767 struct bfa_fcs_fabric_s *fabric = uarg;
768
769 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
770 bfa_trc(fabric->fcs, status);
771
772 switch (status) {
773 case BFA_STATUS_OK:
774 fabric->stats.flogi_accepts++;
775 break;
776
777 case BFA_STATUS_INVALID_MAC:
778 /* Only for CNA */
779 fabric->stats.flogi_acc_err++;
780 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
781
782 return;
783
784 case BFA_STATUS_EPROTOCOL:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800785 switch (fabric->lps->ext_status) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700786 case BFA_EPROTO_BAD_ACCEPT:
787 fabric->stats.flogi_acc_err++;
788 break;
789
790 case BFA_EPROTO_UNKNOWN_RSP:
791 fabric->stats.flogi_unknown_rsp++;
792 break;
793
794 default:
795 break;
796 }
797 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
798
799 return;
800
801 case BFA_STATUS_FABRIC_RJT:
802 fabric->stats.flogi_rejects++;
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700803 if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR &&
804 fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO)
805 fabric->fcs->bbscn_flogi_rjt = BFA_TRUE;
806
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700807 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
808 return;
809
810 default:
811 fabric->stats.flogi_rsp_err++;
812 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
813 return;
814 }
815
Maggie Zhangf7f73812010-12-09 19:08:43 -0800816 fabric->bb_credit = fabric->lps->pr_bbcred;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700817 bfa_trc(fabric->fcs, fabric->bb_credit);
818
Maggie Zhangf7f73812010-12-09 19:08:43 -0800819 if (!(fabric->lps->brcd_switch))
820 fabric->fabric_name = fabric->lps->pr_nwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700821
822 /*
823 * Check port type. It should be 1 = F-port.
824 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800825 if (fabric->lps->fport) {
826 fabric->bport.pid = fabric->lps->lp_pid;
827 fabric->is_npiv = fabric->lps->npiv_en;
828 fabric->is_auth = fabric->lps->auth_req;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700829 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
830 } else {
831 /*
832 * Nport-2-Nport direct attached
833 */
834 fabric->bport.port_topo.pn2n.rem_port_wwn =
Maggie Zhangf7f73812010-12-09 19:08:43 -0800835 fabric->lps->pr_pwwn;
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700836 fabric->fab_type = BFA_FCS_FABRIC_N2N;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700837 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
838 }
839
840 bfa_trc(fabric->fcs, fabric->bport.pid);
841 bfa_trc(fabric->fcs, fabric->is_npiv);
842 bfa_trc(fabric->fcs, fabric->is_auth);
843}
Jing Huang5fbe25c2010-10-18 17:17:23 -0700844/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700845 * Allocate and send FLOGI.
846 */
847static void
848bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
849{
850 struct bfa_s *bfa = fabric->fcs->bfa;
851 struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700852 u8 alpa = 0, bb_scn = 0;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700853
854 if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
855 alpa = bfa_fcport_get_myalpa(bfa);
856
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700857 if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
858 (!fabric->fcs->bbscn_flogi_rjt))
859 bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
860
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700861 bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700862 pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700863
864 fabric->stats.flogi_sent++;
865}
866
867static void
868bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
869{
870 struct bfa_fcs_vport_s *vport;
871 struct list_head *qe, *qen;
872
873 bfa_trc(fabric->fcs, fabric->fabric_name);
874
875 bfa_fcs_fabric_set_opertype(fabric);
876 fabric->stats.fabric_onlines++;
877
Jing Huang5fbe25c2010-10-18 17:17:23 -0700878 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700879 * notify online event to base and then virtual ports
880 */
881 bfa_fcs_lport_online(&fabric->bport);
882
883 list_for_each_safe(qe, qen, &fabric->vport_q) {
884 vport = (struct bfa_fcs_vport_s *) qe;
885 bfa_fcs_vport_online(vport);
886 }
887}
888
889static void
890bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
891{
892 struct bfa_fcs_vport_s *vport;
893 struct list_head *qe, *qen;
894
895 bfa_trc(fabric->fcs, fabric->fabric_name);
896 fabric->stats.fabric_offlines++;
897
Jing Huang5fbe25c2010-10-18 17:17:23 -0700898 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700899 * notify offline event first to vports and then base port.
900 */
901 list_for_each_safe(qe, qen, &fabric->vport_q) {
902 vport = (struct bfa_fcs_vport_s *) qe;
903 bfa_fcs_vport_offline(vport);
904 }
905
906 bfa_fcs_lport_offline(&fabric->bport);
907
908 fabric->fabric_name = 0;
909 fabric->fabric_ip_addr[0] = 0;
910}
911
912static void
913bfa_fcs_fabric_delay(void *cbarg)
914{
915 struct bfa_fcs_fabric_s *fabric = cbarg;
916
917 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
918}
919
Jing Huang5fbe25c2010-10-18 17:17:23 -0700920/*
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700921 * Computes operating BB_SCN value
922 */
923static u8
924bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric)
925{
926 u8 pr_bbscn = fabric->lps->pr_bbscn;
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700927 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700928
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700929 if (!(fcport->cfg.bb_scn_state && pr_bbscn))
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700930 return 0;
931
932 /* return max of local/remote bb_scn values */
933 return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ?
934 pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN);
935}
936
937/*
938 * Check if BB_SCN can be enabled.
939 */
940static bfa_boolean_t
941bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric)
942{
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700943 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
944
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700945 if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) &&
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700946 fcport->cfg.bb_scn_state &&
Krishna Gudipatibe540a92011-06-13 15:53:04 -0700947 !bfa_fcport_is_qos_enabled(fabric->fcs->bfa) &&
948 !bfa_fcport_is_trunk_enabled(fabric->fcs->bfa))
949 return BFA_TRUE;
950 else
951 return BFA_FALSE;
952}
953
954/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700955 * Delete all vports and wait for vport delete completions.
956 */
957static void
958bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
959{
960 struct bfa_fcs_vport_s *vport;
961 struct list_head *qe, *qen;
962
963 list_for_each_safe(qe, qen, &fabric->vport_q) {
964 vport = (struct bfa_fcs_vport_s *) qe;
965 bfa_fcs_vport_fcs_delete(vport);
966 }
967
968 bfa_fcs_lport_delete(&fabric->bport);
969 bfa_wc_wait(&fabric->wc);
970}
971
972static void
973bfa_fcs_fabric_delete_comp(void *cbarg)
974{
975 struct bfa_fcs_fabric_s *fabric = cbarg;
976
977 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
978}
979
Jing Huang5fbe25c2010-10-18 17:17:23 -0700980/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700981 * fcs_fabric_public fabric public functions
982 */
983
Jing Huang5fbe25c2010-10-18 17:17:23 -0700984/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700985 * Attach time initialization.
986 */
987void
988bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
989{
990 struct bfa_fcs_fabric_s *fabric;
991
992 fabric = &fcs->fabric;
Jing Huang6a18b162010-10-18 17:08:54 -0700993 memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700994
Jing Huang5fbe25c2010-10-18 17:17:23 -0700995 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700996 * Initialize base fabric.
997 */
998 fabric->fcs = fcs;
999 INIT_LIST_HEAD(&fabric->vport_q);
1000 INIT_LIST_HEAD(&fabric->vf_q);
1001 fabric->lps = bfa_lps_alloc(fcs->bfa);
Jing Huangd4b671c2010-12-26 21:46:35 -08001002 WARN_ON(!fabric->lps);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001003
Jing Huang5fbe25c2010-10-18 17:17:23 -07001004 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001005 * Initialize fabric delete completion handler. Fabric deletion is
1006 * complete when the last vport delete is complete.
1007 */
1008 bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
1009 bfa_wc_up(&fabric->wc); /* For the base port */
1010
1011 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
1012 bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
1013}
1014
1015void
1016bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
1017{
1018 bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
1019 bfa_trc(fcs, 0);
1020}
1021
Jing Huang5fbe25c2010-10-18 17:17:23 -07001022/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001023 * Module cleanup
1024 */
1025void
1026bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
1027{
1028 struct bfa_fcs_fabric_s *fabric;
1029
1030 bfa_trc(fcs, 0);
1031
Jing Huang5fbe25c2010-10-18 17:17:23 -07001032 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001033 * Cleanup base fabric.
1034 */
1035 fabric = &fcs->fabric;
1036 bfa_lps_delete(fabric->lps);
1037 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
1038}
1039
Jing Huang5fbe25c2010-10-18 17:17:23 -07001040/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001041 * Fabric module start -- kick starts FCS actions
1042 */
1043void
1044bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
1045{
1046 struct bfa_fcs_fabric_s *fabric;
1047
1048 bfa_trc(fcs, 0);
1049 fabric = &fcs->fabric;
1050 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
1051}
1052
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001053
Jing Huang5fbe25c2010-10-18 17:17:23 -07001054/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001055 * Link up notification from BFA physical port module.
1056 */
1057void
1058bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
1059{
1060 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
1061 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
1062}
1063
Jing Huang5fbe25c2010-10-18 17:17:23 -07001064/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001065 * Link down notification from BFA physical port module.
1066 */
1067void
1068bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
1069{
1070 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001071 fabric->fcs->bbscn_flogi_rjt = BFA_FALSE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001072 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
1073}
1074
Jing Huang5fbe25c2010-10-18 17:17:23 -07001075/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001076 * A child vport is being created in the fabric.
1077 *
1078 * Call from vport module at vport creation. A list of base port and vports
1079 * belonging to a fabric is maintained to propagate link events.
1080 *
1081 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
1082 * param[in] vport - Vport being created.
1083 *
1084 * @return None (always succeeds)
1085 */
1086void
1087bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
1088 struct bfa_fcs_vport_s *vport)
1089{
Jing Huang5fbe25c2010-10-18 17:17:23 -07001090 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001091 * - add vport to fabric's vport_q
1092 */
1093 bfa_trc(fabric->fcs, fabric->vf_id);
1094
1095 list_add_tail(&vport->qe, &fabric->vport_q);
1096 fabric->num_vports++;
1097 bfa_wc_up(&fabric->wc);
1098}
1099
Jing Huang5fbe25c2010-10-18 17:17:23 -07001100/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001101 * A child vport is being deleted from fabric.
1102 *
1103 * Vport is being deleted.
1104 */
1105void
1106bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
1107 struct bfa_fcs_vport_s *vport)
1108{
1109 list_del(&vport->qe);
1110 fabric->num_vports--;
1111 bfa_wc_down(&fabric->wc);
1112}
1113
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001114
Jing Huang5fbe25c2010-10-18 17:17:23 -07001115/*
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001116 * Lookup for a vport within a fabric given its pwwn
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001117 */
1118struct bfa_fcs_vport_s *
1119bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
1120{
1121 struct bfa_fcs_vport_s *vport;
1122 struct list_head *qe;
1123
1124 list_for_each(qe, &fabric->vport_q) {
1125 vport = (struct bfa_fcs_vport_s *) qe;
1126 if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn)
1127 return vport;
1128 }
1129
1130 return NULL;
1131}
1132
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001133
1134/*
1135 * Get OUI of the attached switch.
1136 *
1137 * Note : Use of this function should be avoided as much as possible.
1138 * This function should be used only if there is any requirement
1139* to check for FOS version below 6.3.
1140 * To check if the attached fabric is a brocade fabric, use
1141 * bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
1142 * or above only.
1143 */
1144
1145u16
1146bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
1147{
1148 wwn_t fab_nwwn;
1149 u8 *tmp;
1150 u16 oui;
1151
Maggie Zhangf7f73812010-12-09 19:08:43 -08001152 fab_nwwn = fabric->lps->pr_nwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001153
1154 tmp = (u8 *)&fab_nwwn;
1155 oui = (tmp[3] << 8) | tmp[4];
1156
1157 return oui;
1158}
Jing Huang5fbe25c2010-10-18 17:17:23 -07001159/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001160 * Unsolicited frame receive handling.
1161 */
1162void
1163bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1164 u16 len)
1165{
1166 u32 pid = fchs->d_id;
1167 struct bfa_fcs_vport_s *vport;
1168 struct list_head *qe;
1169 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1170 struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;
1171
1172 bfa_trc(fabric->fcs, len);
1173 bfa_trc(fabric->fcs, pid);
1174
Jing Huang5fbe25c2010-10-18 17:17:23 -07001175 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001176 * Look for our own FLOGI frames being looped back. This means an
1177 * external loopback cable is in place. Our own FLOGI frames are
1178 * sometimes looped back when switch port gets temporarily bypassed.
1179 */
Maggie Zhangf16a1752010-12-09 19:12:32 -08001180 if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001181 (els_cmd->els_code == FC_ELS_FLOGI) &&
1182 (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {
1183 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
1184 return;
1185 }
1186
Jing Huang5fbe25c2010-10-18 17:17:23 -07001187 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001188 * FLOGI/EVFP exchanges should be consumed by base fabric.
1189 */
Maggie Zhangf16a1752010-12-09 19:12:32 -08001190 if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001191 bfa_trc(fabric->fcs, pid);
1192 bfa_fcs_fabric_process_uf(fabric, fchs, len);
1193 return;
1194 }
1195
1196 if (fabric->bport.pid == pid) {
Jing Huang5fbe25c2010-10-18 17:17:23 -07001197 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001198 * All authentication frames should be routed to auth
1199 */
1200 bfa_trc(fabric->fcs, els_cmd->els_code);
1201 if (els_cmd->els_code == FC_ELS_AUTH) {
1202 bfa_trc(fabric->fcs, els_cmd->els_code);
1203 return;
1204 }
1205
1206 bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
1207 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
1208 return;
1209 }
1210
Jing Huang5fbe25c2010-10-18 17:17:23 -07001211 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001212 * look for a matching local port ID
1213 */
1214 list_for_each(qe, &fabric->vport_q) {
1215 vport = (struct bfa_fcs_vport_s *) qe;
1216 if (vport->lport.pid == pid) {
1217 bfa_fcs_lport_uf_recv(&vport->lport, fchs, len);
1218 return;
1219 }
1220 }
1221 bfa_trc(fabric->fcs, els_cmd->els_code);
1222 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
1223}
1224
Jing Huang5fbe25c2010-10-18 17:17:23 -07001225/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001226 * Unsolicited frames to be processed by fabric.
1227 */
1228static void
1229bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1230 u16 len)
1231{
1232 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1233
1234 bfa_trc(fabric->fcs, els_cmd->els_code);
1235
1236 switch (els_cmd->els_code) {
1237 case FC_ELS_FLOGI:
1238 bfa_fcs_fabric_process_flogi(fabric, fchs, len);
1239 break;
1240
1241 default:
1242 /*
1243 * need to generate a LS_RJT
1244 */
1245 break;
1246 }
1247}
1248
Jing Huang5fbe25c2010-10-18 17:17:23 -07001249/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001250 * Process incoming FLOGI
1251 */
1252static void
1253bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
1254 struct fchs_s *fchs, u16 len)
1255{
1256 struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);
1257 struct bfa_fcs_lport_s *bport = &fabric->bport;
1258
1259 bfa_trc(fabric->fcs, fchs->s_id);
1260
1261 fabric->stats.flogi_rcvd++;
1262 /*
1263 * Check port type. It should be 0 = n-port.
1264 */
1265 if (flogi->csp.port_type) {
1266 /*
1267 * @todo: may need to send a LS_RJT
1268 */
1269 bfa_trc(fabric->fcs, flogi->port_name);
1270 fabric->stats.flogi_rejected++;
1271 return;
1272 }
1273
Jing Huangba816ea2010-10-18 17:10:50 -07001274 fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001275 fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001276 bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
1277 bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
1278
1279 /*
1280 * Send a Flogi Acc
1281 */
1282 bfa_fcs_fabric_send_flogi_acc(fabric);
1283 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
1284}
1285
1286static void
1287bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
1288{
1289 struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
1290 struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
1291 struct bfa_s *bfa = fabric->fcs->bfa;
1292 struct bfa_fcxp_s *fcxp;
1293 u16 reqlen;
1294 struct fchs_s fchs;
1295
1296 fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001297 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001298 * Do not expect this failure -- expect remote node to retry
1299 */
1300 if (!fcxp)
1301 return;
1302
1303 reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
Maggie Zhangf16a1752010-12-09 19:12:32 -08001304 bfa_hton3b(FC_FABRIC_PORT),
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001305 n2n_port->reply_oxid, pcfg->pwwn,
1306 pcfg->nwwn,
1307 bfa_fcport_get_maxfrsize(bfa),
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001308 bfa_fcport_get_rx_bbcredit(bfa),
1309 bfa_fcs_fabric_oper_bbscn(fabric));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001310
Krishna Gudipati3fd45982011-06-24 20:24:08 -07001311 bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001312 BFA_FALSE, FC_CLASS_3,
1313 reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
1314 FC_MAX_PDUSZ, 0);
1315}
1316
Jing Huang5fbe25c2010-10-18 17:17:23 -07001317/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001318 * Flogi Acc completion callback.
1319 */
1320static void
1321bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1322 bfa_status_t status, u32 rsp_len,
1323 u32 resid_len, struct fchs_s *rspfchs)
1324{
1325 struct bfa_fcs_fabric_s *fabric = cbarg;
1326
1327 bfa_trc(fabric->fcs, status);
1328}
1329
1330/*
1331 *
1332 * @param[in] fabric - fabric
1333 * @param[in] wwn_t - new fabric name
1334 *
1335 * @return - none
1336 */
1337void
1338bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
1339 wwn_t fabric_name)
1340{
1341 struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
1342 char pwwn_ptr[BFA_STRING_32];
1343 char fwwn_ptr[BFA_STRING_32];
1344
1345 bfa_trc(fabric->fcs, fabric_name);
1346
1347 if (fabric->fabric_name == 0) {
1348 /*
1349 * With BRCD switches, we don't get Fabric Name in FLOGI.
1350 * Don't generate a fabric name change event in this case.
1351 */
1352 fabric->fabric_name = fabric_name;
1353 } else {
1354 fabric->fabric_name = fabric_name;
1355 wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));
1356 wwn2str(fwwn_ptr,
1357 bfa_fcs_lport_get_fabric_name(&fabric->bport));
Jing Huang88166242010-12-09 17:11:53 -08001358 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001359 "Base port WWN = %s Fabric WWN = %s\n",
1360 pwwn_ptr, fwwn_ptr);
1361 }
1362}
1363
Jing Huang5fbe25c2010-10-18 17:17:23 -07001364/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001365 * Returns FCS vf structure for a given vf_id.
1366 *
1367 * param[in] vf_id - VF_ID
1368 *
1369 * return
1370 * If lookup succeeds, retuns fcs vf object, otherwise returns NULL
1371 */
1372bfa_fcs_vf_t *
1373bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
1374{
1375 bfa_trc(fcs, vf_id);
1376 if (vf_id == FC_VF_ID_NULL)
1377 return &fcs->fabric;
1378
1379 return NULL;
1380}
1381
Jing Huang5fbe25c2010-10-18 17:17:23 -07001382/*
Krishna Gudipatib85daaf2011-06-13 15:55:11 -07001383 * Return the list of local logical ports present in the given VF.
1384 *
1385 * @param[in] vf vf for which logical ports are returned
1386 * @param[out] lpwwn returned logical port wwn list
1387 * @param[in,out] nlports in:size of lpwwn list;
1388 * out:total elements present,
1389 * actual elements returned is limited by the size
1390 */
1391void
1392bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
1393{
1394 struct list_head *qe;
1395 struct bfa_fcs_vport_s *vport;
1396 int i = 0;
1397 struct bfa_fcs_s *fcs;
1398
1399 if (vf == NULL || lpwwn == NULL || *nlports == 0)
1400 return;
1401
1402 fcs = vf->fcs;
1403
1404 bfa_trc(fcs, vf->vf_id);
1405 bfa_trc(fcs, (uint32_t) *nlports);
1406
1407 lpwwn[i++] = vf->bport.port_cfg.pwwn;
1408
1409 list_for_each(qe, &vf->vport_q) {
1410 if (i >= *nlports)
1411 break;
1412
1413 vport = (struct bfa_fcs_vport_s *) qe;
1414 lpwwn[i++] = vport->lport.port_cfg.pwwn;
1415 }
1416
1417 bfa_trc(fcs, i);
1418 *nlports = i;
1419}
1420
1421/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001422 * BFA FCS PPORT ( physical port)
1423 */
1424static void
1425bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)
1426{
1427 struct bfa_fcs_s *fcs = cbarg;
1428
1429 bfa_trc(fcs, event);
1430
1431 switch (event) {
1432 case BFA_PORT_LINKUP:
1433 bfa_fcs_fabric_link_up(&fcs->fabric);
1434 break;
1435
1436 case BFA_PORT_LINKDOWN:
1437 bfa_fcs_fabric_link_down(&fcs->fabric);
1438 break;
1439
1440 default:
Jing Huangd4b671c2010-12-26 21:46:35 -08001441 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001442 }
1443}
1444
1445void
1446bfa_fcs_port_attach(struct bfa_fcs_s *fcs)
1447{
1448 bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);
1449}
1450
Jing Huang5fbe25c2010-10-18 17:17:23 -07001451/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001452 * BFA FCS UF ( Unsolicited Frames)
1453 */
1454
Jing Huang5fbe25c2010-10-18 17:17:23 -07001455/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001456 * BFA callback for unsolicited frame receive handler.
1457 *
1458 * @param[in] cbarg callback arg for receive handler
1459 * @param[in] uf unsolicited frame descriptor
1460 *
1461 * @return None
1462 */
1463static void
1464bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
1465{
1466 struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg;
1467 struct fchs_s *fchs = bfa_uf_get_frmbuf(uf);
1468 u16 len = bfa_uf_get_frmlen(uf);
1469 struct fc_vft_s *vft;
1470 struct bfa_fcs_fabric_s *fabric;
1471
Jing Huang5fbe25c2010-10-18 17:17:23 -07001472 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001473 * check for VFT header
1474 */
1475 if (fchs->routing == FC_RTG_EXT_HDR &&
1476 fchs->cat_info == FC_CAT_VFT_HDR) {
1477 bfa_stats(fcs, uf.tagged);
1478 vft = bfa_uf_get_frmbuf(uf);
1479 if (fcs->port_vfid == vft->vf_id)
1480 fabric = &fcs->fabric;
1481 else
1482 fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
1483
Jing Huang5fbe25c2010-10-18 17:17:23 -07001484 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001485 * drop frame if vfid is unknown
1486 */
1487 if (!fabric) {
Jing Huangd4b671c2010-12-26 21:46:35 -08001488 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001489 bfa_stats(fcs, uf.vfid_unknown);
1490 bfa_uf_free(uf);
1491 return;
1492 }
1493
Jing Huang5fbe25c2010-10-18 17:17:23 -07001494 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001495 * skip vft header
1496 */
1497 fchs = (struct fchs_s *) (vft + 1);
1498 len -= sizeof(struct fc_vft_s);
1499
1500 bfa_trc(fcs, vft->vf_id);
1501 } else {
1502 bfa_stats(fcs, uf.untagged);
1503 fabric = &fcs->fabric;
1504 }
1505
1506 bfa_trc(fcs, ((u32 *) fchs)[0]);
1507 bfa_trc(fcs, ((u32 *) fchs)[1]);
1508 bfa_trc(fcs, ((u32 *) fchs)[2]);
1509 bfa_trc(fcs, ((u32 *) fchs)[3]);
1510 bfa_trc(fcs, ((u32 *) fchs)[4]);
1511 bfa_trc(fcs, ((u32 *) fchs)[5]);
1512 bfa_trc(fcs, len);
1513
1514 bfa_fcs_fabric_uf_recv(fabric, fchs, len);
1515 bfa_uf_free(uf);
1516}
1517
1518void
1519bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
1520{
1521 bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
1522}