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