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