blob: eb42e74ed42370c17bf2e43b0692540c7ad0f035 [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 Gudipatia36c61f2010-09-15 11:50:55 -070095 int i, npbc_vports;
Krishna Gudipati82794a22010-03-03 17:43:30 -080096 struct bfa_fcs_mod_s *mod;
Jing Huangd9883542010-07-08 19:46:26 -070097 struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
Krishna Gudipati82794a22010-03-03 17:43:30 -080098
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070099 for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
Krishna Gudipati82794a22010-03-03 17:43:30 -0800100 mod = &fcs_modules[i];
101 if (mod->modinit)
102 mod->modinit(fcs);
Jing Huang7725ccf2009-09-23 17:46:15 -0700103 }
Jing Huangd9883542010-07-08 19:46:26 -0700104 /* Initialize pbc vports */
105 if (!fcs->min_cfg) {
106 npbc_vports =
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700107 bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
Jing Huangd9883542010-07-08 19:46:26 -0700108 for (i = 0; i < npbc_vports; i++)
109 bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
110 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700111}
112
Jing Huang7725ccf2009-09-23 17:46:15 -0700113
Jing Huang5fbe25c2010-10-18 17:17:23 -0700114/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700115 * brief
116 * FCS driver details initialization.
Jing Huang7725ccf2009-09-23 17:46:15 -0700117 *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700118 * param[in] fcs FCS instance
119 * param[in] driver_info Driver Details
Jing Huang7725ccf2009-09-23 17:46:15 -0700120 *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700121 * return None
Jing Huang7725ccf2009-09-23 17:46:15 -0700122 */
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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700133/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700134 * brief
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700135 * FCS instance cleanup and exit.
Jing Huang7725ccf2009-09-23 17:46:15 -0700136 *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700137 * param[in] fcs FCS instance
138 * return None
Jing Huang7725ccf2009-09-23 17:46:15 -0700139 */
140void
141bfa_fcs_exit(struct bfa_fcs_s *fcs)
142{
143 struct bfa_fcs_mod_s *mod;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700144 int nmods, i;
Jing Huang7725ccf2009-09-23 17:46:15 -0700145
146 bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
147
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700148 nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
149
150 for (i = 0; i < nmods; i++) {
Jing Huang7725ccf2009-09-23 17:46:15 -0700151
152 mod = &fcs_modules[i];
Krishna Gudipati82794a22010-03-03 17:43:30 -0800153 if (mod->modexit) {
154 bfa_wc_up(&fcs->wc);
155 mod->modexit(fcs);
156 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700157 }
158
159 bfa_wc_wait(&fcs->wc);
160}
161
162
Jing Huang5fbe25c2010-10-18 17:17:23 -0700163/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700164 * Fabric module implementation.
165 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700166
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700167#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);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700199
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);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700212static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
213 enum bfa_fcs_fabric_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700214static 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);
Jing Huang5fbe25c2010-10-18 17:17:23 -0700222/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700223 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700248/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700249 * 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:
Krishna Gudipatidd5aaf42011-06-13 15:51:24 -0700272 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
273 bfa_fcs_fabric_delete(fabric);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700274 break;
275
276 default:
277 bfa_sm_fault(fabric->fcs, event);
278 }
279}
280
Jing Huang5fbe25c2010-10-18 17:17:23 -0700281/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700282 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700311/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700312 * 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);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800346 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700347 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);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800360 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700361 break;
362
363 case BFA_FCS_FABRIC_SM_DELETE:
364 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800365 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700366 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700404/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700405 * 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);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800417 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700418 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);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800431 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700432 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700444/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700445 * Authentication failed
446 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800447void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700448bfa_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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700470/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700471 * Port is in loopback mode.
472 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800473void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700474bfa_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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700496/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700497 * 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);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800509 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700510 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700529/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700530 * Fabric is online - normal operating state.
531 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800532void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700533bfa_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);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800542 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700543 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);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800553 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700554 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700564/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700565 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700588/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700589 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700599/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700600 * 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
Jing Huang88166242010-12-09 17:11:53 -0800613 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700614 "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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700620/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700621 * 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)
626{
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);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800633 bfa_wc_down(&fabric->fcs->wc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700634 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 }
646}
647
648
649
Jing Huang5fbe25c2010-10-18 17:17:23 -0700650/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700651 * 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;
Maggie Zhangf7f73812010-12-09 19:08:43 -0800660 port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn;
661 port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700662}
663
Jing Huang5fbe25c2010-10-18 17:17:23 -0700664/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700665 * Port Symbolic Name Creation for base port.
666 */
667void
668bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
669{
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;
723}
724
Jing Huang5fbe25c2010-10-18 17:17:23 -0700725/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700726 * bfa lps login completion callback
727 */
728void
729bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
730{
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:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800749 switch (fabric->lps->ext_status) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700750 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
Maggie Zhangf7f73812010-12-09 19:08:43 -0800776 fabric->bb_credit = fabric->lps->pr_bbcred;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700777 bfa_trc(fabric->fcs, fabric->bb_credit);
778
Maggie Zhangf7f73812010-12-09 19:08:43 -0800779 if (!(fabric->lps->brcd_switch))
780 fabric->fabric_name = fabric->lps->pr_nwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700781
782 /*
783 * Check port type. It should be 1 = F-port.
784 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800785 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;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700789 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 =
Maggie Zhangf7f73812010-12-09 19:08:43 -0800795 fabric->lps->pr_pwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700796 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}
Jing Huang5fbe25c2010-10-18 17:17:23 -0700803/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700804 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700833 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700834 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700853 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700854 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700875/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700876 * 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);
891}
892
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}
900
Jing Huang5fbe25c2010-10-18 17:17:23 -0700901/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700902 * fcs_fabric_public fabric public functions
903 */
904
Jing Huang5fbe25c2010-10-18 17:17:23 -0700905/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700906 * 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;
Jing Huang6a18b162010-10-18 17:08:54 -0700914 memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700915
Jing Huang5fbe25c2010-10-18 17:17:23 -0700916 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700917 * 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);
Jing Huangd4b671c2010-12-26 21:46:35 -0800923 WARN_ON(!fabric->lps);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700924
Jing Huang5fbe25c2010-10-18 17:17:23 -0700925 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700926 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700943/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700944 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700953 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700954 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700961/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700962 * 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
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700974
Jing Huang5fbe25c2010-10-18 17:17:23 -0700975/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700976 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700985/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700986 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -0700995/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700996 * 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{
Jing Huang5fbe25c2010-10-18 17:17:23 -07001010 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001011 * - 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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001020/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001021 * 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
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001034
Jing Huang5fbe25c2010-10-18 17:17:23 -07001035/*
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001036 * Lookup for a vport within a fabric given its pwwn
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001037 */
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
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001053
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
Maggie Zhangf7f73812010-12-09 19:08:43 -08001072 fab_nwwn = fabric->lps->pr_nwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001073
1074 tmp = (u8 *)&fab_nwwn;
1075 oui = (tmp[3] << 8) | tmp[4];
1076
1077 return oui;
1078}
Jing Huang5fbe25c2010-10-18 17:17:23 -07001079/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001080 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001095 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001096 * 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 */
Maggie Zhangf16a1752010-12-09 19:12:32 -08001100 if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001101 (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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001107 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001108 * FLOGI/EVFP exchanges should be consumed by base fabric.
1109 */
Maggie Zhangf16a1752010-12-09 19:12:32 -08001110 if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001111 bfa_trc(fabric->fcs, pid);
1112 bfa_fcs_fabric_process_uf(fabric, fchs, len);
1113 return;
1114 }
1115
1116 if (fabric->bport.pid == pid) {
Jing Huang5fbe25c2010-10-18 17:17:23 -07001117 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001118 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001131 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001132 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001145/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001146 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001169/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001170 * 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
Jing Huangba816ea2010-10-18 17:10:50 -07001194 fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001195 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);
Jing Huang5fbe25c2010-10-18 17:17:23 -07001216 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001217 * 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),
Maggie Zhangf16a1752010-12-09 19:12:32 -08001223 bfa_hton3b(FC_FABRIC_PORT),
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001224 n2n_port->reply_oxid, pcfg->pwwn,
1225 pcfg->nwwn,
1226 bfa_fcport_get_maxfrsize(bfa),
1227 bfa_fcport_get_rx_bbcredit(bfa));
1228
Maggie Zhangf7f73812010-12-09 19:08:43 -08001229 bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001230 BFA_FALSE, FC_CLASS_3,
1231 reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
1232 FC_MAX_PDUSZ, 0);
1233}
1234
Jing Huang5fbe25c2010-10-18 17:17:23 -07001235/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001236 * 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));
Jing Huang88166242010-12-09 17:11:53 -08001276 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001277 "Base port WWN = %s Fabric WWN = %s\n",
1278 pwwn_ptr, fwwn_ptr);
1279 }
1280}
1281
Jing Huang5fbe25c2010-10-18 17:17:23 -07001282/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001283 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001300/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001301 * 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:
Jing Huangd4b671c2010-12-26 21:46:35 -08001320 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001321 }
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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001330/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001331 * BFA FCS UF ( Unsolicited Frames)
1332 */
1333
Jing Huang5fbe25c2010-10-18 17:17:23 -07001334/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001335 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001351 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001352 * 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
Jing Huang5fbe25c2010-10-18 17:17:23 -07001363 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001364 * drop frame if vfid is unknown
1365 */
1366 if (!fabric) {
Jing Huangd4b671c2010-12-26 21:46:35 -08001367 WARN_ON(1);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001368 bfa_stats(fcs, uf.vfid_unknown);
1369 bfa_uf_free(uf);
1370 return;
1371 }
1372
Jing Huang5fbe25c2010-10-18 17:17:23 -07001373 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001374 * 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}