blob: 5e8c8dee6c97dc946d716eb57a0bee1d4d6436e5 [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);
160 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer,
161 bfa_fcs_port_ms_timeout, ms,
162 BFA_FCS_RETRY_TIMEOUT);
163 break;
164
165 case MSSM_EVENT_RSP_OK:
166 /*
167 * since plogi is done, now invoke MS related sub-modules
168 */
169 bfa_fcs_port_fdmi_online(ms);
170
171 /**
172 * if this is a Vport, go to online state.
173 */
174 if (ms->port->vport) {
175 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
176 break;
177 }
178
179 /*
180 * For a base port we need to get the
181 * switch's IP address.
182 */
183 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
184 bfa_fcs_port_ms_send_gmal(ms, NULL);
185 break;
186
187 case MSSM_EVENT_PORT_OFFLINE:
188 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
189 bfa_fcxp_discard(ms->fcxp);
190 break;
191
192 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800193 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700194 }
195}
196
197static void
198bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
199 enum port_ms_event event)
200{
201 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
202 bfa_trc(ms->port->fcs, event);
203
204 switch (event) {
205 case MSSM_EVENT_TIMEOUT:
206 /*
207 * Retry Timer Expired. Re-send
208 */
209 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
210 bfa_fcs_port_ms_send_plogi(ms, NULL);
211 break;
212
213 case MSSM_EVENT_PORT_OFFLINE:
214 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
215 bfa_timer_stop(&ms->timer);
216 break;
217
218 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800219 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700220 }
221}
222
223static void
224bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
225 enum port_ms_event event)
226{
227 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
228 bfa_trc(ms->port->fcs, event);
229
230 switch (event) {
231 case MSSM_EVENT_PORT_OFFLINE:
232 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
Jing Huang7725ccf2009-09-23 17:46:15 -0700233 break;
234
235 case MSSM_EVENT_PORT_FABRIC_RSCN:
236 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
237 ms->retry_cnt = 0;
238 bfa_fcs_port_ms_send_gfn(ms, NULL);
239 break;
240
241 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800242 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700243 }
244}
245
246static void
247bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
248 enum port_ms_event event)
249{
250 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
251 bfa_trc(ms->port->fcs, event);
252
253 switch (event) {
254 case MSSM_EVENT_FCXP_SENT:
255 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal);
256 break;
257
258 case MSSM_EVENT_PORT_OFFLINE:
259 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
260 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
261 &ms->fcxp_wqe);
262 break;
263
264 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800265 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700266 }
267}
268
269static void
270bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
271{
272 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
273 bfa_trc(ms->port->fcs, event);
274
275 switch (event) {
276 case MSSM_EVENT_RSP_ERROR:
277 /*
278 * Start timer for a delayed retry
279 */
280 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
281 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry);
282 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
283 &ms->timer, bfa_fcs_port_ms_timeout, ms,
284 BFA_FCS_RETRY_TIMEOUT);
285 } else {
286 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
287 bfa_fcs_port_ms_send_gfn(ms, NULL);
288 ms->retry_cnt = 0;
289 }
290 break;
291
292 case MSSM_EVENT_RSP_OK:
293 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
294 bfa_fcs_port_ms_send_gfn(ms, NULL);
295 break;
296
297 case MSSM_EVENT_PORT_OFFLINE:
298 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
299 bfa_fcxp_discard(ms->fcxp);
300 break;
301
302 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800303 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700304 }
305}
306
307static void
308bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
309 enum port_ms_event event)
310{
311 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
312 bfa_trc(ms->port->fcs, event);
313
314 switch (event) {
315 case MSSM_EVENT_TIMEOUT:
316 /*
317 * Retry Timer Expired. Re-send
318 */
319 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
320 bfa_fcs_port_ms_send_gmal(ms, NULL);
321 break;
322
323 case MSSM_EVENT_PORT_OFFLINE:
324 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
325 bfa_timer_stop(&ms->timer);
326 break;
327
328 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800329 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700330 }
331}
332
333/**
334 * ms_pvt MS local functions
335 */
336
337static void
338bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
339{
340 struct bfa_fcs_port_ms_s *ms = ms_cbarg;
341 struct bfa_fcs_port_s *port = ms->port;
342 struct fchs_s fchs;
343 int len;
344 struct bfa_fcxp_s *fcxp;
345
346 bfa_trc(port->fcs, port->pid);
347
348 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
349 if (!fcxp) {
350 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
351 bfa_fcs_port_ms_send_gmal, ms);
352 return;
353 }
354 ms->fcxp = fcxp;
355
356 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
357 bfa_fcs_port_get_fcid(port),
358 bfa_lps_get_peer_nwwn(port->fabric->lps));
359
360 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
361 FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response,
362 (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
363
364 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
365}
366
367static void
368bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
369 void *cbarg, bfa_status_t req_status,
370 u32 rsp_len, u32 resid_len,
371 struct fchs_s *rsp_fchs)
372{
373 struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
374 struct bfa_fcs_port_s *port = ms->port;
375 struct ct_hdr_s *cthdr = NULL;
376 struct fcgs_gmal_resp_s *gmal_resp;
377 struct fc_gmal_entry_s *gmal_entry;
378 u32 num_entries;
379 u8 *rsp_str;
380
381 bfa_trc(port->fcs, req_status);
382 bfa_trc(port->fcs, port->port_cfg.pwwn);
383
384 /*
385 * Sanity Checks
386 */
387 if (req_status != BFA_STATUS_OK) {
388 bfa_trc(port->fcs, req_status);
389 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
390 return;
391 }
392
393 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
394 cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
395
396 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
397 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
398 num_entries = bfa_os_ntohl(gmal_resp->ms_len);
399 if (num_entries == 0) {
400 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
401 return;
402 }
403 /*
404 * The response could contain multiple Entries.
405 * Entries for SNMP interface, etc.
406 * We look for the entry with a telnet prefix.
407 * First "http://" entry refers to IP addr
408 */
409
410 gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma;
411 while (num_entries > 0) {
412 if (strncmp
413 (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP,
414 sizeof(gmal_entry->prefix)) == 0) {
415
416 /*
417 * if the IP address is terminating with a '/',
418 * remove it. *Byte 0 consists of the length
419 * of the string.
420 */
421 rsp_str = &(gmal_entry->prefix[0]);
422 if (rsp_str[gmal_entry->len - 1] == '/')
423 rsp_str[gmal_entry->len - 1] = 0;
424 /*
425 * copy IP Address to fabric
426 */
427 strncpy(bfa_fcs_port_get_fabric_ipaddr(port),
428 gmal_entry->ip_addr,
429 BFA_FCS_FABRIC_IPADDR_SZ);
430 break;
431 } else {
432 --num_entries;
433 ++gmal_entry;
434 }
435 }
436
437 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
438 return;
439 }
440
441 bfa_trc(port->fcs, cthdr->reason_code);
442 bfa_trc(port->fcs, cthdr->exp_code);
443 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
444}
445
446static void
447bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
448 enum port_ms_event event)
449{
450 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
451 bfa_trc(ms->port->fcs, event);
452
453 switch (event) {
454 case MSSM_EVENT_FCXP_SENT:
455 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn);
456 break;
457
458 case MSSM_EVENT_PORT_OFFLINE:
459 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
460 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
461 &ms->fcxp_wqe);
462 break;
463
464 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800465 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700466 }
467}
468
469static void
470bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
471{
472 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
473 bfa_trc(ms->port->fcs, event);
474
475 switch (event) {
476 case MSSM_EVENT_RSP_ERROR:
477 /*
478 * Start timer for a delayed retry
479 */
480 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
481 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry);
482 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
483 &ms->timer, bfa_fcs_port_ms_timeout, ms,
484 BFA_FCS_RETRY_TIMEOUT);
485 } else {
486 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
487 ms->retry_cnt = 0;
488 }
489 break;
490
491 case MSSM_EVENT_RSP_OK:
492 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
493 break;
494
495 case MSSM_EVENT_PORT_OFFLINE:
496 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
497 bfa_fcxp_discard(ms->fcxp);
498 break;
499
500 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800501 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700502 }
503}
504
505static void
506bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
507 enum port_ms_event event)
508{
509 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
510 bfa_trc(ms->port->fcs, event);
511
512 switch (event) {
513 case MSSM_EVENT_TIMEOUT:
514 /*
515 * Retry Timer Expired. Re-send
516 */
517 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
518 bfa_fcs_port_ms_send_gfn(ms, NULL);
519 break;
520
521 case MSSM_EVENT_PORT_OFFLINE:
522 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
523 bfa_timer_stop(&ms->timer);
524 break;
525
526 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800527 bfa_sm_fault(ms->port->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700528 }
529}
530
531/**
532 * ms_pvt MS local functions
533 */
534
535static void
536bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
537{
538 struct bfa_fcs_port_ms_s *ms = ms_cbarg;
539 struct bfa_fcs_port_s *port = ms->port;
540 struct fchs_s fchs;
541 int len;
542 struct bfa_fcxp_s *fcxp;
543
544 bfa_trc(port->fcs, port->pid);
545
546 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
547 if (!fcxp) {
548 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
549 bfa_fcs_port_ms_send_gfn, ms);
550 return;
551 }
552 ms->fcxp = fcxp;
553
554 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
555 bfa_fcs_port_get_fcid(port),
556 bfa_lps_get_peer_nwwn(port->fabric->lps));
557
558 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
559 FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response,
560 (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
561
562 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
563}
564
565static void
566bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
567 bfa_status_t req_status, u32 rsp_len,
568 u32 resid_len, struct fchs_s *rsp_fchs)
569{
570 struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
571 struct bfa_fcs_port_s *port = ms->port;
572 struct ct_hdr_s *cthdr = NULL;
573 wwn_t *gfn_resp;
574
575 bfa_trc(port->fcs, req_status);
576 bfa_trc(port->fcs, port->port_cfg.pwwn);
577
578 /*
579 * Sanity Checks
580 */
581 if (req_status != BFA_STATUS_OK) {
582 bfa_trc(port->fcs, req_status);
583 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
584 return;
585 }
586
587 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
588 cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
589
590 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
591 gfn_resp = (wwn_t *) (cthdr + 1);
592 /*
593 * check if it has actually changed
594 */
595 if ((memcmp
596 ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp,
597 sizeof(wwn_t)) != 0))
598 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
599 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
600 return;
601 }
602
603 bfa_trc(port->fcs, cthdr->reason_code);
604 bfa_trc(port->fcs, cthdr->exp_code);
605 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
606}
607
608/**
609 * ms_pvt MS local functions
610 */
611
612static void
613bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
614{
615 struct bfa_fcs_port_ms_s *ms = ms_cbarg;
616 struct bfa_fcs_port_s *port = ms->port;
617 struct fchs_s fchs;
618 int len;
619 struct bfa_fcxp_s *fcxp;
620
621 bfa_trc(port->fcs, port->pid);
622
623 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
624 if (!fcxp) {
625 port->stats.ms_plogi_alloc_wait++;
626 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
627 bfa_fcs_port_ms_send_plogi, ms);
628 return;
629 }
630 ms->fcxp = fcxp;
631
632 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
633 bfa_os_hton3b(FC_MGMT_SERVER),
634 bfa_fcs_port_get_fcid(port), 0,
635 port->port_cfg.pwwn, port->port_cfg.nwwn,
Krishna Gudipati1c8a4c32010-03-05 19:37:37 -0800636 bfa_fcport_get_maxfrsize(port->fcs->bfa));
Jing Huang7725ccf2009-09-23 17:46:15 -0700637
638 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
639 FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response,
640 (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
641
642 port->stats.ms_plogi_sent++;
643 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
644}
645
646static void
647bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
648 void *cbarg, bfa_status_t req_status,
649 u32 rsp_len, u32 resid_len,
650 struct fchs_s *rsp_fchs)
651{
652 struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
653
654 struct bfa_fcs_port_s *port = ms->port;
655 struct fc_els_cmd_s *els_cmd;
656 struct fc_ls_rjt_s *ls_rjt;
657
658 bfa_trc(port->fcs, req_status);
659 bfa_trc(port->fcs, port->port_cfg.pwwn);
660
661 /*
662 * Sanity Checks
663 */
664 if (req_status != BFA_STATUS_OK) {
665 port->stats.ms_plogi_rsp_err++;
666 bfa_trc(port->fcs, req_status);
667 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
668 return;
669 }
670
671 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
672
673 switch (els_cmd->els_code) {
674
675 case FC_ELS_ACC:
676 if (rsp_len < sizeof(struct fc_logi_s)) {
677 bfa_trc(port->fcs, rsp_len);
678 port->stats.ms_plogi_acc_err++;
679 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
680 break;
681 }
682 port->stats.ms_plogi_accepts++;
683 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
684 break;
685
686 case FC_ELS_LS_RJT:
687 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
688
689 bfa_trc(port->fcs, ls_rjt->reason_code);
690 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
691
692 port->stats.ms_rejects++;
693 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
694 break;
695
696 default:
697 port->stats.ms_plogi_unknown_rsp++;
698 bfa_trc(port->fcs, els_cmd->els_code);
699 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
700 }
701}
702
703static void
704bfa_fcs_port_ms_timeout(void *arg)
705{
706 struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg;
707
708 ms->port->stats.ms_timeouts++;
709 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
710}
711
712
713void
714bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port)
715{
716 struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
717
718 ms->port = port;
719 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
720
721 /*
722 * Invoke init routines of sub modules.
723 */
724 bfa_fcs_port_fdmi_init(ms);
725}
726
727void
728bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port)
729{
730 struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
731
732 ms->port = port;
733 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
Krishna Gudipati25e29342010-03-05 19:38:17 -0800734 bfa_fcs_port_fdmi_offline(ms);
Jing Huang7725ccf2009-09-23 17:46:15 -0700735}
736
737void
738bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port)
739{
740 struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
741
742 ms->port = port;
743 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
744}
745
746void
747bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port)
748{
749 struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
750
751 /*
752 * @todo. Handle this only when in Online state
753 */
754 if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online))
755 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
756}