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

source code of linux/drivers/scsi/bfa/bfa_fcs_lport.c