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
17 BFA_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 */
25 static 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
47 static 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);
50 static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
51 struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
52 static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
53 static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
54 static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
55 static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
56 static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
57 static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
58 static 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);
61 static 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);
64 static 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
67 static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
68 static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
69 static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
70
71 static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
72 static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
73 static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
74
75 static void bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port);
76 static void bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port);
77 static void bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port);
78
79 static 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
110 enum 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
119 static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
120 enum bfa_fcs_lport_event event);
121 static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
122 enum bfa_fcs_lport_event event);
123 static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
124 enum bfa_fcs_lport_event event);
125 static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
126 enum bfa_fcs_lport_event event);
127 static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
128 enum bfa_fcs_lport_event event);
129 static void bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
130 enum bfa_fcs_lport_event event);
131
132 static void
bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)133 bfa_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
150 static void
bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)151 bfa_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(port->vport);
172 else
173 bfa_wc_down(&(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
184 static void
bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)185 bfa_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(port->vport);
209 else
210 bfa_wc_down(&(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
244 static void
bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)245 bfa_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(port->vport);
267 else
268 bfa_wc_down(&(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
300 static void
bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)301 bfa_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(port->vport);
314 else
315 bfa_wc_down(&(port->fabric->stop_wc));
316 }
317 break;
318
319 default:
320 bfa_sm_fault(port->fcs, event);
321 }
322 }
323
324 static void
bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)325 bfa_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 */
352 static void
bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s * port,enum bfa_lport_aen_event event)353 bfa_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(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
371 BFA_AEN_CAT_LPORT, event);
372 }
373
374 /*
375 * Send a LS reject
376 */
377 static void
bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,u8 reason_code,u8 reason_code_expl)378 bfa_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, bfa_fcxp_get_reqbuf(fcxp),
394 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
395 rx_fchs->ox_id, reason_code, reason_code_expl);
396
397 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
398 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
399 FC_MAX_PDUSZ, 0);
400 }
401
402 /*
403 * Send a FCCT Reject
404 */
405 static void
bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,u8 reason_code,u8 reason_code_expl)406 bfa_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, ct_hdr, rx_fchs->s_id,
428 bfa_fcs_lport_get_fcid(port),
429 rx_fchs->ox_id, reason_code, reason_code_expl);
430
431 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
432 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
433 FC_MAX_PDUSZ, 0);
434 }
435
436 /*
437 * Process incoming plogi from a remote port.
438 */
439 static void
bfa_fcs_lport_plogi(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_logi_s * plogi)440 bfa_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(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 FC_LS_RJT_RSN_PROTOCOL_ERROR,
463 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((void *)&bfa_fcs_lport_get_pwwn(port),
472 (void *)&plogi->port_name, 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 FC_LS_RJT_RSN_PROTOCOL_ERROR,
477 FC_LS_RJT_EXP_INVALID_NPORT_ID);
478 return;
479 }
480 port->pid = rx_fchs->d_id;
481 bfa_lps_set_n2n_pid(port->fabric->lps, 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, 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((void *)&bfa_fcs_lport_get_pwwn(port),
494 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
495 port->pid = rx_fchs->d_id;
496 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
497 rport->pid = rx_fchs->s_id;
498 }
499 bfa_fcs_rport_plogi(rport, 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, 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, rx_fchs, plogi);
538 }
539
540 /*
541 * Process incoming ECHO.
542 * Since it does not require a login, it is processed here.
543 */
544 static void
bfa_fcs_lport_echo(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_echo_s * echo,u16 rx_len)545 bfa_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, bfa_fcxp_get_reqbuf(fcxp),
561 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
562 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, bfa_rport, port->fabric->vf_id, port->lp_tag,
577 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
578 FC_MAX_PDUSZ, 0);
579 }
580
581 /*
582 * Process incoming RNID.
583 * Since it does not require a login, it is processed here.
584 */
585 static void
bfa_fcs_lport_rnid(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_rnid_cmd_s * rnid,u16 rx_len)586 bfa_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);
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, bfa_fcxp_get_reqbuf(fcxp),
629 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
630 rx_fchs->ox_id, data_format, &common_id_data,
631 &gen_topo_data);
632
633 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
634 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
635 FC_MAX_PDUSZ, 0);
636 }
637
638 /*
639 * Fill out General Topolpgy Discovery Data for RNID ELS.
640 */
641 static void
bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s * port,struct fc_rnid_general_topology_data_s * gen_topo_data)642 bfa_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
653 static void
bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s * port)654 bfa_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(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, BFA_LPORT_AEN_ONLINE);
669
670 bfad->bfad_flags |= BFAD_PORT_ONLINE;
671 }
672
673 static void
bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s * port)674 bfa_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(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, 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, 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
705 static void
bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s * port)706 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
707 {
708 WARN_ON(1);
709 }
710
711 static void
bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s * port)712 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
713 {
714 WARN_ON(1);
715 }
716
717 static void
bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s * port)718 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
719 {
720 WARN_ON(1);
721 }
722
723 static void
bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs)724 bfa_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, bfa_fcxp_get_reqbuf(fcxp),
738 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
739 rx_fchs->ox_id, 0);
740
741 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
742 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
743 FC_MAX_PDUSZ, 0);
744 }
745 static void
bfa_fcs_lport_deleted(struct bfa_fcs_lport_s * port)746 bfa_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(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, 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(port->vport);
760 else
761 bfa_wc_down(&port->fabric->wc);
762 }
763
764
765 /*
766 * Unsolicited frame receive handling.
767 */
768 void
bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s * lport,struct fchs_s * fchs,u16 len)769 bfa_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(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(lport, fchs,
788 FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
789 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(lport, fchs, (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(lport, fchs,
814 (struct fc_echo_s *)els_cmd, 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(lport, fchs,
823 (struct fc_rnid_cmd_s *) els_cmd, 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(lport, 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(lport, fchs, CT_RSN_NOT_SUPP,
839 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(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(lport, 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(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
892 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 */
899 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s * port,u32 pid)900 bfa_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 */
918 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s * port,u32 pid)919 bfa_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 */
937 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s * port,wwn_t pwwn)938 bfa_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 */
956 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s * port,wwn_t nwwn)957 bfa_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 */
975 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s * port,wwn_t pwwn,u32 pid)976 bfa_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 */
995 void
bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s * port,struct bfa_fcs_rport_s * rport)996 bfa_fcs_lport_add_rport(
997 struct bfa_fcs_lport_s *port,
998 struct bfa_fcs_rport_s *rport)
999 {
1000 list_add_tail(&rport->qe, &port->rport_q);
1001 port->num_rports++;
1002 }
1003
1004 /*
1005 * Called by rport module to when rports are deleted.
1006 */
1007 void
bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s * port,struct bfa_fcs_rport_s * rport)1008 bfa_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(&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 */
1023 void
bfa_fcs_lport_online(struct bfa_fcs_lport_s * port)1024 bfa_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 */
1033 void
bfa_fcs_lport_offline(struct bfa_fcs_lport_s * port)1034 bfa_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 */
1043 void
bfa_fcs_lport_stop(struct bfa_fcs_lport_s * port)1044 bfa_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 */
1055 void
bfa_fcs_lport_delete(struct bfa_fcs_lport_s * port)1056 bfa_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 */
1064 bfa_boolean_t
bfa_fcs_lport_is_online(struct bfa_fcs_lport_s * port)1065 bfa_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 */
1073 void
bfa_fcs_lport_attach(struct bfa_fcs_lport_s * lport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_fcs_vport_s * vport)1074 bfa_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(&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
1092 void
bfa_fcs_lport_init(struct bfa_fcs_lport_s * lport,struct bfa_lport_cfg_s * port_cfg)1093 bfa_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(lport->fcs->bfad, lport,
1103 lport->port_cfg.roles,
1104 lport->fabric->vf_drv,
1105 vport ? vport->vport_drv : NULL);
1106
1107 wwn2str(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(lport, 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
1117 void
bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s * port,char * symname)1118 bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port,
1119 char *symname)
1120 {
1121 strcpy(port->port_cfg.sym_name.symname, 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
1132 void
bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s * port,struct bfa_lport_attr_s * port_attr)1133 bfa_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 */
1177 static void
bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s * port)1178 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
1179 {
1180 bfa_fcs_lport_ns_init(port);
1181 bfa_fcs_lport_scn_init(port);
1182 bfa_fcs_lport_ms_init(port);
1183 }
1184
1185 /*
1186 * Called by port to notify transition to online state.
1187 */
1188 static void
bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s * port)1189 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
1190 {
1191 bfa_fcs_lport_ns_online(port);
1192 bfa_fcs_lport_fab_scn_online(port);
1193 }
1194
1195 /*
1196 * Called by port to notify transition to offline state.
1197 */
1198 static void
bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s * port)1199 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
1200 {
1201 bfa_fcs_lport_ns_offline(port);
1202 bfa_fcs_lport_scn_offline(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 */
1213 static void
bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s * port)1214 bfa_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 */
1221 static void
bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s * port)1222 bfa_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 ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
1240 sizeof(wwn_t)) > 0) {
1241 port->pid = N2N_LOCAL_PID;
1242 bfa_lps_set_n2n_pid(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 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, 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 */
1275 static void
bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s * port)1276 bfa_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
1286 static void
bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s * port)1287 bfa_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 */
1317 static void
bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s * port)1318 bfa_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 */
1325 static void
bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s * port)1326 bfa_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 */
1373 static void
bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s * port)1374 bfa_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 */
1383 static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1384 struct bfa_fcxp_s *fcxp_alloced);
1385 static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1386 struct bfa_fcxp_s *fcxp_alloced);
1387 static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1388 struct bfa_fcxp_s *fcxp_alloced);
1389 static 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);
1396 static 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);
1403 static 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);
1410 static void bfa_fcs_lport_fdmi_timeout(void *arg);
1411 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1412 u8 *pyld);
1413 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1414 u8 *pyld);
1415 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1416 u8 *pyld);
1417 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1418 fdmi, u8 *pyld);
1419 static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1420 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1421 static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1422 struct bfa_fcs_fdmi_port_attr_s *port_attr);
1423 u32 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 */
1432 enum 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
1443 static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1444 enum port_fdmi_event event);
1445 static void bfa_fcs_lport_fdmi_sm_sending_rhba(
1446 struct bfa_fcs_lport_fdmi_s *fdmi,
1447 enum port_fdmi_event event);
1448 static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1449 enum port_fdmi_event event);
1450 static void bfa_fcs_lport_fdmi_sm_rhba_retry(
1451 struct bfa_fcs_lport_fdmi_s *fdmi,
1452 enum port_fdmi_event event);
1453 static void bfa_fcs_lport_fdmi_sm_sending_rprt(
1454 struct bfa_fcs_lport_fdmi_s *fdmi,
1455 enum port_fdmi_event event);
1456 static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1457 enum port_fdmi_event event);
1458 static void bfa_fcs_lport_fdmi_sm_rprt_retry(
1459 struct bfa_fcs_lport_fdmi_s *fdmi,
1460 enum port_fdmi_event event);
1461 static void bfa_fcs_lport_fdmi_sm_sending_rpa(
1462 struct bfa_fcs_lport_fdmi_s *fdmi,
1463 enum port_fdmi_event event);
1464 static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1465 enum port_fdmi_event event);
1466 static void bfa_fcs_lport_fdmi_sm_rpa_retry(
1467 struct bfa_fcs_lport_fdmi_s *fdmi,
1468 enum port_fdmi_event event);
1469 static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1470 enum port_fdmi_event event);
1471 static 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 */
1477 static void
bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1478 bfa_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, 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, 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
1517 static void
bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1518 bfa_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 &fdmi->fcxp_wqe);
1535 break;
1536
1537 default:
1538 bfa_sm_fault(port->fcs, event);
1539 }
1540 }
1541
1542 static void
bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1543 bfa_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, NULL);
1579 break;
1580
1581 case FDMISM_EVENT_PORT_OFFLINE:
1582 bfa_fcxp_discard(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
1591 static void
bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1592 bfa_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, 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(&fdmi->timer);
1612 break;
1613
1614 default:
1615 bfa_sm_fault(port->fcs, event);
1616 }
1617 }
1618
1619 /*
1620 * RPRT : Register Port
1621 */
1622 static void
bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1623 bfa_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 &fdmi->fcxp_wqe);
1640 break;
1641
1642 default:
1643 bfa_sm_fault(port->fcs, event);
1644 }
1645 }
1646
1647 static void
bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1648 bfa_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(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
1694 static void
bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1695 bfa_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, 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(&fdmi->timer);
1715 break;
1716
1717 default:
1718 bfa_sm_fault(port->fcs, event);
1719 }
1720 }
1721
1722 /*
1723 * Register Port Attributes
1724 */
1725 static void
bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1726 bfa_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 &fdmi->fcxp_wqe);
1743 break;
1744
1745 default:
1746 bfa_sm_fault(port->fcs, event);
1747 }
1748 }
1749
1750 static void
bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1751 bfa_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(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
1795 static void
bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1796 bfa_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, 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(&fdmi->timer);
1816 break;
1817
1818 default:
1819 bfa_sm_fault(port->fcs, event);
1820 }
1821 }
1822
1823 static void
bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1824 bfa_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 */
1844 static void
bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1845 bfa_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 */
1859 static void
bfa_fcs_lport_fdmi_send_rhba(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)1860 bfa_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, pyld, bfa_fcs_lport_get_fcid(port),
1884 FDMI_RHBA);
1885
1886 attr_len =
1887 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1888 (u8 *) ((struct ct_hdr_s *) pyld
1889 + 1));
1890
1891 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1892 FC_CLASS_3, (len + attr_len), &fchs,
1893 bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1894 FC_MAX_PDUSZ, FC_FCCT_TOV);
1895
1896 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1897 }
1898
1899 static u16
bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)1900 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1901 {
1902 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1903 struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1904 struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1905 struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1906 struct fdmi_attr_s *attr;
1907 u8 *curr_ptr;
1908 u16 len, count;
1909 u16 templen;
1910
1911 /*
1912 * get hba attributes
1913 */
1914 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1915
1916 rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1917 rhba->port_list.num_ports = cpu_to_be32(1);
1918 rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1919
1920 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1921
1922 count = 0;
1923 len += sizeof(rhba->hba_attr_blk.attr_count);
1924
1925 /*
1926 * fill out the invididual entries of the HBA attrib Block
1927 */
1928 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1929
1930 /*
1931 * Node Name
1932 */
1933 attr = (struct fdmi_attr_s *) curr_ptr;
1934 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1935 templen = sizeof(wwn_t);
1936 memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1937 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1938 len += templen;
1939 count++;
1940 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1941 sizeof(templen));
1942
1943 /*
1944 * Manufacturer
1945 */
1946 attr = (struct fdmi_attr_s *) curr_ptr;
1947 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1948 templen = (u16) strlen(fcs_hba_attr->manufacturer);
1949 memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1950 templen = fc_roundup(templen, sizeof(u32));
1951 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1952 len += templen;
1953 count++;
1954 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1955 sizeof(templen));
1956
1957 /*
1958 * Serial Number
1959 */
1960 attr = (struct fdmi_attr_s *) curr_ptr;
1961 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1962 templen = (u16) strlen(fcs_hba_attr->serial_num);
1963 memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1964 templen = fc_roundup(templen, sizeof(u32));
1965 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1966 len += templen;
1967 count++;
1968 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1969 sizeof(templen));
1970
1971 /*
1972 * Model
1973 */
1974 attr = (struct fdmi_attr_s *) curr_ptr;
1975 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1976 templen = (u16) strlen(fcs_hba_attr->model);
1977 memcpy(attr->value, fcs_hba_attr->model, templen);
1978 templen = fc_roundup(templen, sizeof(u32));
1979 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1980 len += templen;
1981 count++;
1982 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1983 sizeof(templen));
1984
1985 /*
1986 * Model Desc
1987 */
1988 attr = (struct fdmi_attr_s *) curr_ptr;
1989 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1990 templen = (u16) strlen(fcs_hba_attr->model_desc);
1991 memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1992 templen = fc_roundup(templen, sizeof(u32));
1993 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1994 len += templen;
1995 count++;
1996 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1997 sizeof(templen));
1998
1999 /*
2000 * H/W Version
2001 */
2002 if (fcs_hba_attr->hw_version[0] != '\0') {
2003 attr = (struct fdmi_attr_s *) curr_ptr;
2004 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
2005 templen = (u16) strlen(fcs_hba_attr->hw_version);
2006 memcpy(attr->value, fcs_hba_attr->hw_version, templen);
2007 templen = fc_roundup(templen, sizeof(u32));
2008 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2009 len += templen;
2010 count++;
2011 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2012 sizeof(templen));
2013 }
2014
2015 /*
2016 * Driver Version
2017 */
2018 attr = (struct fdmi_attr_s *) curr_ptr;
2019 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
2020 templen = (u16) strlen(fcs_hba_attr->driver_version);
2021 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
2022 templen = fc_roundup(templen, sizeof(u32));
2023 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2024 len += templen;
2025 count++;
2026 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2027 sizeof(templen));
2028
2029 /*
2030 * Option Rom Version
2031 */
2032 if (fcs_hba_attr->option_rom_ver[0] != '\0') {
2033 attr = (struct fdmi_attr_s *) curr_ptr;
2034 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
2035 templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
2036 memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
2037 templen = fc_roundup(templen, sizeof(u32));
2038 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2039 len += templen;
2040 count++;
2041 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2042 sizeof(templen));
2043 }
2044
2045 attr = (struct fdmi_attr_s *) curr_ptr;
2046 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
2047 templen = (u16) strlen(fcs_hba_attr->fw_version);
2048 memcpy(attr->value, fcs_hba_attr->fw_version, templen);
2049 templen = fc_roundup(templen, sizeof(u32));
2050 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2051 len += templen;
2052 count++;
2053 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2054 sizeof(templen));
2055
2056 /*
2057 * OS Name
2058 */
2059 if (fcs_hba_attr->os_name[0] != '\0') {
2060 attr = (struct fdmi_attr_s *) curr_ptr;
2061 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
2062 templen = (u16) strlen(fcs_hba_attr->os_name);
2063 memcpy(attr->value, fcs_hba_attr->os_name, templen);
2064 templen = fc_roundup(templen, sizeof(u32));
2065 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2066 len += templen;
2067 count++;
2068 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2069 sizeof(templen));
2070 }
2071
2072 /*
2073 * MAX_CT_PAYLOAD
2074 */
2075 attr = (struct fdmi_attr_s *) curr_ptr;
2076 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
2077 templen = sizeof(fcs_hba_attr->max_ct_pyld);
2078 memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
2079 templen = fc_roundup(templen, sizeof(u32));
2080 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2081 len += templen;
2082 count++;
2083 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2084 sizeof(templen));
2085 /*
2086 * Send extended attributes ( FOS 7.1 support )
2087 */
2088 if (fdmi->retry_cnt == 0) {
2089 attr = (struct fdmi_attr_s *) curr_ptr;
2090 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME);
2091 templen = sizeof(fcs_hba_attr->node_sym_name);
2092 memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen);
2093 templen = fc_roundup(templen, sizeof(u32));
2094 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2095 len += templen;
2096 count++;
2097 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2098 sizeof(templen));
2099
2100 attr = (struct fdmi_attr_s *) curr_ptr;
2101 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID);
2102 templen = sizeof(fcs_hba_attr->vendor_info);
2103 memcpy(attr->value, &fcs_hba_attr->vendor_info, templen);
2104 templen = fc_roundup(templen, sizeof(u32));
2105 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2106 len += templen;
2107 count++;
2108 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2109 sizeof(templen));
2110
2111 attr = (struct fdmi_attr_s *) curr_ptr;
2112 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS);
2113 templen = sizeof(fcs_hba_attr->num_ports);
2114 memcpy(attr->value, &fcs_hba_attr->num_ports, templen);
2115 templen = fc_roundup(templen, sizeof(u32));
2116 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2117 len += templen;
2118 count++;
2119 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2120 sizeof(templen));
2121
2122 attr = (struct fdmi_attr_s *) curr_ptr;
2123 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME);
2124 templen = sizeof(fcs_hba_attr->fabric_name);
2125 memcpy(attr->value, &fcs_hba_attr->fabric_name, templen);
2126 templen = fc_roundup(templen, sizeof(u32));
2127 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2128 len += templen;
2129 count++;
2130 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2131 sizeof(templen));
2132
2133 attr = (struct fdmi_attr_s *) curr_ptr;
2134 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER);
2135 templen = sizeof(fcs_hba_attr->bios_ver);
2136 memcpy(attr->value, &fcs_hba_attr->bios_ver, templen);
2137 templen = fc_roundup(attr->len, sizeof(u32));
2138 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2139 len += templen;
2140 count++;
2141 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2142 sizeof(templen));
2143 }
2144
2145 /*
2146 * Update size of payload
2147 */
2148 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
2149
2150 rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
2151 return len;
2152 }
2153
2154 static void
bfa_fcs_lport_fdmi_rhba_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)2155 bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2156 void *cbarg, bfa_status_t req_status,
2157 u32 rsp_len, u32 resid_len,
2158 struct fchs_s *rsp_fchs)
2159 {
2160 struct bfa_fcs_lport_fdmi_s *fdmi =
2161 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2162 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2163 struct ct_hdr_s *cthdr = NULL;
2164
2165 bfa_trc(port->fcs, port->port_cfg.pwwn);
2166
2167 /*
2168 * Sanity Checks
2169 */
2170 if (req_status != BFA_STATUS_OK) {
2171 bfa_trc(port->fcs, req_status);
2172 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2173 return;
2174 }
2175
2176 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2177 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2178
2179 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2180 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2181 return;
2182 }
2183
2184 bfa_trc(port->fcs, cthdr->reason_code);
2185 bfa_trc(port->fcs, cthdr->exp_code);
2186 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2187 }
2188
2189 /*
2190 * RPRT : Register Port
2191 */
2192 static void
bfa_fcs_lport_fdmi_send_rprt(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)2193 bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2194 {
2195 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2196 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2197 struct fchs_s fchs;
2198 u16 len, attr_len;
2199 struct bfa_fcxp_s *fcxp;
2200 u8 *pyld;
2201
2202 bfa_trc(port->fcs, port->port_cfg.pwwn);
2203
2204 fcxp = fcxp_alloced ? fcxp_alloced :
2205 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2206 if (!fcxp) {
2207 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2208 bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);
2209 return;
2210 }
2211 fdmi->fcxp = fcxp;
2212
2213 pyld = bfa_fcxp_get_reqbuf(fcxp);
2214 memset(pyld, 0, FC_MAX_PDUSZ);
2215
2216 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2217 FDMI_RPRT);
2218
2219 attr_len =
2220 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
2221 (u8 *) ((struct ct_hdr_s *) pyld
2222 + 1));
2223
2224 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2225 FC_CLASS_3, len + attr_len, &fchs,
2226 bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
2227 FC_MAX_PDUSZ, FC_FCCT_TOV);
2228
2229 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
2230 }
2231
2232 /*
2233 * This routine builds Port Attribute Block that used in RPA, RPRT commands.
2234 */
2235 static u16
bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)2236 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
2237 u8 *pyld)
2238 {
2239 struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
2240 struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
2241 struct fdmi_attr_s *attr;
2242 u8 *curr_ptr;
2243 u16 len;
2244 u8 count = 0;
2245 u16 templen;
2246
2247 /*
2248 * get port attributes
2249 */
2250 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
2251
2252 len = sizeof(port_attrib->attr_count);
2253
2254 /*
2255 * fill out the invididual entries
2256 */
2257 curr_ptr = (u8 *) &port_attrib->port_attr;
2258
2259 /*
2260 * FC4 Types
2261 */
2262 attr = (struct fdmi_attr_s *) curr_ptr;
2263 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
2264 templen = sizeof(fcs_port_attr.supp_fc4_types);
2265 memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
2266 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2267 len += templen;
2268 ++count;
2269 attr->len =
2270 cpu_to_be16(templen + sizeof(attr->type) +
2271 sizeof(templen));
2272
2273 /*
2274 * Supported Speed
2275 */
2276 attr = (struct fdmi_attr_s *) curr_ptr;
2277 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
2278 templen = sizeof(fcs_port_attr.supp_speed);
2279 memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
2280 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2281 len += templen;
2282 ++count;
2283 attr->len =
2284 cpu_to_be16(templen + sizeof(attr->type) +
2285 sizeof(templen));
2286
2287 /*
2288 * current Port Speed
2289 */
2290 attr = (struct fdmi_attr_s *) curr_ptr;
2291 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
2292 templen = sizeof(fcs_port_attr.curr_speed);
2293 memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
2294 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2295 len += templen;
2296 ++count;
2297 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2298 sizeof(templen));
2299
2300 /*
2301 * max frame size
2302 */
2303 attr = (struct fdmi_attr_s *) curr_ptr;
2304 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
2305 templen = sizeof(fcs_port_attr.max_frm_size);
2306 memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
2307 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2308 len += templen;
2309 ++count;
2310 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2311 sizeof(templen));
2312
2313 /*
2314 * OS Device Name
2315 */
2316 if (fcs_port_attr.os_device_name[0] != '\0') {
2317 attr = (struct fdmi_attr_s *) curr_ptr;
2318 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
2319 templen = (u16) strlen(fcs_port_attr.os_device_name);
2320 memcpy(attr->value, fcs_port_attr.os_device_name, templen);
2321 templen = fc_roundup(templen, sizeof(u32));
2322 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2323 len += templen;
2324 ++count;
2325 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2326 sizeof(templen));
2327 }
2328 /*
2329 * Host Name
2330 */
2331 if (fcs_port_attr.host_name[0] != '\0') {
2332 attr = (struct fdmi_attr_s *) curr_ptr;
2333 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
2334 templen = (u16) strlen(fcs_port_attr.host_name);
2335 memcpy(attr->value, fcs_port_attr.host_name, templen);
2336 templen = fc_roundup(templen, sizeof(u32));
2337 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2338 len += templen;
2339 ++count;
2340 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2341 sizeof(templen));
2342 }
2343
2344 if (fdmi->retry_cnt == 0) {
2345 attr = (struct fdmi_attr_s *) curr_ptr;
2346 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_NODE_NAME);
2347 templen = sizeof(fcs_port_attr.node_name);
2348 memcpy(attr->value, &fcs_port_attr.node_name, templen);
2349 templen = fc_roundup(templen, sizeof(u32));
2350 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2351 len += templen;
2352 ++count;
2353 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2354 sizeof(templen));
2355
2356 attr = (struct fdmi_attr_s *) curr_ptr;
2357 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NAME);
2358 templen = sizeof(fcs_port_attr.port_name);
2359 memcpy(attr->value, &fcs_port_attr.port_name, templen);
2360 templen = fc_roundup(templen, sizeof(u32));
2361 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + templen;
2362 len += templen;
2363 ++count;
2364 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2365 sizeof(templen));
2366
2367 if (fcs_port_attr.port_sym_name.symname[0] != '\0') {
2368 attr = (struct fdmi_attr_s *) curr_ptr;
2369 attr->type =
2370 cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SYM_NAME);
2371 templen = sizeof(fcs_port_attr.port_sym_name);
2372 memcpy(attr->value,
2373 &fcs_port_attr.port_sym_name, templen);
2374 templen = fc_roundup(templen, sizeof(u32));
2375 curr_ptr += sizeof(attr->type) +
2376 sizeof(templen) + templen;
2377 len += templen;
2378 ++count;
2379 attr->len = cpu_to_be16(templen +
2380 sizeof(attr->type) + sizeof(templen));
2381 }
2382
2383 attr = (struct fdmi_attr_s *) curr_ptr;
2384 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_TYPE);
2385 templen = sizeof(fcs_port_attr.port_type);
2386 memcpy(attr->value, &fcs_port_attr.port_type, templen);
2387 templen = fc_roundup(templen, sizeof(u32));
2388 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2389 len += templen;
2390 ++count;
2391 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2392 sizeof(templen));
2393
2394 attr = (struct fdmi_attr_s *) curr_ptr;
2395 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_COS);
2396 templen = sizeof(fcs_port_attr.scos);
2397 memcpy(attr->value, &fcs_port_attr.scos, templen);
2398 templen = fc_roundup(templen, sizeof(u32));
2399 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2400 len += templen;
2401 ++count;
2402 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2403 sizeof(templen));
2404
2405 attr = (struct fdmi_attr_s *) curr_ptr;
2406 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FAB_NAME);
2407 templen = sizeof(fcs_port_attr.port_fabric_name);
2408 memcpy(attr->value, &fcs_port_attr.port_fabric_name, templen);
2409 templen = fc_roundup(templen, sizeof(u32));
2410 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2411 len += templen;
2412 ++count;
2413 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2414 sizeof(templen));
2415
2416 attr = (struct fdmi_attr_s *) curr_ptr;
2417 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FC4_TYPE);
2418 templen = sizeof(fcs_port_attr.port_act_fc4_type);
2419 memcpy(attr->value, fcs_port_attr.port_act_fc4_type,
2420 templen);
2421 templen = fc_roundup(templen, sizeof(u32));
2422 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2423 len += templen;
2424 ++count;
2425 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2426 sizeof(templen));
2427
2428 attr = (struct fdmi_attr_s *) curr_ptr;
2429 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_STATE);
2430 templen = sizeof(fcs_port_attr.port_state);
2431 memcpy(attr->value, &fcs_port_attr.port_state, templen);
2432 templen = fc_roundup(templen, sizeof(u32));
2433 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2434 len += templen;
2435 ++count;
2436 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2437 sizeof(templen));
2438
2439 attr = (struct fdmi_attr_s *) curr_ptr;
2440 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NUM_RPRT);
2441 templen = sizeof(fcs_port_attr.num_ports);
2442 memcpy(attr->value, &fcs_port_attr.num_ports, templen);
2443 templen = fc_roundup(templen, sizeof(u32));
2444 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2445 len += templen;
2446 ++count;
2447 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2448 sizeof(templen));
2449 }
2450
2451 /*
2452 * Update size of payload
2453 */
2454 port_attrib->attr_count = cpu_to_be32(count);
2455 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
2456 return len;
2457 }
2458
2459 static u16
bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)2460 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2461 {
2462 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2463 struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
2464 u16 len;
2465
2466 rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
2467 rprt->port_name = bfa_fcs_lport_get_pwwn(port);
2468
2469 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2470 (u8 *) &rprt->port_attr_blk);
2471
2472 len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
2473
2474 return len;
2475 }
2476
2477 static void
bfa_fcs_lport_fdmi_rprt_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)2478 bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2479 void *cbarg, bfa_status_t req_status,
2480 u32 rsp_len, u32 resid_len,
2481 struct fchs_s *rsp_fchs)
2482 {
2483 struct bfa_fcs_lport_fdmi_s *fdmi =
2484 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2485 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2486 struct ct_hdr_s *cthdr = NULL;
2487
2488 bfa_trc(port->fcs, port->port_cfg.pwwn);
2489
2490 /*
2491 * Sanity Checks
2492 */
2493 if (req_status != BFA_STATUS_OK) {
2494 bfa_trc(port->fcs, req_status);
2495 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2496 return;
2497 }
2498
2499 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2500 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2501
2502 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2503 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2504 return;
2505 }
2506
2507 bfa_trc(port->fcs, cthdr->reason_code);
2508 bfa_trc(port->fcs, cthdr->exp_code);
2509 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2510 }
2511
2512 /*
2513 * RPA : Register Port Attributes.
2514 */
2515 static void
bfa_fcs_lport_fdmi_send_rpa(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)2516 bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2517 {
2518 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2519 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2520 struct fchs_s fchs;
2521 u16 len, attr_len;
2522 struct bfa_fcxp_s *fcxp;
2523 u8 *pyld;
2524
2525 bfa_trc(port->fcs, port->port_cfg.pwwn);
2526
2527 fcxp = fcxp_alloced ? fcxp_alloced :
2528 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2529 if (!fcxp) {
2530 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2531 bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);
2532 return;
2533 }
2534 fdmi->fcxp = fcxp;
2535
2536 pyld = bfa_fcxp_get_reqbuf(fcxp);
2537 memset(pyld, 0, FC_MAX_PDUSZ);
2538
2539 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2540 FDMI_RPA);
2541
2542 attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2543 (u8 *) ((struct ct_hdr_s *) pyld + 1));
2544
2545 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2546 FC_CLASS_3, len + attr_len, &fchs,
2547 bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2548 FC_MAX_PDUSZ, FC_FCCT_TOV);
2549
2550 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2551 }
2552
2553 static u16
bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)2554 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2555 {
2556 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2557 struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2558 u16 len;
2559
2560 rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2561
2562 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2563 (u8 *) &rpa->port_attr_blk);
2564
2565 len += sizeof(rpa->port_name);
2566
2567 return len;
2568 }
2569
2570 static void
bfa_fcs_lport_fdmi_rpa_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)2571 bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2572 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2573 u32 resid_len, struct fchs_s *rsp_fchs)
2574 {
2575 struct bfa_fcs_lport_fdmi_s *fdmi =
2576 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2577 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2578 struct ct_hdr_s *cthdr = NULL;
2579
2580 bfa_trc(port->fcs, port->port_cfg.pwwn);
2581
2582 /*
2583 * Sanity Checks
2584 */
2585 if (req_status != BFA_STATUS_OK) {
2586 bfa_trc(port->fcs, req_status);
2587 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2588 return;
2589 }
2590
2591 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2592 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2593
2594 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2595 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2596 return;
2597 }
2598
2599 bfa_trc(port->fcs, cthdr->reason_code);
2600 bfa_trc(port->fcs, cthdr->exp_code);
2601 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2602 }
2603
2604 static void
bfa_fcs_lport_fdmi_timeout(void * arg)2605 bfa_fcs_lport_fdmi_timeout(void *arg)
2606 {
2607 struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2608
2609 bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2610 }
2611
2612 static void
bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s * fdmi,struct bfa_fcs_fdmi_hba_attr_s * hba_attr)2613 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2614 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2615 {
2616 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2617 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2618 struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
2619
2620 memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2621
2622 bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2623 hba_attr->manufacturer);
2624 bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2625 hba_attr->serial_num);
2626 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2627 hba_attr->model);
2628 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2629 hba_attr->model_desc);
2630 bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2631 hba_attr->hw_version);
2632 bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2633 hba_attr->option_rom_ver);
2634 bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2635 hba_attr->fw_version);
2636
2637 strlcpy(hba_attr->driver_version, (char *)driver_info->version,
2638 sizeof(hba_attr->driver_version));
2639
2640 strlcpy(hba_attr->os_name, driver_info->host_os_name,
2641 sizeof(hba_attr->os_name));
2642
2643 /*
2644 * If there is a patch level, append it
2645 * to the os name along with a separator
2646 */
2647 if (driver_info->host_os_patch[0] != '\0') {
2648 strlcat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2649 sizeof(hba_attr->os_name));
2650 strlcat(hba_attr->os_name, driver_info->host_os_patch,
2651 sizeof(hba_attr->os_name));
2652 }
2653
2654 /* Retrieve the max frame size from the port attr */
2655 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
2656 hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size;
2657
2658 strlcpy(hba_attr->node_sym_name.symname,
2659 port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN);
2660 strcpy(hba_attr->vendor_info, "QLogic");
2661 hba_attr->num_ports =
2662 cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc));
2663 hba_attr->fabric_name = port->fabric->lps->pr_nwwn;
2664 strlcpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN);
2665
2666 }
2667
2668 static void
bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s * fdmi,struct bfa_fcs_fdmi_port_attr_s * port_attr)2669 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2670 struct bfa_fcs_fdmi_port_attr_s *port_attr)
2671 {
2672 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2673 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2674 struct bfa_port_attr_s pport_attr;
2675 struct bfa_lport_attr_s lport_attr;
2676
2677 memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2678
2679 /*
2680 * get pport attributes from hal
2681 */
2682 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2683
2684 /*
2685 * get FC4 type Bitmask
2686 */
2687 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2688
2689 /*
2690 * Supported Speeds
2691 */
2692 switch (pport_attr.speed_supported) {
2693 case BFA_PORT_SPEED_16GBPS:
2694 port_attr->supp_speed =
2695 cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
2696 break;
2697
2698 case BFA_PORT_SPEED_10GBPS:
2699 port_attr->supp_speed =
2700 cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
2701 break;
2702
2703 case BFA_PORT_SPEED_8GBPS:
2704 port_attr->supp_speed =
2705 cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
2706 break;
2707
2708 case BFA_PORT_SPEED_4GBPS:
2709 port_attr->supp_speed =
2710 cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
2711 break;
2712
2713 default:
2714 bfa_sm_fault(port->fcs, pport_attr.speed_supported);
2715 }
2716
2717 /*
2718 * Current Speed
2719 */
2720 port_attr->curr_speed = cpu_to_be32(
2721 bfa_fcs_fdmi_convert_speed(pport_attr.speed));
2722
2723 /*
2724 * Max PDU Size.
2725 */
2726 port_attr->max_frm_size = cpu_to_be32(pport_attr.pport_cfg.maxfrsize);
2727
2728 /*
2729 * OS device Name
2730 */
2731 strlcpy(port_attr->os_device_name, driver_info->os_device_name,
2732 sizeof(port_attr->os_device_name));
2733
2734 /*
2735 * Host name
2736 */
2737 strlcpy(port_attr->host_name, driver_info->host_machine_name,
2738 sizeof(port_attr->host_name));
2739
2740 port_attr->node_name = bfa_fcs_lport_get_nwwn(port);
2741 port_attr->port_name = bfa_fcs_lport_get_pwwn(port);
2742
2743 strlcpy(port_attr->port_sym_name.symname,
2744 bfa_fcs_lport_get_psym_name(port).symname, BFA_SYMNAME_MAXLEN);
2745 bfa_fcs_lport_get_attr(port, &lport_attr);
2746 port_attr->port_type = cpu_to_be32(lport_attr.port_type);
2747 port_attr->scos = pport_attr.cos_supported;
2748 port_attr->port_fabric_name = port->fabric->lps->pr_nwwn;
2749 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->port_act_fc4_type);
2750 port_attr->port_state = cpu_to_be32(pport_attr.port_state);
2751 port_attr->num_ports = cpu_to_be32(port->num_rports);
2752 }
2753
2754 /*
2755 * Convert BFA speed to FDMI format.
2756 */
2757 u32
bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)2758 bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
2759 {
2760 u32 ret;
2761
2762 switch (pport_speed) {
2763 case BFA_PORT_SPEED_1GBPS:
2764 case BFA_PORT_SPEED_2GBPS:
2765 ret = pport_speed;
2766 break;
2767
2768 case BFA_PORT_SPEED_4GBPS:
2769 ret = FDMI_TRANS_SPEED_4G;
2770 break;
2771
2772 case BFA_PORT_SPEED_8GBPS:
2773 ret = FDMI_TRANS_SPEED_8G;
2774 break;
2775
2776 case BFA_PORT_SPEED_10GBPS:
2777 ret = FDMI_TRANS_SPEED_10G;
2778 break;
2779
2780 case BFA_PORT_SPEED_16GBPS:
2781 ret = FDMI_TRANS_SPEED_16G;
2782 break;
2783
2784 default:
2785 ret = FDMI_TRANS_SPEED_UNKNOWN;
2786 }
2787 return ret;
2788 }
2789
2790 void
bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s * ms)2791 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2792 {
2793 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2794
2795 fdmi->ms = ms;
2796 if (ms->port->fcs->fdmi_enabled)
2797 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2798 else
2799 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2800 }
2801
2802 void
bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s * ms)2803 bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2804 {
2805 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2806
2807 fdmi->ms = ms;
2808 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2809 }
2810
2811 void
bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s * ms)2812 bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2813 {
2814 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2815
2816 fdmi->ms = ms;
2817 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2818 }
2819
2820 #define BFA_FCS_MS_CMD_MAX_RETRIES 2
2821
2822 /*
2823 * forward declarations
2824 */
2825 static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2826 struct bfa_fcxp_s *fcxp_alloced);
2827 static void bfa_fcs_lport_ms_timeout(void *arg);
2828 static void bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2829 struct bfa_fcxp_s *fcxp,
2830 void *cbarg,
2831 bfa_status_t req_status,
2832 u32 rsp_len,
2833 u32 resid_len,
2834 struct fchs_s *rsp_fchs);
2835
2836 static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2837 struct bfa_fcxp_s *fcxp_alloced);
2838 static void bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2839 struct bfa_fcxp_s *fcxp,
2840 void *cbarg,
2841 bfa_status_t req_status,
2842 u32 rsp_len,
2843 u32 resid_len,
2844 struct fchs_s *rsp_fchs);
2845 static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2846 struct bfa_fcxp_s *fcxp_alloced);
2847 static void bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2848 struct bfa_fcxp_s *fcxp,
2849 void *cbarg,
2850 bfa_status_t req_status,
2851 u32 rsp_len,
2852 u32 resid_len,
2853 struct fchs_s *rsp_fchs);
2854 /*
2855 * fcs_ms_sm FCS MS state machine
2856 */
2857
2858 /*
2859 * MS State Machine events
2860 */
2861 enum port_ms_event {
2862 MSSM_EVENT_PORT_ONLINE = 1,
2863 MSSM_EVENT_PORT_OFFLINE = 2,
2864 MSSM_EVENT_RSP_OK = 3,
2865 MSSM_EVENT_RSP_ERROR = 4,
2866 MSSM_EVENT_TIMEOUT = 5,
2867 MSSM_EVENT_FCXP_SENT = 6,
2868 MSSM_EVENT_PORT_FABRIC_RSCN = 7
2869 };
2870
2871 static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2872 enum port_ms_event event);
2873 static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2874 enum port_ms_event event);
2875 static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2876 enum port_ms_event event);
2877 static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2878 enum port_ms_event event);
2879 static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2880 enum port_ms_event event);
2881 static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2882 enum port_ms_event event);
2883 static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2884 enum port_ms_event event);
2885 static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2886 enum port_ms_event event);
2887 static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2888 enum port_ms_event event);
2889 static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2890 enum port_ms_event event);
2891 static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2892 enum port_ms_event event);
2893 /*
2894 * Start in offline state - awaiting NS to send start.
2895 */
2896 static void
bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2897 bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2898 enum port_ms_event event)
2899 {
2900 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2901 bfa_trc(ms->port->fcs, event);
2902
2903 switch (event) {
2904 case MSSM_EVENT_PORT_ONLINE:
2905 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2906 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2907 break;
2908
2909 case MSSM_EVENT_PORT_OFFLINE:
2910 break;
2911
2912 default:
2913 bfa_sm_fault(ms->port->fcs, event);
2914 }
2915 }
2916
2917 static void
bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2918 bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2919 enum port_ms_event event)
2920 {
2921 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2922 bfa_trc(ms->port->fcs, event);
2923
2924 switch (event) {
2925 case MSSM_EVENT_FCXP_SENT:
2926 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2927 break;
2928
2929 case MSSM_EVENT_PORT_OFFLINE:
2930 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2931 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2932 &ms->fcxp_wqe);
2933 break;
2934
2935 default:
2936 bfa_sm_fault(ms->port->fcs, event);
2937 }
2938 }
2939
2940 static void
bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2941 bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2942 enum port_ms_event event)
2943 {
2944 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2945 bfa_trc(ms->port->fcs, event);
2946
2947 switch (event) {
2948 case MSSM_EVENT_RSP_ERROR:
2949 /*
2950 * Start timer for a delayed retry
2951 */
2952 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2953 ms->port->stats.ms_retries++;
2954 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2955 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2956 BFA_FCS_RETRY_TIMEOUT);
2957 break;
2958
2959 case MSSM_EVENT_RSP_OK:
2960 /*
2961 * since plogi is done, now invoke MS related sub-modules
2962 */
2963 bfa_fcs_lport_fdmi_online(ms);
2964
2965 /*
2966 * if this is a Vport, go to online state.
2967 */
2968 if (ms->port->vport) {
2969 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2970 break;
2971 }
2972
2973 /*
2974 * For a base port we need to get the
2975 * switch's IP address.
2976 */
2977 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2978 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2979 break;
2980
2981 case MSSM_EVENT_PORT_OFFLINE:
2982 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2983 bfa_fcxp_discard(ms->fcxp);
2984 break;
2985
2986 default:
2987 bfa_sm_fault(ms->port->fcs, event);
2988 }
2989 }
2990
2991 static void
bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2992 bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2993 enum port_ms_event event)
2994 {
2995 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2996 bfa_trc(ms->port->fcs, event);
2997
2998 switch (event) {
2999 case MSSM_EVENT_TIMEOUT:
3000 /*
3001 * Retry Timer Expired. Re-send
3002 */
3003 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
3004 bfa_fcs_lport_ms_send_plogi(ms, NULL);
3005 break;
3006
3007 case MSSM_EVENT_PORT_OFFLINE:
3008 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3009 bfa_timer_stop(&ms->timer);
3010 break;
3011
3012 default:
3013 bfa_sm_fault(ms->port->fcs, event);
3014 }
3015 }
3016
3017 static void
bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)3018 bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
3019 enum port_ms_event event)
3020 {
3021 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3022 bfa_trc(ms->port->fcs, event);
3023
3024 switch (event) {
3025 case MSSM_EVENT_PORT_OFFLINE:
3026 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3027 break;
3028
3029 case MSSM_EVENT_PORT_FABRIC_RSCN:
3030 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3031 ms->retry_cnt = 0;
3032 bfa_fcs_lport_ms_send_gfn(ms, NULL);
3033 break;
3034
3035 default:
3036 bfa_sm_fault(ms->port->fcs, event);
3037 }
3038 }
3039
3040 static void
bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)3041 bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
3042 enum port_ms_event event)
3043 {
3044 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3045 bfa_trc(ms->port->fcs, event);
3046
3047 switch (event) {
3048 case MSSM_EVENT_FCXP_SENT:
3049 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
3050 break;
3051
3052 case MSSM_EVENT_PORT_OFFLINE:
3053 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3054 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3055 &ms->fcxp_wqe);
3056 break;
3057
3058 default:
3059 bfa_sm_fault(ms->port->fcs, event);
3060 }
3061 }
3062
3063 static void
bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)3064 bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
3065 enum port_ms_event event)
3066 {
3067 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3068 bfa_trc(ms->port->fcs, event);
3069
3070 switch (event) {
3071 case MSSM_EVENT_RSP_ERROR:
3072 /*
3073 * Start timer for a delayed retry
3074 */
3075 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
3076 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
3077 ms->port->stats.ms_retries++;
3078 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3079 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
3080 BFA_FCS_RETRY_TIMEOUT);
3081 } else {
3082 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3083 bfa_fcs_lport_ms_send_gfn(ms, NULL);
3084 ms->retry_cnt = 0;
3085 }
3086 break;
3087
3088 case MSSM_EVENT_RSP_OK:
3089 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3090 bfa_fcs_lport_ms_send_gfn(ms, NULL);
3091 break;
3092
3093 case MSSM_EVENT_PORT_OFFLINE:
3094 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3095 bfa_fcxp_discard(ms->fcxp);
3096 break;
3097
3098 default:
3099 bfa_sm_fault(ms->port->fcs, event);
3100 }
3101 }
3102
3103 static void
bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)3104 bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
3105 enum port_ms_event event)
3106 {
3107 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3108 bfa_trc(ms->port->fcs, event);
3109
3110 switch (event) {
3111 case MSSM_EVENT_TIMEOUT:
3112 /*
3113 * Retry Timer Expired. Re-send
3114 */
3115 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
3116 bfa_fcs_lport_ms_send_gmal(ms, NULL);
3117 break;
3118
3119 case MSSM_EVENT_PORT_OFFLINE:
3120 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3121 bfa_timer_stop(&ms->timer);
3122 break;
3123
3124 default:
3125 bfa_sm_fault(ms->port->fcs, event);
3126 }
3127 }
3128 /*
3129 * ms_pvt MS local functions
3130 */
3131
3132 static void
bfa_fcs_lport_ms_send_gmal(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)3133 bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3134 {
3135 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3136 bfa_fcs_lport_t *port = ms->port;
3137 struct fchs_s fchs;
3138 int len;
3139 struct bfa_fcxp_s *fcxp;
3140
3141 bfa_trc(port->fcs, port->pid);
3142
3143 fcxp = fcxp_alloced ? fcxp_alloced :
3144 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3145 if (!fcxp) {
3146 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3147 bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);
3148 return;
3149 }
3150 ms->fcxp = fcxp;
3151
3152 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3153 bfa_fcs_lport_get_fcid(port),
3154 port->fabric->lps->pr_nwwn);
3155
3156 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3157 FC_CLASS_3, len, &fchs,
3158 bfa_fcs_lport_ms_gmal_response, (void *)ms,
3159 FC_MAX_PDUSZ, FC_FCCT_TOV);
3160
3161 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3162 }
3163
3164 static void
bfa_fcs_lport_ms_gmal_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)3165 bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3166 void *cbarg, bfa_status_t req_status,
3167 u32 rsp_len, u32 resid_len,
3168 struct fchs_s *rsp_fchs)
3169 {
3170 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3171 bfa_fcs_lport_t *port = ms->port;
3172 struct ct_hdr_s *cthdr = NULL;
3173 struct fcgs_gmal_resp_s *gmal_resp;
3174 struct fcgs_gmal_entry_s *gmal_entry;
3175 u32 num_entries;
3176 u8 *rsp_str;
3177
3178 bfa_trc(port->fcs, req_status);
3179 bfa_trc(port->fcs, port->port_cfg.pwwn);
3180
3181 /*
3182 * Sanity Checks
3183 */
3184 if (req_status != BFA_STATUS_OK) {
3185 bfa_trc(port->fcs, req_status);
3186 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3187 return;
3188 }
3189
3190 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3191 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3192
3193 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3194 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
3195
3196 num_entries = be32_to_cpu(gmal_resp->ms_len);
3197 if (num_entries == 0) {
3198 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3199 return;
3200 }
3201 /*
3202 * The response could contain multiple Entries.
3203 * Entries for SNMP interface, etc.
3204 * We look for the entry with a telnet prefix.
3205 * First "http://" entry refers to IP addr
3206 */
3207
3208 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
3209 while (num_entries > 0) {
3210 if (strncmp(gmal_entry->prefix,
3211 CT_GMAL_RESP_PREFIX_HTTP,
3212 sizeof(gmal_entry->prefix)) == 0) {
3213
3214 /*
3215 * if the IP address is terminating with a '/',
3216 * remove it.
3217 * Byte 0 consists of the length of the string.
3218 */
3219 rsp_str = &(gmal_entry->prefix[0]);
3220 if (rsp_str[gmal_entry->len-1] == '/')
3221 rsp_str[gmal_entry->len-1] = 0;
3222
3223 /* copy IP Address to fabric */
3224 strlcpy(bfa_fcs_lport_get_fabric_ipaddr(port),
3225 gmal_entry->ip_addr,
3226 BFA_FCS_FABRIC_IPADDR_SZ);
3227 break;
3228 } else {
3229 --num_entries;
3230 ++gmal_entry;
3231 }
3232 }
3233
3234 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3235 return;
3236 }
3237
3238 bfa_trc(port->fcs, cthdr->reason_code);
3239 bfa_trc(port->fcs, cthdr->exp_code);
3240 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3241 }
3242
3243 static void
bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)3244 bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
3245 enum port_ms_event event)
3246 {
3247 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3248 bfa_trc(ms->port->fcs, event);
3249
3250 switch (event) {
3251 case MSSM_EVENT_FCXP_SENT:
3252 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
3253 break;
3254
3255 case MSSM_EVENT_PORT_OFFLINE:
3256 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3257 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3258 &ms->fcxp_wqe);
3259 break;
3260
3261 default:
3262 bfa_sm_fault(ms->port->fcs, event);
3263 }
3264 }
3265
3266 static void
bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)3267 bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
3268 enum port_ms_event event)
3269 {
3270 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3271 bfa_trc(ms->port->fcs, event);
3272
3273 switch (event) {
3274 case MSSM_EVENT_RSP_ERROR:
3275 /*
3276 * Start timer for a delayed retry
3277 */
3278 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
3279 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
3280 ms->port->stats.ms_retries++;
3281 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3282 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
3283 BFA_FCS_RETRY_TIMEOUT);
3284 } else {
3285 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
3286 ms->retry_cnt = 0;
3287 }
3288 break;
3289
3290 case MSSM_EVENT_RSP_OK:
3291 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
3292 break;
3293
3294 case MSSM_EVENT_PORT_OFFLINE:
3295 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3296 bfa_fcxp_discard(ms->fcxp);
3297 break;
3298
3299 default:
3300 bfa_sm_fault(ms->port->fcs, event);
3301 }
3302 }
3303
3304 static void
bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)3305 bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
3306 enum port_ms_event event)
3307 {
3308 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3309 bfa_trc(ms->port->fcs, event);
3310
3311 switch (event) {
3312 case MSSM_EVENT_TIMEOUT:
3313 /*
3314 * Retry Timer Expired. Re-send
3315 */
3316 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3317 bfa_fcs_lport_ms_send_gfn(ms, NULL);
3318 break;
3319
3320 case MSSM_EVENT_PORT_OFFLINE:
3321 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3322 bfa_timer_stop(&ms->timer);
3323 break;
3324
3325 default:
3326 bfa_sm_fault(ms->port->fcs, event);
3327 }
3328 }
3329 /*
3330 * ms_pvt MS local functions
3331 */
3332
3333 static void
bfa_fcs_lport_ms_send_gfn(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)3334 bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3335 {
3336 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3337 bfa_fcs_lport_t *port = ms->port;
3338 struct fchs_s fchs;
3339 int len;
3340 struct bfa_fcxp_s *fcxp;
3341
3342 bfa_trc(port->fcs, port->pid);
3343
3344 fcxp = fcxp_alloced ? fcxp_alloced :
3345 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3346 if (!fcxp) {
3347 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3348 bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);
3349 return;
3350 }
3351 ms->fcxp = fcxp;
3352
3353 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3354 bfa_fcs_lport_get_fcid(port),
3355 port->fabric->lps->pr_nwwn);
3356
3357 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3358 FC_CLASS_3, len, &fchs,
3359 bfa_fcs_lport_ms_gfn_response, (void *)ms,
3360 FC_MAX_PDUSZ, FC_FCCT_TOV);
3361
3362 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3363 }
3364
3365 static void
bfa_fcs_lport_ms_gfn_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)3366 bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3367 void *cbarg, bfa_status_t req_status, u32 rsp_len,
3368 u32 resid_len, struct fchs_s *rsp_fchs)
3369 {
3370 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3371 bfa_fcs_lport_t *port = ms->port;
3372 struct ct_hdr_s *cthdr = NULL;
3373 wwn_t *gfn_resp;
3374
3375 bfa_trc(port->fcs, req_status);
3376 bfa_trc(port->fcs, port->port_cfg.pwwn);
3377
3378 /*
3379 * Sanity Checks
3380 */
3381 if (req_status != BFA_STATUS_OK) {
3382 bfa_trc(port->fcs, req_status);
3383 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3384 return;
3385 }
3386
3387 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3388 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3389
3390 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3391 gfn_resp = (wwn_t *)(cthdr + 1);
3392 /* check if it has actually changed */
3393 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
3394 gfn_resp, sizeof(wwn_t)) != 0)) {
3395 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
3396 }
3397 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3398 return;
3399 }
3400
3401 bfa_trc(port->fcs, cthdr->reason_code);
3402 bfa_trc(port->fcs, cthdr->exp_code);
3403 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3404 }
3405
3406 /*
3407 * ms_pvt MS local functions
3408 */
3409
3410 static void
bfa_fcs_lport_ms_send_plogi(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)3411 bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3412 {
3413 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3414 struct bfa_fcs_lport_s *port = ms->port;
3415 struct fchs_s fchs;
3416 int len;
3417 struct bfa_fcxp_s *fcxp;
3418
3419 bfa_trc(port->fcs, port->pid);
3420
3421 fcxp = fcxp_alloced ? fcxp_alloced :
3422 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3423 if (!fcxp) {
3424 port->stats.ms_plogi_alloc_wait++;
3425 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3426 bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);
3427 return;
3428 }
3429 ms->fcxp = fcxp;
3430
3431 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3432 bfa_hton3b(FC_MGMT_SERVER),
3433 bfa_fcs_lport_get_fcid(port), 0,
3434 port->port_cfg.pwwn, port->port_cfg.nwwn,
3435 bfa_fcport_get_maxfrsize(port->fcs->bfa),
3436 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
3437
3438 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3439 FC_CLASS_3, len, &fchs,
3440 bfa_fcs_lport_ms_plogi_response, (void *)ms,
3441 FC_MAX_PDUSZ, FC_ELS_TOV);
3442
3443 port->stats.ms_plogi_sent++;
3444 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3445 }
3446
3447 static void
bfa_fcs_lport_ms_plogi_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)3448 bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3449 void *cbarg, bfa_status_t req_status,
3450 u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
3451 {
3452 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3453 struct bfa_fcs_lport_s *port = ms->port;
3454 struct fc_els_cmd_s *els_cmd;
3455 struct fc_ls_rjt_s *ls_rjt;
3456
3457 bfa_trc(port->fcs, req_status);
3458 bfa_trc(port->fcs, port->port_cfg.pwwn);
3459
3460 /*
3461 * Sanity Checks
3462 */
3463 if (req_status != BFA_STATUS_OK) {
3464 port->stats.ms_plogi_rsp_err++;
3465 bfa_trc(port->fcs, req_status);
3466 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3467 return;
3468 }
3469
3470 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3471
3472 switch (els_cmd->els_code) {
3473
3474 case FC_ELS_ACC:
3475 if (rsp_len < sizeof(struct fc_logi_s)) {
3476 bfa_trc(port->fcs, rsp_len);
3477 port->stats.ms_plogi_acc_err++;
3478 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3479 break;
3480 }
3481 port->stats.ms_plogi_accepts++;
3482 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3483 break;
3484
3485 case FC_ELS_LS_RJT:
3486 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3487
3488 bfa_trc(port->fcs, ls_rjt->reason_code);
3489 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3490
3491 port->stats.ms_rejects++;
3492 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3493 break;
3494
3495 default:
3496 port->stats.ms_plogi_unknown_rsp++;
3497 bfa_trc(port->fcs, els_cmd->els_code);
3498 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3499 }
3500 }
3501
3502 static void
bfa_fcs_lport_ms_timeout(void * arg)3503 bfa_fcs_lport_ms_timeout(void *arg)
3504 {
3505 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
3506
3507 ms->port->stats.ms_timeouts++;
3508 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
3509 }
3510
3511
3512 void
bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s * port)3513 bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
3514 {
3515 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3516
3517 ms->port = port;
3518 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3519
3520 /*
3521 * Invoke init routines of sub modules.
3522 */
3523 bfa_fcs_lport_fdmi_init(ms);
3524 }
3525
3526 void
bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s * port)3527 bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
3528 {
3529 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3530
3531 ms->port = port;
3532 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
3533 bfa_fcs_lport_fdmi_offline(ms);
3534 }
3535
3536 void
bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s * port)3537 bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
3538 {
3539 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3540
3541 ms->port = port;
3542 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
3543 }
3544 void
bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s * port)3545 bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
3546 {
3547 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3548
3549 /* todo. Handle this only when in Online state */
3550 if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
3551 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
3552 }
3553
3554 /*
3555 * @page ns_sm_info VPORT NS State Machine
3556 *
3557 * @section ns_sm_interactions VPORT NS State Machine Interactions
3558 *
3559 * @section ns_sm VPORT NS State Machine
3560 * img ns_sm.jpg
3561 */
3562
3563 /*
3564 * forward declarations
3565 */
3566 static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
3567 struct bfa_fcxp_s *fcxp_alloced);
3568 static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
3569 struct bfa_fcxp_s *fcxp_alloced);
3570 static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
3571 struct bfa_fcxp_s *fcxp_alloced);
3572 static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3573 struct bfa_fcxp_s *fcxp_alloced);
3574 static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3575 struct bfa_fcxp_s *fcxp_alloced);
3576 static void bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg,
3577 struct bfa_fcxp_s *fcxp_alloced);
3578 static void bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg,
3579 struct bfa_fcxp_s *fcxp_alloced);
3580 static void bfa_fcs_lport_ns_timeout(void *arg);
3581 static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3582 struct bfa_fcxp_s *fcxp,
3583 void *cbarg,
3584 bfa_status_t req_status,
3585 u32 rsp_len,
3586 u32 resid_len,
3587 struct fchs_s *rsp_fchs);
3588 static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
3589 struct bfa_fcxp_s *fcxp,
3590 void *cbarg,
3591 bfa_status_t req_status,
3592 u32 rsp_len,
3593 u32 resid_len,
3594 struct fchs_s *rsp_fchs);
3595 static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
3596 struct bfa_fcxp_s *fcxp,
3597 void *cbarg,
3598 bfa_status_t req_status,
3599 u32 rsp_len,
3600 u32 resid_len,
3601 struct fchs_s *rsp_fchs);
3602 static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
3603 struct bfa_fcxp_s *fcxp,
3604 void *cbarg,
3605 bfa_status_t req_status,
3606 u32 rsp_len,
3607 u32 resid_len,
3608 struct fchs_s *rsp_fchs);
3609 static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3610 struct bfa_fcxp_s *fcxp,
3611 void *cbarg,
3612 bfa_status_t req_status,
3613 u32 rsp_len,
3614 u32 resid_len,
3615 struct fchs_s *rsp_fchs);
3616 static void bfa_fcs_lport_ns_rnn_id_response(void *fcsarg,
3617 struct bfa_fcxp_s *fcxp,
3618 void *cbarg,
3619 bfa_status_t req_status,
3620 u32 rsp_len,
3621 u32 resid_len,
3622 struct fchs_s *rsp_fchs);
3623 static void bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg,
3624 struct bfa_fcxp_s *fcxp,
3625 void *cbarg,
3626 bfa_status_t req_status,
3627 u32 rsp_len,
3628 u32 resid_len,
3629 struct fchs_s *rsp_fchs);
3630 static void bfa_fcs_lport_ns_process_gidft_pids(
3631 struct bfa_fcs_lport_s *port,
3632 u32 *pid_buf, u32 n_pids);
3633
3634 static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3635 /*
3636 * fcs_ns_sm FCS nameserver interface state machine
3637 */
3638
3639 /*
3640 * VPort NS State Machine events
3641 */
3642 enum vport_ns_event {
3643 NSSM_EVENT_PORT_ONLINE = 1,
3644 NSSM_EVENT_PORT_OFFLINE = 2,
3645 NSSM_EVENT_PLOGI_SENT = 3,
3646 NSSM_EVENT_RSP_OK = 4,
3647 NSSM_EVENT_RSP_ERROR = 5,
3648 NSSM_EVENT_TIMEOUT = 6,
3649 NSSM_EVENT_NS_QUERY = 7,
3650 NSSM_EVENT_RSPNID_SENT = 8,
3651 NSSM_EVENT_RFTID_SENT = 9,
3652 NSSM_EVENT_RFFID_SENT = 10,
3653 NSSM_EVENT_GIDFT_SENT = 11,
3654 NSSM_EVENT_RNNID_SENT = 12,
3655 NSSM_EVENT_RSNN_NN_SENT = 13,
3656 };
3657
3658 static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3659 enum vport_ns_event event);
3660 static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3661 enum vport_ns_event event);
3662 static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3663 enum vport_ns_event event);
3664 static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3665 enum vport_ns_event event);
3666 static void bfa_fcs_lport_ns_sm_sending_rspn_id(
3667 struct bfa_fcs_lport_ns_s *ns,
3668 enum vport_ns_event event);
3669 static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3670 enum vport_ns_event event);
3671 static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3672 enum vport_ns_event event);
3673 static void bfa_fcs_lport_ns_sm_sending_rft_id(
3674 struct bfa_fcs_lport_ns_s *ns,
3675 enum vport_ns_event event);
3676 static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3677 enum vport_ns_event event);
3678 static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3679 enum vport_ns_event event);
3680 static void bfa_fcs_lport_ns_sm_sending_rff_id(
3681 struct bfa_fcs_lport_ns_s *ns,
3682 enum vport_ns_event event);
3683 static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3684 enum vport_ns_event event);
3685 static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3686 enum vport_ns_event event);
3687 static void bfa_fcs_lport_ns_sm_sending_gid_ft(
3688 struct bfa_fcs_lport_ns_s *ns,
3689 enum vport_ns_event event);
3690 static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3691 enum vport_ns_event event);
3692 static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3693 enum vport_ns_event event);
3694 static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3695 enum vport_ns_event event);
3696 static void bfa_fcs_lport_ns_sm_sending_rnn_id(
3697 struct bfa_fcs_lport_ns_s *ns,
3698 enum vport_ns_event event);
3699 static void bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3700 enum vport_ns_event event);
3701 static void bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3702 enum vport_ns_event event);
3703 static void bfa_fcs_lport_ns_sm_sending_rsnn_nn(
3704 struct bfa_fcs_lport_ns_s *ns,
3705 enum vport_ns_event event);
3706 static void bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3707 enum vport_ns_event event);
3708 static void bfa_fcs_lport_ns_sm_rsnn_nn_retry(
3709 struct bfa_fcs_lport_ns_s *ns,
3710 enum vport_ns_event event);
3711 /*
3712 * Start in offline state - awaiting linkup
3713 */
3714 static void
bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3715 bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3716 enum vport_ns_event event)
3717 {
3718 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3719 bfa_trc(ns->port->fcs, event);
3720
3721 switch (event) {
3722 case NSSM_EVENT_PORT_ONLINE:
3723 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3724 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3725 break;
3726
3727 case NSSM_EVENT_PORT_OFFLINE:
3728 break;
3729
3730 default:
3731 bfa_sm_fault(ns->port->fcs, event);
3732 }
3733 }
3734
3735 static void
bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3736 bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3737 enum vport_ns_event event)
3738 {
3739 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3740 bfa_trc(ns->port->fcs, event);
3741
3742 switch (event) {
3743 case NSSM_EVENT_PLOGI_SENT:
3744 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3745 break;
3746
3747 case NSSM_EVENT_PORT_OFFLINE:
3748 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3749 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3750 &ns->fcxp_wqe);
3751 break;
3752
3753 default:
3754 bfa_sm_fault(ns->port->fcs, event);
3755 }
3756 }
3757
3758 static void
bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3759 bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3760 enum vport_ns_event event)
3761 {
3762 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3763 bfa_trc(ns->port->fcs, event);
3764
3765 switch (event) {
3766 case NSSM_EVENT_RSP_ERROR:
3767 /*
3768 * Start timer for a delayed retry
3769 */
3770 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3771 ns->port->stats.ns_retries++;
3772 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3773 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3774 BFA_FCS_RETRY_TIMEOUT);
3775 break;
3776
3777 case NSSM_EVENT_RSP_OK:
3778 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3779 ns->num_rnnid_retries = 0;
3780 bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3781 break;
3782
3783 case NSSM_EVENT_PORT_OFFLINE:
3784 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3785 bfa_fcxp_discard(ns->fcxp);
3786 break;
3787
3788 default:
3789 bfa_sm_fault(ns->port->fcs, event);
3790 }
3791 }
3792
3793 static void
bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3794 bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3795 enum vport_ns_event event)
3796 {
3797 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3798 bfa_trc(ns->port->fcs, event);
3799
3800 switch (event) {
3801 case NSSM_EVENT_TIMEOUT:
3802 /*
3803 * Retry Timer Expired. Re-send
3804 */
3805 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3806 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3807 break;
3808
3809 case NSSM_EVENT_PORT_OFFLINE:
3810 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3811 bfa_timer_stop(&ns->timer);
3812 break;
3813
3814 default:
3815 bfa_sm_fault(ns->port->fcs, event);
3816 }
3817 }
3818
3819 static void
bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3820 bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3821 enum vport_ns_event event)
3822 {
3823 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3824 bfa_trc(ns->port->fcs, event);
3825
3826 switch (event) {
3827 case NSSM_EVENT_RNNID_SENT:
3828 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id);
3829 break;
3830
3831 case NSSM_EVENT_PORT_OFFLINE:
3832 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3833 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3834 &ns->fcxp_wqe);
3835 break;
3836 default:
3837 bfa_sm_fault(ns->port->fcs, event);
3838 }
3839 }
3840
3841 static void
bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3842 bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3843 enum vport_ns_event event)
3844 {
3845 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3846 bfa_trc(ns->port->fcs, event);
3847
3848 switch (event) {
3849 case NSSM_EVENT_RSP_OK:
3850 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3851 ns->num_rnnid_retries = 0;
3852 ns->num_rsnn_nn_retries = 0;
3853 bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3854 break;
3855
3856 case NSSM_EVENT_RSP_ERROR:
3857 if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) {
3858 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry);
3859 ns->port->stats.ns_retries++;
3860 ns->num_rnnid_retries++;
3861 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3862 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3863 BFA_FCS_RETRY_TIMEOUT);
3864 } else {
3865 bfa_sm_set_state(ns,
3866 bfa_fcs_lport_ns_sm_sending_rspn_id);
3867 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3868 }
3869 break;
3870
3871 case NSSM_EVENT_PORT_OFFLINE:
3872 bfa_fcxp_discard(ns->fcxp);
3873 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3874 break;
3875
3876 default:
3877 bfa_sm_fault(ns->port->fcs, event);
3878 }
3879 }
3880
3881 static void
bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3882 bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3883 enum vport_ns_event event)
3884 {
3885 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3886 bfa_trc(ns->port->fcs, event);
3887
3888 switch (event) {
3889 case NSSM_EVENT_TIMEOUT:
3890 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3891 bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3892 break;
3893
3894 case NSSM_EVENT_PORT_OFFLINE:
3895 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3896 bfa_timer_stop(&ns->timer);
3897 break;
3898
3899 default:
3900 bfa_sm_fault(ns->port->fcs, event);
3901 }
3902 }
3903
3904 static void
bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3905 bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3906 enum vport_ns_event event)
3907 {
3908 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3909 bfa_trc(ns->port->fcs, event);
3910
3911 switch (event) {
3912 case NSSM_EVENT_RSNN_NN_SENT:
3913 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn);
3914 break;
3915
3916 case NSSM_EVENT_PORT_OFFLINE:
3917 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3918 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3919 &ns->fcxp_wqe);
3920 break;
3921
3922 default:
3923 bfa_sm_fault(ns->port->fcs, event);
3924 }
3925 }
3926
3927 static void
bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3928 bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3929 enum vport_ns_event event)
3930 {
3931 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3932 bfa_trc(ns->port->fcs, event);
3933
3934 switch (event) {
3935 case NSSM_EVENT_RSP_OK:
3936 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3937 ns->num_rsnn_nn_retries = 0;
3938 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3939 break;
3940
3941 case NSSM_EVENT_RSP_ERROR:
3942 if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) {
3943 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry);
3944 ns->port->stats.ns_retries++;
3945 ns->num_rsnn_nn_retries++;
3946 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3947 &ns->timer, bfa_fcs_lport_ns_timeout,
3948 ns, BFA_FCS_RETRY_TIMEOUT);
3949 } else {
3950 bfa_sm_set_state(ns,
3951 bfa_fcs_lport_ns_sm_sending_rspn_id);
3952 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3953 }
3954 break;
3955
3956 case NSSM_EVENT_PORT_OFFLINE:
3957 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3958 bfa_fcxp_discard(ns->fcxp);
3959 break;
3960
3961 default:
3962 bfa_sm_fault(ns->port->fcs, event);
3963 }
3964 }
3965
3966 static void
bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3967 bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns,
3968 enum vport_ns_event event)
3969 {
3970 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3971 bfa_trc(ns->port->fcs, event);
3972
3973 switch (event) {
3974 case NSSM_EVENT_TIMEOUT:
3975 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3976 bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3977 break;
3978
3979 case NSSM_EVENT_PORT_OFFLINE:
3980 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3981 bfa_timer_stop(&ns->timer);
3982 break;
3983
3984 default:
3985 bfa_sm_fault(ns->port->fcs, event);
3986 }
3987 }
3988
3989 static void
bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3990 bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3991 enum vport_ns_event event)
3992 {
3993 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3994 bfa_trc(ns->port->fcs, event);
3995
3996 switch (event) {
3997 case NSSM_EVENT_RSPNID_SENT:
3998 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3999 break;
4000
4001 case NSSM_EVENT_PORT_OFFLINE:
4002 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4003 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4004 &ns->fcxp_wqe);
4005 break;
4006
4007 default:
4008 bfa_sm_fault(ns->port->fcs, event);
4009 }
4010 }
4011
4012 static void
bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4013 bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
4014 enum vport_ns_event event)
4015 {
4016 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4017 bfa_trc(ns->port->fcs, event);
4018
4019 switch (event) {
4020 case NSSM_EVENT_RSP_ERROR:
4021 /*
4022 * Start timer for a delayed retry
4023 */
4024 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
4025 ns->port->stats.ns_retries++;
4026 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4027 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4028 BFA_FCS_RETRY_TIMEOUT);
4029 break;
4030
4031 case NSSM_EVENT_RSP_OK:
4032 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
4033 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
4034 break;
4035
4036 case NSSM_EVENT_PORT_OFFLINE:
4037 bfa_fcxp_discard(ns->fcxp);
4038 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4039 break;
4040
4041 default:
4042 bfa_sm_fault(ns->port->fcs, event);
4043 }
4044 }
4045
4046 static void
bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4047 bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
4048 enum vport_ns_event event)
4049 {
4050 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4051 bfa_trc(ns->port->fcs, event);
4052
4053 switch (event) {
4054 case NSSM_EVENT_TIMEOUT:
4055 /*
4056 * Retry Timer Expired. Re-send
4057 */
4058 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
4059 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
4060 break;
4061
4062 case NSSM_EVENT_PORT_OFFLINE:
4063 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4064 bfa_timer_stop(&ns->timer);
4065 break;
4066
4067 default:
4068 bfa_sm_fault(ns->port->fcs, event);
4069 }
4070 }
4071
4072 static void
bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4073 bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
4074 enum vport_ns_event event)
4075 {
4076 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4077 bfa_trc(ns->port->fcs, event);
4078
4079 switch (event) {
4080 case NSSM_EVENT_RFTID_SENT:
4081 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
4082 break;
4083
4084 case NSSM_EVENT_PORT_OFFLINE:
4085 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4086 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4087 &ns->fcxp_wqe);
4088 break;
4089
4090 default:
4091 bfa_sm_fault(ns->port->fcs, event);
4092 }
4093 }
4094
4095 static void
bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4096 bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
4097 enum vport_ns_event event)
4098 {
4099 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4100 bfa_trc(ns->port->fcs, event);
4101
4102 switch (event) {
4103 case NSSM_EVENT_RSP_OK:
4104 /* Now move to register FC4 Features */
4105 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
4106 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
4107 break;
4108
4109 case NSSM_EVENT_RSP_ERROR:
4110 /*
4111 * Start timer for a delayed retry
4112 */
4113 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
4114 ns->port->stats.ns_retries++;
4115 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4116 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4117 BFA_FCS_RETRY_TIMEOUT);
4118 break;
4119
4120 case NSSM_EVENT_PORT_OFFLINE:
4121 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4122 bfa_fcxp_discard(ns->fcxp);
4123 break;
4124
4125 default:
4126 bfa_sm_fault(ns->port->fcs, event);
4127 }
4128 }
4129
4130 static void
bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4131 bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
4132 enum vport_ns_event event)
4133 {
4134 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4135 bfa_trc(ns->port->fcs, event);
4136
4137 switch (event) {
4138 case NSSM_EVENT_TIMEOUT:
4139 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
4140 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
4141 break;
4142
4143 case NSSM_EVENT_PORT_OFFLINE:
4144 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4145 bfa_timer_stop(&ns->timer);
4146 break;
4147
4148 default:
4149 bfa_sm_fault(ns->port->fcs, event);
4150 }
4151 }
4152
4153 static void
bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4154 bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
4155 enum vport_ns_event event)
4156 {
4157 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4158 bfa_trc(ns->port->fcs, event);
4159
4160 switch (event) {
4161 case NSSM_EVENT_RFFID_SENT:
4162 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
4163 break;
4164
4165 case NSSM_EVENT_PORT_OFFLINE:
4166 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4167 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4168 &ns->fcxp_wqe);
4169 break;
4170
4171 default:
4172 bfa_sm_fault(ns->port->fcs, event);
4173 }
4174 }
4175
4176 static void
bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4177 bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
4178 enum vport_ns_event event)
4179 {
4180 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4181 bfa_trc(ns->port->fcs, event);
4182
4183 switch (event) {
4184 case NSSM_EVENT_RSP_OK:
4185
4186 /*
4187 * If min cfg mode is enabled, we donot initiate rport
4188 * discovery with the fabric. Instead, we will retrieve the
4189 * boot targets from HAL/FW.
4190 */
4191 if (__fcs_min_cfg(ns->port->fcs)) {
4192 bfa_fcs_lport_ns_boot_target_disc(ns->port);
4193 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
4194 return;
4195 }
4196
4197 /*
4198 * If the port role is Initiator Mode issue NS query.
4199 * If it is Target Mode, skip this and go to online.
4200 */
4201 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
4202 bfa_sm_set_state(ns,
4203 bfa_fcs_lport_ns_sm_sending_gid_ft);
4204 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4205 }
4206 /*
4207 * kick off mgmt srvr state machine
4208 */
4209 bfa_fcs_lport_ms_online(ns->port);
4210 break;
4211
4212 case NSSM_EVENT_RSP_ERROR:
4213 /*
4214 * Start timer for a delayed retry
4215 */
4216 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
4217 ns->port->stats.ns_retries++;
4218 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4219 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4220 BFA_FCS_RETRY_TIMEOUT);
4221 break;
4222
4223 case NSSM_EVENT_PORT_OFFLINE:
4224 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4225 bfa_fcxp_discard(ns->fcxp);
4226 break;
4227
4228 default:
4229 bfa_sm_fault(ns->port->fcs, event);
4230 }
4231 }
4232
4233 static void
bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4234 bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
4235 enum vport_ns_event event)
4236 {
4237 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4238 bfa_trc(ns->port->fcs, event);
4239
4240 switch (event) {
4241 case NSSM_EVENT_TIMEOUT:
4242 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
4243 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
4244 break;
4245
4246 case NSSM_EVENT_PORT_OFFLINE:
4247 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4248 bfa_timer_stop(&ns->timer);
4249 break;
4250
4251 default:
4252 bfa_sm_fault(ns->port->fcs, event);
4253 }
4254 }
4255 static void
bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4256 bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
4257 enum vport_ns_event event)
4258 {
4259 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4260 bfa_trc(ns->port->fcs, event);
4261
4262 switch (event) {
4263 case NSSM_EVENT_GIDFT_SENT:
4264 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
4265 break;
4266
4267 case NSSM_EVENT_PORT_OFFLINE:
4268 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4269 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4270 &ns->fcxp_wqe);
4271 break;
4272
4273 default:
4274 bfa_sm_fault(ns->port->fcs, event);
4275 }
4276 }
4277
4278 static void
bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4279 bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
4280 enum vport_ns_event event)
4281 {
4282 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4283 bfa_trc(ns->port->fcs, event);
4284
4285 switch (event) {
4286 case NSSM_EVENT_RSP_OK:
4287 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
4288 break;
4289
4290 case NSSM_EVENT_RSP_ERROR:
4291 /*
4292 * TBD: for certain reject codes, we don't need to retry
4293 */
4294 /*
4295 * Start timer for a delayed retry
4296 */
4297 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
4298 ns->port->stats.ns_retries++;
4299 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4300 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4301 BFA_FCS_RETRY_TIMEOUT);
4302 break;
4303
4304 case NSSM_EVENT_PORT_OFFLINE:
4305 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4306 bfa_fcxp_discard(ns->fcxp);
4307 break;
4308
4309 case NSSM_EVENT_NS_QUERY:
4310 break;
4311
4312 default:
4313 bfa_sm_fault(ns->port->fcs, event);
4314 }
4315 }
4316
4317 static void
bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4318 bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
4319 enum vport_ns_event event)
4320 {
4321 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4322 bfa_trc(ns->port->fcs, event);
4323
4324 switch (event) {
4325 case NSSM_EVENT_TIMEOUT:
4326 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
4327 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4328 break;
4329
4330 case NSSM_EVENT_PORT_OFFLINE:
4331 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4332 bfa_timer_stop(&ns->timer);
4333 break;
4334
4335 default:
4336 bfa_sm_fault(ns->port->fcs, event);
4337 }
4338 }
4339
4340 static void
bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)4341 bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
4342 enum vport_ns_event event)
4343 {
4344 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4345 bfa_trc(ns->port->fcs, event);
4346
4347 switch (event) {
4348 case NSSM_EVENT_PORT_OFFLINE:
4349 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4350 break;
4351
4352 case NSSM_EVENT_NS_QUERY:
4353 /*
4354 * If the port role is Initiator Mode issue NS query.
4355 * If it is Target Mode, skip this and go to online.
4356 */
4357 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
4358 bfa_sm_set_state(ns,
4359 bfa_fcs_lport_ns_sm_sending_gid_ft);
4360 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4361 }
4362 break;
4363
4364 default:
4365 bfa_sm_fault(ns->port->fcs, event);
4366 }
4367 }
4368
4369
4370
4371 /*
4372 * ns_pvt Nameserver local functions
4373 */
4374
4375 static void
bfa_fcs_lport_ns_send_plogi(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4376 bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4377 {
4378 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4379 struct bfa_fcs_lport_s *port = ns->port;
4380 struct fchs_s fchs;
4381 int len;
4382 struct bfa_fcxp_s *fcxp;
4383
4384 bfa_trc(port->fcs, port->pid);
4385
4386 fcxp = fcxp_alloced ? fcxp_alloced :
4387 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4388 if (!fcxp) {
4389 port->stats.ns_plogi_alloc_wait++;
4390 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4391 bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);
4392 return;
4393 }
4394 ns->fcxp = fcxp;
4395
4396 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4397 bfa_hton3b(FC_NAME_SERVER),
4398 bfa_fcs_lport_get_fcid(port), 0,
4399 port->port_cfg.pwwn, port->port_cfg.nwwn,
4400 bfa_fcport_get_maxfrsize(port->fcs->bfa),
4401 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
4402
4403 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4404 FC_CLASS_3, len, &fchs,
4405 bfa_fcs_lport_ns_plogi_response, (void *)ns,
4406 FC_MAX_PDUSZ, FC_ELS_TOV);
4407 port->stats.ns_plogi_sent++;
4408
4409 bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
4410 }
4411
4412 static void
bfa_fcs_lport_ns_plogi_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)4413 bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4414 void *cbarg, bfa_status_t req_status, u32 rsp_len,
4415 u32 resid_len, struct fchs_s *rsp_fchs)
4416 {
4417 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4418 struct bfa_fcs_lport_s *port = ns->port;
4419 /* struct fc_logi_s *plogi_resp; */
4420 struct fc_els_cmd_s *els_cmd;
4421 struct fc_ls_rjt_s *ls_rjt;
4422
4423 bfa_trc(port->fcs, req_status);
4424 bfa_trc(port->fcs, port->port_cfg.pwwn);
4425
4426 /*
4427 * Sanity Checks
4428 */
4429 if (req_status != BFA_STATUS_OK) {
4430 bfa_trc(port->fcs, req_status);
4431 port->stats.ns_plogi_rsp_err++;
4432 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4433 return;
4434 }
4435
4436 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4437
4438 switch (els_cmd->els_code) {
4439
4440 case FC_ELS_ACC:
4441 if (rsp_len < sizeof(struct fc_logi_s)) {
4442 bfa_trc(port->fcs, rsp_len);
4443 port->stats.ns_plogi_acc_err++;
4444 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4445 break;
4446 }
4447 port->stats.ns_plogi_accepts++;
4448 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4449 break;
4450
4451 case FC_ELS_LS_RJT:
4452 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4453
4454 bfa_trc(port->fcs, ls_rjt->reason_code);
4455 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4456
4457 port->stats.ns_rejects++;
4458
4459 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4460 break;
4461
4462 default:
4463 port->stats.ns_plogi_unknown_rsp++;
4464 bfa_trc(port->fcs, els_cmd->els_code);
4465 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4466 }
4467 }
4468
4469 /*
4470 * Register node name for port_id
4471 */
4472 static void
bfa_fcs_lport_ns_send_rnn_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4473 bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4474 {
4475 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4476 struct bfa_fcs_lport_s *port = ns->port;
4477 struct fchs_s fchs;
4478 int len;
4479 struct bfa_fcxp_s *fcxp;
4480
4481 bfa_trc(port->fcs, port->port_cfg.pwwn);
4482
4483 fcxp = fcxp_alloced ? fcxp_alloced :
4484 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4485 if (!fcxp) {
4486 port->stats.ns_rnnid_alloc_wait++;
4487 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4488 bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE);
4489 return;
4490 }
4491
4492 ns->fcxp = fcxp;
4493
4494 len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4495 bfa_fcs_lport_get_fcid(port),
4496 bfa_fcs_lport_get_fcid(port),
4497 bfa_fcs_lport_get_nwwn(port));
4498
4499 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4500 FC_CLASS_3, len, &fchs,
4501 bfa_fcs_lport_ns_rnn_id_response, (void *)ns,
4502 FC_MAX_PDUSZ, FC_FCCT_TOV);
4503
4504 port->stats.ns_rnnid_sent++;
4505 bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT);
4506 }
4507
4508 static void
bfa_fcs_lport_ns_rnn_id_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)4509 bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4510 void *cbarg, bfa_status_t req_status,
4511 u32 rsp_len, u32 resid_len,
4512 struct fchs_s *rsp_fchs)
4513
4514 {
4515 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4516 struct bfa_fcs_lport_s *port = ns->port;
4517 struct ct_hdr_s *cthdr = NULL;
4518
4519 bfa_trc(port->fcs, port->port_cfg.pwwn);
4520
4521 /*
4522 * Sanity Checks
4523 */
4524 if (req_status != BFA_STATUS_OK) {
4525 bfa_trc(port->fcs, req_status);
4526 port->stats.ns_rnnid_rsp_err++;
4527 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4528 return;
4529 }
4530
4531 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4532 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4533
4534 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4535 port->stats.ns_rnnid_accepts++;
4536 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4537 return;
4538 }
4539
4540 port->stats.ns_rnnid_rejects++;
4541 bfa_trc(port->fcs, cthdr->reason_code);
4542 bfa_trc(port->fcs, cthdr->exp_code);
4543 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4544 }
4545
4546 /*
4547 * Register the symbolic node name for a given node name.
4548 */
4549 static void
bfa_fcs_lport_ns_send_rsnn_nn(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4550 bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4551 {
4552 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4553 struct bfa_fcs_lport_s *port = ns->port;
4554 struct fchs_s fchs;
4555 int len;
4556 struct bfa_fcxp_s *fcxp;
4557 u8 *nsymbl;
4558
4559 bfa_trc(port->fcs, port->port_cfg.pwwn);
4560
4561 fcxp = fcxp_alloced ? fcxp_alloced :
4562 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4563 if (!fcxp) {
4564 port->stats.ns_rsnn_nn_alloc_wait++;
4565 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4566 bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE);
4567 return;
4568 }
4569 ns->fcxp = fcxp;
4570
4571 nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name(
4572 bfa_fcs_get_base_port(port->fcs)));
4573
4574 len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4575 bfa_fcs_lport_get_fcid(port),
4576 bfa_fcs_lport_get_nwwn(port), nsymbl);
4577
4578 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4579 FC_CLASS_3, len, &fchs,
4580 bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns,
4581 FC_MAX_PDUSZ, FC_FCCT_TOV);
4582
4583 port->stats.ns_rsnn_nn_sent++;
4584
4585 bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT);
4586 }
4587
4588 static void
bfa_fcs_lport_ns_rsnn_nn_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)4589 bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4590 void *cbarg, bfa_status_t req_status,
4591 u32 rsp_len, u32 resid_len,
4592 struct fchs_s *rsp_fchs)
4593 {
4594 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4595 struct bfa_fcs_lport_s *port = ns->port;
4596 struct ct_hdr_s *cthdr = NULL;
4597
4598 bfa_trc(port->fcs, port->port_cfg.pwwn);
4599
4600 /*
4601 * Sanity Checks
4602 */
4603 if (req_status != BFA_STATUS_OK) {
4604 bfa_trc(port->fcs, req_status);
4605 port->stats.ns_rsnn_nn_rsp_err++;
4606 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4607 return;
4608 }
4609
4610 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4611 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4612
4613 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4614 port->stats.ns_rsnn_nn_accepts++;
4615 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4616 return;
4617 }
4618
4619 port->stats.ns_rsnn_nn_rejects++;
4620 bfa_trc(port->fcs, cthdr->reason_code);
4621 bfa_trc(port->fcs, cthdr->exp_code);
4622 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4623 }
4624
4625 /*
4626 * Register the symbolic port name.
4627 */
4628 static void
bfa_fcs_lport_ns_send_rspn_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4629 bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4630 {
4631 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4632 struct bfa_fcs_lport_s *port = ns->port;
4633 struct fchs_s fchs;
4634 int len;
4635 struct bfa_fcxp_s *fcxp;
4636 u8 symbl[256];
4637 u8 *psymbl = &symbl[0];
4638
4639 memset(symbl, 0, sizeof(symbl));
4640
4641 bfa_trc(port->fcs, port->port_cfg.pwwn);
4642
4643 fcxp = fcxp_alloced ? fcxp_alloced :
4644 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4645 if (!fcxp) {
4646 port->stats.ns_rspnid_alloc_wait++;
4647 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4648 bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);
4649 return;
4650 }
4651 ns->fcxp = fcxp;
4652
4653 /*
4654 * for V-Port, form a Port Symbolic Name
4655 */
4656 if (port->vport) {
4657 /*
4658 * For Vports, we append the vport's port symbolic name
4659 * to that of the base port.
4660 */
4661
4662 strlcpy(symbl,
4663 (char *)&(bfa_fcs_lport_get_psym_name
4664 (bfa_fcs_get_base_port(port->fcs))),
4665 sizeof(symbl));
4666
4667 strlcat(symbl, (char *)&(bfa_fcs_lport_get_psym_name(port)),
4668 sizeof(symbl));
4669 } else {
4670 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
4671 }
4672
4673 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4674 bfa_fcs_lport_get_fcid(port), 0, psymbl);
4675
4676 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4677 FC_CLASS_3, len, &fchs,
4678 bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
4679 FC_MAX_PDUSZ, FC_FCCT_TOV);
4680
4681 port->stats.ns_rspnid_sent++;
4682
4683 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
4684 }
4685
4686 static void
bfa_fcs_lport_ns_rspn_id_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)4687 bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4688 void *cbarg, bfa_status_t req_status,
4689 u32 rsp_len, u32 resid_len,
4690 struct fchs_s *rsp_fchs)
4691 {
4692 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4693 struct bfa_fcs_lport_s *port = ns->port;
4694 struct ct_hdr_s *cthdr = NULL;
4695
4696 bfa_trc(port->fcs, port->port_cfg.pwwn);
4697
4698 /*
4699 * Sanity Checks
4700 */
4701 if (req_status != BFA_STATUS_OK) {
4702 bfa_trc(port->fcs, req_status);
4703 port->stats.ns_rspnid_rsp_err++;
4704 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4705 return;
4706 }
4707
4708 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4709 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4710
4711 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4712 port->stats.ns_rspnid_accepts++;
4713 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4714 return;
4715 }
4716
4717 port->stats.ns_rspnid_rejects++;
4718 bfa_trc(port->fcs, cthdr->reason_code);
4719 bfa_trc(port->fcs, cthdr->exp_code);
4720 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4721 }
4722
4723 /*
4724 * Register FC4-Types
4725 */
4726 static void
bfa_fcs_lport_ns_send_rft_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4727 bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4728 {
4729 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4730 struct bfa_fcs_lport_s *port = ns->port;
4731 struct fchs_s fchs;
4732 int len;
4733 struct bfa_fcxp_s *fcxp;
4734
4735 bfa_trc(port->fcs, port->port_cfg.pwwn);
4736
4737 fcxp = fcxp_alloced ? fcxp_alloced :
4738 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4739 if (!fcxp) {
4740 port->stats.ns_rftid_alloc_wait++;
4741 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4742 bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);
4743 return;
4744 }
4745 ns->fcxp = fcxp;
4746
4747 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4748 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
4749
4750 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4751 FC_CLASS_3, len, &fchs,
4752 bfa_fcs_lport_ns_rft_id_response, (void *)ns,
4753 FC_MAX_PDUSZ, FC_FCCT_TOV);
4754
4755 port->stats.ns_rftid_sent++;
4756 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
4757 }
4758
4759 static void
bfa_fcs_lport_ns_rft_id_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)4760 bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4761 void *cbarg, bfa_status_t req_status,
4762 u32 rsp_len, u32 resid_len,
4763 struct fchs_s *rsp_fchs)
4764 {
4765 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4766 struct bfa_fcs_lport_s *port = ns->port;
4767 struct ct_hdr_s *cthdr = NULL;
4768
4769 bfa_trc(port->fcs, port->port_cfg.pwwn);
4770
4771 /*
4772 * Sanity Checks
4773 */
4774 if (req_status != BFA_STATUS_OK) {
4775 bfa_trc(port->fcs, req_status);
4776 port->stats.ns_rftid_rsp_err++;
4777 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4778 return;
4779 }
4780
4781 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4782 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4783
4784 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4785 port->stats.ns_rftid_accepts++;
4786 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4787 return;
4788 }
4789
4790 port->stats.ns_rftid_rejects++;
4791 bfa_trc(port->fcs, cthdr->reason_code);
4792 bfa_trc(port->fcs, cthdr->exp_code);
4793 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4794 }
4795
4796 /*
4797 * Register FC4-Features : Should be done after RFT_ID
4798 */
4799 static void
bfa_fcs_lport_ns_send_rff_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4800 bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4801 {
4802 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4803 struct bfa_fcs_lport_s *port = ns->port;
4804 struct fchs_s fchs;
4805 int len;
4806 struct bfa_fcxp_s *fcxp;
4807 u8 fc4_ftrs = 0;
4808
4809 bfa_trc(port->fcs, port->port_cfg.pwwn);
4810
4811 fcxp = fcxp_alloced ? fcxp_alloced :
4812 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4813 if (!fcxp) {
4814 port->stats.ns_rffid_alloc_wait++;
4815 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4816 bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);
4817 return;
4818 }
4819 ns->fcxp = fcxp;
4820
4821 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
4822 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
4823
4824 len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4825 bfa_fcs_lport_get_fcid(port), 0,
4826 FC_TYPE_FCP, fc4_ftrs);
4827
4828 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4829 FC_CLASS_3, len, &fchs,
4830 bfa_fcs_lport_ns_rff_id_response, (void *)ns,
4831 FC_MAX_PDUSZ, FC_FCCT_TOV);
4832
4833 port->stats.ns_rffid_sent++;
4834 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
4835 }
4836
4837 static void
bfa_fcs_lport_ns_rff_id_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)4838 bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4839 void *cbarg, bfa_status_t req_status,
4840 u32 rsp_len, u32 resid_len,
4841 struct fchs_s *rsp_fchs)
4842 {
4843 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4844 struct bfa_fcs_lport_s *port = ns->port;
4845 struct ct_hdr_s *cthdr = NULL;
4846
4847 bfa_trc(port->fcs, port->port_cfg.pwwn);
4848
4849 /*
4850 * Sanity Checks
4851 */
4852 if (req_status != BFA_STATUS_OK) {
4853 bfa_trc(port->fcs, req_status);
4854 port->stats.ns_rffid_rsp_err++;
4855 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4856 return;
4857 }
4858
4859 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4860 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4861
4862 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4863 port->stats.ns_rffid_accepts++;
4864 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4865 return;
4866 }
4867
4868 port->stats.ns_rffid_rejects++;
4869 bfa_trc(port->fcs, cthdr->reason_code);
4870 bfa_trc(port->fcs, cthdr->exp_code);
4871
4872 if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
4873 /* if this command is not supported, we don't retry */
4874 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4875 } else
4876 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4877 }
4878 /*
4879 * Query Fabric for FC4-Types Devices.
4880 *
4881 * TBD : Need to use a local (FCS private) response buffer, since the response
4882 * can be larger than 2K.
4883 */
4884 static void
bfa_fcs_lport_ns_send_gid_ft(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)4885 bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4886 {
4887 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4888 struct bfa_fcs_lport_s *port = ns->port;
4889 struct fchs_s fchs;
4890 int len;
4891 struct bfa_fcxp_s *fcxp;
4892
4893 bfa_trc(port->fcs, port->pid);
4894
4895 fcxp = fcxp_alloced ? fcxp_alloced :
4896 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4897 if (!fcxp) {
4898 port->stats.ns_gidft_alloc_wait++;
4899 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4900 bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);
4901 return;
4902 }
4903 ns->fcxp = fcxp;
4904
4905 /*
4906 * This query is only initiated for FCP initiator mode.
4907 */
4908 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4909 ns->port->pid, FC_TYPE_FCP);
4910
4911 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4912 FC_CLASS_3, len, &fchs,
4913 bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
4914 bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
4915
4916 port->stats.ns_gidft_sent++;
4917
4918 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
4919 }
4920
4921 static void
bfa_fcs_lport_ns_gid_ft_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)4922 bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4923 void *cbarg, bfa_status_t req_status,
4924 u32 rsp_len, u32 resid_len,
4925 struct fchs_s *rsp_fchs)
4926 {
4927 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4928 struct bfa_fcs_lport_s *port = ns->port;
4929 struct ct_hdr_s *cthdr = NULL;
4930 u32 n_pids;
4931
4932 bfa_trc(port->fcs, port->port_cfg.pwwn);
4933
4934 /*
4935 * Sanity Checks
4936 */
4937 if (req_status != BFA_STATUS_OK) {
4938 bfa_trc(port->fcs, req_status);
4939 port->stats.ns_gidft_rsp_err++;
4940 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4941 return;
4942 }
4943
4944 if (resid_len != 0) {
4945 /*
4946 * TBD : we will need to allocate a larger buffer & retry the
4947 * command
4948 */
4949 bfa_trc(port->fcs, rsp_len);
4950 bfa_trc(port->fcs, resid_len);
4951 return;
4952 }
4953
4954 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4955 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4956
4957 switch (cthdr->cmd_rsp_code) {
4958
4959 case CT_RSP_ACCEPT:
4960
4961 port->stats.ns_gidft_accepts++;
4962 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
4963 bfa_trc(port->fcs, n_pids);
4964 bfa_fcs_lport_ns_process_gidft_pids(port,
4965 (u32 *) (cthdr + 1),
4966 n_pids);
4967 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4968 break;
4969
4970 case CT_RSP_REJECT:
4971
4972 /*
4973 * Check the reason code & explanation.
4974 * There may not have been any FC4 devices in the fabric
4975 */
4976 port->stats.ns_gidft_rejects++;
4977 bfa_trc(port->fcs, cthdr->reason_code);
4978 bfa_trc(port->fcs, cthdr->exp_code);
4979
4980 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4981 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4982
4983 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4984 } else {
4985 /*
4986 * for all other errors, retry
4987 */
4988 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4989 }
4990 break;
4991
4992 default:
4993 port->stats.ns_gidft_unknown_rsp++;
4994 bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4995 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4996 }
4997 }
4998
4999 /*
5000 * This routine will be called by bfa_timer on timer timeouts.
5001 *
5002 * param[in] port - pointer to bfa_fcs_lport_t.
5003 *
5004 * return
5005 * void
5006 *
5007 * Special Considerations:
5008 *
5009 * note
5010 */
5011 static void
bfa_fcs_lport_ns_timeout(void * arg)5012 bfa_fcs_lport_ns_timeout(void *arg)
5013 {
5014 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
5015
5016 ns->port->stats.ns_timeouts++;
5017 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
5018 }
5019
5020 /*
5021 * Process the PID list in GID_FT response
5022 */
5023 static void
bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s * port,u32 * pid_buf,u32 n_pids)5024 bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
5025 u32 n_pids)
5026 {
5027 struct fcgs_gidft_resp_s *gidft_entry;
5028 struct bfa_fcs_rport_s *rport;
5029 u32 ii;
5030 struct bfa_fcs_fabric_s *fabric = port->fabric;
5031 struct bfa_fcs_vport_s *vport;
5032 struct list_head *qe;
5033 u8 found = 0;
5034
5035 for (ii = 0; ii < n_pids; ii++) {
5036 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
5037
5038 if (gidft_entry->pid == port->pid)
5039 continue;
5040
5041 /*
5042 * Ignore PID if it is of base port
5043 * (Avoid vports discovering base port as remote port)
5044 */
5045 if (gidft_entry->pid == fabric->bport.pid)
5046 continue;
5047
5048 /*
5049 * Ignore PID if it is of vport created on the same base port
5050 * (Avoid vport discovering every other vport created on the
5051 * same port as remote port)
5052 */
5053 list_for_each(qe, &fabric->vport_q) {
5054 vport = (struct bfa_fcs_vport_s *) qe;
5055 if (vport->lport.pid == gidft_entry->pid)
5056 found = 1;
5057 }
5058
5059 if (found) {
5060 found = 0;
5061 continue;
5062 }
5063
5064 /*
5065 * Check if this rport already exists
5066 */
5067 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
5068 if (rport == NULL) {
5069 /*
5070 * this is a new device. create rport
5071 */
5072 rport = bfa_fcs_rport_create(port, gidft_entry->pid);
5073 } else {
5074 /*
5075 * this rport already exists
5076 */
5077 bfa_fcs_rport_scn(rport);
5078 }
5079
5080 bfa_trc(port->fcs, gidft_entry->pid);
5081
5082 /*
5083 * if the last entry bit is set, bail out.
5084 */
5085 if (gidft_entry->last)
5086 return;
5087 }
5088 }
5089
5090 /*
5091 * fcs_ns_public FCS nameserver public interfaces
5092 */
5093
5094 /*
5095 * Functions called by port/fab.
5096 * These will send relevant Events to the ns state machine.
5097 */
5098 void
bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s * port)5099 bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
5100 {
5101 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5102
5103 ns->port = port;
5104 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
5105 }
5106
5107 void
bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s * port)5108 bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
5109 {
5110 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5111
5112 ns->port = port;
5113 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
5114 }
5115
5116 void
bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s * port)5117 bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
5118 {
5119 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5120
5121 ns->port = port;
5122 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
5123 }
5124
5125 void
bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s * port)5126 bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
5127 {
5128 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5129
5130 bfa_trc(port->fcs, port->pid);
5131 if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online))
5132 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
5133 }
5134
5135 static void
bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t * port)5136 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
5137 {
5138
5139 struct bfa_fcs_rport_s *rport;
5140 u8 nwwns;
5141 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
5142 int ii;
5143
5144 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
5145
5146 for (ii = 0 ; ii < nwwns; ++ii) {
5147 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
5148 WARN_ON(!rport);
5149 }
5150 }
5151
5152 void
bfa_fcs_lport_ns_util_send_rspn_id(void * cbarg,struct bfa_fcxp_s * fcxp_alloced)5153 bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
5154 {
5155 struct bfa_fcs_lport_ns_s *ns = cbarg;
5156 struct bfa_fcs_lport_s *port = ns->port;
5157 struct fchs_s fchs;
5158 struct bfa_fcxp_s *fcxp;
5159 u8 symbl[256];
5160 int len;
5161
5162 /* Avoid sending RSPN in the following states. */
5163 if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
5164 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
5165 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) ||
5166 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) ||
5167 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry))
5168 return;
5169
5170 memset(symbl, 0, sizeof(symbl));
5171 bfa_trc(port->fcs, port->port_cfg.pwwn);
5172
5173 fcxp = fcxp_alloced ? fcxp_alloced :
5174 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
5175 if (!fcxp) {
5176 port->stats.ns_rspnid_alloc_wait++;
5177 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
5178 bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE);
5179 return;
5180 }
5181
5182 ns->fcxp = fcxp;
5183
5184 if (port->vport) {
5185 /*
5186 * For Vports, we append the vport's port symbolic name
5187 * to that of the base port.
5188 */
5189 strlcpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name
5190 (bfa_fcs_get_base_port(port->fcs))),
5191 sizeof(symbl));
5192
5193 strlcat(symbl,
5194 (char *)&(bfa_fcs_lport_get_psym_name(port)),
5195 sizeof(symbl));
5196 }
5197
5198 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5199 bfa_fcs_lport_get_fcid(port), 0, symbl);
5200
5201 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
5202 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
5203
5204 port->stats.ns_rspnid_sent++;
5205 }
5206
5207 /*
5208 * FCS SCN
5209 */
5210
5211 #define FC_QOS_RSCN_EVENT 0x0c
5212 #define FC_FABRIC_NAME_RSCN_EVENT 0x0d
5213
5214 /*
5215 * forward declarations
5216 */
5217 static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
5218 struct bfa_fcxp_s *fcxp_alloced);
5219 static void bfa_fcs_lport_scn_scr_response(void *fcsarg,
5220 struct bfa_fcxp_s *fcxp,
5221 void *cbarg,
5222 bfa_status_t req_status,
5223 u32 rsp_len,
5224 u32 resid_len,
5225 struct fchs_s *rsp_fchs);
5226 static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
5227 struct fchs_s *rx_fchs);
5228 static void bfa_fcs_lport_scn_timeout(void *arg);
5229
5230 /*
5231 * fcs_scm_sm FCS SCN state machine
5232 */
5233
5234 /*
5235 * VPort SCN State Machine events
5236 */
5237 enum port_scn_event {
5238 SCNSM_EVENT_PORT_ONLINE = 1,
5239 SCNSM_EVENT_PORT_OFFLINE = 2,
5240 SCNSM_EVENT_RSP_OK = 3,
5241 SCNSM_EVENT_RSP_ERROR = 4,
5242 SCNSM_EVENT_TIMEOUT = 5,
5243 SCNSM_EVENT_SCR_SENT = 6,
5244 };
5245
5246 static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
5247 enum port_scn_event event);
5248 static void bfa_fcs_lport_scn_sm_sending_scr(
5249 struct bfa_fcs_lport_scn_s *scn,
5250 enum port_scn_event event);
5251 static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
5252 enum port_scn_event event);
5253 static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
5254 enum port_scn_event event);
5255 static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
5256 enum port_scn_event event);
5257
5258 /*
5259 * Starting state - awaiting link up.
5260 */
5261 static void
bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)5262 bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
5263 enum port_scn_event event)
5264 {
5265 switch (event) {
5266 case SCNSM_EVENT_PORT_ONLINE:
5267 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
5268 bfa_fcs_lport_scn_send_scr(scn, NULL);
5269 break;
5270
5271 case SCNSM_EVENT_PORT_OFFLINE:
5272 break;
5273
5274 default:
5275 bfa_sm_fault(scn->port->fcs, event);
5276 }
5277 }
5278
5279 static void
bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)5280 bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
5281 enum port_scn_event event)
5282 {
5283 switch (event) {
5284 case SCNSM_EVENT_SCR_SENT:
5285 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
5286 break;
5287
5288 case SCNSM_EVENT_PORT_OFFLINE:
5289 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5290 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
5291 break;
5292
5293 default:
5294 bfa_sm_fault(scn->port->fcs, event);
5295 }
5296 }
5297
5298 static void
bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)5299 bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
5300 enum port_scn_event event)
5301 {
5302 struct bfa_fcs_lport_s *port = scn->port;
5303
5304 switch (event) {
5305 case SCNSM_EVENT_RSP_OK:
5306 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
5307 break;
5308
5309 case SCNSM_EVENT_RSP_ERROR:
5310 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
5311 bfa_timer_start(port->fcs->bfa, &scn->timer,
5312 bfa_fcs_lport_scn_timeout, scn,
5313 BFA_FCS_RETRY_TIMEOUT);
5314 break;
5315
5316 case SCNSM_EVENT_PORT_OFFLINE:
5317 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5318 bfa_fcxp_discard(scn->fcxp);
5319 break;
5320
5321 default:
5322 bfa_sm_fault(port->fcs, event);
5323 }
5324 }
5325
5326 static void
bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)5327 bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
5328 enum port_scn_event event)
5329 {
5330 switch (event) {
5331 case SCNSM_EVENT_TIMEOUT:
5332 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
5333 bfa_fcs_lport_scn_send_scr(scn, NULL);
5334 break;
5335
5336 case SCNSM_EVENT_PORT_OFFLINE:
5337 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5338 bfa_timer_stop(&scn->timer);
5339 break;
5340
5341 default:
5342 bfa_sm_fault(scn->port->fcs, event);
5343 }
5344 }
5345
5346 static void
bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)5347 bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
5348 enum port_scn_event event)
5349 {
5350 switch (event) {
5351 case SCNSM_EVENT_PORT_OFFLINE:
5352 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5353 break;
5354
5355 default:
5356 bfa_sm_fault(scn->port->fcs, event);
5357 }
5358 }
5359
5360
5361
5362 /*
5363 * fcs_scn_private FCS SCN private functions
5364 */
5365
5366 /*
5367 * This routine will be called to send a SCR command.
5368 */
5369 static void
bfa_fcs_lport_scn_send_scr(void * scn_cbarg,struct bfa_fcxp_s * fcxp_alloced)5370 bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
5371 {
5372 struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
5373 struct bfa_fcs_lport_s *port = scn->port;
5374 struct fchs_s fchs;
5375 int len;
5376 struct bfa_fcxp_s *fcxp;
5377
5378 bfa_trc(port->fcs, port->pid);
5379 bfa_trc(port->fcs, port->port_cfg.pwwn);
5380
5381 fcxp = fcxp_alloced ? fcxp_alloced :
5382 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
5383 if (!fcxp) {
5384 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
5385 bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);
5386 return;
5387 }
5388 scn->fcxp = fcxp;
5389
5390 /* Handle VU registrations for Base port only */
5391 if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
5392 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5393 port->fabric->lps->brcd_switch,
5394 port->pid, 0);
5395 } else {
5396 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5397 BFA_FALSE,
5398 port->pid, 0);
5399 }
5400
5401 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
5402 FC_CLASS_3, len, &fchs,
5403 bfa_fcs_lport_scn_scr_response,
5404 (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
5405
5406 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
5407 }
5408
5409 static void
bfa_fcs_lport_scn_scr_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)5410 bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
5411 void *cbarg, bfa_status_t req_status, u32 rsp_len,
5412 u32 resid_len, struct fchs_s *rsp_fchs)
5413 {
5414 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
5415 struct bfa_fcs_lport_s *port = scn->port;
5416 struct fc_els_cmd_s *els_cmd;
5417 struct fc_ls_rjt_s *ls_rjt;
5418
5419 bfa_trc(port->fcs, port->port_cfg.pwwn);
5420
5421 /*
5422 * Sanity Checks
5423 */
5424 if (req_status != BFA_STATUS_OK) {
5425 bfa_trc(port->fcs, req_status);
5426 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5427 return;
5428 }
5429
5430 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
5431
5432 switch (els_cmd->els_code) {
5433
5434 case FC_ELS_ACC:
5435 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
5436 break;
5437
5438 case FC_ELS_LS_RJT:
5439
5440 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
5441
5442 bfa_trc(port->fcs, ls_rjt->reason_code);
5443 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
5444
5445 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5446 break;
5447
5448 default:
5449 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5450 }
5451 }
5452
5453 /*
5454 * Send a LS Accept
5455 */
5456 static void
bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs)5457 bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
5458 struct fchs_s *rx_fchs)
5459 {
5460 struct fchs_s fchs;
5461 struct bfa_fcxp_s *fcxp;
5462 struct bfa_rport_s *bfa_rport = NULL;
5463 int len;
5464
5465 bfa_trc(port->fcs, rx_fchs->s_id);
5466
5467 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
5468 if (!fcxp)
5469 return;
5470
5471 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5472 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
5473 rx_fchs->ox_id);
5474
5475 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
5476 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
5477 FC_MAX_PDUSZ, 0);
5478 }
5479
5480 /*
5481 * This routine will be called by bfa_timer on timer timeouts.
5482 *
5483 * param[in] vport - pointer to bfa_fcs_lport_t.
5484 * param[out] vport_status - pointer to return vport status in
5485 *
5486 * return
5487 * void
5488 *
5489 * Special Considerations:
5490 *
5491 * note
5492 */
5493 static void
bfa_fcs_lport_scn_timeout(void * arg)5494 bfa_fcs_lport_scn_timeout(void *arg)
5495 {
5496 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
5497
5498 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
5499 }
5500
5501
5502
5503 /*
5504 * fcs_scn_public FCS state change notification public interfaces
5505 */
5506
5507 /*
5508 * Functions called by port/fab
5509 */
5510 void
bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s * port)5511 bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
5512 {
5513 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5514
5515 scn->port = port;
5516 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5517 }
5518
5519 void
bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s * port)5520 bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
5521 {
5522 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5523
5524 scn->port = port;
5525 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
5526 }
5527
5528 void
bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s * port)5529 bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port)
5530 {
5531 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5532
5533 scn->port = port;
5534 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
5535 }
5536
5537 static void
bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s * port,u32 rpid)5538 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
5539 {
5540 struct bfa_fcs_rport_s *rport;
5541 struct bfa_fcs_fabric_s *fabric = port->fabric;
5542 struct bfa_fcs_vport_s *vport;
5543 struct list_head *qe;
5544
5545 bfa_trc(port->fcs, rpid);
5546
5547 /*
5548 * Ignore PID if it is of base port or of vports created on the
5549 * same base port. It is to avoid vports discovering base port or
5550 * other vports created on same base port as remote port
5551 */
5552 if (rpid == fabric->bport.pid)
5553 return;
5554
5555 list_for_each(qe, &fabric->vport_q) {
5556 vport = (struct bfa_fcs_vport_s *) qe;
5557 if (vport->lport.pid == rpid)
5558 return;
5559 }
5560 /*
5561 * If this is an unknown device, then it just came online.
5562 * Otherwise let rport handle the RSCN event.
5563 */
5564 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
5565 if (!rport)
5566 rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid);
5567
5568 if (rport == NULL) {
5569 /*
5570 * If min cfg mode is enabled, we donot need to
5571 * discover any new rports.
5572 */
5573 if (!__fcs_min_cfg(port->fcs))
5574 rport = bfa_fcs_rport_create(port, rpid);
5575 } else
5576 bfa_fcs_rport_scn(rport);
5577 }
5578
5579 /*
5580 * rscn format based PID comparison
5581 */
5582 #define __fc_pid_match(__c0, __c1, __fmt) \
5583 (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
5584 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
5585 ((__c0)[0] == (__c1)[0])) || \
5586 (((__fmt) == FC_RSCN_FORMAT_AREA) && \
5587 ((__c0)[0] == (__c1)[0]) && \
5588 ((__c0)[1] == (__c1)[1])))
5589
5590 static void
bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s * port,enum fc_rscn_format format,u32 rscn_pid)5591 bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
5592 enum fc_rscn_format format,
5593 u32 rscn_pid)
5594 {
5595 struct bfa_fcs_rport_s *rport;
5596 struct list_head *qe, *qe_next;
5597 u8 *c0, *c1;
5598
5599 bfa_trc(port->fcs, format);
5600 bfa_trc(port->fcs, rscn_pid);
5601
5602 c0 = (u8 *) &rscn_pid;
5603
5604 list_for_each_safe(qe, qe_next, &port->rport_q) {
5605 rport = (struct bfa_fcs_rport_s *) qe;
5606 c1 = (u8 *) &rport->pid;
5607 if (__fc_pid_match(c0, c1, format))
5608 bfa_fcs_rport_scn(rport);
5609 }
5610 }
5611
5612
5613 void
bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s * port,struct fchs_s * fchs,u32 len)5614 bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
5615 struct fchs_s *fchs, u32 len)
5616 {
5617 struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
5618 int num_entries;
5619 u32 rscn_pid;
5620 bfa_boolean_t nsquery = BFA_FALSE, found;
5621 int i = 0, j;
5622
5623 num_entries =
5624 (be16_to_cpu(rscn->payldlen) -
5625 sizeof(u32)) / sizeof(rscn->event[0]);
5626
5627 bfa_trc(port->fcs, num_entries);
5628
5629 port->stats.num_rscn++;
5630
5631 bfa_fcs_lport_scn_send_ls_acc(port, fchs);
5632
5633 for (i = 0; i < num_entries; i++) {
5634 rscn_pid = rscn->event[i].portid;
5635
5636 bfa_trc(port->fcs, rscn->event[i].format);
5637 bfa_trc(port->fcs, rscn_pid);
5638
5639 /* check for duplicate entries in the list */
5640 found = BFA_FALSE;
5641 for (j = 0; j < i; j++) {
5642 if (rscn->event[j].portid == rscn_pid) {
5643 found = BFA_TRUE;
5644 break;
5645 }
5646 }
5647
5648 /* if found in down the list, pid has been already processed */
5649 if (found) {
5650 bfa_trc(port->fcs, rscn_pid);
5651 continue;
5652 }
5653
5654 switch (rscn->event[i].format) {
5655 case FC_RSCN_FORMAT_PORTID:
5656 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
5657 /*
5658 * Ignore this event.
5659 * f/w would have processed it
5660 */
5661 bfa_trc(port->fcs, rscn_pid);
5662 } else {
5663 port->stats.num_portid_rscn++;
5664 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
5665 }
5666 break;
5667
5668 case FC_RSCN_FORMAT_FABRIC:
5669 if (rscn->event[i].qualifier ==
5670 FC_FABRIC_NAME_RSCN_EVENT) {
5671 bfa_fcs_lport_ms_fabric_rscn(port);
5672 break;
5673 }
5674 /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
5675
5676 case FC_RSCN_FORMAT_AREA:
5677 case FC_RSCN_FORMAT_DOMAIN:
5678 nsquery = BFA_TRUE;
5679 bfa_fcs_lport_scn_multiport_rscn(port,
5680 rscn->event[i].format,
5681 rscn_pid);
5682 break;
5683
5684
5685 default:
5686 WARN_ON(1);
5687 nsquery = BFA_TRUE;
5688 }
5689 }
5690
5691 /*
5692 * If any of area, domain or fabric RSCN is received, do a fresh
5693 * discovery to find new devices.
5694 */
5695 if (nsquery)
5696 bfa_fcs_lport_ns_query(port);
5697 }
5698
5699 /*
5700 * BFA FCS port
5701 */
5702 /*
5703 * fcs_port_api BFA FCS port API
5704 */
5705 struct bfa_fcs_lport_s *
bfa_fcs_get_base_port(struct bfa_fcs_s * fcs)5706 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
5707 {
5708 return &fcs->fabric.bport;
5709 }
5710
5711 wwn_t
bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s * port,wwn_t wwn,int index,int nrports,bfa_boolean_t bwwn)5712 bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
5713 int nrports, bfa_boolean_t bwwn)
5714 {
5715 struct list_head *qh, *qe;
5716 struct bfa_fcs_rport_s *rport = NULL;
5717 int i;
5718 struct bfa_fcs_s *fcs;
5719
5720 if (port == NULL || nrports == 0)
5721 return (wwn_t) 0;
5722
5723 fcs = port->fcs;
5724 bfa_trc(fcs, (u32) nrports);
5725
5726 i = 0;
5727 qh = &port->rport_q;
5728 qe = bfa_q_first(qh);
5729
5730 while ((qe != qh) && (i < nrports)) {
5731 rport = (struct bfa_fcs_rport_s *) qe;
5732 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
5733 qe = bfa_q_next(qe);
5734 bfa_trc(fcs, (u32) rport->pwwn);
5735 bfa_trc(fcs, rport->pid);
5736 bfa_trc(fcs, i);
5737 continue;
5738 }
5739
5740 if (bwwn) {
5741 if (!memcmp(&wwn, &rport->pwwn, 8))
5742 break;
5743 } else {
5744 if (i == index)
5745 break;
5746 }
5747
5748 i++;
5749 qe = bfa_q_next(qe);
5750 }
5751
5752 bfa_trc(fcs, i);
5753 if (rport)
5754 return rport->pwwn;
5755 else
5756 return (wwn_t) 0;
5757 }
5758
5759 void
bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s * port,struct bfa_rport_qualifier_s rports[],int * nrports)5760 bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
5761 struct bfa_rport_qualifier_s rports[], int *nrports)
5762 {
5763 struct list_head *qh, *qe;
5764 struct bfa_fcs_rport_s *rport = NULL;
5765 int i;
5766 struct bfa_fcs_s *fcs;
5767
5768 if (port == NULL || rports == NULL || *nrports == 0)
5769 return;
5770
5771 fcs = port->fcs;
5772 bfa_trc(fcs, (u32) *nrports);
5773
5774 i = 0;
5775 qh = &port->rport_q;
5776 qe = bfa_q_first(qh);
5777
5778 while ((qe != qh) && (i < *nrports)) {
5779 rport = (struct bfa_fcs_rport_s *) qe;
5780 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
5781 qe = bfa_q_next(qe);
5782 bfa_trc(fcs, (u32) rport->pwwn);
5783 bfa_trc(fcs, rport->pid);
5784 bfa_trc(fcs, i);
5785 continue;
5786 }
5787
5788 if (!rport->pwwn && !rport->pid) {
5789 qe = bfa_q_next(qe);
5790 continue;
5791 }
5792
5793 rports[i].pwwn = rport->pwwn;
5794 rports[i].pid = rport->pid;
5795
5796 i++;
5797 qe = bfa_q_next(qe);
5798 }
5799
5800 bfa_trc(fcs, i);
5801 *nrports = i;
5802 }
5803
5804 /*
5805 * Iterate's through all the rport's in the given port to
5806 * determine the maximum operating speed.
5807 *
5808 * !!!! To be used in TRL Functionality only !!!!
5809 */
5810 bfa_port_speed_t
bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t * port)5811 bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
5812 {
5813 struct list_head *qh, *qe;
5814 struct bfa_fcs_rport_s *rport = NULL;
5815 struct bfa_fcs_s *fcs;
5816 bfa_port_speed_t max_speed = 0;
5817 struct bfa_port_attr_s port_attr;
5818 bfa_port_speed_t port_speed, rport_speed;
5819 bfa_boolean_t trl_enabled;
5820
5821 if (port == NULL)
5822 return 0;
5823
5824 fcs = port->fcs;
5825 trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
5826
5827 /* Get Physical port's current speed */
5828 bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
5829 port_speed = port_attr.speed;
5830 bfa_trc(fcs, port_speed);
5831
5832 qh = &port->rport_q;
5833 qe = bfa_q_first(qh);
5834
5835 while (qe != qh) {
5836 rport = (struct bfa_fcs_rport_s *) qe;
5837 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
5838 (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
5839 (rport->scsi_function != BFA_RPORT_TARGET)) {
5840 qe = bfa_q_next(qe);
5841 continue;
5842 }
5843
5844 rport_speed = rport->rpf.rpsc_speed;
5845 if ((trl_enabled) && (rport_speed ==
5846 BFA_PORT_SPEED_UNKNOWN)) {
5847 /* Use default ratelim speed setting */
5848 rport_speed =
5849 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
5850 }
5851
5852 if (rport_speed > max_speed)
5853 max_speed = rport_speed;
5854
5855 qe = bfa_q_next(qe);
5856 }
5857
5858 if (max_speed > port_speed)
5859 max_speed = port_speed;
5860
5861 bfa_trc(fcs, max_speed);
5862 return max_speed;
5863 }
5864
5865 struct bfa_fcs_lport_s *
bfa_fcs_lookup_port(struct bfa_fcs_s * fcs,u16 vf_id,wwn_t lpwwn)5866 bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
5867 {
5868 struct bfa_fcs_vport_s *vport;
5869 bfa_fcs_vf_t *vf;
5870
5871 WARN_ON(fcs == NULL);
5872
5873 vf = bfa_fcs_vf_lookup(fcs, vf_id);
5874 if (vf == NULL) {
5875 bfa_trc(fcs, vf_id);
5876 return NULL;
5877 }
5878
5879 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
5880 return &vf->bport;
5881
5882 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
5883 if (vport)
5884 return &vport->lport;
5885
5886 return NULL;
5887 }
5888
5889 /*
5890 * API corresponding to NPIV_VPORT_GETINFO.
5891 */
5892 void
bfa_fcs_lport_get_info(struct bfa_fcs_lport_s * port,struct bfa_lport_info_s * port_info)5893 bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
5894 struct bfa_lport_info_s *port_info)
5895 {
5896
5897 bfa_trc(port->fcs, port->fabric->fabric_name);
5898
5899 if (port->vport == NULL) {
5900 /*
5901 * This is a Physical port
5902 */
5903 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
5904
5905 /*
5906 * @todo : need to fix the state & reason
5907 */
5908 port_info->port_state = 0;
5909 port_info->offline_reason = 0;
5910
5911 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5912 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5913
5914 port_info->max_vports_supp =
5915 bfa_lps_get_max_vport(port->fcs->bfa);
5916 port_info->num_vports_inuse =
5917 port->fabric->num_vports;
5918 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
5919 port_info->num_rports_inuse = port->num_rports;
5920 } else {
5921 /*
5922 * This is a virtual port
5923 */
5924 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
5925
5926 /*
5927 * @todo : need to fix the state & reason
5928 */
5929 port_info->port_state = 0;
5930 port_info->offline_reason = 0;
5931
5932 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5933 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5934 }
5935 }
5936
5937 void
bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s * fcs_port,struct bfa_lport_stats_s * port_stats)5938 bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
5939 struct bfa_lport_stats_s *port_stats)
5940 {
5941 *port_stats = fcs_port->stats;
5942 }
5943
5944 void
bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s * fcs_port)5945 bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
5946 {
5947 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
5948 }
5949
5950 /*
5951 * Let new loop map create missing rports
5952 */
5953 void
bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s * port)5954 bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port)
5955 {
5956 bfa_fcs_lport_loop_online(port);
5957 }
5958
5959 /*
5960 * FCS virtual port state machine
5961 */
5962
5963 #define __vport_fcs(__vp) ((__vp)->lport.fcs)
5964 #define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn)
5965 #define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn)
5966 #define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa)
5967 #define __vport_fcid(__vp) ((__vp)->lport.pid)
5968 #define __vport_fabric(__vp) ((__vp)->lport.fabric)
5969 #define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id)
5970
5971 #define BFA_FCS_VPORT_MAX_RETRIES 5
5972 /*
5973 * Forward declarations
5974 */
5975 static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
5976 static void bfa_fcs_vport_timeout(void *vport_arg);
5977 static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
5978 static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
5979
5980 /*
5981 * fcs_vport_sm FCS virtual port state machine
5982 */
5983
5984 /*
5985 * VPort State Machine events
5986 */
5987 enum bfa_fcs_vport_event {
5988 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */
5989 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */
5990 BFA_FCS_VPORT_SM_START = 3, /* vport start request */
5991 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */
5992 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */
5993 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */
5994 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */
5995 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */
5996 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */
5997 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */
5998 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
5999 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
6000 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
6001 BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */
6002 BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */
6003 };
6004
6005 static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
6006 enum bfa_fcs_vport_event event);
6007 static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
6008 enum bfa_fcs_vport_event event);
6009 static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
6010 enum bfa_fcs_vport_event event);
6011 static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
6012 enum bfa_fcs_vport_event event);
6013 static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
6014 enum bfa_fcs_vport_event event);
6015 static void bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
6016 enum bfa_fcs_vport_event event);
6017 static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
6018 enum bfa_fcs_vport_event event);
6019 static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
6020 enum bfa_fcs_vport_event event);
6021 static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
6022 enum bfa_fcs_vport_event event);
6023 static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
6024 enum bfa_fcs_vport_event event);
6025 static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
6026 enum bfa_fcs_vport_event event);
6027 static void bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
6028 enum bfa_fcs_vport_event event);
6029 static void bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
6030 enum bfa_fcs_vport_event event);
6031
6032 static struct bfa_sm_table_s vport_sm_table[] = {
6033 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
6034 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
6035 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
6036 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
6037 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
6038 {BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
6039 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
6040 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
6041 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
6042 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
6043 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
6044 };
6045
6046 /*
6047 * Beginning state.
6048 */
6049 static void
bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6050 bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
6051 enum bfa_fcs_vport_event event)
6052 {
6053 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6054 bfa_trc(__vport_fcs(vport), event);
6055
6056 switch (event) {
6057 case BFA_FCS_VPORT_SM_CREATE:
6058 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6059 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
6060 break;
6061
6062 default:
6063 bfa_sm_fault(__vport_fcs(vport), event);
6064 }
6065 }
6066
6067 /*
6068 * Created state - a start event is required to start up the state machine.
6069 */
6070 static void
bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6071 bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
6072 enum bfa_fcs_vport_event event)
6073 {
6074 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6075 bfa_trc(__vport_fcs(vport), event);
6076
6077 switch (event) {
6078 case BFA_FCS_VPORT_SM_START:
6079 if (bfa_sm_cmp_state(__vport_fabric(vport),
6080 bfa_fcs_fabric_sm_online)
6081 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
6082 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6083 bfa_fcs_vport_do_fdisc(vport);
6084 } else {
6085 /*
6086 * Fabric is offline or not NPIV capable, stay in
6087 * offline state.
6088 */
6089 vport->vport_stats.fab_no_npiv++;
6090 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6091 }
6092 break;
6093
6094 case BFA_FCS_VPORT_SM_DELETE:
6095 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6096 bfa_fcs_lport_delete(&vport->lport);
6097 break;
6098
6099 case BFA_FCS_VPORT_SM_ONLINE:
6100 case BFA_FCS_VPORT_SM_OFFLINE:
6101 /*
6102 * Ignore ONLINE/OFFLINE events from fabric
6103 * till vport is started.
6104 */
6105 break;
6106
6107 default:
6108 bfa_sm_fault(__vport_fcs(vport), event);
6109 }
6110 }
6111
6112 /*
6113 * Offline state - awaiting ONLINE event from fabric SM.
6114 */
6115 static void
bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6116 bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
6117 enum bfa_fcs_vport_event event)
6118 {
6119 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6120 bfa_trc(__vport_fcs(vport), event);
6121
6122 switch (event) {
6123 case BFA_FCS_VPORT_SM_DELETE:
6124 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6125 bfa_fcs_lport_delete(&vport->lport);
6126 break;
6127
6128 case BFA_FCS_VPORT_SM_ONLINE:
6129 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6130 vport->fdisc_retries = 0;
6131 bfa_fcs_vport_do_fdisc(vport);
6132 break;
6133
6134 case BFA_FCS_VPORT_SM_STOP:
6135 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6136 bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
6137 break;
6138
6139 case BFA_FCS_VPORT_SM_OFFLINE:
6140 /*
6141 * This can happen if the vport couldn't be initialzied
6142 * due the fact that the npiv was not enabled on the switch.
6143 * In that case we will put the vport in offline state.
6144 * However, the link can go down and cause the this event to
6145 * be sent when we are already offline. Ignore it.
6146 */
6147 break;
6148
6149 default:
6150 bfa_sm_fault(__vport_fcs(vport), event);
6151 }
6152 }
6153
6154
6155 /*
6156 * FDISC is sent and awaiting reply from fabric.
6157 */
6158 static void
bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6159 bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
6160 enum bfa_fcs_vport_event event)
6161 {
6162 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6163 bfa_trc(__vport_fcs(vport), event);
6164
6165 switch (event) {
6166 case BFA_FCS_VPORT_SM_DELETE:
6167 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
6168 break;
6169
6170 case BFA_FCS_VPORT_SM_OFFLINE:
6171 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6172 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6173 break;
6174
6175 case BFA_FCS_VPORT_SM_RSP_OK:
6176 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
6177 bfa_fcs_lport_online(&vport->lport);
6178 break;
6179
6180 case BFA_FCS_VPORT_SM_RSP_ERROR:
6181 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
6182 bfa_timer_start(__vport_bfa(vport), &vport->timer,
6183 bfa_fcs_vport_timeout, vport,
6184 BFA_FCS_RETRY_TIMEOUT);
6185 break;
6186
6187 case BFA_FCS_VPORT_SM_RSP_FAILED:
6188 case BFA_FCS_VPORT_SM_FABRIC_MAX:
6189 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6190 break;
6191
6192 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
6193 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
6194 break;
6195
6196 default:
6197 bfa_sm_fault(__vport_fcs(vport), event);
6198 }
6199 }
6200
6201 /*
6202 * FDISC attempt failed - a timer is active to retry FDISC.
6203 */
6204 static void
bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6205 bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
6206 enum bfa_fcs_vport_event event)
6207 {
6208 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6209 bfa_trc(__vport_fcs(vport), event);
6210
6211 switch (event) {
6212 case BFA_FCS_VPORT_SM_DELETE:
6213 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6214 bfa_timer_stop(&vport->timer);
6215 bfa_fcs_lport_delete(&vport->lport);
6216 break;
6217
6218 case BFA_FCS_VPORT_SM_OFFLINE:
6219 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6220 bfa_timer_stop(&vport->timer);
6221 break;
6222
6223 case BFA_FCS_VPORT_SM_TIMEOUT:
6224 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6225 vport->vport_stats.fdisc_retries++;
6226 vport->fdisc_retries++;
6227 bfa_fcs_vport_do_fdisc(vport);
6228 break;
6229
6230 default:
6231 bfa_sm_fault(__vport_fcs(vport), event);
6232 }
6233 }
6234
6235 /*
6236 * FDISC is in progress and we got a vport delete request -
6237 * this is a wait state while we wait for fdisc response and
6238 * we will transition to the appropriate state - on rsp status.
6239 */
6240 static void
bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6241 bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
6242 enum bfa_fcs_vport_event event)
6243 {
6244 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6245 bfa_trc(__vport_fcs(vport), event);
6246
6247 switch (event) {
6248 case BFA_FCS_VPORT_SM_RSP_OK:
6249 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
6250 bfa_fcs_lport_delete(&vport->lport);
6251 break;
6252
6253 case BFA_FCS_VPORT_SM_DELETE:
6254 break;
6255
6256 case BFA_FCS_VPORT_SM_OFFLINE:
6257 case BFA_FCS_VPORT_SM_RSP_ERROR:
6258 case BFA_FCS_VPORT_SM_RSP_FAILED:
6259 case BFA_FCS_VPORT_SM_FABRIC_MAX:
6260 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
6261 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6262 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6263 bfa_fcs_lport_delete(&vport->lport);
6264 break;
6265
6266 default:
6267 bfa_sm_fault(__vport_fcs(vport), event);
6268 }
6269 }
6270
6271 /*
6272 * Vport is online (FDISC is complete).
6273 */
6274 static void
bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6275 bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
6276 enum bfa_fcs_vport_event event)
6277 {
6278 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6279 bfa_trc(__vport_fcs(vport), event);
6280
6281 switch (event) {
6282 case BFA_FCS_VPORT_SM_DELETE:
6283 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
6284 bfa_fcs_lport_delete(&vport->lport);
6285 break;
6286
6287 case BFA_FCS_VPORT_SM_STOP:
6288 bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
6289 bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
6290 break;
6291
6292 case BFA_FCS_VPORT_SM_OFFLINE:
6293 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6294 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6295 bfa_fcs_lport_offline(&vport->lport);
6296 break;
6297
6298 default:
6299 bfa_sm_fault(__vport_fcs(vport), event);
6300 }
6301 }
6302
6303 /*
6304 * Vport is being stopped - awaiting lport stop completion to send
6305 * LOGO to fabric.
6306 */
6307 static void
bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6308 bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
6309 enum bfa_fcs_vport_event event)
6310 {
6311 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6312 bfa_trc(__vport_fcs(vport), event);
6313
6314 switch (event) {
6315 case BFA_FCS_VPORT_SM_STOPCOMP:
6316 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
6317 bfa_fcs_vport_do_logo(vport);
6318 break;
6319
6320 case BFA_FCS_VPORT_SM_OFFLINE:
6321 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6322 break;
6323
6324 default:
6325 bfa_sm_fault(__vport_fcs(vport), event);
6326 }
6327 }
6328
6329 /*
6330 * Vport is being deleted - awaiting lport delete completion to send
6331 * LOGO to fabric.
6332 */
6333 static void
bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6334 bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
6335 enum bfa_fcs_vport_event event)
6336 {
6337 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6338 bfa_trc(__vport_fcs(vport), event);
6339
6340 switch (event) {
6341 case BFA_FCS_VPORT_SM_DELETE:
6342 break;
6343
6344 case BFA_FCS_VPORT_SM_DELCOMP:
6345 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
6346 bfa_fcs_vport_do_logo(vport);
6347 break;
6348
6349 case BFA_FCS_VPORT_SM_OFFLINE:
6350 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6351 break;
6352
6353 default:
6354 bfa_sm_fault(__vport_fcs(vport), event);
6355 }
6356 }
6357
6358 /*
6359 * Error State.
6360 * This state will be set when the Vport Creation fails due
6361 * to errors like Dup WWN. In this state only operation allowed
6362 * is a Vport Delete.
6363 */
6364 static void
bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6365 bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
6366 enum bfa_fcs_vport_event event)
6367 {
6368 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6369 bfa_trc(__vport_fcs(vport), event);
6370
6371 switch (event) {
6372 case BFA_FCS_VPORT_SM_DELETE:
6373 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6374 bfa_fcs_lport_delete(&vport->lport);
6375 break;
6376
6377 default:
6378 bfa_trc(__vport_fcs(vport), event);
6379 }
6380 }
6381
6382 /*
6383 * Lport cleanup is in progress since vport is being deleted. Fabric is
6384 * offline, so no LOGO is needed to complete vport deletion.
6385 */
6386 static void
bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6387 bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
6388 enum bfa_fcs_vport_event event)
6389 {
6390 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6391 bfa_trc(__vport_fcs(vport), event);
6392
6393 switch (event) {
6394 case BFA_FCS_VPORT_SM_DELCOMP:
6395 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6396 bfa_fcs_vport_free(vport);
6397 break;
6398
6399 case BFA_FCS_VPORT_SM_STOPCOMP:
6400 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6401 break;
6402
6403 case BFA_FCS_VPORT_SM_DELETE:
6404 break;
6405
6406 default:
6407 bfa_sm_fault(__vport_fcs(vport), event);
6408 }
6409 }
6410
6411 /*
6412 * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
6413 * is done.
6414 */
6415 static void
bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6416 bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
6417 enum bfa_fcs_vport_event event)
6418 {
6419 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6420 bfa_trc(__vport_fcs(vport), event);
6421
6422 switch (event) {
6423 case BFA_FCS_VPORT_SM_OFFLINE:
6424 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6425 fallthrough;
6426
6427 case BFA_FCS_VPORT_SM_RSP_OK:
6428 case BFA_FCS_VPORT_SM_RSP_ERROR:
6429 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6430 break;
6431
6432 default:
6433 bfa_sm_fault(__vport_fcs(vport), event);
6434 }
6435 }
6436
6437 /*
6438 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
6439 * is done.
6440 */
6441 static void
bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)6442 bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
6443 enum bfa_fcs_vport_event event)
6444 {
6445 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6446 bfa_trc(__vport_fcs(vport), event);
6447
6448 switch (event) {
6449 case BFA_FCS_VPORT_SM_OFFLINE:
6450 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6451 fallthrough;
6452
6453 case BFA_FCS_VPORT_SM_RSP_OK:
6454 case BFA_FCS_VPORT_SM_RSP_ERROR:
6455 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6456 bfa_fcs_vport_free(vport);
6457 break;
6458
6459 case BFA_FCS_VPORT_SM_DELETE:
6460 break;
6461
6462 default:
6463 bfa_sm_fault(__vport_fcs(vport), event);
6464 }
6465 }
6466
6467
6468
6469 /*
6470 * fcs_vport_private FCS virtual port private functions
6471 */
6472 /*
6473 * Send AEN notification
6474 */
6475 static void
bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s * port,enum bfa_lport_aen_event event)6476 bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port,
6477 enum bfa_lport_aen_event event)
6478 {
6479 struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
6480 struct bfa_aen_entry_s *aen_entry;
6481
6482 bfad_get_aen_entry(bfad, aen_entry);
6483 if (!aen_entry)
6484 return;
6485
6486 aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
6487 aen_entry->aen_data.lport.roles = port->port_cfg.roles;
6488 aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
6489 bfa_fcs_get_base_port(port->fcs));
6490 aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
6491
6492 /* Send the AEN notification */
6493 bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
6494 BFA_AEN_CAT_LPORT, event);
6495 }
6496
6497 /*
6498 * This routine will be called to send a FDISC command.
6499 */
6500 static void
bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s * vport)6501 bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
6502 {
6503 bfa_lps_fdisc(vport->lps, vport,
6504 bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
6505 __vport_pwwn(vport), __vport_nwwn(vport));
6506 vport->vport_stats.fdisc_sent++;
6507 }
6508
6509 static void
bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s * vport)6510 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
6511 {
6512 u8 lsrjt_rsn = vport->lps->lsrjt_rsn;
6513 u8 lsrjt_expl = vport->lps->lsrjt_expl;
6514
6515 bfa_trc(__vport_fcs(vport), lsrjt_rsn);
6516 bfa_trc(__vport_fcs(vport), lsrjt_expl);
6517
6518 /* For certain reason codes, we don't want to retry. */
6519 switch (vport->lps->lsrjt_expl) {
6520 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
6521 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
6522 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6523 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6524 else {
6525 bfa_fcs_vport_aen_post(&vport->lport,
6526 BFA_LPORT_AEN_NPIV_DUP_WWN);
6527 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
6528 }
6529 break;
6530
6531 case FC_LS_RJT_EXP_INSUFF_RES:
6532 /*
6533 * This means max logins per port/switch setting on the
6534 * switch was exceeded.
6535 */
6536 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6537 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6538 else {
6539 bfa_fcs_vport_aen_post(&vport->lport,
6540 BFA_LPORT_AEN_NPIV_FABRIC_MAX);
6541 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX);
6542 }
6543 break;
6544
6545 default:
6546 if (vport->fdisc_retries == 0)
6547 bfa_fcs_vport_aen_post(&vport->lport,
6548 BFA_LPORT_AEN_NPIV_UNKNOWN);
6549 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6550 }
6551 }
6552
6553 /*
6554 * Called to send a logout to the fabric. Used when a V-Port is
6555 * deleted/stopped.
6556 */
6557 static void
bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s * vport)6558 bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
6559 {
6560 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6561
6562 vport->vport_stats.logo_sent++;
6563 bfa_lps_fdisclogo(vport->lps);
6564 }
6565
6566
6567 /*
6568 * This routine will be called by bfa_timer on timer timeouts.
6569 *
6570 * param[in] vport - pointer to bfa_fcs_vport_t.
6571 * param[out] vport_status - pointer to return vport status in
6572 *
6573 * return
6574 * void
6575 *
6576 * Special Considerations:
6577 *
6578 * note
6579 */
6580 static void
bfa_fcs_vport_timeout(void * vport_arg)6581 bfa_fcs_vport_timeout(void *vport_arg)
6582 {
6583 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
6584
6585 vport->vport_stats.fdisc_timeouts++;
6586 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
6587 }
6588
6589 static void
bfa_fcs_vport_free(struct bfa_fcs_vport_s * vport)6590 bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
6591 {
6592 struct bfad_vport_s *vport_drv =
6593 (struct bfad_vport_s *)vport->vport_drv;
6594
6595 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
6596 bfa_lps_delete(vport->lps);
6597
6598 if (vport_drv->comp_del) {
6599 complete(vport_drv->comp_del);
6600 return;
6601 }
6602
6603 /*
6604 * We queue the vport delete work to the IM work_q from here.
6605 * The memory for the bfad_vport_s is freed from the FC function
6606 * template vport_delete entry point.
6607 */
6608 bfad_im_port_delete(vport_drv->drv_port.bfad, &vport_drv->drv_port);
6609 }
6610
6611 /*
6612 * fcs_vport_public FCS virtual port public interfaces
6613 */
6614
6615 /*
6616 * Online notification from fabric SM.
6617 */
6618 void
bfa_fcs_vport_online(struct bfa_fcs_vport_s * vport)6619 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
6620 {
6621 vport->vport_stats.fab_online++;
6622 if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
6623 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6624 else
6625 vport->vport_stats.fab_no_npiv++;
6626 }
6627
6628 /*
6629 * Offline notification from fabric SM.
6630 */
6631 void
bfa_fcs_vport_offline(struct bfa_fcs_vport_s * vport)6632 bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
6633 {
6634 vport->vport_stats.fab_offline++;
6635 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6636 }
6637
6638 /*
6639 * Cleanup notification from fabric SM on link timer expiry.
6640 */
6641 void
bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s * vport)6642 bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
6643 {
6644 vport->vport_stats.fab_cleanup++;
6645 }
6646
6647 /*
6648 * Stop notification from fabric SM. To be invoked from within FCS.
6649 */
6650 void
bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s * vport)6651 bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport)
6652 {
6653 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6654 }
6655
6656 /*
6657 * delete notification from fabric SM. To be invoked from within FCS.
6658 */
6659 void
bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s * vport)6660 bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
6661 {
6662 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
6663 }
6664
6665 /*
6666 * Stop completion callback from associated lport
6667 */
6668 void
bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s * vport)6669 bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
6670 {
6671 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
6672 }
6673
6674 /*
6675 * Delete completion callback from associated lport
6676 */
6677 void
bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s * vport)6678 bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
6679 {
6680 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
6681 }
6682
6683
6684
6685 /*
6686 * fcs_vport_api Virtual port API
6687 */
6688
6689 /*
6690 * Use this function to instantiate a new FCS vport object. This
6691 * function will not trigger any HW initialization process (which will be
6692 * done in vport_start() call)
6693 *
6694 * param[in] vport - pointer to bfa_fcs_vport_t. This space
6695 * needs to be allocated by the driver.
6696 * param[in] fcs - FCS instance
6697 * param[in] vport_cfg - vport configuration
6698 * param[in] vf_id - VF_ID if vport is created within a VF.
6699 * FC_VF_ID_NULL to specify base fabric.
6700 * param[in] vport_drv - Opaque handle back to the driver's vport
6701 * structure
6702 *
6703 * retval BFA_STATUS_OK - on success.
6704 * retval BFA_STATUS_FAILED - on failure.
6705 */
6706 bfa_status_t
bfa_fcs_vport_create(struct bfa_fcs_vport_s * vport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_lport_cfg_s * vport_cfg,struct bfad_vport_s * vport_drv)6707 bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
6708 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
6709 struct bfad_vport_s *vport_drv)
6710 {
6711 if (vport_cfg->pwwn == 0)
6712 return BFA_STATUS_INVALID_WWN;
6713
6714 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
6715 return BFA_STATUS_VPORT_WWN_BP;
6716
6717 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
6718 return BFA_STATUS_VPORT_EXISTS;
6719
6720 if (fcs->fabric.num_vports ==
6721 bfa_lps_get_max_vport(fcs->bfa))
6722 return BFA_STATUS_VPORT_MAX;
6723
6724 vport->lps = bfa_lps_alloc(fcs->bfa);
6725 if (!vport->lps)
6726 return BFA_STATUS_VPORT_MAX;
6727
6728 vport->vport_drv = vport_drv;
6729 vport_cfg->preboot_vp = BFA_FALSE;
6730
6731 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6732 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
6733 bfa_fcs_lport_init(&vport->lport, vport_cfg);
6734 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
6735
6736 return BFA_STATUS_OK;
6737 }
6738
6739 /*
6740 * Use this function to instantiate a new FCS PBC vport object. This
6741 * function will not trigger any HW initialization process (which will be
6742 * done in vport_start() call)
6743 *
6744 * param[in] vport - pointer to bfa_fcs_vport_t. This space
6745 * needs to be allocated by the driver.
6746 * param[in] fcs - FCS instance
6747 * param[in] vport_cfg - vport configuration
6748 * param[in] vf_id - VF_ID if vport is created within a VF.
6749 * FC_VF_ID_NULL to specify base fabric.
6750 * param[in] vport_drv - Opaque handle back to the driver's vport
6751 * structure
6752 *
6753 * retval BFA_STATUS_OK - on success.
6754 * retval BFA_STATUS_FAILED - on failure.
6755 */
6756 bfa_status_t
bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s * vport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_lport_cfg_s * vport_cfg,struct bfad_vport_s * vport_drv)6757 bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
6758 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
6759 struct bfad_vport_s *vport_drv)
6760 {
6761 bfa_status_t rc;
6762
6763 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
6764 vport->lport.port_cfg.preboot_vp = BFA_TRUE;
6765
6766 return rc;
6767 }
6768
6769 /*
6770 * Use this function to findout if this is a pbc vport or not.
6771 *
6772 * @param[in] vport - pointer to bfa_fcs_vport_t.
6773 *
6774 * @returns None
6775 */
6776 bfa_boolean_t
bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s * vport)6777 bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
6778 {
6779
6780 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
6781 return BFA_TRUE;
6782 else
6783 return BFA_FALSE;
6784
6785 }
6786
6787 /*
6788 * Use this function initialize the vport.
6789 *
6790 * @param[in] vport - pointer to bfa_fcs_vport_t.
6791 *
6792 * @returns None
6793 */
6794 bfa_status_t
bfa_fcs_vport_start(struct bfa_fcs_vport_s * vport)6795 bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
6796 {
6797 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
6798
6799 return BFA_STATUS_OK;
6800 }
6801
6802 /*
6803 * Use this function quiese the vport object. This function will return
6804 * immediately, when the vport is actually stopped, the
6805 * bfa_drv_vport_stop_cb() will be called.
6806 *
6807 * param[in] vport - pointer to bfa_fcs_vport_t.
6808 *
6809 * return None
6810 */
6811 bfa_status_t
bfa_fcs_vport_stop(struct bfa_fcs_vport_s * vport)6812 bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
6813 {
6814 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6815
6816 return BFA_STATUS_OK;
6817 }
6818
6819 /*
6820 * Use this function to delete a vport object. Fabric object should
6821 * be stopped before this function call.
6822 *
6823 * !!!!!!! Donot invoke this from within FCS !!!!!!!
6824 *
6825 * param[in] vport - pointer to bfa_fcs_vport_t.
6826 *
6827 * return None
6828 */
6829 bfa_status_t
bfa_fcs_vport_delete(struct bfa_fcs_vport_s * vport)6830 bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
6831 {
6832
6833 if (vport->lport.port_cfg.preboot_vp)
6834 return BFA_STATUS_PBC;
6835
6836 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
6837
6838 return BFA_STATUS_OK;
6839 }
6840
6841 /*
6842 * Use this function to get vport's current status info.
6843 *
6844 * param[in] vport pointer to bfa_fcs_vport_t.
6845 * param[out] attr pointer to return vport attributes
6846 *
6847 * return None
6848 */
6849 void
bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s * vport,struct bfa_vport_attr_s * attr)6850 bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
6851 struct bfa_vport_attr_s *attr)
6852 {
6853 if (vport == NULL || attr == NULL)
6854 return;
6855
6856 memset(attr, 0, sizeof(struct bfa_vport_attr_s));
6857
6858 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
6859 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
6860 }
6861
6862
6863 /*
6864 * Lookup a virtual port. Excludes base port from lookup.
6865 */
6866 struct bfa_fcs_vport_s *
bfa_fcs_vport_lookup(struct bfa_fcs_s * fcs,u16 vf_id,wwn_t vpwwn)6867 bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
6868 {
6869 struct bfa_fcs_vport_s *vport;
6870 struct bfa_fcs_fabric_s *fabric;
6871
6872 bfa_trc(fcs, vf_id);
6873 bfa_trc(fcs, vpwwn);
6874
6875 fabric = bfa_fcs_vf_lookup(fcs, vf_id);
6876 if (!fabric) {
6877 bfa_trc(fcs, vf_id);
6878 return NULL;
6879 }
6880
6881 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
6882 return vport;
6883 }
6884
6885 /*
6886 * FDISC Response
6887 */
6888 void
bfa_cb_lps_fdisc_comp(void * bfad,void * uarg,bfa_status_t status)6889 bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
6890 {
6891 struct bfa_fcs_vport_s *vport = uarg;
6892
6893 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6894 bfa_trc(__vport_fcs(vport), status);
6895
6896 switch (status) {
6897 case BFA_STATUS_OK:
6898 /*
6899 * Initialize the V-Port fields
6900 */
6901 __vport_fcid(vport) = vport->lps->lp_pid;
6902 vport->vport_stats.fdisc_accepts++;
6903 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6904 break;
6905
6906 case BFA_STATUS_INVALID_MAC:
6907 /* Only for CNA */
6908 vport->vport_stats.fdisc_acc_bad++;
6909 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6910
6911 break;
6912
6913 case BFA_STATUS_EPROTOCOL:
6914 switch (vport->lps->ext_status) {
6915 case BFA_EPROTO_BAD_ACCEPT:
6916 vport->vport_stats.fdisc_acc_bad++;
6917 break;
6918
6919 case BFA_EPROTO_UNKNOWN_RSP:
6920 vport->vport_stats.fdisc_unknown_rsp++;
6921 break;
6922
6923 default:
6924 break;
6925 }
6926
6927 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6928 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6929 else
6930 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
6931
6932 break;
6933
6934 case BFA_STATUS_ETIMER:
6935 vport->vport_stats.fdisc_timeouts++;
6936 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6937 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6938 else
6939 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
6940 break;
6941
6942 case BFA_STATUS_FABRIC_RJT:
6943 vport->vport_stats.fdisc_rejects++;
6944 bfa_fcs_vport_fdisc_rejected(vport);
6945 break;
6946
6947 default:
6948 vport->vport_stats.fdisc_rsp_err++;
6949 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6950 }
6951 }
6952
6953 /*
6954 * LOGO response
6955 */
6956 void
bfa_cb_lps_fdisclogo_comp(void * bfad,void * uarg)6957 bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
6958 {
6959 struct bfa_fcs_vport_s *vport = uarg;
6960 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6961 }
6962
6963 /*
6964 * Received clear virtual link
6965 */
6966 void
bfa_cb_lps_cvl_event(void * bfad,void * uarg)6967 bfa_cb_lps_cvl_event(void *bfad, void *uarg)
6968 {
6969 struct bfa_fcs_vport_s *vport = uarg;
6970
6971 /* Send an Offline followed by an ONLINE */
6972 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6973 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6974 }
6975