Merge remote branch 'jwb/next' into next
[deliverable/linux.git] / drivers / scsi / bfa / bfa_fcs_lport.c
1 /*
2 * Copyright (c) 2005-2010 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 #include "bfad_drv.h"
19 #include "bfa_fcs.h"
20 #include "bfa_fcbuild.h"
21 #include "bfa_fc.h"
22
23 BFA_TRC_FILE(FCS, PORT);
24
25 static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
26 struct fchs_s *rx_fchs, u8 reason_code,
27 u8 reason_code_expl);
28 static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
29 struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
30 static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
31 static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
32 static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
33 static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
34 static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
35 static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
36 static void bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
37 struct fchs_s *rx_fchs,
38 struct fc_echo_s *echo, u16 len);
39 static void bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
40 struct fchs_s *rx_fchs,
41 struct fc_rnid_cmd_s *rnid, u16 len);
42 static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
43 struct fc_rnid_general_topology_data_s *gen_topo_data);
44
45 static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
46 static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
47 static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
48
49 static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
50 static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
51 static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
52
53 static struct {
54 void (*init) (struct bfa_fcs_lport_s *port);
55 void (*online) (struct bfa_fcs_lport_s *port);
56 void (*offline) (struct bfa_fcs_lport_s *port);
57 } __port_action[] = {
58 {
59 bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
60 bfa_fcs_lport_unknown_offline}, {
61 bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
62 bfa_fcs_lport_fab_offline}, {
63 bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
64 bfa_fcs_lport_n2n_offline},
65 };
66
67 /*
68 * fcs_port_sm FCS logical port state machine
69 */
70
71 enum bfa_fcs_lport_event {
72 BFA_FCS_PORT_SM_CREATE = 1,
73 BFA_FCS_PORT_SM_ONLINE = 2,
74 BFA_FCS_PORT_SM_OFFLINE = 3,
75 BFA_FCS_PORT_SM_DELETE = 4,
76 BFA_FCS_PORT_SM_DELRPORT = 5,
77 };
78
79 static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
80 enum bfa_fcs_lport_event event);
81 static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
82 enum bfa_fcs_lport_event event);
83 static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
84 enum bfa_fcs_lport_event event);
85 static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
86 enum bfa_fcs_lport_event event);
87 static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
88 enum bfa_fcs_lport_event event);
89
90 static void
91 bfa_fcs_lport_sm_uninit(
92 struct bfa_fcs_lport_s *port,
93 enum bfa_fcs_lport_event event)
94 {
95 bfa_trc(port->fcs, port->port_cfg.pwwn);
96 bfa_trc(port->fcs, event);
97
98 switch (event) {
99 case BFA_FCS_PORT_SM_CREATE:
100 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
101 break;
102
103 default:
104 bfa_sm_fault(port->fcs, event);
105 }
106 }
107
108 static void
109 bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
110 enum bfa_fcs_lport_event event)
111 {
112 bfa_trc(port->fcs, port->port_cfg.pwwn);
113 bfa_trc(port->fcs, event);
114
115 switch (event) {
116 case BFA_FCS_PORT_SM_ONLINE:
117 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
118 bfa_fcs_lport_online_actions(port);
119 break;
120
121 case BFA_FCS_PORT_SM_DELETE:
122 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
123 bfa_fcs_lport_deleted(port);
124 break;
125
126 case BFA_FCS_PORT_SM_OFFLINE:
127 break;
128
129 default:
130 bfa_sm_fault(port->fcs, event);
131 }
132 }
133
134 static void
135 bfa_fcs_lport_sm_online(
136 struct bfa_fcs_lport_s *port,
137 enum bfa_fcs_lport_event event)
138 {
139 struct bfa_fcs_rport_s *rport;
140 struct list_head *qe, *qen;
141
142 bfa_trc(port->fcs, port->port_cfg.pwwn);
143 bfa_trc(port->fcs, event);
144
145 switch (event) {
146 case BFA_FCS_PORT_SM_OFFLINE:
147 bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
148 bfa_fcs_lport_offline_actions(port);
149 break;
150
151 case BFA_FCS_PORT_SM_DELETE:
152
153 __port_action[port->fabric->fab_type].offline(port);
154
155 if (port->num_rports == 0) {
156 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
157 bfa_fcs_lport_deleted(port);
158 } else {
159 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
160 list_for_each_safe(qe, qen, &port->rport_q) {
161 rport = (struct bfa_fcs_rport_s *) qe;
162 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
163 }
164 }
165 break;
166
167 case BFA_FCS_PORT_SM_DELRPORT:
168 break;
169
170 default:
171 bfa_sm_fault(port->fcs, event);
172 }
173 }
174
175 static void
176 bfa_fcs_lport_sm_offline(
177 struct bfa_fcs_lport_s *port,
178 enum bfa_fcs_lport_event event)
179 {
180 struct bfa_fcs_rport_s *rport;
181 struct list_head *qe, *qen;
182
183 bfa_trc(port->fcs, port->port_cfg.pwwn);
184 bfa_trc(port->fcs, event);
185
186 switch (event) {
187 case BFA_FCS_PORT_SM_ONLINE:
188 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
189 bfa_fcs_lport_online_actions(port);
190 break;
191
192 case BFA_FCS_PORT_SM_DELETE:
193 if (port->num_rports == 0) {
194 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
195 bfa_fcs_lport_deleted(port);
196 } else {
197 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
198 list_for_each_safe(qe, qen, &port->rport_q) {
199 rport = (struct bfa_fcs_rport_s *) qe;
200 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
201 }
202 }
203 break;
204
205 case BFA_FCS_PORT_SM_DELRPORT:
206 case BFA_FCS_PORT_SM_OFFLINE:
207 break;
208
209 default:
210 bfa_sm_fault(port->fcs, event);
211 }
212 }
213
214 static void
215 bfa_fcs_lport_sm_deleting(
216 struct bfa_fcs_lport_s *port,
217 enum bfa_fcs_lport_event event)
218 {
219 bfa_trc(port->fcs, port->port_cfg.pwwn);
220 bfa_trc(port->fcs, event);
221
222 switch (event) {
223 case BFA_FCS_PORT_SM_DELRPORT:
224 if (port->num_rports == 0) {
225 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
226 bfa_fcs_lport_deleted(port);
227 }
228 break;
229
230 default:
231 bfa_sm_fault(port->fcs, event);
232 }
233 }
234
235 /*
236 * fcs_port_pvt
237 */
238
239 /*
240 * Send a LS reject
241 */
242 static void
243 bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
244 u8 reason_code, u8 reason_code_expl)
245 {
246 struct fchs_s fchs;
247 struct bfa_fcxp_s *fcxp;
248 struct bfa_rport_s *bfa_rport = NULL;
249 int len;
250
251 bfa_trc(port->fcs, rx_fchs->d_id);
252 bfa_trc(port->fcs, rx_fchs->s_id);
253
254 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
255 if (!fcxp)
256 return;
257
258 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
259 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
260 rx_fchs->ox_id, reason_code, reason_code_expl);
261
262 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
263 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
264 FC_MAX_PDUSZ, 0);
265 }
266
267 /*
268 * Process incoming plogi from a remote port.
269 */
270 static void
271 bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
272 struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
273 {
274 struct bfa_fcs_rport_s *rport;
275
276 bfa_trc(port->fcs, rx_fchs->d_id);
277 bfa_trc(port->fcs, rx_fchs->s_id);
278
279 /*
280 * If min cfg mode is enabled, drop any incoming PLOGIs
281 */
282 if (__fcs_min_cfg(port->fcs)) {
283 bfa_trc(port->fcs, rx_fchs->s_id);
284 return;
285 }
286
287 if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
288 bfa_trc(port->fcs, rx_fchs->s_id);
289 /*
290 * send a LS reject
291 */
292 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
293 FC_LS_RJT_RSN_PROTOCOL_ERROR,
294 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
295 return;
296 }
297
298 /*
299 * Direct Attach P2P mode : verify address assigned by the r-port.
300 */
301 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
302 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
303 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
304 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
305 /* Address assigned to us cannot be a WKA */
306 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
307 FC_LS_RJT_RSN_PROTOCOL_ERROR,
308 FC_LS_RJT_EXP_INVALID_NPORT_ID);
309 return;
310 }
311 port->pid = rx_fchs->d_id;
312 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
313 }
314
315 /*
316 * First, check if we know the device by pwwn.
317 */
318 rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
319 if (rport) {
320 /*
321 * Direct Attach P2P mode : handle address assigned by r-port.
322 */
323 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
324 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
325 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
326 port->pid = rx_fchs->d_id;
327 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
328 rport->pid = rx_fchs->s_id;
329 }
330 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
331 return;
332 }
333
334 /*
335 * Next, lookup rport by PID.
336 */
337 rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
338 if (!rport) {
339 /*
340 * Inbound PLOGI from a new device.
341 */
342 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
343 return;
344 }
345
346 /*
347 * Rport is known only by PID.
348 */
349 if (rport->pwwn) {
350 /*
351 * This is a different device with the same pid. Old device
352 * disappeared. Send implicit LOGO to old device.
353 */
354 WARN_ON(rport->pwwn == plogi->port_name);
355 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
356
357 /*
358 * Inbound PLOGI from a new device (with old PID).
359 */
360 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
361 return;
362 }
363
364 /*
365 * PLOGI crossing each other.
366 */
367 WARN_ON(rport->pwwn != WWN_NULL);
368 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
369 }
370
371 /*
372 * Process incoming ECHO.
373 * Since it does not require a login, it is processed here.
374 */
375 static void
376 bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
377 struct fc_echo_s *echo, u16 rx_len)
378 {
379 struct fchs_s fchs;
380 struct bfa_fcxp_s *fcxp;
381 struct bfa_rport_s *bfa_rport = NULL;
382 int len, pyld_len;
383
384 bfa_trc(port->fcs, rx_fchs->s_id);
385 bfa_trc(port->fcs, rx_fchs->d_id);
386
387 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
388 if (!fcxp)
389 return;
390
391 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
392 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
393 rx_fchs->ox_id);
394
395 /*
396 * Copy the payload (if any) from the echo frame
397 */
398 pyld_len = rx_len - sizeof(struct fchs_s);
399 bfa_trc(port->fcs, rx_len);
400 bfa_trc(port->fcs, pyld_len);
401
402 if (pyld_len > len)
403 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
404 sizeof(struct fc_echo_s), (echo + 1),
405 (pyld_len - sizeof(struct fc_echo_s)));
406
407 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
408 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
409 FC_MAX_PDUSZ, 0);
410 }
411
412 /*
413 * Process incoming RNID.
414 * Since it does not require a login, it is processed here.
415 */
416 static void
417 bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
418 struct fc_rnid_cmd_s *rnid, u16 rx_len)
419 {
420 struct fc_rnid_common_id_data_s common_id_data;
421 struct fc_rnid_general_topology_data_s gen_topo_data;
422 struct fchs_s fchs;
423 struct bfa_fcxp_s *fcxp;
424 struct bfa_rport_s *bfa_rport = NULL;
425 u16 len;
426 u32 data_format;
427
428 bfa_trc(port->fcs, rx_fchs->s_id);
429 bfa_trc(port->fcs, rx_fchs->d_id);
430 bfa_trc(port->fcs, rx_len);
431
432 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
433 if (!fcxp)
434 return;
435
436 /*
437 * Check Node Indentification Data Format
438 * We only support General Topology Discovery Format.
439 * For any other requested Data Formats, we return Common Node Id Data
440 * only, as per FC-LS.
441 */
442 bfa_trc(port->fcs, rnid->node_id_data_format);
443 if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
444 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
445 /*
446 * Get General topology data for this port
447 */
448 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
449 } else {
450 data_format = RNID_NODEID_DATA_FORMAT_COMMON;
451 }
452
453 /*
454 * Copy the Node Id Info
455 */
456 common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
457 common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
458
459 len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
460 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
461 rx_fchs->ox_id, data_format, &common_id_data,
462 &gen_topo_data);
463
464 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
465 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
466 FC_MAX_PDUSZ, 0);
467 }
468
469 /*
470 * Fill out General Topolpgy Discovery Data for RNID ELS.
471 */
472 static void
473 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
474 struct fc_rnid_general_topology_data_s *gen_topo_data)
475 {
476 memset(gen_topo_data, 0,
477 sizeof(struct fc_rnid_general_topology_data_s));
478
479 gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
480 gen_topo_data->phy_port_num = 0; /* @todo */
481 gen_topo_data->num_attached_nodes = cpu_to_be32(1);
482 }
483
484 static void
485 bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
486 {
487 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
488 char lpwwn_buf[BFA_STRING_32];
489
490 bfa_trc(port->fcs, port->fabric->oper_type);
491
492 __port_action[port->fabric->fab_type].init(port);
493 __port_action[port->fabric->fab_type].online(port);
494
495 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
496 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
497 "Logical port online: WWN = %s Role = %s\n",
498 lpwwn_buf, "Initiator");
499
500 bfad->bfad_flags |= BFAD_PORT_ONLINE;
501 }
502
503 static void
504 bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
505 {
506 struct list_head *qe, *qen;
507 struct bfa_fcs_rport_s *rport;
508 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
509 char lpwwn_buf[BFA_STRING_32];
510
511 bfa_trc(port->fcs, port->fabric->oper_type);
512
513 __port_action[port->fabric->fab_type].offline(port);
514
515 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
516 if (bfa_sm_cmp_state(port->fabric,
517 bfa_fcs_fabric_sm_online) == BFA_TRUE)
518 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
519 "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
520 lpwwn_buf, "Initiator");
521 else
522 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
523 "Logical port taken offline: WWN = %s Role = %s\n",
524 lpwwn_buf, "Initiator");
525
526 list_for_each_safe(qe, qen, &port->rport_q) {
527 rport = (struct bfa_fcs_rport_s *) qe;
528 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
529 }
530 }
531
532 static void
533 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
534 {
535 WARN_ON(1);
536 }
537
538 static void
539 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
540 {
541 WARN_ON(1);
542 }
543
544 static void
545 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
546 {
547 WARN_ON(1);
548 }
549
550 static void
551 bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
552 {
553 struct fchs_s fchs;
554 struct bfa_fcxp_s *fcxp;
555 int len;
556
557 bfa_trc(port->fcs, rx_fchs->d_id);
558 bfa_trc(port->fcs, rx_fchs->s_id);
559
560 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
561 if (!fcxp)
562 return;
563
564 len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
565 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
566 rx_fchs->ox_id, 0);
567
568 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
569 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
570 FC_MAX_PDUSZ, 0);
571 }
572 static void
573 bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
574 {
575 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
576 char lpwwn_buf[BFA_STRING_32];
577
578 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
579 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
580 "Logical port deleted: WWN = %s Role = %s\n",
581 lpwwn_buf, "Initiator");
582
583 /* Base port will be deleted by the OS driver */
584 if (port->vport) {
585 bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
586 port->fabric->vf_drv,
587 port->vport ? port->vport->vport_drv : NULL);
588 bfa_fcs_vport_delete_comp(port->vport);
589 } else {
590 bfa_wc_down(&port->fabric->wc);
591 }
592 }
593
594
595 /*
596 * Unsolicited frame receive handling.
597 */
598 void
599 bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
600 struct fchs_s *fchs, u16 len)
601 {
602 u32 pid = fchs->s_id;
603 struct bfa_fcs_rport_s *rport = NULL;
604 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
605
606 bfa_stats(lport, uf_recvs);
607 bfa_trc(lport->fcs, fchs->type);
608
609 if (!bfa_fcs_lport_is_online(lport)) {
610 bfa_stats(lport, uf_recv_drops);
611 return;
612 }
613
614 /*
615 * First, handle ELSs that donot require a login.
616 */
617 /*
618 * Handle PLOGI first
619 */
620 if ((fchs->type == FC_TYPE_ELS) &&
621 (els_cmd->els_code == FC_ELS_PLOGI)) {
622 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
623 return;
624 }
625
626 /*
627 * Handle ECHO separately.
628 */
629 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
630 bfa_fcs_lport_echo(lport, fchs,
631 (struct fc_echo_s *)els_cmd, len);
632 return;
633 }
634
635 /*
636 * Handle RNID separately.
637 */
638 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
639 bfa_fcs_lport_rnid(lport, fchs,
640 (struct fc_rnid_cmd_s *) els_cmd, len);
641 return;
642 }
643
644 if (fchs->type == FC_TYPE_BLS) {
645 if ((fchs->routing == FC_RTG_BASIC_LINK) &&
646 (fchs->cat_info == FC_CAT_ABTS))
647 bfa_fcs_lport_abts_acc(lport, fchs);
648 return;
649 }
650 /*
651 * look for a matching remote port ID
652 */
653 rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
654 if (rport) {
655 bfa_trc(rport->fcs, fchs->s_id);
656 bfa_trc(rport->fcs, fchs->d_id);
657 bfa_trc(rport->fcs, fchs->type);
658
659 bfa_fcs_rport_uf_recv(rport, fchs, len);
660 return;
661 }
662
663 /*
664 * Only handles ELS frames for now.
665 */
666 if (fchs->type != FC_TYPE_ELS) {
667 bfa_trc(lport->fcs, fchs->s_id);
668 bfa_trc(lport->fcs, fchs->d_id);
669 /* ignore type FC_TYPE_FC_FSS */
670 if (fchs->type != FC_TYPE_FC_FSS)
671 bfa_sm_fault(lport->fcs, fchs->type);
672 return;
673 }
674
675 bfa_trc(lport->fcs, els_cmd->els_code);
676 if (els_cmd->els_code == FC_ELS_RSCN) {
677 bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
678 return;
679 }
680
681 if (els_cmd->els_code == FC_ELS_LOGO) {
682 /*
683 * @todo Handle LOGO frames received.
684 */
685 return;
686 }
687
688 if (els_cmd->els_code == FC_ELS_PRLI) {
689 /*
690 * @todo Handle PRLI frames received.
691 */
692 return;
693 }
694
695 /*
696 * Unhandled ELS frames. Send a LS_RJT.
697 */
698 bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
699 FC_LS_RJT_EXP_NO_ADDL_INFO);
700
701 }
702
703 /*
704 * PID based Lookup for a R-Port in the Port R-Port Queue
705 */
706 struct bfa_fcs_rport_s *
707 bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
708 {
709 struct bfa_fcs_rport_s *rport;
710 struct list_head *qe;
711
712 list_for_each(qe, &port->rport_q) {
713 rport = (struct bfa_fcs_rport_s *) qe;
714 if (rport->pid == pid)
715 return rport;
716 }
717
718 bfa_trc(port->fcs, pid);
719 return NULL;
720 }
721
722 /*
723 * PWWN based Lookup for a R-Port in the Port R-Port Queue
724 */
725 struct bfa_fcs_rport_s *
726 bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
727 {
728 struct bfa_fcs_rport_s *rport;
729 struct list_head *qe;
730
731 list_for_each(qe, &port->rport_q) {
732 rport = (struct bfa_fcs_rport_s *) qe;
733 if (wwn_is_equal(rport->pwwn, pwwn))
734 return rport;
735 }
736
737 bfa_trc(port->fcs, pwwn);
738 return NULL;
739 }
740
741 /*
742 * NWWN based Lookup for a R-Port in the Port R-Port Queue
743 */
744 struct bfa_fcs_rport_s *
745 bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
746 {
747 struct bfa_fcs_rport_s *rport;
748 struct list_head *qe;
749
750 list_for_each(qe, &port->rport_q) {
751 rport = (struct bfa_fcs_rport_s *) qe;
752 if (wwn_is_equal(rport->nwwn, nwwn))
753 return rport;
754 }
755
756 bfa_trc(port->fcs, nwwn);
757 return NULL;
758 }
759
760 /*
761 * Called by rport module when new rports are discovered.
762 */
763 void
764 bfa_fcs_lport_add_rport(
765 struct bfa_fcs_lport_s *port,
766 struct bfa_fcs_rport_s *rport)
767 {
768 list_add_tail(&rport->qe, &port->rport_q);
769 port->num_rports++;
770 }
771
772 /*
773 * Called by rport module to when rports are deleted.
774 */
775 void
776 bfa_fcs_lport_del_rport(
777 struct bfa_fcs_lport_s *port,
778 struct bfa_fcs_rport_s *rport)
779 {
780 WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
781 list_del(&rport->qe);
782 port->num_rports--;
783
784 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
785 }
786
787 /*
788 * Called by fabric for base port when fabric login is complete.
789 * Called by vport for virtual ports when FDISC is complete.
790 */
791 void
792 bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
793 {
794 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
795 }
796
797 /*
798 * Called by fabric for base port when fabric goes offline.
799 * Called by vport for virtual ports when virtual port becomes offline.
800 */
801 void
802 bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
803 {
804 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
805 }
806
807 /*
808 * Called by fabric to delete base lport and associated resources.
809 *
810 * Called by vport to delete lport and associated resources. Should call
811 * bfa_fcs_vport_delete_comp() for vports on completion.
812 */
813 void
814 bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
815 {
816 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
817 }
818
819 /*
820 * Return TRUE if port is online, else return FALSE
821 */
822 bfa_boolean_t
823 bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
824 {
825 return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
826 }
827
828 /*
829 * Attach time initialization of logical ports.
830 */
831 void
832 bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
833 u16 vf_id, struct bfa_fcs_vport_s *vport)
834 {
835 lport->fcs = fcs;
836 lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
837 lport->vport = vport;
838 lport->lp_tag = (vport) ? vport->lps->lp_tag :
839 lport->fabric->lps->lp_tag;
840
841 INIT_LIST_HEAD(&lport->rport_q);
842 lport->num_rports = 0;
843 }
844
845 /*
846 * Logical port initialization of base or virtual port.
847 * Called by fabric for base port or by vport for virtual ports.
848 */
849
850 void
851 bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
852 struct bfa_lport_cfg_s *port_cfg)
853 {
854 struct bfa_fcs_vport_s *vport = lport->vport;
855 struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
856 char lpwwn_buf[BFA_STRING_32];
857
858 lport->port_cfg = *port_cfg;
859
860 lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
861 lport->port_cfg.roles,
862 lport->fabric->vf_drv,
863 vport ? vport->vport_drv : NULL);
864
865 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
866 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
867 "New logical port created: WWN = %s Role = %s\n",
868 lpwwn_buf, "Initiator");
869
870 bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
871 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
872 }
873
874 /*
875 * fcs_lport_api
876 */
877
878 void
879 bfa_fcs_lport_get_attr(
880 struct bfa_fcs_lport_s *port,
881 struct bfa_lport_attr_s *port_attr)
882 {
883 if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
884 port_attr->pid = port->pid;
885 else
886 port_attr->pid = 0;
887
888 port_attr->port_cfg = port->port_cfg;
889
890 if (port->fabric) {
891 port_attr->port_type = port->fabric->oper_type;
892 port_attr->loopback = bfa_sm_cmp_state(port->fabric,
893 bfa_fcs_fabric_sm_loopback);
894 port_attr->authfail =
895 bfa_sm_cmp_state(port->fabric,
896 bfa_fcs_fabric_sm_auth_failed);
897 port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port);
898 memcpy(port_attr->fabric_ip_addr,
899 bfa_fcs_lport_get_fabric_ipaddr(port),
900 BFA_FCS_FABRIC_IPADDR_SZ);
901
902 if (port->vport != NULL) {
903 port_attr->port_type = BFA_PORT_TYPE_VPORT;
904 port_attr->fpma_mac =
905 port->vport->lps->lp_mac;
906 } else {
907 port_attr->fpma_mac =
908 port->fabric->lps->lp_mac;
909 }
910 } else {
911 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
912 port_attr->state = BFA_LPORT_UNINIT;
913 }
914 }
915
916 /*
917 * bfa_fcs_lport_fab port fab functions
918 */
919
920 /*
921 * Called by port to initialize fabric services of the base port.
922 */
923 static void
924 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
925 {
926 bfa_fcs_lport_ns_init(port);
927 bfa_fcs_lport_scn_init(port);
928 bfa_fcs_lport_ms_init(port);
929 }
930
931 /*
932 * Called by port to notify transition to online state.
933 */
934 static void
935 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
936 {
937 bfa_fcs_lport_ns_online(port);
938 bfa_fcs_lport_scn_online(port);
939 }
940
941 /*
942 * Called by port to notify transition to offline state.
943 */
944 static void
945 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
946 {
947 bfa_fcs_lport_ns_offline(port);
948 bfa_fcs_lport_scn_offline(port);
949 bfa_fcs_lport_ms_offline(port);
950 }
951
952 /*
953 * bfa_fcs_lport_n2n functions
954 */
955
956 /*
957 * Called by fcs/port to initialize N2N topology.
958 */
959 static void
960 bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
961 {
962 }
963
964 /*
965 * Called by fcs/port to notify transition to online state.
966 */
967 static void
968 bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
969 {
970 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
971 struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
972 struct bfa_fcs_rport_s *rport;
973
974 bfa_trc(port->fcs, pcfg->pwwn);
975
976 /*
977 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
978 * and assign an Address. if not, we need to wait for its PLOGI.
979 *
980 * If our PWWN is < than that of the remote port, it will send a PLOGI
981 * with the PIDs assigned. The rport state machine take care of this
982 * incoming PLOGI.
983 */
984 if (memcmp
985 ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
986 sizeof(wwn_t)) > 0) {
987 port->pid = N2N_LOCAL_PID;
988 bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
989 /*
990 * First, check if we know the device by pwwn.
991 */
992 rport = bfa_fcs_lport_get_rport_by_pwwn(port,
993 n2n_port->rem_port_wwn);
994 if (rport) {
995 bfa_trc(port->fcs, rport->pid);
996 bfa_trc(port->fcs, rport->pwwn);
997 rport->pid = N2N_REMOTE_PID;
998 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
999 return;
1000 }
1001
1002 /*
1003 * In n2n there can be only one rport. Delete the old one
1004 * whose pid should be zero, because it is offline.
1005 */
1006 if (port->num_rports > 0) {
1007 rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1008 WARN_ON(rport == NULL);
1009 if (rport) {
1010 bfa_trc(port->fcs, rport->pwwn);
1011 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
1012 }
1013 }
1014 bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1015 }
1016 }
1017
1018 /*
1019 * Called by fcs/port to notify transition to offline state.
1020 */
1021 static void
1022 bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1023 {
1024 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1025
1026 bfa_trc(port->fcs, port->pid);
1027 port->pid = 0;
1028 n2n_port->rem_port_wwn = 0;
1029 n2n_port->reply_oxid = 0;
1030 }
1031
1032 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1033
1034 /*
1035 * forward declarations
1036 */
1037 static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1038 struct bfa_fcxp_s *fcxp_alloced);
1039 static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1040 struct bfa_fcxp_s *fcxp_alloced);
1041 static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1042 struct bfa_fcxp_s *fcxp_alloced);
1043 static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1044 struct bfa_fcxp_s *fcxp,
1045 void *cbarg,
1046 bfa_status_t req_status,
1047 u32 rsp_len,
1048 u32 resid_len,
1049 struct fchs_s *rsp_fchs);
1050 static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1051 struct bfa_fcxp_s *fcxp,
1052 void *cbarg,
1053 bfa_status_t req_status,
1054 u32 rsp_len,
1055 u32 resid_len,
1056 struct fchs_s *rsp_fchs);
1057 static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1058 struct bfa_fcxp_s *fcxp,
1059 void *cbarg,
1060 bfa_status_t req_status,
1061 u32 rsp_len,
1062 u32 resid_len,
1063 struct fchs_s *rsp_fchs);
1064 static void bfa_fcs_lport_fdmi_timeout(void *arg);
1065 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1066 u8 *pyld);
1067 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1068 u8 *pyld);
1069 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1070 u8 *pyld);
1071 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1072 fdmi, u8 *pyld);
1073 static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1074 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1075 static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1076 struct bfa_fcs_fdmi_port_attr_s *port_attr);
1077 /*
1078 * fcs_fdmi_sm FCS FDMI state machine
1079 */
1080
1081 /*
1082 * FDMI State Machine events
1083 */
1084 enum port_fdmi_event {
1085 FDMISM_EVENT_PORT_ONLINE = 1,
1086 FDMISM_EVENT_PORT_OFFLINE = 2,
1087 FDMISM_EVENT_RSP_OK = 4,
1088 FDMISM_EVENT_RSP_ERROR = 5,
1089 FDMISM_EVENT_TIMEOUT = 6,
1090 FDMISM_EVENT_RHBA_SENT = 7,
1091 FDMISM_EVENT_RPRT_SENT = 8,
1092 FDMISM_EVENT_RPA_SENT = 9,
1093 };
1094
1095 static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1096 enum port_fdmi_event event);
1097 static void bfa_fcs_lport_fdmi_sm_sending_rhba(
1098 struct bfa_fcs_lport_fdmi_s *fdmi,
1099 enum port_fdmi_event event);
1100 static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1101 enum port_fdmi_event event);
1102 static void bfa_fcs_lport_fdmi_sm_rhba_retry(
1103 struct bfa_fcs_lport_fdmi_s *fdmi,
1104 enum port_fdmi_event event);
1105 static void bfa_fcs_lport_fdmi_sm_sending_rprt(
1106 struct bfa_fcs_lport_fdmi_s *fdmi,
1107 enum port_fdmi_event event);
1108 static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1109 enum port_fdmi_event event);
1110 static void bfa_fcs_lport_fdmi_sm_rprt_retry(
1111 struct bfa_fcs_lport_fdmi_s *fdmi,
1112 enum port_fdmi_event event);
1113 static void bfa_fcs_lport_fdmi_sm_sending_rpa(
1114 struct bfa_fcs_lport_fdmi_s *fdmi,
1115 enum port_fdmi_event event);
1116 static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1117 enum port_fdmi_event event);
1118 static void bfa_fcs_lport_fdmi_sm_rpa_retry(
1119 struct bfa_fcs_lport_fdmi_s *fdmi,
1120 enum port_fdmi_event event);
1121 static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1122 enum port_fdmi_event event);
1123 static void bfa_fcs_lport_fdmi_sm_disabled(
1124 struct bfa_fcs_lport_fdmi_s *fdmi,
1125 enum port_fdmi_event event);
1126 /*
1127 * Start in offline state - awaiting MS to send start.
1128 */
1129 static void
1130 bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1131 enum port_fdmi_event event)
1132 {
1133 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1134
1135 bfa_trc(port->fcs, port->port_cfg.pwwn);
1136 bfa_trc(port->fcs, event);
1137
1138 fdmi->retry_cnt = 0;
1139
1140 switch (event) {
1141 case FDMISM_EVENT_PORT_ONLINE:
1142 if (port->vport) {
1143 /*
1144 * For Vports, register a new port.
1145 */
1146 bfa_sm_set_state(fdmi,
1147 bfa_fcs_lport_fdmi_sm_sending_rprt);
1148 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1149 } else {
1150 /*
1151 * For a base port, we should first register the HBA
1152 * atribute. The HBA attribute also contains the base
1153 * port registration.
1154 */
1155 bfa_sm_set_state(fdmi,
1156 bfa_fcs_lport_fdmi_sm_sending_rhba);
1157 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1158 }
1159 break;
1160
1161 case FDMISM_EVENT_PORT_OFFLINE:
1162 break;
1163
1164 default:
1165 bfa_sm_fault(port->fcs, event);
1166 }
1167 }
1168
1169 static void
1170 bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1171 enum port_fdmi_event event)
1172 {
1173 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1174
1175 bfa_trc(port->fcs, port->port_cfg.pwwn);
1176 bfa_trc(port->fcs, event);
1177
1178 switch (event) {
1179 case FDMISM_EVENT_RHBA_SENT:
1180 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1181 break;
1182
1183 case FDMISM_EVENT_PORT_OFFLINE:
1184 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1185 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1186 &fdmi->fcxp_wqe);
1187 break;
1188
1189 default:
1190 bfa_sm_fault(port->fcs, event);
1191 }
1192 }
1193
1194 static void
1195 bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1196 enum port_fdmi_event event)
1197 {
1198 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1199
1200 bfa_trc(port->fcs, port->port_cfg.pwwn);
1201 bfa_trc(port->fcs, event);
1202
1203 switch (event) {
1204 case FDMISM_EVENT_RSP_ERROR:
1205 /*
1206 * if max retries have not been reached, start timer for a
1207 * delayed retry
1208 */
1209 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1210 bfa_sm_set_state(fdmi,
1211 bfa_fcs_lport_fdmi_sm_rhba_retry);
1212 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1213 &fdmi->timer,
1214 bfa_fcs_lport_fdmi_timeout, fdmi,
1215 BFA_FCS_RETRY_TIMEOUT);
1216 } else {
1217 /*
1218 * set state to offline
1219 */
1220 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1221 }
1222 break;
1223
1224 case FDMISM_EVENT_RSP_OK:
1225 /*
1226 * Initiate Register Port Attributes
1227 */
1228 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1229 fdmi->retry_cnt = 0;
1230 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1231 break;
1232
1233 case FDMISM_EVENT_PORT_OFFLINE:
1234 bfa_fcxp_discard(fdmi->fcxp);
1235 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1236 break;
1237
1238 default:
1239 bfa_sm_fault(port->fcs, event);
1240 }
1241 }
1242
1243 static void
1244 bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1245 enum port_fdmi_event event)
1246 {
1247 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1248
1249 bfa_trc(port->fcs, port->port_cfg.pwwn);
1250 bfa_trc(port->fcs, event);
1251
1252 switch (event) {
1253 case FDMISM_EVENT_TIMEOUT:
1254 /*
1255 * Retry Timer Expired. Re-send
1256 */
1257 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1258 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1259 break;
1260
1261 case FDMISM_EVENT_PORT_OFFLINE:
1262 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1263 bfa_timer_stop(&fdmi->timer);
1264 break;
1265
1266 default:
1267 bfa_sm_fault(port->fcs, event);
1268 }
1269 }
1270
1271 /*
1272 * RPRT : Register Port
1273 */
1274 static void
1275 bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1276 enum port_fdmi_event event)
1277 {
1278 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1279
1280 bfa_trc(port->fcs, port->port_cfg.pwwn);
1281 bfa_trc(port->fcs, event);
1282
1283 switch (event) {
1284 case FDMISM_EVENT_RPRT_SENT:
1285 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1286 break;
1287
1288 case FDMISM_EVENT_PORT_OFFLINE:
1289 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1290 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1291 &fdmi->fcxp_wqe);
1292 break;
1293
1294 default:
1295 bfa_sm_fault(port->fcs, event);
1296 }
1297 }
1298
1299 static void
1300 bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1301 enum port_fdmi_event event)
1302 {
1303 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1304
1305 bfa_trc(port->fcs, port->port_cfg.pwwn);
1306 bfa_trc(port->fcs, event);
1307
1308 switch (event) {
1309 case FDMISM_EVENT_RSP_ERROR:
1310 /*
1311 * if max retries have not been reached, start timer for a
1312 * delayed retry
1313 */
1314 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1315 bfa_sm_set_state(fdmi,
1316 bfa_fcs_lport_fdmi_sm_rprt_retry);
1317 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1318 &fdmi->timer,
1319 bfa_fcs_lport_fdmi_timeout, fdmi,
1320 BFA_FCS_RETRY_TIMEOUT);
1321
1322 } else {
1323 /*
1324 * set state to offline
1325 */
1326 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1327 fdmi->retry_cnt = 0;
1328 }
1329 break;
1330
1331 case FDMISM_EVENT_RSP_OK:
1332 fdmi->retry_cnt = 0;
1333 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1334 break;
1335
1336 case FDMISM_EVENT_PORT_OFFLINE:
1337 bfa_fcxp_discard(fdmi->fcxp);
1338 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1339 break;
1340
1341 default:
1342 bfa_sm_fault(port->fcs, event);
1343 }
1344 }
1345
1346 static void
1347 bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1348 enum port_fdmi_event event)
1349 {
1350 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1351
1352 bfa_trc(port->fcs, port->port_cfg.pwwn);
1353 bfa_trc(port->fcs, event);
1354
1355 switch (event) {
1356 case FDMISM_EVENT_TIMEOUT:
1357 /*
1358 * Retry Timer Expired. Re-send
1359 */
1360 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1361 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1362 break;
1363
1364 case FDMISM_EVENT_PORT_OFFLINE:
1365 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1366 bfa_timer_stop(&fdmi->timer);
1367 break;
1368
1369 default:
1370 bfa_sm_fault(port->fcs, event);
1371 }
1372 }
1373
1374 /*
1375 * Register Port Attributes
1376 */
1377 static void
1378 bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1379 enum port_fdmi_event event)
1380 {
1381 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1382
1383 bfa_trc(port->fcs, port->port_cfg.pwwn);
1384 bfa_trc(port->fcs, event);
1385
1386 switch (event) {
1387 case FDMISM_EVENT_RPA_SENT:
1388 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1389 break;
1390
1391 case FDMISM_EVENT_PORT_OFFLINE:
1392 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1393 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1394 &fdmi->fcxp_wqe);
1395 break;
1396
1397 default:
1398 bfa_sm_fault(port->fcs, event);
1399 }
1400 }
1401
1402 static void
1403 bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1404 enum port_fdmi_event event)
1405 {
1406 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1407
1408 bfa_trc(port->fcs, port->port_cfg.pwwn);
1409 bfa_trc(port->fcs, event);
1410
1411 switch (event) {
1412 case FDMISM_EVENT_RSP_ERROR:
1413 /*
1414 * if max retries have not been reached, start timer for a
1415 * delayed retry
1416 */
1417 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1418 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1419 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1420 &fdmi->timer,
1421 bfa_fcs_lport_fdmi_timeout, fdmi,
1422 BFA_FCS_RETRY_TIMEOUT);
1423 } else {
1424 /*
1425 * set state to offline
1426 */
1427 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1428 fdmi->retry_cnt = 0;
1429 }
1430 break;
1431
1432 case FDMISM_EVENT_RSP_OK:
1433 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1434 fdmi->retry_cnt = 0;
1435 break;
1436
1437 case FDMISM_EVENT_PORT_OFFLINE:
1438 bfa_fcxp_discard(fdmi->fcxp);
1439 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1440 break;
1441
1442 default:
1443 bfa_sm_fault(port->fcs, event);
1444 }
1445 }
1446
1447 static void
1448 bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1449 enum port_fdmi_event event)
1450 {
1451 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1452
1453 bfa_trc(port->fcs, port->port_cfg.pwwn);
1454 bfa_trc(port->fcs, event);
1455
1456 switch (event) {
1457 case FDMISM_EVENT_TIMEOUT:
1458 /*
1459 * Retry Timer Expired. Re-send
1460 */
1461 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1462 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1463 break;
1464
1465 case FDMISM_EVENT_PORT_OFFLINE:
1466 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1467 bfa_timer_stop(&fdmi->timer);
1468 break;
1469
1470 default:
1471 bfa_sm_fault(port->fcs, event);
1472 }
1473 }
1474
1475 static void
1476 bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1477 enum port_fdmi_event event)
1478 {
1479 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1480
1481 bfa_trc(port->fcs, port->port_cfg.pwwn);
1482 bfa_trc(port->fcs, event);
1483
1484 switch (event) {
1485 case FDMISM_EVENT_PORT_OFFLINE:
1486 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1487 break;
1488
1489 default:
1490 bfa_sm_fault(port->fcs, event);
1491 }
1492 }
1493 /*
1494 * FDMI is disabled state.
1495 */
1496 static void
1497 bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1498 enum port_fdmi_event event)
1499 {
1500 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1501
1502 bfa_trc(port->fcs, port->port_cfg.pwwn);
1503 bfa_trc(port->fcs, event);
1504
1505 /* No op State. It can only be enabled at Driver Init. */
1506 }
1507
1508 /*
1509 * RHBA : Register HBA Attributes.
1510 */
1511 static void
1512 bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1513 {
1514 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1515 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1516 struct fchs_s fchs;
1517 int len, attr_len;
1518 struct bfa_fcxp_s *fcxp;
1519 u8 *pyld;
1520
1521 bfa_trc(port->fcs, port->port_cfg.pwwn);
1522
1523 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1524 if (!fcxp) {
1525 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1526 bfa_fcs_lport_fdmi_send_rhba, fdmi);
1527 return;
1528 }
1529 fdmi->fcxp = fcxp;
1530
1531 pyld = bfa_fcxp_get_reqbuf(fcxp);
1532 memset(pyld, 0, FC_MAX_PDUSZ);
1533
1534 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1535 FDMI_RHBA);
1536
1537 attr_len =
1538 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1539 (u8 *) ((struct ct_hdr_s *) pyld
1540 + 1));
1541
1542 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1543 FC_CLASS_3, (len + attr_len), &fchs,
1544 bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1545 FC_MAX_PDUSZ, FC_FCCT_TOV);
1546
1547 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1548 }
1549
1550 static u16
1551 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1552 {
1553 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1554 struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1555 struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1556 struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1557 struct fdmi_attr_s *attr;
1558 u8 *curr_ptr;
1559 u16 len, count;
1560 u16 templen;
1561
1562 /*
1563 * get hba attributes
1564 */
1565 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1566
1567 rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1568 rhba->port_list.num_ports = cpu_to_be32(1);
1569 rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1570
1571 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1572
1573 count = 0;
1574 len += sizeof(rhba->hba_attr_blk.attr_count);
1575
1576 /*
1577 * fill out the invididual entries of the HBA attrib Block
1578 */
1579 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1580
1581 /*
1582 * Node Name
1583 */
1584 attr = (struct fdmi_attr_s *) curr_ptr;
1585 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1586 templen = sizeof(wwn_t);
1587 memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1588 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1589 len += templen;
1590 count++;
1591 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1592 sizeof(templen));
1593
1594 /*
1595 * Manufacturer
1596 */
1597 attr = (struct fdmi_attr_s *) curr_ptr;
1598 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1599 templen = (u16) strlen(fcs_hba_attr->manufacturer);
1600 memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1601 templen = fc_roundup(templen, sizeof(u32));
1602 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1603 len += templen;
1604 count++;
1605 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1606 sizeof(templen));
1607
1608 /*
1609 * Serial Number
1610 */
1611 attr = (struct fdmi_attr_s *) curr_ptr;
1612 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1613 templen = (u16) strlen(fcs_hba_attr->serial_num);
1614 memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1615 templen = fc_roundup(templen, sizeof(u32));
1616 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1617 len += templen;
1618 count++;
1619 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1620 sizeof(templen));
1621
1622 /*
1623 * Model
1624 */
1625 attr = (struct fdmi_attr_s *) curr_ptr;
1626 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1627 templen = (u16) strlen(fcs_hba_attr->model);
1628 memcpy(attr->value, fcs_hba_attr->model, templen);
1629 templen = fc_roundup(templen, sizeof(u32));
1630 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1631 len += templen;
1632 count++;
1633 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1634 sizeof(templen));
1635
1636 /*
1637 * Model Desc
1638 */
1639 attr = (struct fdmi_attr_s *) curr_ptr;
1640 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1641 templen = (u16) strlen(fcs_hba_attr->model_desc);
1642 memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1643 templen = fc_roundup(templen, sizeof(u32));
1644 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1645 len += templen;
1646 count++;
1647 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1648 sizeof(templen));
1649
1650 /*
1651 * H/W Version
1652 */
1653 if (fcs_hba_attr->hw_version[0] != '\0') {
1654 attr = (struct fdmi_attr_s *) curr_ptr;
1655 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
1656 templen = (u16) strlen(fcs_hba_attr->hw_version);
1657 memcpy(attr->value, fcs_hba_attr->hw_version, templen);
1658 templen = fc_roundup(templen, sizeof(u32));
1659 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1660 len += templen;
1661 count++;
1662 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1663 sizeof(templen));
1664 }
1665
1666 /*
1667 * Driver Version
1668 */
1669 attr = (struct fdmi_attr_s *) curr_ptr;
1670 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
1671 templen = (u16) strlen(fcs_hba_attr->driver_version);
1672 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1673 templen = fc_roundup(templen, sizeof(u32));
1674 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1675 len += templen;;
1676 count++;
1677 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1678 sizeof(templen));
1679
1680 /*
1681 * Option Rom Version
1682 */
1683 if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1684 attr = (struct fdmi_attr_s *) curr_ptr;
1685 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
1686 templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
1687 memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
1688 templen = fc_roundup(templen, sizeof(u32));
1689 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1690 len += templen;
1691 count++;
1692 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1693 sizeof(templen));
1694 }
1695
1696 /*
1697 * f/w Version = driver version
1698 */
1699 attr = (struct fdmi_attr_s *) curr_ptr;
1700 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
1701 templen = (u16) strlen(fcs_hba_attr->driver_version);
1702 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1703 templen = fc_roundup(templen, sizeof(u32));
1704 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1705 len += templen;
1706 count++;
1707 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1708 sizeof(templen));
1709
1710 /*
1711 * OS Name
1712 */
1713 if (fcs_hba_attr->os_name[0] != '\0') {
1714 attr = (struct fdmi_attr_s *) curr_ptr;
1715 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
1716 templen = (u16) strlen(fcs_hba_attr->os_name);
1717 memcpy(attr->value, fcs_hba_attr->os_name, templen);
1718 templen = fc_roundup(templen, sizeof(u32));
1719 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1720 len += templen;
1721 count++;
1722 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1723 sizeof(templen));
1724 }
1725
1726 /*
1727 * MAX_CT_PAYLOAD
1728 */
1729 attr = (struct fdmi_attr_s *) curr_ptr;
1730 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
1731 templen = sizeof(fcs_hba_attr->max_ct_pyld);
1732 memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
1733 len += templen;
1734 count++;
1735 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1736 sizeof(templen));
1737
1738 /*
1739 * Update size of payload
1740 */
1741 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1742
1743 rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
1744 return len;
1745 }
1746
1747 static void
1748 bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1749 void *cbarg, bfa_status_t req_status,
1750 u32 rsp_len, u32 resid_len,
1751 struct fchs_s *rsp_fchs)
1752 {
1753 struct bfa_fcs_lport_fdmi_s *fdmi =
1754 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1755 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1756 struct ct_hdr_s *cthdr = NULL;
1757
1758 bfa_trc(port->fcs, port->port_cfg.pwwn);
1759
1760 /*
1761 * Sanity Checks
1762 */
1763 if (req_status != BFA_STATUS_OK) {
1764 bfa_trc(port->fcs, req_status);
1765 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1766 return;
1767 }
1768
1769 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1770 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1771
1772 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1773 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1774 return;
1775 }
1776
1777 bfa_trc(port->fcs, cthdr->reason_code);
1778 bfa_trc(port->fcs, cthdr->exp_code);
1779 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1780 }
1781
1782 /*
1783 * RPRT : Register Port
1784 */
1785 static void
1786 bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1787 {
1788 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1789 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1790 struct fchs_s fchs;
1791 u16 len, attr_len;
1792 struct bfa_fcxp_s *fcxp;
1793 u8 *pyld;
1794
1795 bfa_trc(port->fcs, port->port_cfg.pwwn);
1796
1797 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1798 if (!fcxp) {
1799 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1800 bfa_fcs_lport_fdmi_send_rprt, fdmi);
1801 return;
1802 }
1803 fdmi->fcxp = fcxp;
1804
1805 pyld = bfa_fcxp_get_reqbuf(fcxp);
1806 memset(pyld, 0, FC_MAX_PDUSZ);
1807
1808 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1809 FDMI_RPRT);
1810
1811 attr_len =
1812 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1813 (u8 *) ((struct ct_hdr_s *) pyld
1814 + 1));
1815
1816 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1817 FC_CLASS_3, len + attr_len, &fchs,
1818 bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1819 FC_MAX_PDUSZ, FC_FCCT_TOV);
1820
1821 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1822 }
1823
1824 /*
1825 * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1826 */
1827 static u16
1828 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1829 u8 *pyld)
1830 {
1831 struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1832 struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1833 struct fdmi_attr_s *attr;
1834 u8 *curr_ptr;
1835 u16 len;
1836 u8 count = 0;
1837 u16 templen;
1838
1839 /*
1840 * get port attributes
1841 */
1842 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1843
1844 len = sizeof(port_attrib->attr_count);
1845
1846 /*
1847 * fill out the invididual entries
1848 */
1849 curr_ptr = (u8 *) &port_attrib->port_attr;
1850
1851 /*
1852 * FC4 Types
1853 */
1854 attr = (struct fdmi_attr_s *) curr_ptr;
1855 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
1856 templen = sizeof(fcs_port_attr.supp_fc4_types);
1857 memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
1858 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1859 len += templen;
1860 ++count;
1861 attr->len =
1862 cpu_to_be16(templen + sizeof(attr->type) +
1863 sizeof(templen));
1864
1865 /*
1866 * Supported Speed
1867 */
1868 attr = (struct fdmi_attr_s *) curr_ptr;
1869 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
1870 templen = sizeof(fcs_port_attr.supp_speed);
1871 memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
1872 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1873 len += templen;
1874 ++count;
1875 attr->len =
1876 cpu_to_be16(templen + sizeof(attr->type) +
1877 sizeof(templen));
1878
1879 /*
1880 * current Port Speed
1881 */
1882 attr = (struct fdmi_attr_s *) curr_ptr;
1883 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
1884 templen = sizeof(fcs_port_attr.curr_speed);
1885 memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
1886 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1887 len += templen;
1888 ++count;
1889 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1890 sizeof(templen));
1891
1892 /*
1893 * max frame size
1894 */
1895 attr = (struct fdmi_attr_s *) curr_ptr;
1896 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
1897 templen = sizeof(fcs_port_attr.max_frm_size);
1898 memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
1899 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1900 len += templen;
1901 ++count;
1902 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1903 sizeof(templen));
1904
1905 /*
1906 * OS Device Name
1907 */
1908 if (fcs_port_attr.os_device_name[0] != '\0') {
1909 attr = (struct fdmi_attr_s *) curr_ptr;
1910 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
1911 templen = (u16) strlen(fcs_port_attr.os_device_name);
1912 memcpy(attr->value, fcs_port_attr.os_device_name, templen);
1913 templen = fc_roundup(templen, sizeof(u32));
1914 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1915 len += templen;
1916 ++count;
1917 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1918 sizeof(templen));
1919 }
1920 /*
1921 * Host Name
1922 */
1923 if (fcs_port_attr.host_name[0] != '\0') {
1924 attr = (struct fdmi_attr_s *) curr_ptr;
1925 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
1926 templen = (u16) strlen(fcs_port_attr.host_name);
1927 memcpy(attr->value, fcs_port_attr.host_name, templen);
1928 templen = fc_roundup(templen, sizeof(u32));
1929 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1930 len += templen;
1931 ++count;
1932 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1933 sizeof(templen));
1934 }
1935
1936 /*
1937 * Update size of payload
1938 */
1939 port_attrib->attr_count = cpu_to_be32(count);
1940 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1941 return len;
1942 }
1943
1944 static u16
1945 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1946 {
1947 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1948 struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
1949 u16 len;
1950
1951 rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
1952 rprt->port_name = bfa_fcs_lport_get_pwwn(port);
1953
1954 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
1955 (u8 *) &rprt->port_attr_blk);
1956
1957 len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
1958
1959 return len;
1960 }
1961
1962 static void
1963 bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1964 void *cbarg, bfa_status_t req_status,
1965 u32 rsp_len, u32 resid_len,
1966 struct fchs_s *rsp_fchs)
1967 {
1968 struct bfa_fcs_lport_fdmi_s *fdmi =
1969 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1970 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1971 struct ct_hdr_s *cthdr = NULL;
1972
1973 bfa_trc(port->fcs, port->port_cfg.pwwn);
1974
1975 /*
1976 * Sanity Checks
1977 */
1978 if (req_status != BFA_STATUS_OK) {
1979 bfa_trc(port->fcs, req_status);
1980 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1981 return;
1982 }
1983
1984 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1985 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1986
1987 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1988 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1989 return;
1990 }
1991
1992 bfa_trc(port->fcs, cthdr->reason_code);
1993 bfa_trc(port->fcs, cthdr->exp_code);
1994 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1995 }
1996
1997 /*
1998 * RPA : Register Port Attributes.
1999 */
2000 static void
2001 bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2002 {
2003 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2004 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2005 struct fchs_s fchs;
2006 u16 len, attr_len;
2007 struct bfa_fcxp_s *fcxp;
2008 u8 *pyld;
2009
2010 bfa_trc(port->fcs, port->port_cfg.pwwn);
2011
2012 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2013 if (!fcxp) {
2014 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2015 bfa_fcs_lport_fdmi_send_rpa, fdmi);
2016 return;
2017 }
2018 fdmi->fcxp = fcxp;
2019
2020 pyld = bfa_fcxp_get_reqbuf(fcxp);
2021 memset(pyld, 0, FC_MAX_PDUSZ);
2022
2023 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2024 FDMI_RPA);
2025
2026 attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2027 (u8 *) ((struct ct_hdr_s *) pyld + 1));
2028
2029 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2030 FC_CLASS_3, len + attr_len, &fchs,
2031 bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2032 FC_MAX_PDUSZ, FC_FCCT_TOV);
2033
2034 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2035 }
2036
2037 static u16
2038 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2039 {
2040 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2041 struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2042 u16 len;
2043
2044 rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2045
2046 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2047 (u8 *) &rpa->port_attr_blk);
2048
2049 len += sizeof(rpa->port_name);
2050
2051 return len;
2052 }
2053
2054 static void
2055 bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2056 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2057 u32 resid_len, struct fchs_s *rsp_fchs)
2058 {
2059 struct bfa_fcs_lport_fdmi_s *fdmi =
2060 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2061 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2062 struct ct_hdr_s *cthdr = NULL;
2063
2064 bfa_trc(port->fcs, port->port_cfg.pwwn);
2065
2066 /*
2067 * Sanity Checks
2068 */
2069 if (req_status != BFA_STATUS_OK) {
2070 bfa_trc(port->fcs, req_status);
2071 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2072 return;
2073 }
2074
2075 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2076 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2077
2078 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2079 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2080 return;
2081 }
2082
2083 bfa_trc(port->fcs, cthdr->reason_code);
2084 bfa_trc(port->fcs, cthdr->exp_code);
2085 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2086 }
2087
2088 static void
2089 bfa_fcs_lport_fdmi_timeout(void *arg)
2090 {
2091 struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2092
2093 bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2094 }
2095
2096 static void
2097 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2098 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2099 {
2100 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2101 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2102
2103 memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2104
2105 bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2106 hba_attr->manufacturer);
2107 bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2108 hba_attr->serial_num);
2109 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2110 hba_attr->model);
2111 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2112 hba_attr->model_desc);
2113 bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2114 hba_attr->hw_version);
2115 bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2116 hba_attr->option_rom_ver);
2117 bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2118 hba_attr->fw_version);
2119
2120 strncpy(hba_attr->driver_version, (char *)driver_info->version,
2121 sizeof(hba_attr->driver_version));
2122
2123 strncpy(hba_attr->os_name, driver_info->host_os_name,
2124 sizeof(hba_attr->os_name));
2125
2126 /*
2127 * If there is a patch level, append it
2128 * to the os name along with a separator
2129 */
2130 if (driver_info->host_os_patch[0] != '\0') {
2131 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2132 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2133 strncat(hba_attr->os_name, driver_info->host_os_patch,
2134 sizeof(driver_info->host_os_patch));
2135 }
2136
2137 hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
2138 }
2139
2140 static void
2141 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2142 struct bfa_fcs_fdmi_port_attr_s *port_attr)
2143 {
2144 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2145 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2146 struct bfa_port_attr_s pport_attr;
2147
2148 memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2149
2150 /*
2151 * get pport attributes from hal
2152 */
2153 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2154
2155 /*
2156 * get FC4 type Bitmask
2157 */
2158 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2159
2160 /*
2161 * Supported Speeds
2162 */
2163 port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
2164
2165 /*
2166 * Current Speed
2167 */
2168 port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
2169
2170 /*
2171 * Max PDU Size.
2172 */
2173 port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
2174
2175 /*
2176 * OS device Name
2177 */
2178 strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2179 sizeof(port_attr->os_device_name));
2180
2181 /*
2182 * Host name
2183 */
2184 strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2185 sizeof(port_attr->host_name));
2186
2187 }
2188
2189
2190 void
2191 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2192 {
2193 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2194
2195 fdmi->ms = ms;
2196 if (ms->port->fcs->fdmi_enabled)
2197 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2198 else
2199 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2200 }
2201
2202 void
2203 bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2204 {
2205 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2206
2207 fdmi->ms = ms;
2208 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2209 }
2210
2211 void
2212 bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2213 {
2214 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2215
2216 fdmi->ms = ms;
2217 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2218 }
2219
2220 #define BFA_FCS_MS_CMD_MAX_RETRIES 2
2221
2222 /*
2223 * forward declarations
2224 */
2225 static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2226 struct bfa_fcxp_s *fcxp_alloced);
2227 static void bfa_fcs_lport_ms_timeout(void *arg);
2228 static void bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2229 struct bfa_fcxp_s *fcxp,
2230 void *cbarg,
2231 bfa_status_t req_status,
2232 u32 rsp_len,
2233 u32 resid_len,
2234 struct fchs_s *rsp_fchs);
2235
2236 static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2237 struct bfa_fcxp_s *fcxp_alloced);
2238 static void bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2239 struct bfa_fcxp_s *fcxp,
2240 void *cbarg,
2241 bfa_status_t req_status,
2242 u32 rsp_len,
2243 u32 resid_len,
2244 struct fchs_s *rsp_fchs);
2245 static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2246 struct bfa_fcxp_s *fcxp_alloced);
2247 static void bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2248 struct bfa_fcxp_s *fcxp,
2249 void *cbarg,
2250 bfa_status_t req_status,
2251 u32 rsp_len,
2252 u32 resid_len,
2253 struct fchs_s *rsp_fchs);
2254 /*
2255 * fcs_ms_sm FCS MS state machine
2256 */
2257
2258 /*
2259 * MS State Machine events
2260 */
2261 enum port_ms_event {
2262 MSSM_EVENT_PORT_ONLINE = 1,
2263 MSSM_EVENT_PORT_OFFLINE = 2,
2264 MSSM_EVENT_RSP_OK = 3,
2265 MSSM_EVENT_RSP_ERROR = 4,
2266 MSSM_EVENT_TIMEOUT = 5,
2267 MSSM_EVENT_FCXP_SENT = 6,
2268 MSSM_EVENT_PORT_FABRIC_RSCN = 7
2269 };
2270
2271 static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2272 enum port_ms_event event);
2273 static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2274 enum port_ms_event event);
2275 static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2276 enum port_ms_event event);
2277 static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2278 enum port_ms_event event);
2279 static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2280 enum port_ms_event event);
2281 static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2282 enum port_ms_event event);
2283 static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2284 enum port_ms_event event);
2285 static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2286 enum port_ms_event event);
2287 static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2288 enum port_ms_event event);
2289 static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2290 enum port_ms_event event);
2291 static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2292 enum port_ms_event event);
2293 /*
2294 * Start in offline state - awaiting NS to send start.
2295 */
2296 static void
2297 bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2298 enum port_ms_event event)
2299 {
2300 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2301 bfa_trc(ms->port->fcs, event);
2302
2303 switch (event) {
2304 case MSSM_EVENT_PORT_ONLINE:
2305 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2306 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2307 break;
2308
2309 case MSSM_EVENT_PORT_OFFLINE:
2310 break;
2311
2312 default:
2313 bfa_sm_fault(ms->port->fcs, event);
2314 }
2315 }
2316
2317 static void
2318 bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2319 enum port_ms_event event)
2320 {
2321 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2322 bfa_trc(ms->port->fcs, event);
2323
2324 switch (event) {
2325 case MSSM_EVENT_FCXP_SENT:
2326 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2327 break;
2328
2329 case MSSM_EVENT_PORT_OFFLINE:
2330 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2331 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2332 &ms->fcxp_wqe);
2333 break;
2334
2335 default:
2336 bfa_sm_fault(ms->port->fcs, event);
2337 }
2338 }
2339
2340 static void
2341 bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2342 enum port_ms_event event)
2343 {
2344 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2345 bfa_trc(ms->port->fcs, event);
2346
2347 switch (event) {
2348 case MSSM_EVENT_RSP_ERROR:
2349 /*
2350 * Start timer for a delayed retry
2351 */
2352 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2353 ms->port->stats.ms_retries++;
2354 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2355 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2356 BFA_FCS_RETRY_TIMEOUT);
2357 break;
2358
2359 case MSSM_EVENT_RSP_OK:
2360 /*
2361 * since plogi is done, now invoke MS related sub-modules
2362 */
2363 bfa_fcs_lport_fdmi_online(ms);
2364
2365 /*
2366 * if this is a Vport, go to online state.
2367 */
2368 if (ms->port->vport) {
2369 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2370 break;
2371 }
2372
2373 /*
2374 * For a base port we need to get the
2375 * switch's IP address.
2376 */
2377 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2378 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2379 break;
2380
2381 case MSSM_EVENT_PORT_OFFLINE:
2382 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2383 bfa_fcxp_discard(ms->fcxp);
2384 break;
2385
2386 default:
2387 bfa_sm_fault(ms->port->fcs, event);
2388 }
2389 }
2390
2391 static void
2392 bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2393 enum port_ms_event event)
2394 {
2395 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2396 bfa_trc(ms->port->fcs, event);
2397
2398 switch (event) {
2399 case MSSM_EVENT_TIMEOUT:
2400 /*
2401 * Retry Timer Expired. Re-send
2402 */
2403 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2404 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2405 break;
2406
2407 case MSSM_EVENT_PORT_OFFLINE:
2408 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2409 bfa_timer_stop(&ms->timer);
2410 break;
2411
2412 default:
2413 bfa_sm_fault(ms->port->fcs, event);
2414 }
2415 }
2416
2417 static void
2418 bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2419 enum port_ms_event event)
2420 {
2421 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2422 bfa_trc(ms->port->fcs, event);
2423
2424 switch (event) {
2425 case MSSM_EVENT_PORT_OFFLINE:
2426 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2427 break;
2428
2429 case MSSM_EVENT_PORT_FABRIC_RSCN:
2430 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2431 ms->retry_cnt = 0;
2432 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2433 break;
2434
2435 default:
2436 bfa_sm_fault(ms->port->fcs, event);
2437 }
2438 }
2439
2440 static void
2441 bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2442 enum port_ms_event event)
2443 {
2444 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2445 bfa_trc(ms->port->fcs, event);
2446
2447 switch (event) {
2448 case MSSM_EVENT_FCXP_SENT:
2449 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2450 break;
2451
2452 case MSSM_EVENT_PORT_OFFLINE:
2453 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2454 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2455 &ms->fcxp_wqe);
2456 break;
2457
2458 default:
2459 bfa_sm_fault(ms->port->fcs, event);
2460 }
2461 }
2462
2463 static void
2464 bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2465 enum port_ms_event event)
2466 {
2467 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2468 bfa_trc(ms->port->fcs, event);
2469
2470 switch (event) {
2471 case MSSM_EVENT_RSP_ERROR:
2472 /*
2473 * Start timer for a delayed retry
2474 */
2475 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2476 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2477 ms->port->stats.ms_retries++;
2478 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2479 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2480 BFA_FCS_RETRY_TIMEOUT);
2481 } else {
2482 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2483 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2484 ms->retry_cnt = 0;
2485 }
2486 break;
2487
2488 case MSSM_EVENT_RSP_OK:
2489 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2490 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2491 break;
2492
2493 case MSSM_EVENT_PORT_OFFLINE:
2494 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2495 bfa_fcxp_discard(ms->fcxp);
2496 break;
2497
2498 default:
2499 bfa_sm_fault(ms->port->fcs, event);
2500 }
2501 }
2502
2503 static void
2504 bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2505 enum port_ms_event event)
2506 {
2507 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2508 bfa_trc(ms->port->fcs, event);
2509
2510 switch (event) {
2511 case MSSM_EVENT_TIMEOUT:
2512 /*
2513 * Retry Timer Expired. Re-send
2514 */
2515 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2516 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2517 break;
2518
2519 case MSSM_EVENT_PORT_OFFLINE:
2520 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2521 bfa_timer_stop(&ms->timer);
2522 break;
2523
2524 default:
2525 bfa_sm_fault(ms->port->fcs, event);
2526 }
2527 }
2528 /*
2529 * ms_pvt MS local functions
2530 */
2531
2532 static void
2533 bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2534 {
2535 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2536 bfa_fcs_lport_t *port = ms->port;
2537 struct fchs_s fchs;
2538 int len;
2539 struct bfa_fcxp_s *fcxp;
2540
2541 bfa_trc(port->fcs, port->pid);
2542
2543 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2544 if (!fcxp) {
2545 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2546 bfa_fcs_lport_ms_send_gmal, ms);
2547 return;
2548 }
2549 ms->fcxp = fcxp;
2550
2551 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2552 bfa_fcs_lport_get_fcid(port),
2553 port->fabric->lps->pr_nwwn);
2554
2555 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2556 FC_CLASS_3, len, &fchs,
2557 bfa_fcs_lport_ms_gmal_response, (void *)ms,
2558 FC_MAX_PDUSZ, FC_FCCT_TOV);
2559
2560 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2561 }
2562
2563 static void
2564 bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2565 void *cbarg, bfa_status_t req_status,
2566 u32 rsp_len, u32 resid_len,
2567 struct fchs_s *rsp_fchs)
2568 {
2569 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2570 bfa_fcs_lport_t *port = ms->port;
2571 struct ct_hdr_s *cthdr = NULL;
2572 struct fcgs_gmal_resp_s *gmal_resp;
2573 struct fcgs_gmal_entry_s *gmal_entry;
2574 u32 num_entries;
2575 u8 *rsp_str;
2576
2577 bfa_trc(port->fcs, req_status);
2578 bfa_trc(port->fcs, port->port_cfg.pwwn);
2579
2580 /*
2581 * Sanity Checks
2582 */
2583 if (req_status != BFA_STATUS_OK) {
2584 bfa_trc(port->fcs, req_status);
2585 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2586 return;
2587 }
2588
2589 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2590 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2591
2592 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2593 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2594
2595 num_entries = be32_to_cpu(gmal_resp->ms_len);
2596 if (num_entries == 0) {
2597 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2598 return;
2599 }
2600 /*
2601 * The response could contain multiple Entries.
2602 * Entries for SNMP interface, etc.
2603 * We look for the entry with a telnet prefix.
2604 * First "http://" entry refers to IP addr
2605 */
2606
2607 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2608 while (num_entries > 0) {
2609 if (strncmp(gmal_entry->prefix,
2610 CT_GMAL_RESP_PREFIX_HTTP,
2611 sizeof(gmal_entry->prefix)) == 0) {
2612
2613 /*
2614 * if the IP address is terminating with a '/',
2615 * remove it.
2616 * Byte 0 consists of the length of the string.
2617 */
2618 rsp_str = &(gmal_entry->prefix[0]);
2619 if (rsp_str[gmal_entry->len-1] == '/')
2620 rsp_str[gmal_entry->len-1] = 0;
2621
2622 /* copy IP Address to fabric */
2623 strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2624 gmal_entry->ip_addr,
2625 BFA_FCS_FABRIC_IPADDR_SZ);
2626 break;
2627 } else {
2628 --num_entries;
2629 ++gmal_entry;
2630 }
2631 }
2632
2633 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2634 return;
2635 }
2636
2637 bfa_trc(port->fcs, cthdr->reason_code);
2638 bfa_trc(port->fcs, cthdr->exp_code);
2639 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2640 }
2641
2642 static void
2643 bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2644 enum port_ms_event event)
2645 {
2646 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2647 bfa_trc(ms->port->fcs, event);
2648
2649 switch (event) {
2650 case MSSM_EVENT_FCXP_SENT:
2651 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2652 break;
2653
2654 case MSSM_EVENT_PORT_OFFLINE:
2655 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2656 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2657 &ms->fcxp_wqe);
2658 break;
2659
2660 default:
2661 bfa_sm_fault(ms->port->fcs, event);
2662 }
2663 }
2664
2665 static void
2666 bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2667 enum port_ms_event event)
2668 {
2669 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2670 bfa_trc(ms->port->fcs, event);
2671
2672 switch (event) {
2673 case MSSM_EVENT_RSP_ERROR:
2674 /*
2675 * Start timer for a delayed retry
2676 */
2677 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2678 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2679 ms->port->stats.ms_retries++;
2680 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2681 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2682 BFA_FCS_RETRY_TIMEOUT);
2683 } else {
2684 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2685 ms->retry_cnt = 0;
2686 }
2687 break;
2688
2689 case MSSM_EVENT_RSP_OK:
2690 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2691 break;
2692
2693 case MSSM_EVENT_PORT_OFFLINE:
2694 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2695 bfa_fcxp_discard(ms->fcxp);
2696 break;
2697
2698 default:
2699 bfa_sm_fault(ms->port->fcs, event);
2700 }
2701 }
2702
2703 static void
2704 bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2705 enum port_ms_event event)
2706 {
2707 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2708 bfa_trc(ms->port->fcs, event);
2709
2710 switch (event) {
2711 case MSSM_EVENT_TIMEOUT:
2712 /*
2713 * Retry Timer Expired. Re-send
2714 */
2715 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2716 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2717 break;
2718
2719 case MSSM_EVENT_PORT_OFFLINE:
2720 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2721 bfa_timer_stop(&ms->timer);
2722 break;
2723
2724 default:
2725 bfa_sm_fault(ms->port->fcs, event);
2726 }
2727 }
2728 /*
2729 * ms_pvt MS local functions
2730 */
2731
2732 static void
2733 bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2734 {
2735 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2736 bfa_fcs_lport_t *port = ms->port;
2737 struct fchs_s fchs;
2738 int len;
2739 struct bfa_fcxp_s *fcxp;
2740
2741 bfa_trc(port->fcs, port->pid);
2742
2743 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2744 if (!fcxp) {
2745 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2746 bfa_fcs_lport_ms_send_gfn, ms);
2747 return;
2748 }
2749 ms->fcxp = fcxp;
2750
2751 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2752 bfa_fcs_lport_get_fcid(port),
2753 port->fabric->lps->pr_nwwn);
2754
2755 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2756 FC_CLASS_3, len, &fchs,
2757 bfa_fcs_lport_ms_gfn_response, (void *)ms,
2758 FC_MAX_PDUSZ, FC_FCCT_TOV);
2759
2760 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2761 }
2762
2763 static void
2764 bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2765 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2766 u32 resid_len, struct fchs_s *rsp_fchs)
2767 {
2768 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2769 bfa_fcs_lport_t *port = ms->port;
2770 struct ct_hdr_s *cthdr = NULL;
2771 wwn_t *gfn_resp;
2772
2773 bfa_trc(port->fcs, req_status);
2774 bfa_trc(port->fcs, port->port_cfg.pwwn);
2775
2776 /*
2777 * Sanity Checks
2778 */
2779 if (req_status != BFA_STATUS_OK) {
2780 bfa_trc(port->fcs, req_status);
2781 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2782 return;
2783 }
2784
2785 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2786 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2787
2788 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2789 gfn_resp = (wwn_t *)(cthdr + 1);
2790 /* check if it has actually changed */
2791 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2792 gfn_resp, sizeof(wwn_t)) != 0)) {
2793 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2794 }
2795 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2796 return;
2797 }
2798
2799 bfa_trc(port->fcs, cthdr->reason_code);
2800 bfa_trc(port->fcs, cthdr->exp_code);
2801 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2802 }
2803
2804 /*
2805 * ms_pvt MS local functions
2806 */
2807
2808 static void
2809 bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2810 {
2811 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2812 struct bfa_fcs_lport_s *port = ms->port;
2813 struct fchs_s fchs;
2814 int len;
2815 struct bfa_fcxp_s *fcxp;
2816
2817 bfa_trc(port->fcs, port->pid);
2818
2819 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2820 if (!fcxp) {
2821 port->stats.ms_plogi_alloc_wait++;
2822 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2823 bfa_fcs_lport_ms_send_plogi, ms);
2824 return;
2825 }
2826 ms->fcxp = fcxp;
2827
2828 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2829 bfa_hton3b(FC_MGMT_SERVER),
2830 bfa_fcs_lport_get_fcid(port), 0,
2831 port->port_cfg.pwwn, port->port_cfg.nwwn,
2832 bfa_fcport_get_maxfrsize(port->fcs->bfa));
2833
2834 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2835 FC_CLASS_3, len, &fchs,
2836 bfa_fcs_lport_ms_plogi_response, (void *)ms,
2837 FC_MAX_PDUSZ, FC_ELS_TOV);
2838
2839 port->stats.ms_plogi_sent++;
2840 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2841 }
2842
2843 static void
2844 bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2845 void *cbarg, bfa_status_t req_status,
2846 u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
2847 {
2848 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2849 struct bfa_fcs_lport_s *port = ms->port;
2850 struct fc_els_cmd_s *els_cmd;
2851 struct fc_ls_rjt_s *ls_rjt;
2852
2853 bfa_trc(port->fcs, req_status);
2854 bfa_trc(port->fcs, port->port_cfg.pwwn);
2855
2856 /*
2857 * Sanity Checks
2858 */
2859 if (req_status != BFA_STATUS_OK) {
2860 port->stats.ms_plogi_rsp_err++;
2861 bfa_trc(port->fcs, req_status);
2862 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2863 return;
2864 }
2865
2866 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2867
2868 switch (els_cmd->els_code) {
2869
2870 case FC_ELS_ACC:
2871 if (rsp_len < sizeof(struct fc_logi_s)) {
2872 bfa_trc(port->fcs, rsp_len);
2873 port->stats.ms_plogi_acc_err++;
2874 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2875 break;
2876 }
2877 port->stats.ms_plogi_accepts++;
2878 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2879 break;
2880
2881 case FC_ELS_LS_RJT:
2882 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2883
2884 bfa_trc(port->fcs, ls_rjt->reason_code);
2885 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2886
2887 port->stats.ms_rejects++;
2888 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2889 break;
2890
2891 default:
2892 port->stats.ms_plogi_unknown_rsp++;
2893 bfa_trc(port->fcs, els_cmd->els_code);
2894 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2895 }
2896 }
2897
2898 static void
2899 bfa_fcs_lport_ms_timeout(void *arg)
2900 {
2901 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2902
2903 ms->port->stats.ms_timeouts++;
2904 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2905 }
2906
2907
2908 void
2909 bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2910 {
2911 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2912
2913 ms->port = port;
2914 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2915
2916 /*
2917 * Invoke init routines of sub modules.
2918 */
2919 bfa_fcs_lport_fdmi_init(ms);
2920 }
2921
2922 void
2923 bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2924 {
2925 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2926
2927 ms->port = port;
2928 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2929 bfa_fcs_lport_fdmi_offline(ms);
2930 }
2931
2932 void
2933 bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
2934 {
2935 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2936
2937 ms->port = port;
2938 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
2939 }
2940 void
2941 bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
2942 {
2943 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2944
2945 /* todo. Handle this only when in Online state */
2946 if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
2947 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
2948 }
2949
2950 /*
2951 * @page ns_sm_info VPORT NS State Machine
2952 *
2953 * @section ns_sm_interactions VPORT NS State Machine Interactions
2954 *
2955 * @section ns_sm VPORT NS State Machine
2956 * img ns_sm.jpg
2957 */
2958
2959 /*
2960 * forward declarations
2961 */
2962 static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
2963 struct bfa_fcxp_s *fcxp_alloced);
2964 static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
2965 struct bfa_fcxp_s *fcxp_alloced);
2966 static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
2967 struct bfa_fcxp_s *fcxp_alloced);
2968 static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
2969 struct bfa_fcxp_s *fcxp_alloced);
2970 static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
2971 struct bfa_fcxp_s *fcxp_alloced);
2972 static void bfa_fcs_lport_ns_timeout(void *arg);
2973 static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
2974 struct bfa_fcxp_s *fcxp,
2975 void *cbarg,
2976 bfa_status_t req_status,
2977 u32 rsp_len,
2978 u32 resid_len,
2979 struct fchs_s *rsp_fchs);
2980 static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
2981 struct bfa_fcxp_s *fcxp,
2982 void *cbarg,
2983 bfa_status_t req_status,
2984 u32 rsp_len,
2985 u32 resid_len,
2986 struct fchs_s *rsp_fchs);
2987 static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
2988 struct bfa_fcxp_s *fcxp,
2989 void *cbarg,
2990 bfa_status_t req_status,
2991 u32 rsp_len,
2992 u32 resid_len,
2993 struct fchs_s *rsp_fchs);
2994 static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
2995 struct bfa_fcxp_s *fcxp,
2996 void *cbarg,
2997 bfa_status_t req_status,
2998 u32 rsp_len,
2999 u32 resid_len,
3000 struct fchs_s *rsp_fchs);
3001 static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3002 struct bfa_fcxp_s *fcxp,
3003 void *cbarg,
3004 bfa_status_t req_status,
3005 u32 rsp_len,
3006 u32 resid_len,
3007 struct fchs_s *rsp_fchs);
3008 static void bfa_fcs_lport_ns_process_gidft_pids(
3009 struct bfa_fcs_lport_s *port,
3010 u32 *pid_buf, u32 n_pids);
3011
3012 static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3013 /*
3014 * fcs_ns_sm FCS nameserver interface state machine
3015 */
3016
3017 /*
3018 * VPort NS State Machine events
3019 */
3020 enum vport_ns_event {
3021 NSSM_EVENT_PORT_ONLINE = 1,
3022 NSSM_EVENT_PORT_OFFLINE = 2,
3023 NSSM_EVENT_PLOGI_SENT = 3,
3024 NSSM_EVENT_RSP_OK = 4,
3025 NSSM_EVENT_RSP_ERROR = 5,
3026 NSSM_EVENT_TIMEOUT = 6,
3027 NSSM_EVENT_NS_QUERY = 7,
3028 NSSM_EVENT_RSPNID_SENT = 8,
3029 NSSM_EVENT_RFTID_SENT = 9,
3030 NSSM_EVENT_RFFID_SENT = 10,
3031 NSSM_EVENT_GIDFT_SENT = 11,
3032 };
3033
3034 static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3035 enum vport_ns_event event);
3036 static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3037 enum vport_ns_event event);
3038 static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3039 enum vport_ns_event event);
3040 static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3041 enum vport_ns_event event);
3042 static void bfa_fcs_lport_ns_sm_sending_rspn_id(
3043 struct bfa_fcs_lport_ns_s *ns,
3044 enum vport_ns_event event);
3045 static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3046 enum vport_ns_event event);
3047 static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3048 enum vport_ns_event event);
3049 static void bfa_fcs_lport_ns_sm_sending_rft_id(
3050 struct bfa_fcs_lport_ns_s *ns,
3051 enum vport_ns_event event);
3052 static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3053 enum vport_ns_event event);
3054 static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3055 enum vport_ns_event event);
3056 static void bfa_fcs_lport_ns_sm_sending_rff_id(
3057 struct bfa_fcs_lport_ns_s *ns,
3058 enum vport_ns_event event);
3059 static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3060 enum vport_ns_event event);
3061 static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3062 enum vport_ns_event event);
3063 static void bfa_fcs_lport_ns_sm_sending_gid_ft(
3064 struct bfa_fcs_lport_ns_s *ns,
3065 enum vport_ns_event event);
3066 static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3067 enum vport_ns_event event);
3068 static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3069 enum vport_ns_event event);
3070 static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3071 enum vport_ns_event event);
3072 /*
3073 * Start in offline state - awaiting linkup
3074 */
3075 static void
3076 bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3077 enum vport_ns_event event)
3078 {
3079 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3080 bfa_trc(ns->port->fcs, event);
3081
3082 switch (event) {
3083 case NSSM_EVENT_PORT_ONLINE:
3084 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3085 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3086 break;
3087
3088 case NSSM_EVENT_PORT_OFFLINE:
3089 break;
3090
3091 default:
3092 bfa_sm_fault(ns->port->fcs, event);
3093 }
3094 }
3095
3096 static void
3097 bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3098 enum vport_ns_event event)
3099 {
3100 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3101 bfa_trc(ns->port->fcs, event);
3102
3103 switch (event) {
3104 case NSSM_EVENT_PLOGI_SENT:
3105 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3106 break;
3107
3108 case NSSM_EVENT_PORT_OFFLINE:
3109 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3110 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3111 &ns->fcxp_wqe);
3112 break;
3113
3114 default:
3115 bfa_sm_fault(ns->port->fcs, event);
3116 }
3117 }
3118
3119 static void
3120 bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3121 enum vport_ns_event event)
3122 {
3123 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3124 bfa_trc(ns->port->fcs, event);
3125
3126 switch (event) {
3127 case NSSM_EVENT_RSP_ERROR:
3128 /*
3129 * Start timer for a delayed retry
3130 */
3131 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3132 ns->port->stats.ns_retries++;
3133 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3134 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3135 BFA_FCS_RETRY_TIMEOUT);
3136 break;
3137
3138 case NSSM_EVENT_RSP_OK:
3139 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3140 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3141 break;
3142
3143 case NSSM_EVENT_PORT_OFFLINE:
3144 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3145 bfa_fcxp_discard(ns->fcxp);
3146 break;
3147
3148 default:
3149 bfa_sm_fault(ns->port->fcs, event);
3150 }
3151 }
3152
3153 static void
3154 bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3155 enum vport_ns_event event)
3156 {
3157 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3158 bfa_trc(ns->port->fcs, event);
3159
3160 switch (event) {
3161 case NSSM_EVENT_TIMEOUT:
3162 /*
3163 * Retry Timer Expired. Re-send
3164 */
3165 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3166 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3167 break;
3168
3169 case NSSM_EVENT_PORT_OFFLINE:
3170 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3171 bfa_timer_stop(&ns->timer);
3172 break;
3173
3174 default:
3175 bfa_sm_fault(ns->port->fcs, event);
3176 }
3177 }
3178
3179 static void
3180 bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3181 enum vport_ns_event event)
3182 {
3183 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3184 bfa_trc(ns->port->fcs, event);
3185
3186 switch (event) {
3187 case NSSM_EVENT_RSPNID_SENT:
3188 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3189 break;
3190
3191 case NSSM_EVENT_PORT_OFFLINE:
3192 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3193 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3194 &ns->fcxp_wqe);
3195 break;
3196
3197 default:
3198 bfa_sm_fault(ns->port->fcs, event);
3199 }
3200 }
3201
3202 static void
3203 bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3204 enum vport_ns_event event)
3205 {
3206 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3207 bfa_trc(ns->port->fcs, event);
3208
3209 switch (event) {
3210 case NSSM_EVENT_RSP_ERROR:
3211 /*
3212 * Start timer for a delayed retry
3213 */
3214 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3215 ns->port->stats.ns_retries++;
3216 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3217 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3218 BFA_FCS_RETRY_TIMEOUT);
3219 break;
3220
3221 case NSSM_EVENT_RSP_OK:
3222 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3223 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3224 break;
3225
3226 case NSSM_EVENT_PORT_OFFLINE:
3227 bfa_fcxp_discard(ns->fcxp);
3228 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3229 break;
3230
3231 default:
3232 bfa_sm_fault(ns->port->fcs, event);
3233 }
3234 }
3235
3236 static void
3237 bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3238 enum vport_ns_event event)
3239 {
3240 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3241 bfa_trc(ns->port->fcs, event);
3242
3243 switch (event) {
3244 case NSSM_EVENT_TIMEOUT:
3245 /*
3246 * Retry Timer Expired. Re-send
3247 */
3248 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3249 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3250 break;
3251
3252 case NSSM_EVENT_PORT_OFFLINE:
3253 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3254 bfa_timer_stop(&ns->timer);
3255 break;
3256
3257 default:
3258 bfa_sm_fault(ns->port->fcs, event);
3259 }
3260 }
3261
3262 static void
3263 bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3264 enum vport_ns_event event)
3265 {
3266 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3267 bfa_trc(ns->port->fcs, event);
3268
3269 switch (event) {
3270 case NSSM_EVENT_RFTID_SENT:
3271 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3272 break;
3273
3274 case NSSM_EVENT_PORT_OFFLINE:
3275 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3276 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3277 &ns->fcxp_wqe);
3278 break;
3279
3280 default:
3281 bfa_sm_fault(ns->port->fcs, event);
3282 }
3283 }
3284
3285 static void
3286 bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3287 enum vport_ns_event event)
3288 {
3289 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3290 bfa_trc(ns->port->fcs, event);
3291
3292 switch (event) {
3293 case NSSM_EVENT_RSP_OK:
3294 /* Now move to register FC4 Features */
3295 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3296 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3297 break;
3298
3299 case NSSM_EVENT_RSP_ERROR:
3300 /*
3301 * Start timer for a delayed retry
3302 */
3303 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3304 ns->port->stats.ns_retries++;
3305 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3306 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3307 BFA_FCS_RETRY_TIMEOUT);
3308 break;
3309
3310 case NSSM_EVENT_PORT_OFFLINE:
3311 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3312 bfa_fcxp_discard(ns->fcxp);
3313 break;
3314
3315 default:
3316 bfa_sm_fault(ns->port->fcs, event);
3317 }
3318 }
3319
3320 static void
3321 bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3322 enum vport_ns_event event)
3323 {
3324 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3325 bfa_trc(ns->port->fcs, event);
3326
3327 switch (event) {
3328 case NSSM_EVENT_TIMEOUT:
3329 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3330 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3331 break;
3332
3333 case NSSM_EVENT_PORT_OFFLINE:
3334 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3335 bfa_timer_stop(&ns->timer);
3336 break;
3337
3338 default:
3339 bfa_sm_fault(ns->port->fcs, event);
3340 }
3341 }
3342
3343 static void
3344 bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3345 enum vport_ns_event event)
3346 {
3347 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3348 bfa_trc(ns->port->fcs, event);
3349
3350 switch (event) {
3351 case NSSM_EVENT_RFFID_SENT:
3352 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3353 break;
3354
3355 case NSSM_EVENT_PORT_OFFLINE:
3356 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3357 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3358 &ns->fcxp_wqe);
3359 break;
3360
3361 default:
3362 bfa_sm_fault(ns->port->fcs, event);
3363 }
3364 }
3365
3366 static void
3367 bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3368 enum vport_ns_event event)
3369 {
3370 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3371 bfa_trc(ns->port->fcs, event);
3372
3373 switch (event) {
3374 case NSSM_EVENT_RSP_OK:
3375
3376 /*
3377 * If min cfg mode is enabled, we donot initiate rport
3378 * discovery with the fabric. Instead, we will retrieve the
3379 * boot targets from HAL/FW.
3380 */
3381 if (__fcs_min_cfg(ns->port->fcs)) {
3382 bfa_fcs_lport_ns_boot_target_disc(ns->port);
3383 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3384 return;
3385 }
3386
3387 /*
3388 * If the port role is Initiator Mode issue NS query.
3389 * If it is Target Mode, skip this and go to online.
3390 */
3391 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3392 bfa_sm_set_state(ns,
3393 bfa_fcs_lport_ns_sm_sending_gid_ft);
3394 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3395 }
3396 /*
3397 * kick off mgmt srvr state machine
3398 */
3399 bfa_fcs_lport_ms_online(ns->port);
3400 break;
3401
3402 case NSSM_EVENT_RSP_ERROR:
3403 /*
3404 * Start timer for a delayed retry
3405 */
3406 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3407 ns->port->stats.ns_retries++;
3408 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3409 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3410 BFA_FCS_RETRY_TIMEOUT);
3411 break;
3412
3413 case NSSM_EVENT_PORT_OFFLINE:
3414 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3415 bfa_fcxp_discard(ns->fcxp);
3416 break;
3417
3418 default:
3419 bfa_sm_fault(ns->port->fcs, event);
3420 }
3421 }
3422
3423 static void
3424 bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3425 enum vport_ns_event event)
3426 {
3427 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3428 bfa_trc(ns->port->fcs, event);
3429
3430 switch (event) {
3431 case NSSM_EVENT_TIMEOUT:
3432 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3433 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3434 break;
3435
3436 case NSSM_EVENT_PORT_OFFLINE:
3437 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3438 bfa_timer_stop(&ns->timer);
3439 break;
3440
3441 default:
3442 bfa_sm_fault(ns->port->fcs, event);
3443 }
3444 }
3445 static void
3446 bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3447 enum vport_ns_event event)
3448 {
3449 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3450 bfa_trc(ns->port->fcs, event);
3451
3452 switch (event) {
3453 case NSSM_EVENT_GIDFT_SENT:
3454 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3455 break;
3456
3457 case NSSM_EVENT_PORT_OFFLINE:
3458 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3459 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3460 &ns->fcxp_wqe);
3461 break;
3462
3463 default:
3464 bfa_sm_fault(ns->port->fcs, event);
3465 }
3466 }
3467
3468 static void
3469 bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3470 enum vport_ns_event event)
3471 {
3472 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3473 bfa_trc(ns->port->fcs, event);
3474
3475 switch (event) {
3476 case NSSM_EVENT_RSP_OK:
3477 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3478 break;
3479
3480 case NSSM_EVENT_RSP_ERROR:
3481 /*
3482 * TBD: for certain reject codes, we don't need to retry
3483 */
3484 /*
3485 * Start timer for a delayed retry
3486 */
3487 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3488 ns->port->stats.ns_retries++;
3489 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3490 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3491 BFA_FCS_RETRY_TIMEOUT);
3492 break;
3493
3494 case NSSM_EVENT_PORT_OFFLINE:
3495 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3496 bfa_fcxp_discard(ns->fcxp);
3497 break;
3498
3499 case NSSM_EVENT_NS_QUERY:
3500 break;
3501
3502 default:
3503 bfa_sm_fault(ns->port->fcs, event);
3504 }
3505 }
3506
3507 static void
3508 bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3509 enum vport_ns_event event)
3510 {
3511 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3512 bfa_trc(ns->port->fcs, event);
3513
3514 switch (event) {
3515 case NSSM_EVENT_TIMEOUT:
3516 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3517 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3518 break;
3519
3520 case NSSM_EVENT_PORT_OFFLINE:
3521 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3522 bfa_timer_stop(&ns->timer);
3523 break;
3524
3525 default:
3526 bfa_sm_fault(ns->port->fcs, event);
3527 }
3528 }
3529
3530 static void
3531 bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3532 enum vport_ns_event event)
3533 {
3534 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3535 bfa_trc(ns->port->fcs, event);
3536
3537 switch (event) {
3538 case NSSM_EVENT_PORT_OFFLINE:
3539 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3540 break;
3541
3542 case NSSM_EVENT_NS_QUERY:
3543 /*
3544 * If the port role is Initiator Mode issue NS query.
3545 * If it is Target Mode, skip this and go to online.
3546 */
3547 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3548 bfa_sm_set_state(ns,
3549 bfa_fcs_lport_ns_sm_sending_gid_ft);
3550 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3551 };
3552 break;
3553
3554 default:
3555 bfa_sm_fault(ns->port->fcs, event);
3556 }
3557 }
3558
3559
3560
3561 /*
3562 * ns_pvt Nameserver local functions
3563 */
3564
3565 static void
3566 bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3567 {
3568 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3569 struct bfa_fcs_lport_s *port = ns->port;
3570 struct fchs_s fchs;
3571 int len;
3572 struct bfa_fcxp_s *fcxp;
3573
3574 bfa_trc(port->fcs, port->pid);
3575
3576 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3577 if (!fcxp) {
3578 port->stats.ns_plogi_alloc_wait++;
3579 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3580 bfa_fcs_lport_ns_send_plogi, ns);
3581 return;
3582 }
3583 ns->fcxp = fcxp;
3584
3585 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3586 bfa_hton3b(FC_NAME_SERVER),
3587 bfa_fcs_lport_get_fcid(port), 0,
3588 port->port_cfg.pwwn, port->port_cfg.nwwn,
3589 bfa_fcport_get_maxfrsize(port->fcs->bfa));
3590
3591 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3592 FC_CLASS_3, len, &fchs,
3593 bfa_fcs_lport_ns_plogi_response, (void *)ns,
3594 FC_MAX_PDUSZ, FC_ELS_TOV);
3595 port->stats.ns_plogi_sent++;
3596
3597 bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3598 }
3599
3600 static void
3601 bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3602 void *cbarg, bfa_status_t req_status, u32 rsp_len,
3603 u32 resid_len, struct fchs_s *rsp_fchs)
3604 {
3605 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3606 struct bfa_fcs_lport_s *port = ns->port;
3607 /* struct fc_logi_s *plogi_resp; */
3608 struct fc_els_cmd_s *els_cmd;
3609 struct fc_ls_rjt_s *ls_rjt;
3610
3611 bfa_trc(port->fcs, req_status);
3612 bfa_trc(port->fcs, port->port_cfg.pwwn);
3613
3614 /*
3615 * Sanity Checks
3616 */
3617 if (req_status != BFA_STATUS_OK) {
3618 bfa_trc(port->fcs, req_status);
3619 port->stats.ns_plogi_rsp_err++;
3620 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3621 return;
3622 }
3623
3624 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3625
3626 switch (els_cmd->els_code) {
3627
3628 case FC_ELS_ACC:
3629 if (rsp_len < sizeof(struct fc_logi_s)) {
3630 bfa_trc(port->fcs, rsp_len);
3631 port->stats.ns_plogi_acc_err++;
3632 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3633 break;
3634 }
3635 port->stats.ns_plogi_accepts++;
3636 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3637 break;
3638
3639 case FC_ELS_LS_RJT:
3640 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3641
3642 bfa_trc(port->fcs, ls_rjt->reason_code);
3643 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3644
3645 port->stats.ns_rejects++;
3646
3647 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3648 break;
3649
3650 default:
3651 port->stats.ns_plogi_unknown_rsp++;
3652 bfa_trc(port->fcs, els_cmd->els_code);
3653 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3654 }
3655 }
3656
3657 /*
3658 * Register the symbolic port name.
3659 */
3660 static void
3661 bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3662 {
3663 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3664 struct bfa_fcs_lport_s *port = ns->port;
3665 struct fchs_s fchs;
3666 int len;
3667 struct bfa_fcxp_s *fcxp;
3668 u8 symbl[256];
3669 u8 *psymbl = &symbl[0];
3670
3671 memset(symbl, 0, sizeof(symbl));
3672
3673 bfa_trc(port->fcs, port->port_cfg.pwwn);
3674
3675 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3676 if (!fcxp) {
3677 port->stats.ns_rspnid_alloc_wait++;
3678 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3679 bfa_fcs_lport_ns_send_rspn_id, ns);
3680 return;
3681 }
3682 ns->fcxp = fcxp;
3683
3684 /*
3685 * for V-Port, form a Port Symbolic Name
3686 */
3687 if (port->vport) {
3688 /*
3689 * For Vports, we append the vport's port symbolic name
3690 * to that of the base port.
3691 */
3692
3693 strncpy((char *)psymbl,
3694 (char *) &
3695 (bfa_fcs_lport_get_psym_name
3696 (bfa_fcs_get_base_port(port->fcs))),
3697 strlen((char *) &
3698 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3699 (port->fcs))));
3700
3701 /* Ensure we have a null terminating string. */
3702 ((char *)psymbl)[strlen((char *) &
3703 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3704 (port->fcs)))] = 0;
3705 strncat((char *)psymbl,
3706 (char *) &(bfa_fcs_lport_get_psym_name(port)),
3707 strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
3708 } else {
3709 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
3710 }
3711
3712 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3713 bfa_fcs_lport_get_fcid(port), 0, psymbl);
3714
3715 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3716 FC_CLASS_3, len, &fchs,
3717 bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
3718 FC_MAX_PDUSZ, FC_FCCT_TOV);
3719
3720 port->stats.ns_rspnid_sent++;
3721
3722 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3723 }
3724
3725 static void
3726 bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3727 void *cbarg, bfa_status_t req_status,
3728 u32 rsp_len, u32 resid_len,
3729 struct fchs_s *rsp_fchs)
3730 {
3731 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3732 struct bfa_fcs_lport_s *port = ns->port;
3733 struct ct_hdr_s *cthdr = NULL;
3734
3735 bfa_trc(port->fcs, port->port_cfg.pwwn);
3736
3737 /*
3738 * Sanity Checks
3739 */
3740 if (req_status != BFA_STATUS_OK) {
3741 bfa_trc(port->fcs, req_status);
3742 port->stats.ns_rspnid_rsp_err++;
3743 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3744 return;
3745 }
3746
3747 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3748 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3749
3750 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3751 port->stats.ns_rspnid_accepts++;
3752 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3753 return;
3754 }
3755
3756 port->stats.ns_rspnid_rejects++;
3757 bfa_trc(port->fcs, cthdr->reason_code);
3758 bfa_trc(port->fcs, cthdr->exp_code);
3759 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3760 }
3761
3762 /*
3763 * Register FC4-Types
3764 */
3765 static void
3766 bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3767 {
3768 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3769 struct bfa_fcs_lport_s *port = ns->port;
3770 struct fchs_s fchs;
3771 int len;
3772 struct bfa_fcxp_s *fcxp;
3773
3774 bfa_trc(port->fcs, port->port_cfg.pwwn);
3775
3776 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3777 if (!fcxp) {
3778 port->stats.ns_rftid_alloc_wait++;
3779 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3780 bfa_fcs_lport_ns_send_rft_id, ns);
3781 return;
3782 }
3783 ns->fcxp = fcxp;
3784
3785 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3786 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
3787
3788 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3789 FC_CLASS_3, len, &fchs,
3790 bfa_fcs_lport_ns_rft_id_response, (void *)ns,
3791 FC_MAX_PDUSZ, FC_FCCT_TOV);
3792
3793 port->stats.ns_rftid_sent++;
3794 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3795 }
3796
3797 static void
3798 bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3799 void *cbarg, bfa_status_t req_status,
3800 u32 rsp_len, u32 resid_len,
3801 struct fchs_s *rsp_fchs)
3802 {
3803 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3804 struct bfa_fcs_lport_s *port = ns->port;
3805 struct ct_hdr_s *cthdr = NULL;
3806
3807 bfa_trc(port->fcs, port->port_cfg.pwwn);
3808
3809 /*
3810 * Sanity Checks
3811 */
3812 if (req_status != BFA_STATUS_OK) {
3813 bfa_trc(port->fcs, req_status);
3814 port->stats.ns_rftid_rsp_err++;
3815 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3816 return;
3817 }
3818
3819 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3820 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3821
3822 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3823 port->stats.ns_rftid_accepts++;
3824 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3825 return;
3826 }
3827
3828 port->stats.ns_rftid_rejects++;
3829 bfa_trc(port->fcs, cthdr->reason_code);
3830 bfa_trc(port->fcs, cthdr->exp_code);
3831 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3832 }
3833
3834 /*
3835 * Register FC4-Features : Should be done after RFT_ID
3836 */
3837 static void
3838 bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3839 {
3840 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3841 struct bfa_fcs_lport_s *port = ns->port;
3842 struct fchs_s fchs;
3843 int len;
3844 struct bfa_fcxp_s *fcxp;
3845 u8 fc4_ftrs = 0;
3846
3847 bfa_trc(port->fcs, port->port_cfg.pwwn);
3848
3849 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3850 if (!fcxp) {
3851 port->stats.ns_rffid_alloc_wait++;
3852 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3853 bfa_fcs_lport_ns_send_rff_id, ns);
3854 return;
3855 }
3856 ns->fcxp = fcxp;
3857
3858 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
3859 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
3860
3861 len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3862 bfa_fcs_lport_get_fcid(port), 0,
3863 FC_TYPE_FCP, fc4_ftrs);
3864
3865 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3866 FC_CLASS_3, len, &fchs,
3867 bfa_fcs_lport_ns_rff_id_response, (void *)ns,
3868 FC_MAX_PDUSZ, FC_FCCT_TOV);
3869
3870 port->stats.ns_rffid_sent++;
3871 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
3872 }
3873
3874 static void
3875 bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3876 void *cbarg, bfa_status_t req_status,
3877 u32 rsp_len, u32 resid_len,
3878 struct fchs_s *rsp_fchs)
3879 {
3880 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3881 struct bfa_fcs_lport_s *port = ns->port;
3882 struct ct_hdr_s *cthdr = NULL;
3883
3884 bfa_trc(port->fcs, port->port_cfg.pwwn);
3885
3886 /*
3887 * Sanity Checks
3888 */
3889 if (req_status != BFA_STATUS_OK) {
3890 bfa_trc(port->fcs, req_status);
3891 port->stats.ns_rffid_rsp_err++;
3892 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3893 return;
3894 }
3895
3896 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3897 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3898
3899 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3900 port->stats.ns_rffid_accepts++;
3901 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3902 return;
3903 }
3904
3905 port->stats.ns_rffid_rejects++;
3906 bfa_trc(port->fcs, cthdr->reason_code);
3907 bfa_trc(port->fcs, cthdr->exp_code);
3908
3909 if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
3910 /* if this command is not supported, we don't retry */
3911 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3912 } else
3913 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3914 }
3915 /*
3916 * Query Fabric for FC4-Types Devices.
3917 *
3918 * TBD : Need to use a local (FCS private) response buffer, since the response
3919 * can be larger than 2K.
3920 */
3921 static void
3922 bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3923 {
3924 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3925 struct bfa_fcs_lport_s *port = ns->port;
3926 struct fchs_s fchs;
3927 int len;
3928 struct bfa_fcxp_s *fcxp;
3929
3930 bfa_trc(port->fcs, port->pid);
3931
3932 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3933 if (!fcxp) {
3934 port->stats.ns_gidft_alloc_wait++;
3935 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3936 bfa_fcs_lport_ns_send_gid_ft, ns);
3937 return;
3938 }
3939 ns->fcxp = fcxp;
3940
3941 /*
3942 * This query is only initiated for FCP initiator mode.
3943 */
3944 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3945 ns->port->pid, FC_TYPE_FCP);
3946
3947 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3948 FC_CLASS_3, len, &fchs,
3949 bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
3950 bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
3951
3952 port->stats.ns_gidft_sent++;
3953
3954 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
3955 }
3956
3957 static void
3958 bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3959 void *cbarg, bfa_status_t req_status,
3960 u32 rsp_len, u32 resid_len,
3961 struct fchs_s *rsp_fchs)
3962 {
3963 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3964 struct bfa_fcs_lport_s *port = ns->port;
3965 struct ct_hdr_s *cthdr = NULL;
3966 u32 n_pids;
3967
3968 bfa_trc(port->fcs, port->port_cfg.pwwn);
3969
3970 /*
3971 * Sanity Checks
3972 */
3973 if (req_status != BFA_STATUS_OK) {
3974 bfa_trc(port->fcs, req_status);
3975 port->stats.ns_gidft_rsp_err++;
3976 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3977 return;
3978 }
3979
3980 if (resid_len != 0) {
3981 /*
3982 * TBD : we will need to allocate a larger buffer & retry the
3983 * command
3984 */
3985 bfa_trc(port->fcs, rsp_len);
3986 bfa_trc(port->fcs, resid_len);
3987 return;
3988 }
3989
3990 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3991 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3992
3993 switch (cthdr->cmd_rsp_code) {
3994
3995 case CT_RSP_ACCEPT:
3996
3997 port->stats.ns_gidft_accepts++;
3998 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
3999 bfa_trc(port->fcs, n_pids);
4000 bfa_fcs_lport_ns_process_gidft_pids(port,
4001 (u32 *) (cthdr + 1),
4002 n_pids);
4003 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4004 break;
4005
4006 case CT_RSP_REJECT:
4007
4008 /*
4009 * Check the reason code & explanation.
4010 * There may not have been any FC4 devices in the fabric
4011 */
4012 port->stats.ns_gidft_rejects++;
4013 bfa_trc(port->fcs, cthdr->reason_code);
4014 bfa_trc(port->fcs, cthdr->exp_code);
4015
4016 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4017 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4018
4019 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4020 } else {
4021 /*
4022 * for all other errors, retry
4023 */
4024 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4025 }
4026 break;
4027
4028 default:
4029 port->stats.ns_gidft_unknown_rsp++;
4030 bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4031 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4032 }
4033 }
4034
4035 /*
4036 * This routine will be called by bfa_timer on timer timeouts.
4037 *
4038 * param[in] port - pointer to bfa_fcs_lport_t.
4039 *
4040 * return
4041 * void
4042 *
4043 * Special Considerations:
4044 *
4045 * note
4046 */
4047 static void
4048 bfa_fcs_lport_ns_timeout(void *arg)
4049 {
4050 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4051
4052 ns->port->stats.ns_timeouts++;
4053 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4054 }
4055
4056 /*
4057 * Process the PID list in GID_FT response
4058 */
4059 static void
4060 bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4061 u32 n_pids)
4062 {
4063 struct fcgs_gidft_resp_s *gidft_entry;
4064 struct bfa_fcs_rport_s *rport;
4065 u32 ii;
4066
4067 for (ii = 0; ii < n_pids; ii++) {
4068 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4069
4070 if (gidft_entry->pid == port->pid)
4071 continue;
4072
4073 /*
4074 * Check if this rport already exists
4075 */
4076 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4077 if (rport == NULL) {
4078 /*
4079 * this is a new device. create rport
4080 */
4081 rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4082 } else {
4083 /*
4084 * this rport already exists
4085 */
4086 bfa_fcs_rport_scn(rport);
4087 }
4088
4089 bfa_trc(port->fcs, gidft_entry->pid);
4090
4091 /*
4092 * if the last entry bit is set, bail out.
4093 */
4094 if (gidft_entry->last)
4095 return;
4096 }
4097 }
4098
4099 /*
4100 * fcs_ns_public FCS nameserver public interfaces
4101 */
4102
4103 /*
4104 * Functions called by port/fab.
4105 * These will send relevant Events to the ns state machine.
4106 */
4107 void
4108 bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4109 {
4110 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4111
4112 ns->port = port;
4113 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4114 }
4115
4116 void
4117 bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4118 {
4119 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4120
4121 ns->port = port;
4122 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4123 }
4124
4125 void
4126 bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4127 {
4128 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4129
4130 ns->port = port;
4131 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4132 }
4133
4134 void
4135 bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4136 {
4137 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4138
4139 bfa_trc(port->fcs, port->pid);
4140 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4141 }
4142
4143 static void
4144 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4145 {
4146
4147 struct bfa_fcs_rport_s *rport;
4148 u8 nwwns;
4149 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
4150 int ii;
4151
4152 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4153
4154 for (ii = 0 ; ii < nwwns; ++ii) {
4155 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
4156 WARN_ON(!rport);
4157 }
4158 }
4159
4160 /*
4161 * FCS SCN
4162 */
4163
4164 #define FC_QOS_RSCN_EVENT 0x0c
4165 #define FC_FABRIC_NAME_RSCN_EVENT 0x0d
4166
4167 /*
4168 * forward declarations
4169 */
4170 static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4171 struct bfa_fcxp_s *fcxp_alloced);
4172 static void bfa_fcs_lport_scn_scr_response(void *fcsarg,
4173 struct bfa_fcxp_s *fcxp,
4174 void *cbarg,
4175 bfa_status_t req_status,
4176 u32 rsp_len,
4177 u32 resid_len,
4178 struct fchs_s *rsp_fchs);
4179 static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4180 struct fchs_s *rx_fchs);
4181 static void bfa_fcs_lport_scn_timeout(void *arg);
4182
4183 /*
4184 * fcs_scm_sm FCS SCN state machine
4185 */
4186
4187 /*
4188 * VPort SCN State Machine events
4189 */
4190 enum port_scn_event {
4191 SCNSM_EVENT_PORT_ONLINE = 1,
4192 SCNSM_EVENT_PORT_OFFLINE = 2,
4193 SCNSM_EVENT_RSP_OK = 3,
4194 SCNSM_EVENT_RSP_ERROR = 4,
4195 SCNSM_EVENT_TIMEOUT = 5,
4196 SCNSM_EVENT_SCR_SENT = 6,
4197 };
4198
4199 static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4200 enum port_scn_event event);
4201 static void bfa_fcs_lport_scn_sm_sending_scr(
4202 struct bfa_fcs_lport_scn_s *scn,
4203 enum port_scn_event event);
4204 static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4205 enum port_scn_event event);
4206 static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4207 enum port_scn_event event);
4208 static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4209 enum port_scn_event event);
4210
4211 /*
4212 * Starting state - awaiting link up.
4213 */
4214 static void
4215 bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4216 enum port_scn_event event)
4217 {
4218 switch (event) {
4219 case SCNSM_EVENT_PORT_ONLINE:
4220 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4221 bfa_fcs_lport_scn_send_scr(scn, NULL);
4222 break;
4223
4224 case SCNSM_EVENT_PORT_OFFLINE:
4225 break;
4226
4227 default:
4228 bfa_sm_fault(scn->port->fcs, event);
4229 }
4230 }
4231
4232 static void
4233 bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4234 enum port_scn_event event)
4235 {
4236 switch (event) {
4237 case SCNSM_EVENT_SCR_SENT:
4238 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4239 break;
4240
4241 case SCNSM_EVENT_PORT_OFFLINE:
4242 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4243 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4244 break;
4245
4246 default:
4247 bfa_sm_fault(scn->port->fcs, event);
4248 }
4249 }
4250
4251 static void
4252 bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4253 enum port_scn_event event)
4254 {
4255 struct bfa_fcs_lport_s *port = scn->port;
4256
4257 switch (event) {
4258 case SCNSM_EVENT_RSP_OK:
4259 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4260 break;
4261
4262 case SCNSM_EVENT_RSP_ERROR:
4263 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4264 bfa_timer_start(port->fcs->bfa, &scn->timer,
4265 bfa_fcs_lport_scn_timeout, scn,
4266 BFA_FCS_RETRY_TIMEOUT);
4267 break;
4268
4269 case SCNSM_EVENT_PORT_OFFLINE:
4270 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4271 bfa_fcxp_discard(scn->fcxp);
4272 break;
4273
4274 default:
4275 bfa_sm_fault(port->fcs, event);
4276 }
4277 }
4278
4279 static void
4280 bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4281 enum port_scn_event event)
4282 {
4283 switch (event) {
4284 case SCNSM_EVENT_TIMEOUT:
4285 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4286 bfa_fcs_lport_scn_send_scr(scn, NULL);
4287 break;
4288
4289 case SCNSM_EVENT_PORT_OFFLINE:
4290 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4291 bfa_timer_stop(&scn->timer);
4292 break;
4293
4294 default:
4295 bfa_sm_fault(scn->port->fcs, event);
4296 }
4297 }
4298
4299 static void
4300 bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4301 enum port_scn_event event)
4302 {
4303 switch (event) {
4304 case SCNSM_EVENT_PORT_OFFLINE:
4305 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4306 break;
4307
4308 default:
4309 bfa_sm_fault(scn->port->fcs, event);
4310 }
4311 }
4312
4313
4314
4315 /*
4316 * fcs_scn_private FCS SCN private functions
4317 */
4318
4319 /*
4320 * This routine will be called to send a SCR command.
4321 */
4322 static void
4323 bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4324 {
4325 struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
4326 struct bfa_fcs_lport_s *port = scn->port;
4327 struct fchs_s fchs;
4328 int len;
4329 struct bfa_fcxp_s *fcxp;
4330
4331 bfa_trc(port->fcs, port->pid);
4332 bfa_trc(port->fcs, port->port_cfg.pwwn);
4333
4334 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4335 if (!fcxp) {
4336 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4337 bfa_fcs_lport_scn_send_scr, scn);
4338 return;
4339 }
4340 scn->fcxp = fcxp;
4341
4342 /* Handle VU registrations for Base port only */
4343 if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
4344 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4345 port->fabric->lps->brcd_switch,
4346 port->pid, 0);
4347 } else {
4348 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4349 BFA_FALSE,
4350 port->pid, 0);
4351 }
4352
4353 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4354 FC_CLASS_3, len, &fchs,
4355 bfa_fcs_lport_scn_scr_response,
4356 (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
4357
4358 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4359 }
4360
4361 static void
4362 bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4363 void *cbarg, bfa_status_t req_status, u32 rsp_len,
4364 u32 resid_len, struct fchs_s *rsp_fchs)
4365 {
4366 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
4367 struct bfa_fcs_lport_s *port = scn->port;
4368 struct fc_els_cmd_s *els_cmd;
4369 struct fc_ls_rjt_s *ls_rjt;
4370
4371 bfa_trc(port->fcs, port->port_cfg.pwwn);
4372
4373 /*
4374 * Sanity Checks
4375 */
4376 if (req_status != BFA_STATUS_OK) {
4377 bfa_trc(port->fcs, req_status);
4378 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4379 return;
4380 }
4381
4382 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4383
4384 switch (els_cmd->els_code) {
4385
4386 case FC_ELS_ACC:
4387 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4388 break;
4389
4390 case FC_ELS_LS_RJT:
4391
4392 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4393
4394 bfa_trc(port->fcs, ls_rjt->reason_code);
4395 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4396
4397 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4398 break;
4399
4400 default:
4401 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4402 }
4403 }
4404
4405 /*
4406 * Send a LS Accept
4407 */
4408 static void
4409 bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4410 struct fchs_s *rx_fchs)
4411 {
4412 struct fchs_s fchs;
4413 struct bfa_fcxp_s *fcxp;
4414 struct bfa_rport_s *bfa_rport = NULL;
4415 int len;
4416
4417 bfa_trc(port->fcs, rx_fchs->s_id);
4418
4419 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4420 if (!fcxp)
4421 return;
4422
4423 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4424 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
4425 rx_fchs->ox_id);
4426
4427 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4428 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4429 FC_MAX_PDUSZ, 0);
4430 }
4431
4432 /*
4433 * This routine will be called by bfa_timer on timer timeouts.
4434 *
4435 * param[in] vport - pointer to bfa_fcs_lport_t.
4436 * param[out] vport_status - pointer to return vport status in
4437 *
4438 * return
4439 * void
4440 *
4441 * Special Considerations:
4442 *
4443 * note
4444 */
4445 static void
4446 bfa_fcs_lport_scn_timeout(void *arg)
4447 {
4448 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4449
4450 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4451 }
4452
4453
4454
4455 /*
4456 * fcs_scn_public FCS state change notification public interfaces
4457 */
4458
4459 /*
4460 * Functions called by port/fab
4461 */
4462 void
4463 bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4464 {
4465 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4466
4467 scn->port = port;
4468 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4469 }
4470
4471 void
4472 bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4473 {
4474 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4475
4476 scn->port = port;
4477 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4478 }
4479
4480 void
4481 bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4482 {
4483 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4484
4485 scn->port = port;
4486 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4487 }
4488
4489 static void
4490 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4491 {
4492 struct bfa_fcs_rport_s *rport;
4493
4494 bfa_trc(port->fcs, rpid);
4495
4496 /*
4497 * If this is an unknown device, then it just came online.
4498 * Otherwise let rport handle the RSCN event.
4499 */
4500 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4501 if (rport == NULL) {
4502 /*
4503 * If min cfg mode is enabled, we donot need to
4504 * discover any new rports.
4505 */
4506 if (!__fcs_min_cfg(port->fcs))
4507 rport = bfa_fcs_rport_create(port, rpid);
4508 } else
4509 bfa_fcs_rport_scn(rport);
4510 }
4511
4512 /*
4513 * rscn format based PID comparison
4514 */
4515 #define __fc_pid_match(__c0, __c1, __fmt) \
4516 (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
4517 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
4518 ((__c0)[0] == (__c1)[0])) || \
4519 (((__fmt) == FC_RSCN_FORMAT_AREA) && \
4520 ((__c0)[0] == (__c1)[0]) && \
4521 ((__c0)[1] == (__c1)[1])))
4522
4523 static void
4524 bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4525 enum fc_rscn_format format,
4526 u32 rscn_pid)
4527 {
4528 struct bfa_fcs_rport_s *rport;
4529 struct list_head *qe, *qe_next;
4530 u8 *c0, *c1;
4531
4532 bfa_trc(port->fcs, format);
4533 bfa_trc(port->fcs, rscn_pid);
4534
4535 c0 = (u8 *) &rscn_pid;
4536
4537 list_for_each_safe(qe, qe_next, &port->rport_q) {
4538 rport = (struct bfa_fcs_rport_s *) qe;
4539 c1 = (u8 *) &rport->pid;
4540 if (__fc_pid_match(c0, c1, format))
4541 bfa_fcs_rport_scn(rport);
4542 }
4543 }
4544
4545
4546 void
4547 bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4548 struct fchs_s *fchs, u32 len)
4549 {
4550 struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
4551 int num_entries;
4552 u32 rscn_pid;
4553 bfa_boolean_t nsquery = BFA_FALSE, found;
4554 int i = 0, j;
4555
4556 num_entries =
4557 (be16_to_cpu(rscn->payldlen) -
4558 sizeof(u32)) / sizeof(rscn->event[0]);
4559
4560 bfa_trc(port->fcs, num_entries);
4561
4562 port->stats.num_rscn++;
4563
4564 bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4565
4566 for (i = 0; i < num_entries; i++) {
4567 rscn_pid = rscn->event[i].portid;
4568
4569 bfa_trc(port->fcs, rscn->event[i].format);
4570 bfa_trc(port->fcs, rscn_pid);
4571
4572 /* check for duplicate entries in the list */
4573 found = BFA_FALSE;
4574 for (j = 0; j < i; j++) {
4575 if (rscn->event[j].portid == rscn_pid) {
4576 found = BFA_TRUE;
4577 break;
4578 }
4579 }
4580
4581 /* if found in down the list, pid has been already processed */
4582 if (found) {
4583 bfa_trc(port->fcs, rscn_pid);
4584 continue;
4585 }
4586
4587 switch (rscn->event[i].format) {
4588 case FC_RSCN_FORMAT_PORTID:
4589 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4590 /*
4591 * Ignore this event.
4592 * f/w would have processed it
4593 */
4594 bfa_trc(port->fcs, rscn_pid);
4595 } else {
4596 port->stats.num_portid_rscn++;
4597 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
4598 }
4599 break;
4600
4601 case FC_RSCN_FORMAT_FABRIC:
4602 if (rscn->event[i].qualifier ==
4603 FC_FABRIC_NAME_RSCN_EVENT) {
4604 bfa_fcs_lport_ms_fabric_rscn(port);
4605 break;
4606 }
4607 /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
4608
4609 case FC_RSCN_FORMAT_AREA:
4610 case FC_RSCN_FORMAT_DOMAIN:
4611 nsquery = BFA_TRUE;
4612 bfa_fcs_lport_scn_multiport_rscn(port,
4613 rscn->event[i].format,
4614 rscn_pid);
4615 break;
4616
4617
4618 default:
4619 WARN_ON(1);
4620 nsquery = BFA_TRUE;
4621 }
4622 }
4623
4624 /*
4625 * If any of area, domain or fabric RSCN is received, do a fresh
4626 * discovery to find new devices.
4627 */
4628 if (nsquery)
4629 bfa_fcs_lport_ns_query(port);
4630 }
4631
4632 /*
4633 * BFA FCS port
4634 */
4635 /*
4636 * fcs_port_api BFA FCS port API
4637 */
4638 struct bfa_fcs_lport_s *
4639 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4640 {
4641 return &fcs->fabric.bport;
4642 }
4643
4644 wwn_t
4645 bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4646 int nrports, bfa_boolean_t bwwn)
4647 {
4648 struct list_head *qh, *qe;
4649 struct bfa_fcs_rport_s *rport = NULL;
4650 int i;
4651 struct bfa_fcs_s *fcs;
4652
4653 if (port == NULL || nrports == 0)
4654 return (wwn_t) 0;
4655
4656 fcs = port->fcs;
4657 bfa_trc(fcs, (u32) nrports);
4658
4659 i = 0;
4660 qh = &port->rport_q;
4661 qe = bfa_q_first(qh);
4662
4663 while ((qe != qh) && (i < nrports)) {
4664 rport = (struct bfa_fcs_rport_s *) qe;
4665 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
4666 qe = bfa_q_next(qe);
4667 bfa_trc(fcs, (u32) rport->pwwn);
4668 bfa_trc(fcs, rport->pid);
4669 bfa_trc(fcs, i);
4670 continue;
4671 }
4672
4673 if (bwwn) {
4674 if (!memcmp(&wwn, &rport->pwwn, 8))
4675 break;
4676 } else {
4677 if (i == index)
4678 break;
4679 }
4680
4681 i++;
4682 qe = bfa_q_next(qe);
4683 }
4684
4685 bfa_trc(fcs, i);
4686 if (rport)
4687 return rport->pwwn;
4688 else
4689 return (wwn_t) 0;
4690 }
4691
4692 void
4693 bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4694 wwn_t rport_wwns[], int *nrports)
4695 {
4696 struct list_head *qh, *qe;
4697 struct bfa_fcs_rport_s *rport = NULL;
4698 int i;
4699 struct bfa_fcs_s *fcs;
4700
4701 if (port == NULL || rport_wwns == NULL || *nrports == 0)
4702 return;
4703
4704 fcs = port->fcs;
4705 bfa_trc(fcs, (u32) *nrports);
4706
4707 i = 0;
4708 qh = &port->rport_q;
4709 qe = bfa_q_first(qh);
4710
4711 while ((qe != qh) && (i < *nrports)) {
4712 rport = (struct bfa_fcs_rport_s *) qe;
4713 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
4714 qe = bfa_q_next(qe);
4715 bfa_trc(fcs, (u32) rport->pwwn);
4716 bfa_trc(fcs, rport->pid);
4717 bfa_trc(fcs, i);
4718 continue;
4719 }
4720
4721 rport_wwns[i] = rport->pwwn;
4722
4723 i++;
4724 qe = bfa_q_next(qe);
4725 }
4726
4727 bfa_trc(fcs, i);
4728 *nrports = i;
4729 }
4730
4731 /*
4732 * Iterate's through all the rport's in the given port to
4733 * determine the maximum operating speed.
4734 *
4735 * !!!! To be used in TRL Functionality only !!!!
4736 */
4737 bfa_port_speed_t
4738 bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4739 {
4740 struct list_head *qh, *qe;
4741 struct bfa_fcs_rport_s *rport = NULL;
4742 struct bfa_fcs_s *fcs;
4743 bfa_port_speed_t max_speed = 0;
4744 struct bfa_port_attr_s port_attr;
4745 bfa_port_speed_t port_speed, rport_speed;
4746 bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
4747
4748
4749 if (port == NULL)
4750 return 0;
4751
4752 fcs = port->fcs;
4753
4754 /* Get Physical port's current speed */
4755 bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4756 port_speed = port_attr.speed;
4757 bfa_trc(fcs, port_speed);
4758
4759 qh = &port->rport_q;
4760 qe = bfa_q_first(qh);
4761
4762 while (qe != qh) {
4763 rport = (struct bfa_fcs_rport_s *) qe;
4764 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
4765 (bfa_fcs_rport_get_state(rport) ==
4766 BFA_RPORT_OFFLINE)) {
4767 qe = bfa_q_next(qe);
4768 continue;
4769 }
4770
4771 rport_speed = rport->rpf.rpsc_speed;
4772 if ((trl_enabled) && (rport_speed ==
4773 BFA_PORT_SPEED_UNKNOWN)) {
4774 /* Use default ratelim speed setting */
4775 rport_speed =
4776 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4777 }
4778
4779 if ((rport_speed == BFA_PORT_SPEED_8GBPS) ||
4780 (rport_speed > port_speed)) {
4781 max_speed = rport_speed;
4782 break;
4783 } else if (rport_speed > max_speed) {
4784 max_speed = rport_speed;
4785 }
4786
4787 qe = bfa_q_next(qe);
4788 }
4789
4790 bfa_trc(fcs, max_speed);
4791 return max_speed;
4792 }
4793
4794 struct bfa_fcs_lport_s *
4795 bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4796 {
4797 struct bfa_fcs_vport_s *vport;
4798 bfa_fcs_vf_t *vf;
4799
4800 WARN_ON(fcs == NULL);
4801
4802 vf = bfa_fcs_vf_lookup(fcs, vf_id);
4803 if (vf == NULL) {
4804 bfa_trc(fcs, vf_id);
4805 return NULL;
4806 }
4807
4808 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
4809 return &vf->bport;
4810
4811 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
4812 if (vport)
4813 return &vport->lport;
4814
4815 return NULL;
4816 }
4817
4818 /*
4819 * API corresponding to NPIV_VPORT_GETINFO.
4820 */
4821 void
4822 bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
4823 struct bfa_lport_info_s *port_info)
4824 {
4825
4826 bfa_trc(port->fcs, port->fabric->fabric_name);
4827
4828 if (port->vport == NULL) {
4829 /*
4830 * This is a Physical port
4831 */
4832 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
4833
4834 /*
4835 * @todo : need to fix the state & reason
4836 */
4837 port_info->port_state = 0;
4838 port_info->offline_reason = 0;
4839
4840 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4841 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4842
4843 port_info->max_vports_supp =
4844 bfa_lps_get_max_vport(port->fcs->bfa);
4845 port_info->num_vports_inuse =
4846 port->fabric->num_vports;
4847 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
4848 port_info->num_rports_inuse = port->num_rports;
4849 } else {
4850 /*
4851 * This is a virtual port
4852 */
4853 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
4854
4855 /*
4856 * @todo : need to fix the state & reason
4857 */
4858 port_info->port_state = 0;
4859 port_info->offline_reason = 0;
4860
4861 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4862 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4863 }
4864 }
4865
4866 void
4867 bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
4868 struct bfa_lport_stats_s *port_stats)
4869 {
4870 *port_stats = fcs_port->stats;
4871 }
4872
4873 void
4874 bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
4875 {
4876 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
4877 }
4878
4879 /*
4880 * FCS virtual port state machine
4881 */
4882
4883 #define __vport_fcs(__vp) ((__vp)->lport.fcs)
4884 #define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn)
4885 #define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn)
4886 #define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa)
4887 #define __vport_fcid(__vp) ((__vp)->lport.pid)
4888 #define __vport_fabric(__vp) ((__vp)->lport.fabric)
4889 #define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id)
4890
4891 #define BFA_FCS_VPORT_MAX_RETRIES 5
4892 /*
4893 * Forward declarations
4894 */
4895 static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
4896 static void bfa_fcs_vport_timeout(void *vport_arg);
4897 static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
4898 static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
4899
4900 /*
4901 * fcs_vport_sm FCS virtual port state machine
4902 */
4903
4904 /*
4905 * VPort State Machine events
4906 */
4907 enum bfa_fcs_vport_event {
4908 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */
4909 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */
4910 BFA_FCS_VPORT_SM_START = 3, /* vport start request */
4911 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */
4912 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */
4913 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */
4914 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */
4915 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */
4916 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */
4917 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */
4918 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
4919 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
4920 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
4921 };
4922
4923 static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4924 enum bfa_fcs_vport_event event);
4925 static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4926 enum bfa_fcs_vport_event event);
4927 static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
4928 enum bfa_fcs_vport_event event);
4929 static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
4930 enum bfa_fcs_vport_event event);
4931 static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
4932 enum bfa_fcs_vport_event event);
4933 static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
4934 enum bfa_fcs_vport_event event);
4935 static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
4936 enum bfa_fcs_vport_event event);
4937 static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
4938 enum bfa_fcs_vport_event event);
4939 static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
4940 enum bfa_fcs_vport_event event);
4941 static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
4942 enum bfa_fcs_vport_event event);
4943
4944 static struct bfa_sm_table_s vport_sm_table[] = {
4945 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
4946 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
4947 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
4948 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
4949 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
4950 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
4951 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
4952 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
4953 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
4954 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
4955 };
4956
4957 /*
4958 * Beginning state.
4959 */
4960 static void
4961 bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4962 enum bfa_fcs_vport_event event)
4963 {
4964 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4965 bfa_trc(__vport_fcs(vport), event);
4966
4967 switch (event) {
4968 case BFA_FCS_VPORT_SM_CREATE:
4969 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
4970 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
4971 break;
4972
4973 default:
4974 bfa_sm_fault(__vport_fcs(vport), event);
4975 }
4976 }
4977
4978 /*
4979 * Created state - a start event is required to start up the state machine.
4980 */
4981 static void
4982 bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4983 enum bfa_fcs_vport_event event)
4984 {
4985 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4986 bfa_trc(__vport_fcs(vport), event);
4987
4988 switch (event) {
4989 case BFA_FCS_VPORT_SM_START:
4990 if (bfa_sm_cmp_state(__vport_fabric(vport),
4991 bfa_fcs_fabric_sm_online)
4992 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
4993 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
4994 bfa_fcs_vport_do_fdisc(vport);
4995 } else {
4996 /*
4997 * Fabric is offline or not NPIV capable, stay in
4998 * offline state.
4999 */
5000 vport->vport_stats.fab_no_npiv++;
5001 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5002 }
5003 break;
5004
5005 case BFA_FCS_VPORT_SM_DELETE:
5006 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5007 bfa_fcs_lport_delete(&vport->lport);
5008 break;
5009
5010 case BFA_FCS_VPORT_SM_ONLINE:
5011 case BFA_FCS_VPORT_SM_OFFLINE:
5012 /*
5013 * Ignore ONLINE/OFFLINE events from fabric
5014 * till vport is started.
5015 */
5016 break;
5017
5018 default:
5019 bfa_sm_fault(__vport_fcs(vport), event);
5020 }
5021 }
5022
5023 /*
5024 * Offline state - awaiting ONLINE event from fabric SM.
5025 */
5026 static void
5027 bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5028 enum bfa_fcs_vport_event event)
5029 {
5030 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5031 bfa_trc(__vport_fcs(vport), event);
5032
5033 switch (event) {
5034 case BFA_FCS_VPORT_SM_DELETE:
5035 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5036 bfa_fcs_lport_delete(&vport->lport);
5037 break;
5038
5039 case BFA_FCS_VPORT_SM_ONLINE:
5040 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5041 vport->fdisc_retries = 0;
5042 bfa_fcs_vport_do_fdisc(vport);
5043 break;
5044
5045 case BFA_FCS_VPORT_SM_OFFLINE:
5046 /*
5047 * This can happen if the vport couldn't be initialzied
5048 * due the fact that the npiv was not enabled on the switch.
5049 * In that case we will put the vport in offline state.
5050 * However, the link can go down and cause the this event to
5051 * be sent when we are already offline. Ignore it.
5052 */
5053 break;
5054
5055 default:
5056 bfa_sm_fault(__vport_fcs(vport), event);
5057 }
5058 }
5059
5060
5061 /*
5062 * FDISC is sent and awaiting reply from fabric.
5063 */
5064 static void
5065 bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5066 enum bfa_fcs_vport_event event)
5067 {
5068 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5069 bfa_trc(__vport_fcs(vport), event);
5070
5071 switch (event) {
5072 case BFA_FCS_VPORT_SM_DELETE:
5073 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5074 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5075 bfa_fcs_lport_delete(&vport->lport);
5076 break;
5077
5078 case BFA_FCS_VPORT_SM_OFFLINE:
5079 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5080 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5081 break;
5082
5083 case BFA_FCS_VPORT_SM_RSP_OK:
5084 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5085 bfa_fcs_lport_online(&vport->lport);
5086 break;
5087
5088 case BFA_FCS_VPORT_SM_RSP_ERROR:
5089 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5090 bfa_timer_start(__vport_bfa(vport), &vport->timer,
5091 bfa_fcs_vport_timeout, vport,
5092 BFA_FCS_RETRY_TIMEOUT);
5093 break;
5094
5095 case BFA_FCS_VPORT_SM_RSP_FAILED:
5096 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5097 break;
5098
5099 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5100 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5101 break;
5102
5103 default:
5104 bfa_sm_fault(__vport_fcs(vport), event);
5105 }
5106 }
5107
5108 /*
5109 * FDISC attempt failed - a timer is active to retry FDISC.
5110 */
5111 static void
5112 bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5113 enum bfa_fcs_vport_event event)
5114 {
5115 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5116 bfa_trc(__vport_fcs(vport), event);
5117
5118 switch (event) {
5119 case BFA_FCS_VPORT_SM_DELETE:
5120 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5121 bfa_timer_stop(&vport->timer);
5122 bfa_fcs_lport_delete(&vport->lport);
5123 break;
5124
5125 case BFA_FCS_VPORT_SM_OFFLINE:
5126 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5127 bfa_timer_stop(&vport->timer);
5128 break;
5129
5130 case BFA_FCS_VPORT_SM_TIMEOUT:
5131 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5132 vport->vport_stats.fdisc_retries++;
5133 vport->fdisc_retries++;
5134 bfa_fcs_vport_do_fdisc(vport);
5135 break;
5136
5137 default:
5138 bfa_sm_fault(__vport_fcs(vport), event);
5139 }
5140 }
5141
5142 /*
5143 * Vport is online (FDISC is complete).
5144 */
5145 static void
5146 bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5147 enum bfa_fcs_vport_event event)
5148 {
5149 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5150 bfa_trc(__vport_fcs(vport), event);
5151
5152 switch (event) {
5153 case BFA_FCS_VPORT_SM_DELETE:
5154 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5155 bfa_fcs_lport_delete(&vport->lport);
5156 break;
5157
5158 case BFA_FCS_VPORT_SM_OFFLINE:
5159 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5160 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5161 bfa_fcs_lport_offline(&vport->lport);
5162 break;
5163
5164 default:
5165 bfa_sm_fault(__vport_fcs(vport), event);
5166 }
5167 }
5168
5169 /*
5170 * Vport is being deleted - awaiting lport delete completion to send
5171 * LOGO to fabric.
5172 */
5173 static void
5174 bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5175 enum bfa_fcs_vport_event event)
5176 {
5177 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5178 bfa_trc(__vport_fcs(vport), event);
5179
5180 switch (event) {
5181 case BFA_FCS_VPORT_SM_DELETE:
5182 break;
5183
5184 case BFA_FCS_VPORT_SM_DELCOMP:
5185 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
5186 bfa_fcs_vport_do_logo(vport);
5187 break;
5188
5189 case BFA_FCS_VPORT_SM_OFFLINE:
5190 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5191 break;
5192
5193 default:
5194 bfa_sm_fault(__vport_fcs(vport), event);
5195 }
5196 }
5197
5198 /*
5199 * Error State.
5200 * This state will be set when the Vport Creation fails due
5201 * to errors like Dup WWN. In this state only operation allowed
5202 * is a Vport Delete.
5203 */
5204 static void
5205 bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5206 enum bfa_fcs_vport_event event)
5207 {
5208 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5209 bfa_trc(__vport_fcs(vport), event);
5210
5211 switch (event) {
5212 case BFA_FCS_VPORT_SM_DELETE:
5213 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5214 bfa_fcs_lport_delete(&vport->lport);
5215 break;
5216
5217 default:
5218 bfa_trc(__vport_fcs(vport), event);
5219 }
5220 }
5221
5222 /*
5223 * Lport cleanup is in progress since vport is being deleted. Fabric is
5224 * offline, so no LOGO is needed to complete vport deletion.
5225 */
5226 static void
5227 bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5228 enum bfa_fcs_vport_event event)
5229 {
5230 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5231 bfa_trc(__vport_fcs(vport), event);
5232
5233 switch (event) {
5234 case BFA_FCS_VPORT_SM_DELCOMP:
5235 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5236 bfa_fcs_vport_free(vport);
5237 break;
5238
5239 case BFA_FCS_VPORT_SM_DELETE:
5240 break;
5241
5242 default:
5243 bfa_sm_fault(__vport_fcs(vport), event);
5244 }
5245 }
5246
5247 /*
5248 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
5249 * is done.
5250 */
5251 static void
5252 bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5253 enum bfa_fcs_vport_event event)
5254 {
5255 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5256 bfa_trc(__vport_fcs(vport), event);
5257
5258 switch (event) {
5259 case BFA_FCS_VPORT_SM_OFFLINE:
5260 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5261 /*
5262 * !!! fall through !!!
5263 */
5264
5265 case BFA_FCS_VPORT_SM_RSP_OK:
5266 case BFA_FCS_VPORT_SM_RSP_ERROR:
5267 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5268 bfa_fcs_vport_free(vport);
5269 break;
5270
5271 case BFA_FCS_VPORT_SM_DELETE:
5272 break;
5273
5274 default:
5275 bfa_sm_fault(__vport_fcs(vport), event);
5276 }
5277 }
5278
5279
5280
5281 /*
5282 * fcs_vport_private FCS virtual port private functions
5283 */
5284 /*
5285 * This routine will be called to send a FDISC command.
5286 */
5287 static void
5288 bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
5289 {
5290 bfa_lps_fdisc(vport->lps, vport,
5291 bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
5292 __vport_pwwn(vport), __vport_nwwn(vport));
5293 vport->vport_stats.fdisc_sent++;
5294 }
5295
5296 static void
5297 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5298 {
5299 u8 lsrjt_rsn = vport->lps->lsrjt_rsn;
5300 u8 lsrjt_expl = vport->lps->lsrjt_expl;
5301
5302 bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5303 bfa_trc(__vport_fcs(vport), lsrjt_expl);
5304
5305 /* For certain reason codes, we don't want to retry. */
5306 switch (vport->lps->lsrjt_expl) {
5307 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
5308 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
5309 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5310 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5311 else
5312 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
5313 break;
5314
5315 case FC_LS_RJT_EXP_INSUFF_RES:
5316 /*
5317 * This means max logins per port/switch setting on the
5318 * switch was exceeded.
5319 */
5320 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5321 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5322 else
5323 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
5324 break;
5325
5326 default:
5327 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5328 }
5329 }
5330
5331 /*
5332 * Called to send a logout to the fabric. Used when a V-Port is
5333 * deleted/stopped.
5334 */
5335 static void
5336 bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5337 {
5338 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5339
5340 vport->vport_stats.logo_sent++;
5341 bfa_lps_fdisclogo(vport->lps);
5342 }
5343
5344
5345 /*
5346 * This routine will be called by bfa_timer on timer timeouts.
5347 *
5348 * param[in] vport - pointer to bfa_fcs_vport_t.
5349 * param[out] vport_status - pointer to return vport status in
5350 *
5351 * return
5352 * void
5353 *
5354 * Special Considerations:
5355 *
5356 * note
5357 */
5358 static void
5359 bfa_fcs_vport_timeout(void *vport_arg)
5360 {
5361 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5362
5363 vport->vport_stats.fdisc_timeouts++;
5364 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5365 }
5366
5367 static void
5368 bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5369 {
5370 struct bfad_vport_s *vport_drv =
5371 (struct bfad_vport_s *)vport->vport_drv;
5372
5373 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5374
5375 if (vport_drv->comp_del)
5376 complete(vport_drv->comp_del);
5377
5378 bfa_lps_delete(vport->lps);
5379 }
5380
5381
5382
5383 /*
5384 * fcs_vport_public FCS virtual port public interfaces
5385 */
5386
5387 /*
5388 * Online notification from fabric SM.
5389 */
5390 void
5391 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5392 {
5393 vport->vport_stats.fab_online++;
5394 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5395 }
5396
5397 /*
5398 * Offline notification from fabric SM.
5399 */
5400 void
5401 bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5402 {
5403 vport->vport_stats.fab_offline++;
5404 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5405 }
5406
5407 /*
5408 * Cleanup notification from fabric SM on link timer expiry.
5409 */
5410 void
5411 bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5412 {
5413 vport->vport_stats.fab_cleanup++;
5414 }
5415 /*
5416 * delete notification from fabric SM. To be invoked from within FCS.
5417 */
5418 void
5419 bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5420 {
5421 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5422 }
5423
5424 /*
5425 * Delete completion callback from associated lport
5426 */
5427 void
5428 bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5429 {
5430 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5431 }
5432
5433
5434
5435 /*
5436 * fcs_vport_api Virtual port API
5437 */
5438
5439 /*
5440 * Use this function to instantiate a new FCS vport object. This
5441 * function will not trigger any HW initialization process (which will be
5442 * done in vport_start() call)
5443 *
5444 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5445 * needs to be allocated by the driver.
5446 * param[in] fcs - FCS instance
5447 * param[in] vport_cfg - vport configuration
5448 * param[in] vf_id - VF_ID if vport is created within a VF.
5449 * FC_VF_ID_NULL to specify base fabric.
5450 * param[in] vport_drv - Opaque handle back to the driver's vport
5451 * structure
5452 *
5453 * retval BFA_STATUS_OK - on success.
5454 * retval BFA_STATUS_FAILED - on failure.
5455 */
5456 bfa_status_t
5457 bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5458 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5459 struct bfad_vport_s *vport_drv)
5460 {
5461 if (vport_cfg->pwwn == 0)
5462 return BFA_STATUS_INVALID_WWN;
5463
5464 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5465 return BFA_STATUS_VPORT_WWN_BP;
5466
5467 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5468 return BFA_STATUS_VPORT_EXISTS;
5469
5470 if (fcs->fabric.num_vports ==
5471 bfa_lps_get_max_vport(fcs->bfa))
5472 return BFA_STATUS_VPORT_MAX;
5473
5474 vport->lps = bfa_lps_alloc(fcs->bfa);
5475 if (!vport->lps)
5476 return BFA_STATUS_VPORT_MAX;
5477
5478 vport->vport_drv = vport_drv;
5479 vport_cfg->preboot_vp = BFA_FALSE;
5480
5481 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5482 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
5483 bfa_fcs_lport_init(&vport->lport, vport_cfg);
5484 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
5485
5486 return BFA_STATUS_OK;
5487 }
5488
5489 /*
5490 * Use this function to instantiate a new FCS PBC vport object. This
5491 * function will not trigger any HW initialization process (which will be
5492 * done in vport_start() call)
5493 *
5494 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5495 * needs to be allocated by the driver.
5496 * param[in] fcs - FCS instance
5497 * param[in] vport_cfg - vport configuration
5498 * param[in] vf_id - VF_ID if vport is created within a VF.
5499 * FC_VF_ID_NULL to specify base fabric.
5500 * param[in] vport_drv - Opaque handle back to the driver's vport
5501 * structure
5502 *
5503 * retval BFA_STATUS_OK - on success.
5504 * retval BFA_STATUS_FAILED - on failure.
5505 */
5506 bfa_status_t
5507 bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5508 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5509 struct bfad_vport_s *vport_drv)
5510 {
5511 bfa_status_t rc;
5512
5513 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5514 vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5515
5516 return rc;
5517 }
5518
5519 /*
5520 * Use this function to findout if this is a pbc vport or not.
5521 *
5522 * @param[in] vport - pointer to bfa_fcs_vport_t.
5523 *
5524 * @returns None
5525 */
5526 bfa_boolean_t
5527 bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5528 {
5529
5530 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5531 return BFA_TRUE;
5532 else
5533 return BFA_FALSE;
5534
5535 }
5536
5537 /*
5538 * Use this function initialize the vport.
5539 *
5540 * @param[in] vport - pointer to bfa_fcs_vport_t.
5541 *
5542 * @returns None
5543 */
5544 bfa_status_t
5545 bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5546 {
5547 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5548
5549 return BFA_STATUS_OK;
5550 }
5551
5552 /*
5553 * Use this function quiese the vport object. This function will return
5554 * immediately, when the vport is actually stopped, the
5555 * bfa_drv_vport_stop_cb() will be called.
5556 *
5557 * param[in] vport - pointer to bfa_fcs_vport_t.
5558 *
5559 * return None
5560 */
5561 bfa_status_t
5562 bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5563 {
5564 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5565
5566 return BFA_STATUS_OK;
5567 }
5568
5569 /*
5570 * Use this function to delete a vport object. Fabric object should
5571 * be stopped before this function call.
5572 *
5573 * !!!!!!! Donot invoke this from within FCS !!!!!!!
5574 *
5575 * param[in] vport - pointer to bfa_fcs_vport_t.
5576 *
5577 * return None
5578 */
5579 bfa_status_t
5580 bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5581 {
5582
5583 if (vport->lport.port_cfg.preboot_vp)
5584 return BFA_STATUS_PBC;
5585
5586 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5587
5588 return BFA_STATUS_OK;
5589 }
5590
5591 /*
5592 * Use this function to get vport's current status info.
5593 *
5594 * param[in] vport pointer to bfa_fcs_vport_t.
5595 * param[out] attr pointer to return vport attributes
5596 *
5597 * return None
5598 */
5599 void
5600 bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5601 struct bfa_vport_attr_s *attr)
5602 {
5603 if (vport == NULL || attr == NULL)
5604 return;
5605
5606 memset(attr, 0, sizeof(struct bfa_vport_attr_s));
5607
5608 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5609 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5610 }
5611
5612
5613 /*
5614 * Lookup a virtual port. Excludes base port from lookup.
5615 */
5616 struct bfa_fcs_vport_s *
5617 bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5618 {
5619 struct bfa_fcs_vport_s *vport;
5620 struct bfa_fcs_fabric_s *fabric;
5621
5622 bfa_trc(fcs, vf_id);
5623 bfa_trc(fcs, vpwwn);
5624
5625 fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5626 if (!fabric) {
5627 bfa_trc(fcs, vf_id);
5628 return NULL;
5629 }
5630
5631 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5632 return vport;
5633 }
5634
5635 /*
5636 * FDISC Response
5637 */
5638 void
5639 bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5640 {
5641 struct bfa_fcs_vport_s *vport = uarg;
5642
5643 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5644 bfa_trc(__vport_fcs(vport), status);
5645
5646 switch (status) {
5647 case BFA_STATUS_OK:
5648 /*
5649 * Initialize the V-Port fields
5650 */
5651 __vport_fcid(vport) = vport->lps->lp_pid;
5652 vport->vport_stats.fdisc_accepts++;
5653 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5654 break;
5655
5656 case BFA_STATUS_INVALID_MAC:
5657 /* Only for CNA */
5658 vport->vport_stats.fdisc_acc_bad++;
5659 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5660
5661 break;
5662
5663 case BFA_STATUS_EPROTOCOL:
5664 switch (vport->lps->ext_status) {
5665 case BFA_EPROTO_BAD_ACCEPT:
5666 vport->vport_stats.fdisc_acc_bad++;
5667 break;
5668
5669 case BFA_EPROTO_UNKNOWN_RSP:
5670 vport->vport_stats.fdisc_unknown_rsp++;
5671 break;
5672
5673 default:
5674 break;
5675 }
5676
5677 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5678 break;
5679
5680 case BFA_STATUS_FABRIC_RJT:
5681 vport->vport_stats.fdisc_rejects++;
5682 bfa_fcs_vport_fdisc_rejected(vport);
5683 break;
5684
5685 default:
5686 vport->vport_stats.fdisc_rsp_err++;
5687 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5688 }
5689 }
5690
5691 /*
5692 * LOGO response
5693 */
5694 void
5695 bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
5696 {
5697 struct bfa_fcs_vport_s *vport = uarg;
5698 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5699 }
5700
5701 /*
5702 * Received clear virtual link
5703 */
5704 void
5705 bfa_cb_lps_cvl_event(void *bfad, void *uarg)
5706 {
5707 struct bfa_fcs_vport_s *vport = uarg;
5708
5709 /* Send an Offline followed by an ONLINE */
5710 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5711 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5712 }
This page took 0.168099 seconds and 6 git commands to generate.