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