blob: 1d579ef261227a80517cf7f0f1b9a2144205d78b [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3 * All rights reserved
4 * www.brocade.com
5 *
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17
18
19#include <bfa.h>
20#include <bfa_svc.h>
21#include "fcs_lport.h"
22#include "fcs_rport.h"
23#include "fcs_trcmod.h"
24#include "fcs_fcxp.h"
25#include "lport_priv.h"
26
27BFA_TRC_FILE(FCS, MS);
28
29#define BFA_FCS_MS_CMD_MAX_RETRIES 2
30/*
31 * forward declarations
32 */
33static void bfa_fcs_port_ms_send_plogi(void *ms_cbarg,
34 struct bfa_fcxp_s *fcxp_alloced);
35static void bfa_fcs_port_ms_timeout(void *arg);
36static void bfa_fcs_port_ms_plogi_response(void *fcsarg,
37 struct bfa_fcxp_s *fcxp,
38 void *cbarg,
39 bfa_status_t req_status,
40 u32 rsp_len,
41 u32 resid_len,
42 struct fchs_s *rsp_fchs);
43
44static void bfa_fcs_port_ms_send_gmal(void *ms_cbarg,
45 struct bfa_fcxp_s *fcxp_alloced);
46static void bfa_fcs_port_ms_gmal_response(void *fcsarg,
47 struct bfa_fcxp_s *fcxp,
48 void *cbarg,
49 bfa_status_t req_status,
50 u32 rsp_len,
51 u32 resid_len,
52 struct fchs_s *rsp_fchs);
53static void bfa_fcs_port_ms_send_gfn(void *ms_cbarg,
54 struct bfa_fcxp_s *fcxp_alloced);
55static void bfa_fcs_port_ms_gfn_response(void *fcsarg,
56 struct bfa_fcxp_s *fcxp,
57 void *cbarg,
58 bfa_status_t req_status,
59 u32 rsp_len,
60 u32 resid_len,
61 struct fchs_s *rsp_fchs);
62/**
63 * fcs_ms_sm FCS MS state machine
64 */
65
66/**
67 * MS State Machine events
68 */
69enum port_ms_event {
70 MSSM_EVENT_PORT_ONLINE = 1,
71 MSSM_EVENT_PORT_OFFLINE = 2,
72 MSSM_EVENT_RSP_OK = 3,
73 MSSM_EVENT_RSP_ERROR = 4,
74 MSSM_EVENT_TIMEOUT = 5,
75 MSSM_EVENT_FCXP_SENT = 6,
76 MSSM_EVENT_PORT_FABRIC_RSCN = 7
77};
78
79static void bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
80 enum port_ms_event event);
81static void bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
82 enum port_ms_event event);
83static void bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms,
84 enum port_ms_event event);
85static void bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
86 enum port_ms_event event);
87static void bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
88 enum port_ms_event event);
89static void bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms,
90 enum port_ms_event event);
91static void bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
92 enum port_ms_event event);
93static void bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
94 enum port_ms_event event);
95static void bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms,
96 enum port_ms_event event);
97static void bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
98 enum port_ms_event event);
99static void bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
100 enum port_ms_event event);
101/**
102 * Start in offline state - awaiting NS to send start.
103 */
104static void
105bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
106 enum port_ms_event event)
107{
108 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
109 bfa_trc(ms->port->fcs, event);
110
111 switch (event) {
112 case MSSM_EVENT_PORT_ONLINE:
113 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
114 bfa_fcs_port_ms_send_plogi(ms, NULL);
115 break;
116
117 case MSSM_EVENT_PORT_OFFLINE:
118 break;
119
120 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800121 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700122 }
123}
124
125static void
126bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
127 enum port_ms_event event)
128{
129 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
130 bfa_trc(ms->port->fcs, event);
131
132 switch (event) {
133 case MSSM_EVENT_FCXP_SENT:
134 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi);
135 break;
136
137 case MSSM_EVENT_PORT_OFFLINE:
138 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
139 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
140 &ms->fcxp_wqe);
141 break;
142
143 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800144 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700145 }
146}
147
148static void
149bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
150{
151 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
152 bfa_trc(ms->port->fcs, event);
153
154 switch (event) {
155 case MSSM_EVENT_RSP_ERROR:
156 /*
157 * Start timer for a delayed retry
158 */
159 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry);
Jing Huangb85d0452010-07-08 19:48:49 -0700160 ms->port->stats.ms_retries++;
Jing Huang7725ccf2009-09-23 17:46:15 -0700161 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer,
162 bfa_fcs_port_ms_timeout, ms,
163 BFA_FCS_RETRY_TIMEOUT);
164 break;
165
166 case MSSM_EVENT_RSP_OK:
167 /*
168 * since plogi is done, now invoke MS related sub-modules
169 */
170 bfa_fcs_port_fdmi_online(ms);
171
172 /**
173 * if this is a Vport, go to online state.
174 */
175 if (ms->port->vport) {
176 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
177 break;
178 }
179
180 /*
181 * For a base port we need to get the
182 * switch's IP address.
183 */
184 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
185 bfa_fcs_port_ms_send_gmal(ms, NULL);
186 break;
187
188 case MSSM_EVENT_PORT_OFFLINE:
189 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
190 bfa_fcxp_discard(ms->fcxp);
191 break;
192
193 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800194 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700195 }
196}
197
198static void
199bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
200 enum port_ms_event event)
201{
202 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
203 bfa_trc(ms->port->fcs, event);
204
205 switch (event) {
206 case MSSM_EVENT_TIMEOUT:
207 /*
208 * Retry Timer Expired. Re-send
209 */
210 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
211 bfa_fcs_port_ms_send_plogi(ms, NULL);
212 break;
213
214 case MSSM_EVENT_PORT_OFFLINE:
215 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
216 bfa_timer_stop(&ms->timer);
217 break;
218
219 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800220 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700221 }
222}
223
224static void
225bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
226 enum port_ms_event event)
227{
228 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
229 bfa_trc(ms->port->fcs, event);
230
231 switch (event) {
232 case MSSM_EVENT_PORT_OFFLINE:
233 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
Jing Huang7725ccf2009-09-23 17:46:15 -0700234 break;
235
236 case MSSM_EVENT_PORT_FABRIC_RSCN:
237 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
238 ms->retry_cnt = 0;
239 bfa_fcs_port_ms_send_gfn(ms, NULL);
240 break;
241
242 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800243 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700244 }
245}
246
247static void
248bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
249 enum port_ms_event event)
250{
251 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
252 bfa_trc(ms->port->fcs, event);
253
254 switch (event) {
255 case MSSM_EVENT_FCXP_SENT:
256 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal);
257 break;
258
259 case MSSM_EVENT_PORT_OFFLINE:
260 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
261 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
262 &ms->fcxp_wqe);
263 break;
264
265 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800266 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700267 }
268}
269
270static void
271bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
272{
273 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
274 bfa_trc(ms->port->fcs, event);
275
276 switch (event) {
277 case MSSM_EVENT_RSP_ERROR:
278 /*
279 * Start timer for a delayed retry
280 */
281 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
282 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry);
Jing Huangb85d0452010-07-08 19:48:49 -0700283 ms->port->stats.ms_retries++;
Jing Huang7725ccf2009-09-23 17:46:15 -0700284 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
285 &ms->timer, bfa_fcs_port_ms_timeout, ms,
286 BFA_FCS_RETRY_TIMEOUT);
287 } else {
288 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
289 bfa_fcs_port_ms_send_gfn(ms, NULL);
290 ms->retry_cnt = 0;
291 }
292 break;
293
294 case MSSM_EVENT_RSP_OK:
295 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
296 bfa_fcs_port_ms_send_gfn(ms, NULL);
297 break;
298
299 case MSSM_EVENT_PORT_OFFLINE:
300 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
301 bfa_fcxp_discard(ms->fcxp);
302 break;
303
304 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800305 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700306 }
307}
308
309static void
310bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
311 enum port_ms_event event)
312{
313 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
314 bfa_trc(ms->port->fcs, event);
315
316 switch (event) {
317 case MSSM_EVENT_TIMEOUT:
318 /*
319 * Retry Timer Expired. Re-send
320 */
321 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
322 bfa_fcs_port_ms_send_gmal(ms, NULL);
323 break;
324
325 case MSSM_EVENT_PORT_OFFLINE:
326 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
327 bfa_timer_stop(&ms->timer);
328 break;
329
330 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800331 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700332 }
333}
334
335/**
336 * ms_pvt MS local functions
337 */
338
339static void
340bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
341{
342 struct bfa_fcs_port_ms_s *ms = ms_cbarg;
343 struct bfa_fcs_port_s *port = ms->port;
344 struct fchs_s fchs;
345 int len;
346 struct bfa_fcxp_s *fcxp;
347
348 bfa_trc(port->fcs, port->pid);
349
350 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
351 if (!fcxp) {
352 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
353 bfa_fcs_port_ms_send_gmal, ms);
354 return;
355 }
356 ms->fcxp = fcxp;
357
358 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
359 bfa_fcs_port_get_fcid(port),
360 bfa_lps_get_peer_nwwn(port->fabric->lps));
361
362 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
363 FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response,
Jing Huang4f1806b2010-07-08 19:50:15 -0700364 (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
Jing Huang7725ccf2009-09-23 17:46:15 -0700365
366 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
367}
368
369static void
370bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
371 void *cbarg, bfa_status_t req_status,
372 u32 rsp_len, u32 resid_len,
373 struct fchs_s *rsp_fchs)
374{
375 struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
376 struct bfa_fcs_port_s *port = ms->port;
377 struct ct_hdr_s *cthdr = NULL;
378 struct fcgs_gmal_resp_s *gmal_resp;
379 struct fc_gmal_entry_s *gmal_entry;
380 u32 num_entries;
381 u8 *rsp_str;
382
383 bfa_trc(port->fcs, req_status);
384 bfa_trc(port->fcs, port->port_cfg.pwwn);
385
386 /*
387 * Sanity Checks
388 */
389 if (req_status != BFA_STATUS_OK) {
390 bfa_trc(port->fcs, req_status);
391 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
392 return;
393 }
394
395 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
396 cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
397
398 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
399 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
400 num_entries = bfa_os_ntohl(gmal_resp->ms_len);
401 if (num_entries == 0) {
402 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
403 return;
404 }
405 /*
406 * The response could contain multiple Entries.
407 * Entries for SNMP interface, etc.
408 * We look for the entry with a telnet prefix.
409 * First "http://" entry refers to IP addr
410 */
411
412 gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma;
413 while (num_entries > 0) {
414 if (strncmp
415 (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP,
416 sizeof(gmal_entry->prefix)) == 0) {
417
418 /*
419 * if the IP address is terminating with a '/',
420 * remove it. *Byte 0 consists of the length
421 * of the string.
422 */
423 rsp_str = &(gmal_entry->prefix[0]);
424 if (rsp_str[gmal_entry->len - 1] == '/')
425 rsp_str[gmal_entry->len - 1] = 0;
426 /*
427 * copy IP Address to fabric
428 */
429 strncpy(bfa_fcs_port_get_fabric_ipaddr(port),
430 gmal_entry->ip_addr,
431 BFA_FCS_FABRIC_IPADDR_SZ);
432 break;
433 } else {
434 --num_entries;
435 ++gmal_entry;
436 }
437 }
438
439 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
440 return;
441 }
442
443 bfa_trc(port->fcs, cthdr->reason_code);
444 bfa_trc(port->fcs, cthdr->exp_code);
445 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
446}
447
448static void
449bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
450 enum port_ms_event event)
451{
452 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
453 bfa_trc(ms->port->fcs, event);
454
455 switch (event) {
456 case MSSM_EVENT_FCXP_SENT:
457 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn);
458 break;
459
460 case MSSM_EVENT_PORT_OFFLINE:
461 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
462 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
463 &ms->fcxp_wqe);
464 break;
465
466 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800467 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700468 }
469}
470
471static void
472bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
473{
474 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
475 bfa_trc(ms->port->fcs, event);
476
477 switch (event) {
478 case MSSM_EVENT_RSP_ERROR:
479 /*
480 * Start timer for a delayed retry
481 */
482 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
483 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry);
Jing Huangb85d0452010-07-08 19:48:49 -0700484 ms->port->stats.ms_retries++;
Jing Huang7725ccf2009-09-23 17:46:15 -0700485 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
486 &ms->timer, bfa_fcs_port_ms_timeout, ms,
487 BFA_FCS_RETRY_TIMEOUT);
488 } else {
489 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
490 ms->retry_cnt = 0;
491 }
492 break;
493
494 case MSSM_EVENT_RSP_OK:
495 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
496 break;
497
498 case MSSM_EVENT_PORT_OFFLINE:
499 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
500 bfa_fcxp_discard(ms->fcxp);
501 break;
502
503 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800504 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700505 }
506}
507
508static void
509bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
510 enum port_ms_event event)
511{
512 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
513 bfa_trc(ms->port->fcs, event);
514
515 switch (event) {
516 case MSSM_EVENT_TIMEOUT:
517 /*
518 * Retry Timer Expired. Re-send
519 */
520 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
521 bfa_fcs_port_ms_send_gfn(ms, NULL);
522 break;
523
524 case MSSM_EVENT_PORT_OFFLINE:
525 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
526 bfa_timer_stop(&ms->timer);
527 break;
528
529 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800530 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700531 }
532}
533
534/**
535 * ms_pvt MS local functions
536 */
537
538static void
539bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
540{
541 struct bfa_fcs_port_ms_s *ms = ms_cbarg;
542 struct bfa_fcs_port_s *port = ms->port;
543 struct fchs_s fchs;
544 int len;
545 struct bfa_fcxp_s *fcxp;
546
547 bfa_trc(port->fcs, port->pid);
548
549 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
550 if (!fcxp) {
551 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
552 bfa_fcs_port_ms_send_gfn, ms);
553 return;
554 }
555 ms->fcxp = fcxp;
556
557 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
558 bfa_fcs_port_get_fcid(port),
559 bfa_lps_get_peer_nwwn(port->fabric->lps));
560
561 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
562 FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response,
Jing Huang4f1806b2010-07-08 19:50:15 -0700563 (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
Jing Huang7725ccf2009-09-23 17:46:15 -0700564
565 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
566}
567
568static void
569bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
570 bfa_status_t req_status, u32 rsp_len,
571 u32 resid_len, struct fchs_s *rsp_fchs)
572{
573 struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
574 struct bfa_fcs_port_s *port = ms->port;
575 struct ct_hdr_s *cthdr = NULL;
576 wwn_t *gfn_resp;
577
578 bfa_trc(port->fcs, req_status);
579 bfa_trc(port->fcs, port->port_cfg.pwwn);
580
581 /*
582 * Sanity Checks
583 */
584 if (req_status != BFA_STATUS_OK) {
585 bfa_trc(port->fcs, req_status);
586 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
587 return;
588 }
589
590 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
591 cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
592
593 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
594 gfn_resp = (wwn_t *) (cthdr + 1);
595 /*
596 * check if it has actually changed
597 */
598 if ((memcmp
599 ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp,
600 sizeof(wwn_t)) != 0))
601 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
602 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
603 return;
604 }
605
606 bfa_trc(port->fcs, cthdr->reason_code);
607 bfa_trc(port->fcs, cthdr->exp_code);
608 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
609}
610
611/**
612 * ms_pvt MS local functions
613 */
614
615static void
616bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
617{
618 struct bfa_fcs_port_ms_s *ms = ms_cbarg;
619 struct bfa_fcs_port_s *port = ms->port;
620 struct fchs_s fchs;
621 int len;
622 struct bfa_fcxp_s *fcxp;
623
624 bfa_trc(port->fcs, port->pid);
625
626 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
627 if (!fcxp) {
628 port->stats.ms_plogi_alloc_wait++;
629 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
630 bfa_fcs_port_ms_send_plogi, ms);
631 return;
632 }
633 ms->fcxp = fcxp;
634
635 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
636 bfa_os_hton3b(FC_MGMT_SERVER),
637 bfa_fcs_port_get_fcid(port), 0,
638 port->port_cfg.pwwn, port->port_cfg.nwwn,
Krishna Gudipati1c8a4c32010-03-05 19:37:37 -0800639 bfa_fcport_get_maxfrsize(port->fcs->bfa));
Jing Huang7725ccf2009-09-23 17:46:15 -0700640
641 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
642 FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response,
Jing Huang4f1806b2010-07-08 19:50:15 -0700643 (void *)ms, FC_MAX_PDUSZ, FC_ELS_TOV);
Jing Huang7725ccf2009-09-23 17:46:15 -0700644
645 port->stats.ms_plogi_sent++;
646 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
647}
648
649static void
650bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
651 void *cbarg, bfa_status_t req_status,
652 u32 rsp_len, u32 resid_len,
653 struct fchs_s *rsp_fchs)
654{
655 struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
656
657 struct bfa_fcs_port_s *port = ms->port;
658 struct fc_els_cmd_s *els_cmd;
659 struct fc_ls_rjt_s *ls_rjt;
660
661 bfa_trc(port->fcs, req_status);
662 bfa_trc(port->fcs, port->port_cfg.pwwn);
663
664 /*
665 * Sanity Checks
666 */
667 if (req_status != BFA_STATUS_OK) {
668 port->stats.ms_plogi_rsp_err++;
669 bfa_trc(port->fcs, req_status);
670 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
671 return;
672 }
673
674 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
675
676 switch (els_cmd->els_code) {
677
678 case FC_ELS_ACC:
679 if (rsp_len < sizeof(struct fc_logi_s)) {
680 bfa_trc(port->fcs, rsp_len);
681 port->stats.ms_plogi_acc_err++;
682 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
683 break;
684 }
685 port->stats.ms_plogi_accepts++;
686 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
687 break;
688
689 case FC_ELS_LS_RJT:
690 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
691
692 bfa_trc(port->fcs, ls_rjt->reason_code);
693 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
694
695 port->stats.ms_rejects++;
696 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
697 break;
698
699 default:
700 port->stats.ms_plogi_unknown_rsp++;
701 bfa_trc(port->fcs, els_cmd->els_code);
702 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
703 }
704}
705
706static void
707bfa_fcs_port_ms_timeout(void *arg)
708{
709 struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg;
710
711 ms->port->stats.ms_timeouts++;
712 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
713}
714
715
716void
717bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port)
718{
719 struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
720
721 ms->port = port;
722 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
723
724 /*
725 * Invoke init routines of sub modules.
726 */
727 bfa_fcs_port_fdmi_init(ms);
728}
729
730void
731bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port)
732{
733 struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
734
735 ms->port = port;
736 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
Krishna Gudipati25e29342010-03-05 19:38:17 -0800737 bfa_fcs_port_fdmi_offline(ms);
Jing Huang7725ccf2009-09-23 17:46:15 -0700738}
739
740void
741bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port)
742{
743 struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
744
745 ms->port = port;
746 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
747}
748
749void
750bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port)
751{
752 struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
753
754 /*
755 * @todo. Handle this only when in Online state
756 */
757 if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online))
758 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
759}