GNU Linux-libre 5.10.153-gnu1
[releases.git] / drivers / scsi / bfa / bfa_svc.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4  * Copyright (c) 2014- QLogic Corporation.
5  * All rights reserved
6  * www.qlogic.com
7  *
8  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
9  */
10
11 #include "bfad_drv.h"
12 #include "bfad_im.h"
13 #include "bfa_plog.h"
14 #include "bfa_cs.h"
15 #include "bfa_modules.h"
16
17 BFA_TRC_FILE(HAL, FCXP);
18
19 /*
20  * LPS related definitions
21  */
22 #define BFA_LPS_MIN_LPORTS      (1)
23 #define BFA_LPS_MAX_LPORTS      (256)
24
25 /*
26  * Maximum Vports supported per physical port or vf.
27  */
28 #define BFA_LPS_MAX_VPORTS_SUPP_CB  255
29 #define BFA_LPS_MAX_VPORTS_SUPP_CT  190
30
31
32 /*
33  * FC PORT related definitions
34  */
35 /*
36  * The port is considered disabled if corresponding physical port or IOC are
37  * disabled explicitly
38  */
39 #define BFA_PORT_IS_DISABLED(bfa) \
40         ((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
41         (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
42
43 /*
44  * BFA port state machine events
45  */
46 enum bfa_fcport_sm_event {
47         BFA_FCPORT_SM_START     = 1,    /*  start port state machine    */
48         BFA_FCPORT_SM_STOP      = 2,    /*  stop port state machine     */
49         BFA_FCPORT_SM_ENABLE    = 3,    /*  enable port         */
50         BFA_FCPORT_SM_DISABLE   = 4,    /*  disable port state machine */
51         BFA_FCPORT_SM_FWRSP     = 5,    /*  firmware enable/disable rsp */
52         BFA_FCPORT_SM_LINKUP    = 6,    /*  firmware linkup event       */
53         BFA_FCPORT_SM_LINKDOWN  = 7,    /*  firmware linkup down        */
54         BFA_FCPORT_SM_QRESUME   = 8,    /*  CQ space available  */
55         BFA_FCPORT_SM_HWFAIL    = 9,    /*  IOC h/w failure             */
56         BFA_FCPORT_SM_DPORTENABLE = 10, /*  enable dport      */
57         BFA_FCPORT_SM_DPORTDISABLE = 11,/*  disable dport     */
58         BFA_FCPORT_SM_FAA_MISCONFIG = 12,       /* FAA misconfiguratin */
59         BFA_FCPORT_SM_DDPORTENABLE  = 13,       /* enable ddport        */
60         BFA_FCPORT_SM_DDPORTDISABLE = 14,       /* disable ddport       */
61 };
62
63 /*
64  * BFA port link notification state machine events
65  */
66
67 enum bfa_fcport_ln_sm_event {
68         BFA_FCPORT_LN_SM_LINKUP         = 1,    /*  linkup event        */
69         BFA_FCPORT_LN_SM_LINKDOWN       = 2,    /*  linkdown event      */
70         BFA_FCPORT_LN_SM_NOTIFICATION   = 3     /*  done notification   */
71 };
72
73 /*
74  * RPORT related definitions
75  */
76 #define bfa_rport_offline_cb(__rp) do {                                 \
77         if ((__rp)->bfa->fcs)                                           \
78                 bfa_cb_rport_offline((__rp)->rport_drv);      \
79         else {                                                          \
80                 bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,              \
81                                 __bfa_cb_rport_offline, (__rp));      \
82         }                                                               \
83 } while (0)
84
85 #define bfa_rport_online_cb(__rp) do {                                  \
86         if ((__rp)->bfa->fcs)                                           \
87                 bfa_cb_rport_online((__rp)->rport_drv);      \
88         else {                                                          \
89                 bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,              \
90                                   __bfa_cb_rport_online, (__rp));      \
91                 }                                                       \
92 } while (0)
93
94 /*
95  * forward declarations FCXP related functions
96  */
97 static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
98 static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
99                                 struct bfi_fcxp_send_rsp_s *fcxp_rsp);
100 static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
101                                 struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
102 static void     bfa_fcxp_qresume(void *cbarg);
103 static void     bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
104                                 struct bfi_fcxp_send_req_s *send_req);
105
106 /*
107  * forward declarations for LPS functions
108  */
109 static void bfa_lps_login_rsp(struct bfa_s *bfa,
110                                 struct bfi_lps_login_rsp_s *rsp);
111 static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);
112 static void bfa_lps_logout_rsp(struct bfa_s *bfa,
113                                 struct bfi_lps_logout_rsp_s *rsp);
114 static void bfa_lps_reqq_resume(void *lps_arg);
115 static void bfa_lps_free(struct bfa_lps_s *lps);
116 static void bfa_lps_send_login(struct bfa_lps_s *lps);
117 static void bfa_lps_send_logout(struct bfa_lps_s *lps);
118 static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
119 static void bfa_lps_login_comp(struct bfa_lps_s *lps);
120 static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
121 static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
122
123 /*
124  * forward declaration for LPS state machine
125  */
126 static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
127 static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
128 static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
129                                         event);
130 static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
131 static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
132                                         enum bfa_lps_event event);
133 static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
134 static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
135                                         event);
136
137 /*
138  * forward declaration for FC Port functions
139  */
140 static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
141 static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
142 static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
143 static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
144 static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
145 static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
146 static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
147                         enum bfa_port_linkstate event, bfa_boolean_t trunk);
148 static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
149                                 enum bfa_port_linkstate event);
150 static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
151 static void bfa_fcport_stats_get_timeout(void *cbarg);
152 static void bfa_fcport_stats_clr_timeout(void *cbarg);
153 static void bfa_trunk_iocdisable(struct bfa_s *bfa);
154
155 /*
156  * forward declaration for FC PORT state machine
157  */
158 static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
159                                         enum bfa_fcport_sm_event event);
160 static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
161                                         enum bfa_fcport_sm_event event);
162 static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
163                                         enum bfa_fcport_sm_event event);
164 static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
165                                         enum bfa_fcport_sm_event event);
166 static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
167                                         enum bfa_fcport_sm_event event);
168 static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
169                                         enum bfa_fcport_sm_event event);
170 static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
171                                         enum bfa_fcport_sm_event event);
172 static void     bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
173                                         enum bfa_fcport_sm_event event);
174 static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
175                                         enum bfa_fcport_sm_event event);
176 static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
177                                         enum bfa_fcport_sm_event event);
178 static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
179                                         enum bfa_fcport_sm_event event);
180 static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
181                                         enum bfa_fcport_sm_event event);
182 static void     bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
183                                         enum bfa_fcport_sm_event event);
184 static void     bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
185                                         enum bfa_fcport_sm_event event);
186 static void     bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
187                                         enum bfa_fcport_sm_event event);
188
189 static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
190                                         enum bfa_fcport_ln_sm_event event);
191 static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
192                                         enum bfa_fcport_ln_sm_event event);
193 static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
194                                         enum bfa_fcport_ln_sm_event event);
195 static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
196                                         enum bfa_fcport_ln_sm_event event);
197 static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
198                                         enum bfa_fcport_ln_sm_event event);
199 static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
200                                         enum bfa_fcport_ln_sm_event event);
201 static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
202                                         enum bfa_fcport_ln_sm_event event);
203
204 static struct bfa_sm_table_s hal_port_sm_table[] = {
205         {BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
206         {BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
207         {BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
208         {BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
209         {BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
210         {BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
211         {BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
212         {BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
213         {BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
214         {BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
215         {BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
216         {BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
217         {BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
218         {BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT},
219         {BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
220 };
221
222
223 /*
224  * forward declaration for RPORT related functions
225  */
226 static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
227 static void             bfa_rport_free(struct bfa_rport_s *rport);
228 static bfa_boolean_t    bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
229 static bfa_boolean_t    bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
230 static bfa_boolean_t    bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
231 static void             __bfa_cb_rport_online(void *cbarg,
232                                                 bfa_boolean_t complete);
233 static void             __bfa_cb_rport_offline(void *cbarg,
234                                                 bfa_boolean_t complete);
235
236 /*
237  * forward declaration for RPORT state machine
238  */
239 static void     bfa_rport_sm_uninit(struct bfa_rport_s *rp,
240                                         enum bfa_rport_event event);
241 static void     bfa_rport_sm_created(struct bfa_rport_s *rp,
242                                         enum bfa_rport_event event);
243 static void     bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
244                                         enum bfa_rport_event event);
245 static void     bfa_rport_sm_online(struct bfa_rport_s *rp,
246                                         enum bfa_rport_event event);
247 static void     bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
248                                         enum bfa_rport_event event);
249 static void     bfa_rport_sm_offline(struct bfa_rport_s *rp,
250                                         enum bfa_rport_event event);
251 static void     bfa_rport_sm_deleting(struct bfa_rport_s *rp,
252                                         enum bfa_rport_event event);
253 static void     bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
254                                         enum bfa_rport_event event);
255 static void     bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
256                                         enum bfa_rport_event event);
257 static void     bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
258                                         enum bfa_rport_event event);
259 static void     bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
260                                         enum bfa_rport_event event);
261 static void     bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
262                                         enum bfa_rport_event event);
263 static void     bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
264                                         enum bfa_rport_event event);
265
266 /*
267  * PLOG related definitions
268  */
269 static int
270 plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
271 {
272         if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
273                 (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
274                 return 1;
275
276         if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
277                 (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
278                 return 1;
279
280         return 0;
281 }
282
283 static void
284 bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
285 {
286         u16 tail;
287         struct bfa_plog_rec_s *pl_recp;
288
289         if (plog->plog_enabled == 0)
290                 return;
291
292         if (plkd_validate_logrec(pl_rec)) {
293                 WARN_ON(1);
294                 return;
295         }
296
297         tail = plog->tail;
298
299         pl_recp = &(plog->plog_recs[tail]);
300
301         memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
302
303         pl_recp->tv = ktime_get_real_seconds();
304         BFA_PL_LOG_REC_INCR(plog->tail);
305
306         if (plog->head == plog->tail)
307                 BFA_PL_LOG_REC_INCR(plog->head);
308 }
309
310 void
311 bfa_plog_init(struct bfa_plog_s *plog)
312 {
313         memset((char *)plog, 0, sizeof(struct bfa_plog_s));
314
315         memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
316         plog->head = plog->tail = 0;
317         plog->plog_enabled = 1;
318 }
319
320 void
321 bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
322                 enum bfa_plog_eid event,
323                 u16 misc, char *log_str)
324 {
325         struct bfa_plog_rec_s  lp;
326
327         if (plog->plog_enabled) {
328                 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
329                 lp.mid = mid;
330                 lp.eid = event;
331                 lp.log_type = BFA_PL_LOG_TYPE_STRING;
332                 lp.misc = misc;
333                 strlcpy(lp.log_entry.string_log, log_str,
334                         BFA_PL_STRING_LOG_SZ);
335                 lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
336                 bfa_plog_add(plog, &lp);
337         }
338 }
339
340 void
341 bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
342                 enum bfa_plog_eid event,
343                 u16 misc, u32 *intarr, u32 num_ints)
344 {
345         struct bfa_plog_rec_s  lp;
346         u32 i;
347
348         if (num_ints > BFA_PL_INT_LOG_SZ)
349                 num_ints = BFA_PL_INT_LOG_SZ;
350
351         if (plog->plog_enabled) {
352                 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
353                 lp.mid = mid;
354                 lp.eid = event;
355                 lp.log_type = BFA_PL_LOG_TYPE_INT;
356                 lp.misc = misc;
357
358                 for (i = 0; i < num_ints; i++)
359                         lp.log_entry.int_log[i] = intarr[i];
360
361                 lp.log_num_ints = (u8) num_ints;
362
363                 bfa_plog_add(plog, &lp);
364         }
365 }
366
367 void
368 bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
369                         enum bfa_plog_eid event,
370                         u16 misc, struct fchs_s *fchdr)
371 {
372         struct bfa_plog_rec_s  lp;
373         u32     *tmp_int = (u32 *) fchdr;
374         u32     ints[BFA_PL_INT_LOG_SZ];
375
376         if (plog->plog_enabled) {
377                 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
378
379                 ints[0] = tmp_int[0];
380                 ints[1] = tmp_int[1];
381                 ints[2] = tmp_int[4];
382
383                 bfa_plog_intarr(plog, mid, event, misc, ints, 3);
384         }
385 }
386
387 void
388 bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
389                       enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
390                       u32 pld_w0)
391 {
392         struct bfa_plog_rec_s  lp;
393         u32     *tmp_int = (u32 *) fchdr;
394         u32     ints[BFA_PL_INT_LOG_SZ];
395
396         if (plog->plog_enabled) {
397                 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
398
399                 ints[0] = tmp_int[0];
400                 ints[1] = tmp_int[1];
401                 ints[2] = tmp_int[4];
402                 ints[3] = pld_w0;
403
404                 bfa_plog_intarr(plog, mid, event, misc, ints, 4);
405         }
406 }
407
408
409 /*
410  *  fcxp_pvt BFA FCXP private functions
411  */
412
413 static void
414 claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
415 {
416         u16     i;
417         struct bfa_fcxp_s *fcxp;
418
419         fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
420         memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
421
422         INIT_LIST_HEAD(&mod->fcxp_req_free_q);
423         INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);
424         INIT_LIST_HEAD(&mod->fcxp_active_q);
425         INIT_LIST_HEAD(&mod->fcxp_req_unused_q);
426         INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);
427
428         mod->fcxp_list = fcxp;
429
430         for (i = 0; i < mod->num_fcxps; i++) {
431                 fcxp->fcxp_mod = mod;
432                 fcxp->fcxp_tag = i;
433
434                 if (i < (mod->num_fcxps / 2)) {
435                         list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
436                         fcxp->req_rsp = BFA_TRUE;
437                 } else {
438                         list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
439                         fcxp->req_rsp = BFA_FALSE;
440                 }
441
442                 bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
443                 fcxp->reqq_waiting = BFA_FALSE;
444
445                 fcxp = fcxp + 1;
446         }
447
448         bfa_mem_kva_curp(mod) = (void *)fcxp;
449 }
450
451 void
452 bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
453                 struct bfa_s *bfa)
454 {
455         struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa);
456         struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa);
457         struct bfa_mem_dma_s *seg_ptr;
458         u16     nsegs, idx, per_seg_fcxp;
459         u16     num_fcxps = cfg->fwcfg.num_fcxp_reqs;
460         u32     per_fcxp_sz;
461
462         if (num_fcxps == 0)
463                 return;
464
465         if (cfg->drvcfg.min_cfg)
466                 per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;
467         else
468                 per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ;
469
470         /* dma memory */
471         nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz);
472         per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz);
473
474         bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) {
475                 if (num_fcxps >= per_seg_fcxp) {
476                         num_fcxps -= per_seg_fcxp;
477                         bfa_mem_dma_setup(minfo, seg_ptr,
478                                 per_seg_fcxp * per_fcxp_sz);
479                 } else
480                         bfa_mem_dma_setup(minfo, seg_ptr,
481                                 num_fcxps * per_fcxp_sz);
482         }
483
484         /* kva memory */
485         bfa_mem_kva_setup(minfo, fcxp_kva,
486                 cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));
487 }
488
489 void
490 bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
491                 struct bfa_pcidev_s *pcidev)
492 {
493         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
494
495         mod->bfa = bfa;
496         mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
497
498         /*
499          * Initialize FCXP request and response payload sizes.
500          */
501         mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
502         if (!cfg->drvcfg.min_cfg)
503                 mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
504
505         INIT_LIST_HEAD(&mod->req_wait_q);
506         INIT_LIST_HEAD(&mod->rsp_wait_q);
507
508         claim_fcxps_mem(mod);
509 }
510
511 void
512 bfa_fcxp_iocdisable(struct bfa_s *bfa)
513 {
514         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
515         struct bfa_fcxp_s *fcxp;
516         struct list_head              *qe, *qen;
517
518         /* Enqueue unused fcxp resources to free_q */
519         list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);
520         list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);
521
522         list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
523                 fcxp = (struct bfa_fcxp_s *) qe;
524                 if (fcxp->caller == NULL) {
525                         fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
526                                         BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
527                         bfa_fcxp_free(fcxp);
528                 } else {
529                         fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
530                         bfa_cb_queue(bfa, &fcxp->hcb_qe,
531                                      __bfa_fcxp_send_cbfn, fcxp);
532                 }
533         }
534 }
535
536 static struct bfa_fcxp_s *
537 bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)
538 {
539         struct bfa_fcxp_s *fcxp;
540
541         if (req)
542                 bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);
543         else
544                 bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);
545
546         if (fcxp)
547                 list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
548
549         return fcxp;
550 }
551
552 static void
553 bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
554                struct bfa_s *bfa,
555                u8 *use_ibuf,
556                u32 *nr_sgles,
557                bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
558                bfa_fcxp_get_sglen_t *r_sglen_cbfn,
559                struct list_head *r_sgpg_q,
560                int n_sgles,
561                bfa_fcxp_get_sgaddr_t sga_cbfn,
562                bfa_fcxp_get_sglen_t sglen_cbfn)
563 {
564
565         WARN_ON(bfa == NULL);
566
567         bfa_trc(bfa, fcxp->fcxp_tag);
568
569         if (n_sgles == 0) {
570                 *use_ibuf = 1;
571         } else {
572                 WARN_ON(*sga_cbfn == NULL);
573                 WARN_ON(*sglen_cbfn == NULL);
574
575                 *use_ibuf = 0;
576                 *r_sga_cbfn = sga_cbfn;
577                 *r_sglen_cbfn = sglen_cbfn;
578
579                 *nr_sgles = n_sgles;
580
581                 /*
582                  * alloc required sgpgs
583                  */
584                 if (n_sgles > BFI_SGE_INLINE)
585                         WARN_ON(1);
586         }
587
588 }
589
590 static void
591 bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
592                void *caller, struct bfa_s *bfa, int nreq_sgles,
593                int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
594                bfa_fcxp_get_sglen_t req_sglen_cbfn,
595                bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
596                bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
597 {
598
599         WARN_ON(bfa == NULL);
600
601         bfa_trc(bfa, fcxp->fcxp_tag);
602
603         fcxp->caller = caller;
604
605         bfa_fcxp_init_reqrsp(fcxp, bfa,
606                 &fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
607                 &fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
608                 nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
609
610         bfa_fcxp_init_reqrsp(fcxp, bfa,
611                 &fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
612                 &fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
613                 nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
614
615 }
616
617 static void
618 bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
619 {
620         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
621         struct bfa_fcxp_wqe_s *wqe;
622
623         if (fcxp->req_rsp)
624                 bfa_q_deq(&mod->req_wait_q, &wqe);
625         else
626                 bfa_q_deq(&mod->rsp_wait_q, &wqe);
627
628         if (wqe) {
629                 bfa_trc(mod->bfa, fcxp->fcxp_tag);
630
631                 bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
632                         wqe->nrsp_sgles, wqe->req_sga_cbfn,
633                         wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
634                         wqe->rsp_sglen_cbfn);
635
636                 wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
637                 return;
638         }
639
640         WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
641         list_del(&fcxp->qe);
642
643         if (fcxp->req_rsp)
644                 list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
645         else
646                 list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
647 }
648
649 static void
650 bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
651                    bfa_status_t req_status, u32 rsp_len,
652                    u32 resid_len, struct fchs_s *rsp_fchs)
653 {
654         /* discarded fcxp completion */
655 }
656
657 static void
658 __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
659 {
660         struct bfa_fcxp_s *fcxp = cbarg;
661
662         if (complete) {
663                 fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
664                                 fcxp->rsp_status, fcxp->rsp_len,
665                                 fcxp->residue_len, &fcxp->rsp_fchs);
666         } else {
667                 bfa_fcxp_free(fcxp);
668         }
669 }
670
671 static void
672 hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
673 {
674         struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
675         struct bfa_fcxp_s       *fcxp;
676         u16             fcxp_tag = be16_to_cpu(fcxp_rsp->fcxp_tag);
677
678         bfa_trc(bfa, fcxp_tag);
679
680         fcxp_rsp->rsp_len = be32_to_cpu(fcxp_rsp->rsp_len);
681
682         /*
683          * @todo f/w should not set residue to non-0 when everything
684          *       is received.
685          */
686         if (fcxp_rsp->req_status == BFA_STATUS_OK)
687                 fcxp_rsp->residue_len = 0;
688         else
689                 fcxp_rsp->residue_len = be32_to_cpu(fcxp_rsp->residue_len);
690
691         fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
692
693         WARN_ON(fcxp->send_cbfn == NULL);
694
695         hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
696
697         if (fcxp->send_cbfn != NULL) {
698                 bfa_trc(mod->bfa, (NULL == fcxp->caller));
699                 if (fcxp->caller == NULL) {
700                         fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
701                                         fcxp_rsp->req_status, fcxp_rsp->rsp_len,
702                                         fcxp_rsp->residue_len, &fcxp_rsp->fchs);
703                         /*
704                          * fcxp automatically freed on return from the callback
705                          */
706                         bfa_fcxp_free(fcxp);
707                 } else {
708                         fcxp->rsp_status = fcxp_rsp->req_status;
709                         fcxp->rsp_len = fcxp_rsp->rsp_len;
710                         fcxp->residue_len = fcxp_rsp->residue_len;
711                         fcxp->rsp_fchs = fcxp_rsp->fchs;
712
713                         bfa_cb_queue(bfa, &fcxp->hcb_qe,
714                                         __bfa_fcxp_send_cbfn, fcxp);
715                 }
716         } else {
717                 bfa_trc(bfa, (NULL == fcxp->send_cbfn));
718         }
719 }
720
721 static void
722 hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
723                  struct fchs_s *fchs)
724 {
725         /*
726          * TODO: TX ox_id
727          */
728         if (reqlen > 0) {
729                 if (fcxp->use_ireqbuf) {
730                         u32     pld_w0 =
731                                 *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
732
733                         bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
734                                         BFA_PL_EID_TX,
735                                         reqlen + sizeof(struct fchs_s), fchs,
736                                         pld_w0);
737                 } else {
738                         bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
739                                         BFA_PL_EID_TX,
740                                         reqlen + sizeof(struct fchs_s),
741                                         fchs);
742                 }
743         } else {
744                 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
745                                reqlen + sizeof(struct fchs_s), fchs);
746         }
747 }
748
749 static void
750 hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
751                  struct bfi_fcxp_send_rsp_s *fcxp_rsp)
752 {
753         if (fcxp_rsp->rsp_len > 0) {
754                 if (fcxp->use_irspbuf) {
755                         u32     pld_w0 =
756                                 *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
757
758                         bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
759                                               BFA_PL_EID_RX,
760                                               (u16) fcxp_rsp->rsp_len,
761                                               &fcxp_rsp->fchs, pld_w0);
762                 } else {
763                         bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
764                                        BFA_PL_EID_RX,
765                                        (u16) fcxp_rsp->rsp_len,
766                                        &fcxp_rsp->fchs);
767                 }
768         } else {
769                 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
770                                (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
771         }
772 }
773
774 /*
775  * Handler to resume sending fcxp when space in available in cpe queue.
776  */
777 static void
778 bfa_fcxp_qresume(void *cbarg)
779 {
780         struct bfa_fcxp_s               *fcxp = cbarg;
781         struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
782         struct bfi_fcxp_send_req_s      *send_req;
783
784         fcxp->reqq_waiting = BFA_FALSE;
785         send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
786         bfa_fcxp_queue(fcxp, send_req);
787 }
788
789 /*
790  * Queue fcxp send request to foimrware.
791  */
792 static void
793 bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
794 {
795         struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
796         struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
797         struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
798         struct bfa_rport_s              *rport = reqi->bfa_rport;
799
800         bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
801                     bfa_fn_lpu(bfa));
802
803         send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
804         if (rport) {
805                 send_req->rport_fw_hndl = rport->fw_handle;
806                 send_req->max_frmsz = cpu_to_be16(rport->rport_info.max_frmsz);
807                 if (send_req->max_frmsz == 0)
808                         send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
809         } else {
810                 send_req->rport_fw_hndl = 0;
811                 send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
812         }
813
814         send_req->vf_id = cpu_to_be16(reqi->vf_id);
815         send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);
816         send_req->class = reqi->class;
817         send_req->rsp_timeout = rspi->rsp_timeout;
818         send_req->cts = reqi->cts;
819         send_req->fchs = reqi->fchs;
820
821         send_req->req_len = cpu_to_be32(reqi->req_tot_len);
822         send_req->rsp_maxlen = cpu_to_be32(rspi->rsp_maxlen);
823
824         /*
825          * setup req sgles
826          */
827         if (fcxp->use_ireqbuf == 1) {
828                 bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
829                                         BFA_FCXP_REQ_PLD_PA(fcxp));
830         } else {
831                 if (fcxp->nreq_sgles > 0) {
832                         WARN_ON(fcxp->nreq_sgles != 1);
833                         bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
834                                 fcxp->req_sga_cbfn(fcxp->caller, 0));
835                 } else {
836                         WARN_ON(reqi->req_tot_len != 0);
837                         bfa_alen_set(&send_req->rsp_alen, 0, 0);
838                 }
839         }
840
841         /*
842          * setup rsp sgles
843          */
844         if (fcxp->use_irspbuf == 1) {
845                 WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
846
847                 bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
848                                         BFA_FCXP_RSP_PLD_PA(fcxp));
849         } else {
850                 if (fcxp->nrsp_sgles > 0) {
851                         WARN_ON(fcxp->nrsp_sgles != 1);
852                         bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
853                                 fcxp->rsp_sga_cbfn(fcxp->caller, 0));
854
855                 } else {
856                         WARN_ON(rspi->rsp_maxlen != 0);
857                         bfa_alen_set(&send_req->rsp_alen, 0, 0);
858                 }
859         }
860
861         hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
862
863         bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);
864
865         bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
866         bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
867 }
868
869 /*
870  * Allocate an FCXP instance to send a response or to send a request
871  * that has a response. Request/response buffers are allocated by caller.
872  *
873  * @param[in]   bfa             BFA bfa instance
874  * @param[in]   nreq_sgles      Number of SG elements required for request
875  *                              buffer. 0, if fcxp internal buffers are used.
876  *                              Use bfa_fcxp_get_reqbuf() to get the
877  *                              internal req buffer.
878  * @param[in]   req_sgles       SG elements describing request buffer. Will be
879  *                              copied in by BFA and hence can be freed on
880  *                              return from this function.
881  * @param[in]   get_req_sga     function ptr to be called to get a request SG
882  *                              Address (given the sge index).
883  * @param[in]   get_req_sglen   function ptr to be called to get a request SG
884  *                              len (given the sge index).
885  * @param[in]   get_rsp_sga     function ptr to be called to get a response SG
886  *                              Address (given the sge index).
887  * @param[in]   get_rsp_sglen   function ptr to be called to get a response SG
888  *                              len (given the sge index).
889  * @param[in]   req             Allocated FCXP is used to send req or rsp?
890  *                              request - BFA_TRUE, response - BFA_FALSE
891  *
892  * @return FCXP instance. NULL on failure.
893  */
894 struct bfa_fcxp_s *
895 bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
896                 int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
897                 bfa_fcxp_get_sglen_t req_sglen_cbfn,
898                 bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
899                 bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
900 {
901         struct bfa_fcxp_s *fcxp = NULL;
902
903         WARN_ON(bfa == NULL);
904
905         fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);
906         if (fcxp == NULL)
907                 return NULL;
908
909         bfa_trc(bfa, fcxp->fcxp_tag);
910
911         bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
912                         req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
913
914         return fcxp;
915 }
916
917 /*
918  * Get the internal request buffer pointer
919  *
920  * @param[in]   fcxp    BFA fcxp pointer
921  *
922  * @return              pointer to the internal request buffer
923  */
924 void *
925 bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
926 {
927         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
928         void    *reqbuf;
929
930         WARN_ON(fcxp->use_ireqbuf != 1);
931         reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
932                                 mod->req_pld_sz + mod->rsp_pld_sz);
933         return reqbuf;
934 }
935
936 u32
937 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
938 {
939         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
940
941         return mod->req_pld_sz;
942 }
943
944 /*
945  * Get the internal response buffer pointer
946  *
947  * @param[in]   fcxp    BFA fcxp pointer
948  *
949  * @return              pointer to the internal request buffer
950  */
951 void *
952 bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
953 {
954         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
955         void    *fcxp_buf;
956
957         WARN_ON(fcxp->use_irspbuf != 1);
958
959         fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
960                                 mod->req_pld_sz + mod->rsp_pld_sz);
961
962         /* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
963         return ((u8 *) fcxp_buf) + mod->req_pld_sz;
964 }
965
966 /*
967  * Free the BFA FCXP
968  *
969  * @param[in]   fcxp                    BFA fcxp pointer
970  *
971  * @return              void
972  */
973 void
974 bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
975 {
976         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
977
978         WARN_ON(fcxp == NULL);
979         bfa_trc(mod->bfa, fcxp->fcxp_tag);
980         bfa_fcxp_put(fcxp);
981 }
982
983 /*
984  * Send a FCXP request
985  *
986  * @param[in]   fcxp    BFA fcxp pointer
987  * @param[in]   rport   BFA rport pointer. Could be left NULL for WKA rports
988  * @param[in]   vf_id   virtual Fabric ID
989  * @param[in]   lp_tag  lport tag
990  * @param[in]   cts     use Continuous sequence
991  * @param[in]   cos     fc Class of Service
992  * @param[in]   reqlen  request length, does not include FCHS length
993  * @param[in]   fchs    fc Header Pointer. The header content will be copied
994  *                      in by BFA.
995  *
996  * @param[in]   cbfn    call back function to be called on receiving
997  *                                                              the response
998  * @param[in]   cbarg   arg for cbfn
999  * @param[in]   rsp_timeout
1000  *                      response timeout
1001  *
1002  * @return              bfa_status_t
1003  */
1004 void
1005 bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
1006               u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
1007               u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
1008               void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
1009 {
1010         struct bfa_s                    *bfa  = fcxp->fcxp_mod->bfa;
1011         struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
1012         struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
1013         struct bfi_fcxp_send_req_s      *send_req;
1014
1015         bfa_trc(bfa, fcxp->fcxp_tag);
1016
1017         /*
1018          * setup request/response info
1019          */
1020         reqi->bfa_rport = rport;
1021         reqi->vf_id = vf_id;
1022         reqi->lp_tag = lp_tag;
1023         reqi->class = cos;
1024         rspi->rsp_timeout = rsp_timeout;
1025         reqi->cts = cts;
1026         reqi->fchs = *fchs;
1027         reqi->req_tot_len = reqlen;
1028         rspi->rsp_maxlen = rsp_maxlen;
1029         fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
1030         fcxp->send_cbarg = cbarg;
1031
1032         /*
1033          * If no room in CPE queue, wait for space in request queue
1034          */
1035         send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
1036         if (!send_req) {
1037                 bfa_trc(bfa, fcxp->fcxp_tag);
1038                 fcxp->reqq_waiting = BFA_TRUE;
1039                 bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
1040                 return;
1041         }
1042
1043         bfa_fcxp_queue(fcxp, send_req);
1044 }
1045
1046 /*
1047  * Abort a BFA FCXP
1048  *
1049  * @param[in]   fcxp    BFA fcxp pointer
1050  *
1051  * @return              void
1052  */
1053 bfa_status_t
1054 bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
1055 {
1056         bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
1057         WARN_ON(1);
1058         return BFA_STATUS_OK;
1059 }
1060
1061 void
1062 bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1063                bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1064                void *caller, int nreq_sgles,
1065                int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1066                bfa_fcxp_get_sglen_t req_sglen_cbfn,
1067                bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1068                bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
1069 {
1070         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1071
1072         if (req)
1073                 WARN_ON(!list_empty(&mod->fcxp_req_free_q));
1074         else
1075                 WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
1076
1077         wqe->alloc_cbfn = alloc_cbfn;
1078         wqe->alloc_cbarg = alloc_cbarg;
1079         wqe->caller = caller;
1080         wqe->bfa = bfa;
1081         wqe->nreq_sgles = nreq_sgles;
1082         wqe->nrsp_sgles = nrsp_sgles;
1083         wqe->req_sga_cbfn = req_sga_cbfn;
1084         wqe->req_sglen_cbfn = req_sglen_cbfn;
1085         wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1086         wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1087
1088         if (req)
1089                 list_add_tail(&wqe->qe, &mod->req_wait_q);
1090         else
1091                 list_add_tail(&wqe->qe, &mod->rsp_wait_q);
1092 }
1093
1094 void
1095 bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1096 {
1097         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1098
1099         WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
1100                 !bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
1101         list_del(&wqe->qe);
1102 }
1103
1104 void
1105 bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
1106 {
1107         /*
1108          * If waiting for room in request queue, cancel reqq wait
1109          * and free fcxp.
1110          */
1111         if (fcxp->reqq_waiting) {
1112                 fcxp->reqq_waiting = BFA_FALSE;
1113                 bfa_reqq_wcancel(&fcxp->reqq_wqe);
1114                 bfa_fcxp_free(fcxp);
1115                 return;
1116         }
1117
1118         fcxp->send_cbfn = bfa_fcxp_null_comp;
1119 }
1120
1121 void
1122 bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
1123 {
1124         switch (msg->mhdr.msg_id) {
1125         case BFI_FCXP_I2H_SEND_RSP:
1126                 hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
1127                 break;
1128
1129         default:
1130                 bfa_trc(bfa, msg->mhdr.msg_id);
1131                 WARN_ON(1);
1132         }
1133 }
1134
1135 u32
1136 bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
1137 {
1138         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1139
1140         return mod->rsp_pld_sz;
1141 }
1142
1143 void
1144 bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
1145 {
1146         struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
1147         struct list_head        *qe;
1148         int     i;
1149
1150         for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
1151                 if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
1152                         bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
1153                         list_add_tail(qe, &mod->fcxp_req_unused_q);
1154                 } else {
1155                         bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
1156                         list_add_tail(qe, &mod->fcxp_rsp_unused_q);
1157                 }
1158         }
1159 }
1160
1161 /*
1162  *  BFA LPS state machine functions
1163  */
1164
1165 /*
1166  * Init state -- no login
1167  */
1168 static void
1169 bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
1170 {
1171         bfa_trc(lps->bfa, lps->bfa_tag);
1172         bfa_trc(lps->bfa, event);
1173
1174         switch (event) {
1175         case BFA_LPS_SM_LOGIN:
1176                 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1177                         bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
1178                         bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1179                 } else {
1180                         bfa_sm_set_state(lps, bfa_lps_sm_login);
1181                         bfa_lps_send_login(lps);
1182                 }
1183
1184                 if (lps->fdisc)
1185                         bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1186                                 BFA_PL_EID_LOGIN, 0, "FDISC Request");
1187                 else
1188                         bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1189                                 BFA_PL_EID_LOGIN, 0, "FLOGI Request");
1190                 break;
1191
1192         case BFA_LPS_SM_LOGOUT:
1193                 bfa_lps_logout_comp(lps);
1194                 break;
1195
1196         case BFA_LPS_SM_DELETE:
1197                 bfa_lps_free(lps);
1198                 break;
1199
1200         case BFA_LPS_SM_RX_CVL:
1201         case BFA_LPS_SM_OFFLINE:
1202                 break;
1203
1204         case BFA_LPS_SM_FWRSP:
1205                 /*
1206                  * Could happen when fabric detects loopback and discards
1207                  * the lps request. Fw will eventually sent out the timeout
1208                  * Just ignore
1209                  */
1210                 break;
1211         case BFA_LPS_SM_SET_N2N_PID:
1212                 /*
1213                  * When topology is set to loop, bfa_lps_set_n2n_pid() sends
1214                  * this event. Ignore this event.
1215                  */
1216                 break;
1217
1218         default:
1219                 bfa_sm_fault(lps->bfa, event);
1220         }
1221 }
1222
1223 /*
1224  * login is in progress -- awaiting response from firmware
1225  */
1226 static void
1227 bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1228 {
1229         bfa_trc(lps->bfa, lps->bfa_tag);
1230         bfa_trc(lps->bfa, event);
1231
1232         switch (event) {
1233         case BFA_LPS_SM_FWRSP:
1234                 if (lps->status == BFA_STATUS_OK) {
1235                         bfa_sm_set_state(lps, bfa_lps_sm_online);
1236                         if (lps->fdisc)
1237                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1238                                         BFA_PL_EID_LOGIN, 0, "FDISC Accept");
1239                         else
1240                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1241                                         BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
1242                         /* If N2N, send the assigned PID to FW */
1243                         bfa_trc(lps->bfa, lps->fport);
1244                         bfa_trc(lps->bfa, lps->lp_pid);
1245
1246                         if (!lps->fport && lps->lp_pid)
1247                                 bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1248                 } else {
1249                         bfa_sm_set_state(lps, bfa_lps_sm_init);
1250                         if (lps->fdisc)
1251                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1252                                         BFA_PL_EID_LOGIN, 0,
1253                                         "FDISC Fail (RJT or timeout)");
1254                         else
1255                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1256                                         BFA_PL_EID_LOGIN, 0,
1257                                         "FLOGI Fail (RJT or timeout)");
1258                 }
1259                 bfa_lps_login_comp(lps);
1260                 break;
1261
1262         case BFA_LPS_SM_OFFLINE:
1263         case BFA_LPS_SM_DELETE:
1264                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1265                 break;
1266
1267         case BFA_LPS_SM_SET_N2N_PID:
1268                 bfa_trc(lps->bfa, lps->fport);
1269                 bfa_trc(lps->bfa, lps->lp_pid);
1270                 break;
1271
1272         default:
1273                 bfa_sm_fault(lps->bfa, event);
1274         }
1275 }
1276
1277 /*
1278  * login pending - awaiting space in request queue
1279  */
1280 static void
1281 bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1282 {
1283         bfa_trc(lps->bfa, lps->bfa_tag);
1284         bfa_trc(lps->bfa, event);
1285
1286         switch (event) {
1287         case BFA_LPS_SM_RESUME:
1288                 bfa_sm_set_state(lps, bfa_lps_sm_login);
1289                 bfa_lps_send_login(lps);
1290                 break;
1291
1292         case BFA_LPS_SM_OFFLINE:
1293         case BFA_LPS_SM_DELETE:
1294                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1295                 bfa_reqq_wcancel(&lps->wqe);
1296                 break;
1297
1298         case BFA_LPS_SM_RX_CVL:
1299                 /*
1300                  * Login was not even sent out; so when getting out
1301                  * of this state, it will appear like a login retry
1302                  * after Clear virtual link
1303                  */
1304                 break;
1305
1306         default:
1307                 bfa_sm_fault(lps->bfa, event);
1308         }
1309 }
1310
1311 /*
1312  * login complete
1313  */
1314 static void
1315 bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
1316 {
1317         bfa_trc(lps->bfa, lps->bfa_tag);
1318         bfa_trc(lps->bfa, event);
1319
1320         switch (event) {
1321         case BFA_LPS_SM_LOGOUT:
1322                 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1323                         bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1324                         bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1325                 } else {
1326                         bfa_sm_set_state(lps, bfa_lps_sm_logout);
1327                         bfa_lps_send_logout(lps);
1328                 }
1329                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1330                         BFA_PL_EID_LOGO, 0, "Logout");
1331                 break;
1332
1333         case BFA_LPS_SM_RX_CVL:
1334                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1335
1336                 /* Let the vport module know about this event */
1337                 bfa_lps_cvl_event(lps);
1338                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1339                         BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1340                 break;
1341
1342         case BFA_LPS_SM_SET_N2N_PID:
1343                 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1344                         bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
1345                         bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1346                 } else
1347                         bfa_lps_send_set_n2n_pid(lps);
1348                 break;
1349
1350         case BFA_LPS_SM_OFFLINE:
1351         case BFA_LPS_SM_DELETE:
1352                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1353                 break;
1354
1355         default:
1356                 bfa_sm_fault(lps->bfa, event);
1357         }
1358 }
1359
1360 /*
1361  * login complete
1362  */
1363 static void
1364 bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1365 {
1366         bfa_trc(lps->bfa, lps->bfa_tag);
1367         bfa_trc(lps->bfa, event);
1368
1369         switch (event) {
1370         case BFA_LPS_SM_RESUME:
1371                 bfa_sm_set_state(lps, bfa_lps_sm_online);
1372                 bfa_lps_send_set_n2n_pid(lps);
1373                 break;
1374
1375         case BFA_LPS_SM_LOGOUT:
1376                 bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1377                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1378                         BFA_PL_EID_LOGO, 0, "Logout");
1379                 break;
1380
1381         case BFA_LPS_SM_RX_CVL:
1382                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1383                 bfa_reqq_wcancel(&lps->wqe);
1384
1385                 /* Let the vport module know about this event */
1386                 bfa_lps_cvl_event(lps);
1387                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1388                         BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1389                 break;
1390
1391         case BFA_LPS_SM_OFFLINE:
1392         case BFA_LPS_SM_DELETE:
1393                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1394                 bfa_reqq_wcancel(&lps->wqe);
1395                 break;
1396
1397         default:
1398                 bfa_sm_fault(lps->bfa, event);
1399         }
1400 }
1401
1402 /*
1403  * logout in progress - awaiting firmware response
1404  */
1405 static void
1406 bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1407 {
1408         bfa_trc(lps->bfa, lps->bfa_tag);
1409         bfa_trc(lps->bfa, event);
1410
1411         switch (event) {
1412         case BFA_LPS_SM_FWRSP:
1413         case BFA_LPS_SM_OFFLINE:
1414                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1415                 bfa_lps_logout_comp(lps);
1416                 break;
1417
1418         case BFA_LPS_SM_DELETE:
1419                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1420                 break;
1421
1422         default:
1423                 bfa_sm_fault(lps->bfa, event);
1424         }
1425 }
1426
1427 /*
1428  * logout pending -- awaiting space in request queue
1429  */
1430 static void
1431 bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1432 {
1433         bfa_trc(lps->bfa, lps->bfa_tag);
1434         bfa_trc(lps->bfa, event);
1435
1436         switch (event) {
1437         case BFA_LPS_SM_RESUME:
1438                 bfa_sm_set_state(lps, bfa_lps_sm_logout);
1439                 bfa_lps_send_logout(lps);
1440                 break;
1441
1442         case BFA_LPS_SM_OFFLINE:
1443         case BFA_LPS_SM_DELETE:
1444                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1445                 bfa_reqq_wcancel(&lps->wqe);
1446                 break;
1447
1448         default:
1449                 bfa_sm_fault(lps->bfa, event);
1450         }
1451 }
1452
1453
1454
1455 /*
1456  *  lps_pvt BFA LPS private functions
1457  */
1458
1459 /*
1460  * return memory requirement
1461  */
1462 void
1463 bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
1464                 struct bfa_s *bfa)
1465 {
1466         struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);
1467
1468         if (cfg->drvcfg.min_cfg)
1469                 bfa_mem_kva_setup(minfo, lps_kva,
1470                         sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);
1471         else
1472                 bfa_mem_kva_setup(minfo, lps_kva,
1473                         sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);
1474 }
1475
1476 /*
1477  * bfa module attach at initialization time
1478  */
1479 void
1480 bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1481         struct bfa_pcidev_s *pcidev)
1482 {
1483         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1484         struct bfa_lps_s        *lps;
1485         int                     i;
1486
1487         mod->num_lps = BFA_LPS_MAX_LPORTS;
1488         if (cfg->drvcfg.min_cfg)
1489                 mod->num_lps = BFA_LPS_MIN_LPORTS;
1490         else
1491                 mod->num_lps = BFA_LPS_MAX_LPORTS;
1492         mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);
1493
1494         bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);
1495
1496         INIT_LIST_HEAD(&mod->lps_free_q);
1497         INIT_LIST_HEAD(&mod->lps_active_q);
1498         INIT_LIST_HEAD(&mod->lps_login_q);
1499
1500         for (i = 0; i < mod->num_lps; i++, lps++) {
1501                 lps->bfa        = bfa;
1502                 lps->bfa_tag    = (u8) i;
1503                 lps->reqq       = BFA_REQQ_LPS;
1504                 bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
1505                 list_add_tail(&lps->qe, &mod->lps_free_q);
1506         }
1507 }
1508
1509 /*
1510  * IOC in disabled state -- consider all lps offline
1511  */
1512 void
1513 bfa_lps_iocdisable(struct bfa_s *bfa)
1514 {
1515         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1516         struct bfa_lps_s        *lps;
1517         struct list_head                *qe, *qen;
1518
1519         list_for_each_safe(qe, qen, &mod->lps_active_q) {
1520                 lps = (struct bfa_lps_s *) qe;
1521                 bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1522         }
1523         list_for_each_safe(qe, qen, &mod->lps_login_q) {
1524                 lps = (struct bfa_lps_s *) qe;
1525                 bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1526         }
1527         list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
1528 }
1529
1530 /*
1531  * Firmware login response
1532  */
1533 static void
1534 bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1535 {
1536         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1537         struct bfa_lps_s        *lps;
1538
1539         WARN_ON(rsp->bfa_tag >= mod->num_lps);
1540         lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1541
1542         lps->status = rsp->status;
1543         switch (rsp->status) {
1544         case BFA_STATUS_OK:
1545                 lps->fw_tag     = rsp->fw_tag;
1546                 lps->fport      = rsp->f_port;
1547                 if (lps->fport)
1548                         lps->lp_pid = rsp->lp_pid;
1549                 lps->npiv_en    = rsp->npiv_en;
1550                 lps->pr_bbcred  = be16_to_cpu(rsp->bb_credit);
1551                 lps->pr_pwwn    = rsp->port_name;
1552                 lps->pr_nwwn    = rsp->node_name;
1553                 lps->auth_req   = rsp->auth_req;
1554                 lps->lp_mac     = rsp->lp_mac;
1555                 lps->brcd_switch = rsp->brcd_switch;
1556                 lps->fcf_mac    = rsp->fcf_mac;
1557
1558                 break;
1559
1560         case BFA_STATUS_FABRIC_RJT:
1561                 lps->lsrjt_rsn = rsp->lsrjt_rsn;
1562                 lps->lsrjt_expl = rsp->lsrjt_expl;
1563
1564                 break;
1565
1566         case BFA_STATUS_EPROTOCOL:
1567                 lps->ext_status = rsp->ext_status;
1568
1569                 break;
1570
1571         case BFA_STATUS_VPORT_MAX:
1572                 if (rsp->ext_status)
1573                         bfa_lps_no_res(lps, rsp->ext_status);
1574                 break;
1575
1576         default:
1577                 /* Nothing to do with other status */
1578                 break;
1579         }
1580
1581         list_del(&lps->qe);
1582         list_add_tail(&lps->qe, &mod->lps_active_q);
1583         bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1584 }
1585
1586 static void
1587 bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
1588 {
1589         struct bfa_s            *bfa = first_lps->bfa;
1590         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1591         struct list_head        *qe, *qe_next;
1592         struct bfa_lps_s        *lps;
1593
1594         bfa_trc(bfa, count);
1595
1596         qe = bfa_q_next(first_lps);
1597
1598         while (count && qe) {
1599                 qe_next = bfa_q_next(qe);
1600                 lps = (struct bfa_lps_s *)qe;
1601                 bfa_trc(bfa, lps->bfa_tag);
1602                 lps->status = first_lps->status;
1603                 list_del(&lps->qe);
1604                 list_add_tail(&lps->qe, &mod->lps_active_q);
1605                 bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1606                 qe = qe_next;
1607                 count--;
1608         }
1609 }
1610
1611 /*
1612  * Firmware logout response
1613  */
1614 static void
1615 bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
1616 {
1617         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1618         struct bfa_lps_s        *lps;
1619
1620         WARN_ON(rsp->bfa_tag >= mod->num_lps);
1621         lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1622
1623         bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1624 }
1625
1626 /*
1627  * Firmware received a Clear virtual link request (for FCoE)
1628  */
1629 static void
1630 bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
1631 {
1632         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1633         struct bfa_lps_s        *lps;
1634
1635         lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
1636
1637         bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
1638 }
1639
1640 /*
1641  * Space is available in request queue, resume queueing request to firmware.
1642  */
1643 static void
1644 bfa_lps_reqq_resume(void *lps_arg)
1645 {
1646         struct bfa_lps_s        *lps = lps_arg;
1647
1648         bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
1649 }
1650
1651 /*
1652  * lps is freed -- triggered by vport delete
1653  */
1654 static void
1655 bfa_lps_free(struct bfa_lps_s *lps)
1656 {
1657         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
1658
1659         lps->lp_pid = 0;
1660         list_del(&lps->qe);
1661         list_add_tail(&lps->qe, &mod->lps_free_q);
1662 }
1663
1664 /*
1665  * send login request to firmware
1666  */
1667 static void
1668 bfa_lps_send_login(struct bfa_lps_s *lps)
1669 {
1670         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
1671         struct bfi_lps_login_req_s      *m;
1672
1673         m = bfa_reqq_next(lps->bfa, lps->reqq);
1674         WARN_ON(!m);
1675
1676         bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
1677                 bfa_fn_lpu(lps->bfa));
1678
1679         m->bfa_tag      = lps->bfa_tag;
1680         m->alpa         = lps->alpa;
1681         m->pdu_size     = cpu_to_be16(lps->pdusz);
1682         m->pwwn         = lps->pwwn;
1683         m->nwwn         = lps->nwwn;
1684         m->fdisc        = lps->fdisc;
1685         m->auth_en      = lps->auth_en;
1686
1687         bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1688         list_del(&lps->qe);
1689         list_add_tail(&lps->qe, &mod->lps_login_q);
1690 }
1691
1692 /*
1693  * send logout request to firmware
1694  */
1695 static void
1696 bfa_lps_send_logout(struct bfa_lps_s *lps)
1697 {
1698         struct bfi_lps_logout_req_s *m;
1699
1700         m = bfa_reqq_next(lps->bfa, lps->reqq);
1701         WARN_ON(!m);
1702
1703         bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
1704                 bfa_fn_lpu(lps->bfa));
1705
1706         m->fw_tag = lps->fw_tag;
1707         m->port_name = lps->pwwn;
1708         bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1709 }
1710
1711 /*
1712  * send n2n pid set request to firmware
1713  */
1714 static void
1715 bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
1716 {
1717         struct bfi_lps_n2n_pid_req_s *m;
1718
1719         m = bfa_reqq_next(lps->bfa, lps->reqq);
1720         WARN_ON(!m);
1721
1722         bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
1723                 bfa_fn_lpu(lps->bfa));
1724
1725         m->fw_tag = lps->fw_tag;
1726         m->lp_pid = lps->lp_pid;
1727         bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1728 }
1729
1730 /*
1731  * Indirect login completion handler for non-fcs
1732  */
1733 static void
1734 bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
1735 {
1736         struct bfa_lps_s *lps   = arg;
1737
1738         if (!complete)
1739                 return;
1740
1741         if (lps->fdisc)
1742                 bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1743         else
1744                 bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1745 }
1746
1747 /*
1748  * Login completion handler -- direct call for fcs, queue for others
1749  */
1750 static void
1751 bfa_lps_login_comp(struct bfa_lps_s *lps)
1752 {
1753         if (!lps->bfa->fcs) {
1754                 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
1755                         lps);
1756                 return;
1757         }
1758
1759         if (lps->fdisc)
1760                 bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1761         else
1762                 bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1763 }
1764
1765 /*
1766  * Indirect logout completion handler for non-fcs
1767  */
1768 static void
1769 bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1770 {
1771         struct bfa_lps_s *lps   = arg;
1772
1773         if (!complete)
1774                 return;
1775
1776         if (lps->fdisc)
1777                 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1778         else
1779                 bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
1780 }
1781
1782 /*
1783  * Logout completion handler -- direct call for fcs, queue for others
1784  */
1785 static void
1786 bfa_lps_logout_comp(struct bfa_lps_s *lps)
1787 {
1788         if (!lps->bfa->fcs) {
1789                 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
1790                         lps);
1791                 return;
1792         }
1793         if (lps->fdisc)
1794                 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1795 }
1796
1797 /*
1798  * Clear virtual link completion handler for non-fcs
1799  */
1800 static void
1801 bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
1802 {
1803         struct bfa_lps_s *lps   = arg;
1804
1805         if (!complete)
1806                 return;
1807
1808         /* Clear virtual link to base port will result in link down */
1809         if (lps->fdisc)
1810                 bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1811 }
1812
1813 /*
1814  * Received Clear virtual link event --direct call for fcs,
1815  * queue for others
1816  */
1817 static void
1818 bfa_lps_cvl_event(struct bfa_lps_s *lps)
1819 {
1820         if (!lps->bfa->fcs) {
1821                 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
1822                         lps);
1823                 return;
1824         }
1825
1826         /* Clear virtual link to base port will result in link down */
1827         if (lps->fdisc)
1828                 bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1829 }
1830
1831
1832
1833 /*
1834  *  lps_public BFA LPS public functions
1835  */
1836
1837 u32
1838 bfa_lps_get_max_vport(struct bfa_s *bfa)
1839 {
1840         if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
1841                 return BFA_LPS_MAX_VPORTS_SUPP_CT;
1842         else
1843                 return BFA_LPS_MAX_VPORTS_SUPP_CB;
1844 }
1845
1846 /*
1847  * Allocate a lport srvice tag.
1848  */
1849 struct bfa_lps_s  *
1850 bfa_lps_alloc(struct bfa_s *bfa)
1851 {
1852         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1853         struct bfa_lps_s        *lps = NULL;
1854
1855         bfa_q_deq(&mod->lps_free_q, &lps);
1856
1857         if (lps == NULL)
1858                 return NULL;
1859
1860         list_add_tail(&lps->qe, &mod->lps_active_q);
1861
1862         bfa_sm_set_state(lps, bfa_lps_sm_init);
1863         return lps;
1864 }
1865
1866 /*
1867  * Free lport service tag. This can be called anytime after an alloc.
1868  * No need to wait for any pending login/logout completions.
1869  */
1870 void
1871 bfa_lps_delete(struct bfa_lps_s *lps)
1872 {
1873         bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
1874 }
1875
1876 /*
1877  * Initiate a lport login.
1878  */
1879 void
1880 bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1881         wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
1882 {
1883         lps->uarg       = uarg;
1884         lps->alpa       = alpa;
1885         lps->pdusz      = pdusz;
1886         lps->pwwn       = pwwn;
1887         lps->nwwn       = nwwn;
1888         lps->fdisc      = BFA_FALSE;
1889         lps->auth_en    = auth_en;
1890         bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1891 }
1892
1893 /*
1894  * Initiate a lport fdisc login.
1895  */
1896 void
1897 bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
1898         wwn_t nwwn)
1899 {
1900         lps->uarg       = uarg;
1901         lps->alpa       = 0;
1902         lps->pdusz      = pdusz;
1903         lps->pwwn       = pwwn;
1904         lps->nwwn       = nwwn;
1905         lps->fdisc      = BFA_TRUE;
1906         lps->auth_en    = BFA_FALSE;
1907         bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1908 }
1909
1910
1911 /*
1912  * Initiate a lport FDSIC logout.
1913  */
1914 void
1915 bfa_lps_fdisclogo(struct bfa_lps_s *lps)
1916 {
1917         bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
1918 }
1919
1920 u8
1921 bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
1922 {
1923         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1924
1925         return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
1926 }
1927
1928 /*
1929  * Return lport services tag given the pid
1930  */
1931 u8
1932 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
1933 {
1934         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1935         struct bfa_lps_s        *lps;
1936         int                     i;
1937
1938         for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
1939                 if (lps->lp_pid == pid)
1940                         return lps->bfa_tag;
1941         }
1942
1943         /* Return base port tag anyway */
1944         return 0;
1945 }
1946
1947
1948 /*
1949  * return port id assigned to the base lport
1950  */
1951 u32
1952 bfa_lps_get_base_pid(struct bfa_s *bfa)
1953 {
1954         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1955
1956         return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
1957 }
1958
1959 /*
1960  * Set PID in case of n2n (which is assigned during PLOGI)
1961  */
1962 void
1963 bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
1964 {
1965         bfa_trc(lps->bfa, lps->bfa_tag);
1966         bfa_trc(lps->bfa, n2n_pid);
1967
1968         lps->lp_pid = n2n_pid;
1969         bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1970 }
1971
1972 /*
1973  * LPS firmware message class handler.
1974  */
1975 void
1976 bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1977 {
1978         union bfi_lps_i2h_msg_u msg;
1979
1980         bfa_trc(bfa, m->mhdr.msg_id);
1981         msg.msg = m;
1982
1983         switch (m->mhdr.msg_id) {
1984         case BFI_LPS_I2H_LOGIN_RSP:
1985                 bfa_lps_login_rsp(bfa, msg.login_rsp);
1986                 break;
1987
1988         case BFI_LPS_I2H_LOGOUT_RSP:
1989                 bfa_lps_logout_rsp(bfa, msg.logout_rsp);
1990                 break;
1991
1992         case BFI_LPS_I2H_CVL_EVENT:
1993                 bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
1994                 break;
1995
1996         default:
1997                 bfa_trc(bfa, m->mhdr.msg_id);
1998                 WARN_ON(1);
1999         }
2000 }
2001
2002 static void
2003 bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
2004 {
2005         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2006         struct bfa_aen_entry_s  *aen_entry;
2007
2008         bfad_get_aen_entry(bfad, aen_entry);
2009         if (!aen_entry)
2010                 return;
2011
2012         aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
2013         aen_entry->aen_data.port.pwwn = fcport->pwwn;
2014
2015         /* Send the AEN notification */
2016         bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq,
2017                                   BFA_AEN_CAT_PORT, event);
2018 }
2019
2020 /*
2021  * FC PORT state machine functions
2022  */
2023 static void
2024 bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
2025                         enum bfa_fcport_sm_event event)
2026 {
2027         bfa_trc(fcport->bfa, event);
2028
2029         switch (event) {
2030         case BFA_FCPORT_SM_START:
2031                 /*
2032                  * Start event after IOC is configured and BFA is started.
2033                  */
2034                 fcport->use_flash_cfg = BFA_TRUE;
2035
2036                 if (bfa_fcport_send_enable(fcport)) {
2037                         bfa_trc(fcport->bfa, BFA_TRUE);
2038                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2039                 } else {
2040                         bfa_trc(fcport->bfa, BFA_FALSE);
2041                         bfa_sm_set_state(fcport,
2042                                         bfa_fcport_sm_enabling_qwait);
2043                 }
2044                 break;
2045
2046         case BFA_FCPORT_SM_ENABLE:
2047                 /*
2048                  * Port is persistently configured to be in enabled state. Do
2049                  * not change state. Port enabling is done when START event is
2050                  * received.
2051                  */
2052                 break;
2053
2054         case BFA_FCPORT_SM_DISABLE:
2055                 /*
2056                  * If a port is persistently configured to be disabled, the
2057                  * first event will a port disable request.
2058                  */
2059                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2060                 break;
2061
2062         case BFA_FCPORT_SM_HWFAIL:
2063                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2064                 break;
2065
2066         default:
2067                 bfa_sm_fault(fcport->bfa, event);
2068         }
2069 }
2070
2071 static void
2072 bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
2073                                 enum bfa_fcport_sm_event event)
2074 {
2075         char pwwn_buf[BFA_STRING_32];
2076         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2077         bfa_trc(fcport->bfa, event);
2078
2079         switch (event) {
2080         case BFA_FCPORT_SM_QRESUME:
2081                 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2082                 bfa_fcport_send_enable(fcport);
2083                 break;
2084
2085         case BFA_FCPORT_SM_STOP:
2086                 bfa_reqq_wcancel(&fcport->reqq_wait);
2087                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2088                 break;
2089
2090         case BFA_FCPORT_SM_ENABLE:
2091                 /*
2092                  * Already enable is in progress.
2093                  */
2094                 break;
2095
2096         case BFA_FCPORT_SM_DISABLE:
2097                 /*
2098                  * Just send disable request to firmware when room becomes
2099                  * available in request queue.
2100                  */
2101                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2102                 bfa_reqq_wcancel(&fcport->reqq_wait);
2103                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2104                                 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2105                 wwn2str(pwwn_buf, fcport->pwwn);
2106                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2107                         "Base port disabled: WWN = %s\n", pwwn_buf);
2108                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2109                 break;
2110
2111         case BFA_FCPORT_SM_LINKUP:
2112         case BFA_FCPORT_SM_LINKDOWN:
2113                 /*
2114                  * Possible to get link events when doing back-to-back
2115                  * enable/disables.
2116                  */
2117                 break;
2118
2119         case BFA_FCPORT_SM_HWFAIL:
2120                 bfa_reqq_wcancel(&fcport->reqq_wait);
2121                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2122                 break;
2123
2124         case BFA_FCPORT_SM_FAA_MISCONFIG:
2125                 bfa_fcport_reset_linkinfo(fcport);
2126                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2127                 bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2128                 break;
2129
2130         default:
2131                 bfa_sm_fault(fcport->bfa, event);
2132         }
2133 }
2134
2135 static void
2136 bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
2137                                                 enum bfa_fcport_sm_event event)
2138 {
2139         char pwwn_buf[BFA_STRING_32];
2140         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2141         bfa_trc(fcport->bfa, event);
2142
2143         switch (event) {
2144         case BFA_FCPORT_SM_FWRSP:
2145         case BFA_FCPORT_SM_LINKDOWN:
2146                 bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2147                 break;
2148
2149         case BFA_FCPORT_SM_LINKUP:
2150                 bfa_fcport_update_linkinfo(fcport);
2151                 bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2152
2153                 WARN_ON(!fcport->event_cbfn);
2154                 bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2155                 break;
2156
2157         case BFA_FCPORT_SM_ENABLE:
2158                 /*
2159                  * Already being enabled.
2160                  */
2161                 break;
2162
2163         case BFA_FCPORT_SM_DISABLE:
2164                 if (bfa_fcport_send_disable(fcport))
2165                         bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2166                 else
2167                         bfa_sm_set_state(fcport,
2168                                          bfa_fcport_sm_disabling_qwait);
2169
2170                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2171                                 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2172                 wwn2str(pwwn_buf, fcport->pwwn);
2173                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2174                         "Base port disabled: WWN = %s\n", pwwn_buf);
2175                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2176                 break;
2177
2178         case BFA_FCPORT_SM_STOP:
2179                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2180                 break;
2181
2182         case BFA_FCPORT_SM_HWFAIL:
2183                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2184                 break;
2185
2186         case BFA_FCPORT_SM_FAA_MISCONFIG:
2187                 bfa_fcport_reset_linkinfo(fcport);
2188                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2189                 bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2190                 break;
2191
2192         default:
2193                 bfa_sm_fault(fcport->bfa, event);
2194         }
2195 }
2196
2197 static void
2198 bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
2199                                                 enum bfa_fcport_sm_event event)
2200 {
2201         struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2202         char pwwn_buf[BFA_STRING_32];
2203         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2204
2205         bfa_trc(fcport->bfa, event);
2206
2207         switch (event) {
2208         case BFA_FCPORT_SM_LINKUP:
2209                 bfa_fcport_update_linkinfo(fcport);
2210                 bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2211                 WARN_ON(!fcport->event_cbfn);
2212                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2213                                 BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
2214                 if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
2215
2216                         bfa_trc(fcport->bfa,
2217                                 pevent->link_state.attr.vc_fcf.fcf.fipenabled);
2218                         bfa_trc(fcport->bfa,
2219                                 pevent->link_state.attr.vc_fcf.fcf.fipfailed);
2220
2221                         if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
2222                                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2223                                         BFA_PL_EID_FIP_FCF_DISC, 0,
2224                                         "FIP FCF Discovery Failed");
2225                         else
2226                                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2227                                         BFA_PL_EID_FIP_FCF_DISC, 0,
2228                                         "FIP FCF Discovered");
2229                 }
2230
2231                 bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2232                 wwn2str(pwwn_buf, fcport->pwwn);
2233                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2234                         "Base port online: WWN = %s\n", pwwn_buf);
2235                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
2236
2237                 /* If QoS is enabled and it is not online, send AEN */
2238                 if (fcport->cfg.qos_enabled &&
2239                     fcport->qos_attr.state != BFA_QOS_ONLINE)
2240                         bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
2241                 break;
2242
2243         case BFA_FCPORT_SM_LINKDOWN:
2244                 /*
2245                  * Possible to get link down event.
2246                  */
2247                 break;
2248
2249         case BFA_FCPORT_SM_ENABLE:
2250                 /*
2251                  * Already enabled.
2252                  */
2253                 break;
2254
2255         case BFA_FCPORT_SM_DISABLE:
2256                 if (bfa_fcport_send_disable(fcport))
2257                         bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2258                 else
2259                         bfa_sm_set_state(fcport,
2260                                          bfa_fcport_sm_disabling_qwait);
2261
2262                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2263                                 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2264                 wwn2str(pwwn_buf, fcport->pwwn);
2265                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2266                         "Base port disabled: WWN = %s\n", pwwn_buf);
2267                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2268                 break;
2269
2270         case BFA_FCPORT_SM_STOP:
2271                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2272                 break;
2273
2274         case BFA_FCPORT_SM_HWFAIL:
2275                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2276                 break;
2277
2278         case BFA_FCPORT_SM_FAA_MISCONFIG:
2279                 bfa_fcport_reset_linkinfo(fcport);
2280                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2281                 bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2282                 break;
2283
2284         default:
2285                 bfa_sm_fault(fcport->bfa, event);
2286         }
2287 }
2288
2289 static void
2290 bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
2291         enum bfa_fcport_sm_event event)
2292 {
2293         char pwwn_buf[BFA_STRING_32];
2294         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2295
2296         bfa_trc(fcport->bfa, event);
2297
2298         switch (event) {
2299         case BFA_FCPORT_SM_ENABLE:
2300                 /*
2301                  * Already enabled.
2302                  */
2303                 break;
2304
2305         case BFA_FCPORT_SM_DISABLE:
2306                 if (bfa_fcport_send_disable(fcport))
2307                         bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2308                 else
2309                         bfa_sm_set_state(fcport,
2310                                          bfa_fcport_sm_disabling_qwait);
2311
2312                 bfa_fcport_reset_linkinfo(fcport);
2313                 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2314                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2315                                 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2316                 wwn2str(pwwn_buf, fcport->pwwn);
2317                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2318                         "Base port offline: WWN = %s\n", pwwn_buf);
2319                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2320                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2321                         "Base port disabled: WWN = %s\n", pwwn_buf);
2322                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2323                 break;
2324
2325         case BFA_FCPORT_SM_LINKDOWN:
2326                 bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2327                 bfa_fcport_reset_linkinfo(fcport);
2328                 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2329                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2330                                 BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
2331                 wwn2str(pwwn_buf, fcport->pwwn);
2332                 if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2333                         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2334                                 "Base port offline: WWN = %s\n", pwwn_buf);
2335                         bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2336                 } else {
2337                         BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2338                                 "Base port (WWN = %s) "
2339                                 "lost fabric connectivity\n", pwwn_buf);
2340                         bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2341                 }
2342                 break;
2343
2344         case BFA_FCPORT_SM_STOP:
2345                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2346                 bfa_fcport_reset_linkinfo(fcport);
2347                 wwn2str(pwwn_buf, fcport->pwwn);
2348                 if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2349                         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2350                                 "Base port offline: WWN = %s\n", pwwn_buf);
2351                         bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2352                 } else {
2353                         BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2354                                 "Base port (WWN = %s) "
2355                                 "lost fabric connectivity\n", pwwn_buf);
2356                         bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2357                 }
2358                 break;
2359
2360         case BFA_FCPORT_SM_HWFAIL:
2361                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2362                 bfa_fcport_reset_linkinfo(fcport);
2363                 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2364                 wwn2str(pwwn_buf, fcport->pwwn);
2365                 if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2366                         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2367                                 "Base port offline: WWN = %s\n", pwwn_buf);
2368                         bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2369                 } else {
2370                         BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2371                                 "Base port (WWN = %s) "
2372                                 "lost fabric connectivity\n", pwwn_buf);
2373                         bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2374                 }
2375                 break;
2376
2377         case BFA_FCPORT_SM_FAA_MISCONFIG:
2378                 bfa_fcport_reset_linkinfo(fcport);
2379                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2380                 bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2381                 break;
2382
2383         default:
2384                 bfa_sm_fault(fcport->bfa, event);
2385         }
2386 }
2387
2388 static void
2389 bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
2390                                  enum bfa_fcport_sm_event event)
2391 {
2392         bfa_trc(fcport->bfa, event);
2393
2394         switch (event) {
2395         case BFA_FCPORT_SM_QRESUME:
2396                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2397                 bfa_fcport_send_disable(fcport);
2398                 break;
2399
2400         case BFA_FCPORT_SM_STOP:
2401                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2402                 bfa_reqq_wcancel(&fcport->reqq_wait);
2403                 break;
2404
2405         case BFA_FCPORT_SM_ENABLE:
2406                 bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
2407                 break;
2408
2409         case BFA_FCPORT_SM_DISABLE:
2410                 /*
2411                  * Already being disabled.
2412                  */
2413                 break;
2414
2415         case BFA_FCPORT_SM_LINKUP:
2416         case BFA_FCPORT_SM_LINKDOWN:
2417                 /*
2418                  * Possible to get link events when doing back-to-back
2419                  * enable/disables.
2420                  */
2421                 break;
2422
2423         case BFA_FCPORT_SM_HWFAIL:
2424                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2425                 bfa_reqq_wcancel(&fcport->reqq_wait);
2426                 break;
2427
2428         case BFA_FCPORT_SM_FAA_MISCONFIG:
2429                 bfa_fcport_reset_linkinfo(fcport);
2430                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2431                 bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2432                 break;
2433
2434         default:
2435                 bfa_sm_fault(fcport->bfa, event);
2436         }
2437 }
2438
2439 static void
2440 bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
2441                                  enum bfa_fcport_sm_event event)
2442 {
2443         bfa_trc(fcport->bfa, event);
2444
2445         switch (event) {
2446         case BFA_FCPORT_SM_QRESUME:
2447                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2448                 bfa_fcport_send_disable(fcport);
2449                 if (bfa_fcport_send_enable(fcport))
2450                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2451                 else
2452                         bfa_sm_set_state(fcport,
2453                                          bfa_fcport_sm_enabling_qwait);
2454                 break;
2455
2456         case BFA_FCPORT_SM_STOP:
2457                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2458                 bfa_reqq_wcancel(&fcport->reqq_wait);
2459                 break;
2460
2461         case BFA_FCPORT_SM_ENABLE:
2462                 break;
2463
2464         case BFA_FCPORT_SM_DISABLE:
2465                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2466                 break;
2467
2468         case BFA_FCPORT_SM_LINKUP:
2469         case BFA_FCPORT_SM_LINKDOWN:
2470                 /*
2471                  * Possible to get link events when doing back-to-back
2472                  * enable/disables.
2473                  */
2474                 break;
2475
2476         case BFA_FCPORT_SM_HWFAIL:
2477                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2478                 bfa_reqq_wcancel(&fcport->reqq_wait);
2479                 break;
2480
2481         default:
2482                 bfa_sm_fault(fcport->bfa, event);
2483         }
2484 }
2485
2486 static void
2487 bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
2488                                                 enum bfa_fcport_sm_event event)
2489 {
2490         char pwwn_buf[BFA_STRING_32];
2491         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2492         bfa_trc(fcport->bfa, event);
2493
2494         switch (event) {
2495         case BFA_FCPORT_SM_FWRSP:
2496                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2497                 break;
2498
2499         case BFA_FCPORT_SM_DISABLE:
2500                 /*
2501                  * Already being disabled.
2502                  */
2503                 break;
2504
2505         case BFA_FCPORT_SM_ENABLE:
2506                 if (bfa_fcport_send_enable(fcport))
2507                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2508                 else
2509                         bfa_sm_set_state(fcport,
2510                                          bfa_fcport_sm_enabling_qwait);
2511
2512                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2513                                 BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2514                 wwn2str(pwwn_buf, fcport->pwwn);
2515                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2516                         "Base port enabled: WWN = %s\n", pwwn_buf);
2517                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2518                 break;
2519
2520         case BFA_FCPORT_SM_STOP:
2521                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2522                 break;
2523
2524         case BFA_FCPORT_SM_LINKUP:
2525         case BFA_FCPORT_SM_LINKDOWN:
2526                 /*
2527                  * Possible to get link events when doing back-to-back
2528                  * enable/disables.
2529                  */
2530                 break;
2531
2532         case BFA_FCPORT_SM_HWFAIL:
2533                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2534                 break;
2535
2536         default:
2537                 bfa_sm_fault(fcport->bfa, event);
2538         }
2539 }
2540
2541 static void
2542 bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
2543                                                 enum bfa_fcport_sm_event event)
2544 {
2545         char pwwn_buf[BFA_STRING_32];
2546         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2547         bfa_trc(fcport->bfa, event);
2548
2549         switch (event) {
2550         case BFA_FCPORT_SM_START:
2551                 /*
2552                  * Ignore start event for a port that is disabled.
2553                  */
2554                 break;
2555
2556         case BFA_FCPORT_SM_STOP:
2557                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2558                 break;
2559
2560         case BFA_FCPORT_SM_ENABLE:
2561                 if (bfa_fcport_send_enable(fcport))
2562                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2563                 else
2564                         bfa_sm_set_state(fcport,
2565                                          bfa_fcport_sm_enabling_qwait);
2566
2567                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2568                                 BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2569                 wwn2str(pwwn_buf, fcport->pwwn);
2570                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2571                         "Base port enabled: WWN = %s\n", pwwn_buf);
2572                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2573                 break;
2574
2575         case BFA_FCPORT_SM_DISABLE:
2576                 /*
2577                  * Already disabled.
2578                  */
2579                 break;
2580
2581         case BFA_FCPORT_SM_HWFAIL:
2582                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2583                 break;
2584
2585         case BFA_FCPORT_SM_DPORTENABLE:
2586                 bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
2587                 break;
2588
2589         case BFA_FCPORT_SM_DDPORTENABLE:
2590                 bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
2591                 break;
2592
2593         default:
2594                 bfa_sm_fault(fcport->bfa, event);
2595         }
2596 }
2597
2598 static void
2599 bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
2600                          enum bfa_fcport_sm_event event)
2601 {
2602         bfa_trc(fcport->bfa, event);
2603
2604         switch (event) {
2605         case BFA_FCPORT_SM_START:
2606                 if (bfa_fcport_send_enable(fcport))
2607                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2608                 else
2609                         bfa_sm_set_state(fcport,
2610                                          bfa_fcport_sm_enabling_qwait);
2611                 break;
2612
2613         default:
2614                 /*
2615                  * Ignore all other events.
2616                  */
2617                 ;
2618         }
2619 }
2620
2621 /*
2622  * Port is enabled. IOC is down/failed.
2623  */
2624 static void
2625 bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
2626                          enum bfa_fcport_sm_event event)
2627 {
2628         bfa_trc(fcport->bfa, event);
2629
2630         switch (event) {
2631         case BFA_FCPORT_SM_START:
2632                 if (bfa_fcport_send_enable(fcport))
2633                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2634                 else
2635                         bfa_sm_set_state(fcport,
2636                                          bfa_fcport_sm_enabling_qwait);
2637                 break;
2638
2639         default:
2640                 /*
2641                  * Ignore all events.
2642                  */
2643                 ;
2644         }
2645 }
2646
2647 /*
2648  * Port is disabled. IOC is down/failed.
2649  */
2650 static void
2651 bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
2652                          enum bfa_fcport_sm_event event)
2653 {
2654         bfa_trc(fcport->bfa, event);
2655
2656         switch (event) {
2657         case BFA_FCPORT_SM_START:
2658                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2659                 break;
2660
2661         case BFA_FCPORT_SM_ENABLE:
2662                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2663                 break;
2664
2665         default:
2666                 /*
2667                  * Ignore all events.
2668                  */
2669                 ;
2670         }
2671 }
2672
2673 static void
2674 bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
2675 {
2676         bfa_trc(fcport->bfa, event);
2677
2678         switch (event) {
2679         case BFA_FCPORT_SM_DPORTENABLE:
2680         case BFA_FCPORT_SM_DISABLE:
2681         case BFA_FCPORT_SM_ENABLE:
2682         case BFA_FCPORT_SM_START:
2683                 /*
2684                  * Ignore event for a port that is dport
2685                  */
2686                 break;
2687
2688         case BFA_FCPORT_SM_STOP:
2689                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2690                 break;
2691
2692         case BFA_FCPORT_SM_HWFAIL:
2693                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2694                 break;
2695
2696         case BFA_FCPORT_SM_DPORTDISABLE:
2697                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2698                 break;
2699
2700         default:
2701                 bfa_sm_fault(fcport->bfa, event);
2702         }
2703 }
2704
2705 static void
2706 bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
2707                         enum bfa_fcport_sm_event event)
2708 {
2709         bfa_trc(fcport->bfa, event);
2710
2711         switch (event) {
2712         case BFA_FCPORT_SM_DISABLE:
2713         case BFA_FCPORT_SM_DDPORTDISABLE:
2714                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2715                 break;
2716
2717         case BFA_FCPORT_SM_DPORTENABLE:
2718         case BFA_FCPORT_SM_DPORTDISABLE:
2719         case BFA_FCPORT_SM_ENABLE:
2720         case BFA_FCPORT_SM_START:
2721                 /*
2722                  * Ignore event for a port that is ddport
2723                  */
2724                 break;
2725
2726         case BFA_FCPORT_SM_STOP:
2727                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2728                 break;
2729
2730         case BFA_FCPORT_SM_HWFAIL:
2731                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2732                 break;
2733
2734         default:
2735                 bfa_sm_fault(fcport->bfa, event);
2736         }
2737 }
2738
2739 static void
2740 bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
2741                             enum bfa_fcport_sm_event event)
2742 {
2743         bfa_trc(fcport->bfa, event);
2744
2745         switch (event) {
2746         case BFA_FCPORT_SM_DPORTENABLE:
2747         case BFA_FCPORT_SM_ENABLE:
2748         case BFA_FCPORT_SM_START:
2749                 /*
2750                  * Ignore event for a port as there is FAA misconfig
2751                  */
2752                 break;
2753
2754         case BFA_FCPORT_SM_DISABLE:
2755                 if (bfa_fcport_send_disable(fcport))
2756                         bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2757                 else
2758                         bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2759
2760                 bfa_fcport_reset_linkinfo(fcport);
2761                 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2762                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2763                              BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2764                 bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2765                 break;
2766
2767         case BFA_FCPORT_SM_STOP:
2768                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2769                 break;
2770
2771         case BFA_FCPORT_SM_HWFAIL:
2772                 bfa_fcport_reset_linkinfo(fcport);
2773                 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2774                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2775                 break;
2776
2777         default:
2778                 bfa_sm_fault(fcport->bfa, event);
2779         }
2780 }
2781
2782 /*
2783  * Link state is down
2784  */
2785 static void
2786 bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
2787                 enum bfa_fcport_ln_sm_event event)
2788 {
2789         bfa_trc(ln->fcport->bfa, event);
2790
2791         switch (event) {
2792         case BFA_FCPORT_LN_SM_LINKUP:
2793                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2794                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2795                 break;
2796
2797         default:
2798                 bfa_sm_fault(ln->fcport->bfa, event);
2799         }
2800 }
2801
2802 /*
2803  * Link state is waiting for down notification
2804  */
2805 static void
2806 bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
2807                 enum bfa_fcport_ln_sm_event event)
2808 {
2809         bfa_trc(ln->fcport->bfa, event);
2810
2811         switch (event) {
2812         case BFA_FCPORT_LN_SM_LINKUP:
2813                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2814                 break;
2815
2816         case BFA_FCPORT_LN_SM_NOTIFICATION:
2817                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2818                 break;
2819
2820         default:
2821                 bfa_sm_fault(ln->fcport->bfa, event);
2822         }
2823 }
2824
2825 /*
2826  * Link state is waiting for down notification and there is a pending up
2827  */
2828 static void
2829 bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
2830                 enum bfa_fcport_ln_sm_event event)
2831 {
2832         bfa_trc(ln->fcport->bfa, event);
2833
2834         switch (event) {
2835         case BFA_FCPORT_LN_SM_LINKDOWN:
2836                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2837                 break;
2838
2839         case BFA_FCPORT_LN_SM_NOTIFICATION:
2840                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2841                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2842                 break;
2843
2844         default:
2845                 bfa_sm_fault(ln->fcport->bfa, event);
2846         }
2847 }
2848
2849 /*
2850  * Link state is up
2851  */
2852 static void
2853 bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
2854                 enum bfa_fcport_ln_sm_event event)
2855 {
2856         bfa_trc(ln->fcport->bfa, event);
2857
2858         switch (event) {
2859         case BFA_FCPORT_LN_SM_LINKDOWN:
2860                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2861                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2862                 break;
2863
2864         default:
2865                 bfa_sm_fault(ln->fcport->bfa, event);
2866         }
2867 }
2868
2869 /*
2870  * Link state is waiting for up notification
2871  */
2872 static void
2873 bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
2874                 enum bfa_fcport_ln_sm_event event)
2875 {
2876         bfa_trc(ln->fcport->bfa, event);
2877
2878         switch (event) {
2879         case BFA_FCPORT_LN_SM_LINKDOWN:
2880                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2881                 break;
2882
2883         case BFA_FCPORT_LN_SM_NOTIFICATION:
2884                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
2885                 break;
2886
2887         default:
2888                 bfa_sm_fault(ln->fcport->bfa, event);
2889         }
2890 }
2891
2892 /*
2893  * Link state is waiting for up notification and there is a pending down
2894  */
2895 static void
2896 bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
2897                 enum bfa_fcport_ln_sm_event event)
2898 {
2899         bfa_trc(ln->fcport->bfa, event);
2900
2901         switch (event) {
2902         case BFA_FCPORT_LN_SM_LINKUP:
2903                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
2904                 break;
2905
2906         case BFA_FCPORT_LN_SM_NOTIFICATION:
2907                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2908                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2909                 break;
2910
2911         default:
2912                 bfa_sm_fault(ln->fcport->bfa, event);
2913         }
2914 }
2915
2916 /*
2917  * Link state is waiting for up notification and there are pending down and up
2918  */
2919 static void
2920 bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
2921                         enum bfa_fcport_ln_sm_event event)
2922 {
2923         bfa_trc(ln->fcport->bfa, event);
2924
2925         switch (event) {
2926         case BFA_FCPORT_LN_SM_LINKDOWN:
2927                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2928                 break;
2929
2930         case BFA_FCPORT_LN_SM_NOTIFICATION:
2931                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2932                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2933                 break;
2934
2935         default:
2936                 bfa_sm_fault(ln->fcport->bfa, event);
2937         }
2938 }
2939
2940 static void
2941 __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
2942 {
2943         struct bfa_fcport_ln_s *ln = cbarg;
2944
2945         if (complete)
2946                 ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
2947         else
2948                 bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2949 }
2950
2951 /*
2952  * Send SCN notification to upper layers.
2953  * trunk - false if caller is fcport to ignore fcport event in trunked mode
2954  */
2955 static void
2956 bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
2957         bfa_boolean_t trunk)
2958 {
2959         if (fcport->cfg.trunked && !trunk)
2960                 return;
2961
2962         switch (event) {
2963         case BFA_PORT_LINKUP:
2964                 bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
2965                 break;
2966         case BFA_PORT_LINKDOWN:
2967                 bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
2968                 break;
2969         default:
2970                 WARN_ON(1);
2971         }
2972 }
2973
2974 static void
2975 bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
2976 {
2977         struct bfa_fcport_s *fcport = ln->fcport;
2978
2979         if (fcport->bfa->fcs) {
2980                 fcport->event_cbfn(fcport->event_cbarg, event);
2981                 bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2982         } else {
2983                 ln->ln_event = event;
2984                 bfa_cb_queue(fcport->bfa, &ln->ln_qe,
2985                         __bfa_cb_fcport_event, ln);
2986         }
2987 }
2988
2989 #define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
2990                                                         BFA_CACHELINE_SZ))
2991
2992 void
2993 bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
2994                    struct bfa_s *bfa)
2995 {
2996         struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);
2997
2998         bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);
2999 }
3000
3001 static void
3002 bfa_fcport_qresume(void *cbarg)
3003 {
3004         struct bfa_fcport_s *fcport = cbarg;
3005
3006         bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
3007 }
3008
3009 static void
3010 bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
3011 {
3012         struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;
3013
3014         fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);
3015         fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma);
3016         fcport->stats = (union bfa_fcport_stats_u *)
3017                                 bfa_mem_dma_virt(fcport_dma);
3018 }
3019
3020 /*
3021  * Memory initialization.
3022  */
3023 void
3024 bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
3025                 struct bfa_pcidev_s *pcidev)
3026 {
3027         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3028         struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
3029         struct bfa_fcport_ln_s *ln = &fcport->ln;
3030
3031         fcport->bfa = bfa;
3032         ln->fcport = fcport;
3033
3034         bfa_fcport_mem_claim(fcport);
3035
3036         bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
3037         bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
3038
3039         /*
3040          * initialize time stamp for stats reset
3041          */
3042         fcport->stats_reset_time = ktime_get_seconds();
3043         fcport->stats_dma_ready = BFA_FALSE;
3044
3045         /*
3046          * initialize and set default configuration
3047          */
3048         port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
3049         port_cfg->speed = BFA_PORT_SPEED_AUTO;
3050         port_cfg->trunked = BFA_FALSE;
3051         port_cfg->maxfrsize = 0;
3052
3053         port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
3054         port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;
3055         port_cfg->qos_bw.med = BFA_QOS_BW_MED;
3056         port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
3057
3058         fcport->fec_state = BFA_FEC_OFFLINE;
3059
3060         INIT_LIST_HEAD(&fcport->stats_pending_q);
3061         INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3062
3063         bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
3064 }
3065
3066 void
3067 bfa_fcport_start(struct bfa_s *bfa)
3068 {
3069         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
3070 }
3071
3072 /*
3073  * Called when IOC failure is detected.
3074  */
3075 void
3076 bfa_fcport_iocdisable(struct bfa_s *bfa)
3077 {
3078         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3079
3080         bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
3081         bfa_trunk_iocdisable(bfa);
3082 }
3083
3084 /*
3085  * Update loop info in fcport for SCN online
3086  */
3087 static void
3088 bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
3089                         struct bfa_fcport_loop_info_s *loop_info)
3090 {
3091         fcport->myalpa = loop_info->myalpa;
3092         fcport->alpabm_valid =
3093                         loop_info->alpabm_val;
3094         memcpy(fcport->alpabm.alpa_bm,
3095                         loop_info->alpabm.alpa_bm,
3096                         sizeof(struct fc_alpabm_s));
3097 }
3098
3099 static void
3100 bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
3101 {
3102         struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
3103         struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3104
3105         fcport->speed = pevent->link_state.speed;
3106         fcport->topology = pevent->link_state.topology;
3107
3108         if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
3109                 bfa_fcport_update_loop_info(fcport,
3110                                 &pevent->link_state.attr.loop_info);
3111                 return;
3112         }
3113
3114         /* QoS Details */
3115         fcport->qos_attr = pevent->link_state.qos_attr;
3116         fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
3117
3118         if (fcport->cfg.bb_cr_enabled)
3119                 fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;
3120
3121         fcport->fec_state = pevent->link_state.fec_state;
3122
3123         /*
3124          * update trunk state if applicable
3125          */
3126         if (!fcport->cfg.trunked)
3127                 trunk->attr.state = BFA_TRUNK_DISABLED;
3128
3129         /* update FCoE specific */
3130         fcport->fcoe_vlan =
3131                 be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
3132
3133         bfa_trc(fcport->bfa, fcport->speed);
3134         bfa_trc(fcport->bfa, fcport->topology);
3135 }
3136
3137 static void
3138 bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
3139 {
3140         fcport->speed = BFA_PORT_SPEED_UNKNOWN;
3141         fcport->topology = BFA_PORT_TOPOLOGY_NONE;
3142         fcport->fec_state = BFA_FEC_OFFLINE;
3143 }
3144
3145 /*
3146  * Send port enable message to firmware.
3147  */
3148 static bfa_boolean_t
3149 bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
3150 {
3151         struct bfi_fcport_enable_req_s *m;
3152
3153         /*
3154          * Increment message tag before queue check, so that responses to old
3155          * requests are discarded.
3156          */
3157         fcport->msgtag++;
3158
3159         /*
3160          * check for room in queue to send request now
3161          */
3162         m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3163         if (!m) {
3164                 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3165                                                         &fcport->reqq_wait);
3166                 return BFA_FALSE;
3167         }
3168
3169         bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
3170                         bfa_fn_lpu(fcport->bfa));
3171         m->nwwn = fcport->nwwn;
3172         m->pwwn = fcport->pwwn;
3173         m->port_cfg = fcport->cfg;
3174         m->msgtag = fcport->msgtag;
3175         m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
3176          m->use_flash_cfg = fcport->use_flash_cfg;
3177         bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
3178         bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
3179         bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
3180
3181         /*
3182          * queue I/O message to firmware
3183          */
3184         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3185         return BFA_TRUE;
3186 }
3187
3188 /*
3189  * Send port disable message to firmware.
3190  */
3191 static  bfa_boolean_t
3192 bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
3193 {
3194         struct bfi_fcport_req_s *m;
3195
3196         /*
3197          * Increment message tag before queue check, so that responses to old
3198          * requests are discarded.
3199          */
3200         fcport->msgtag++;
3201
3202         /*
3203          * check for room in queue to send request now
3204          */
3205         m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3206         if (!m) {
3207                 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3208                                                         &fcport->reqq_wait);
3209                 return BFA_FALSE;
3210         }
3211
3212         bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
3213                         bfa_fn_lpu(fcport->bfa));
3214         m->msgtag = fcport->msgtag;
3215
3216         /*
3217          * queue I/O message to firmware
3218          */
3219         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3220
3221         return BFA_TRUE;
3222 }
3223
3224 static void
3225 bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
3226 {
3227         fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
3228         fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
3229
3230         bfa_trc(fcport->bfa, fcport->pwwn);
3231         bfa_trc(fcport->bfa, fcport->nwwn);
3232 }
3233
3234 static void
3235 bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
3236         struct bfa_qos_stats_s *s)
3237 {
3238         u32     *dip = (u32 *) d;
3239         __be32  *sip = (__be32 *) s;
3240         int             i;
3241
3242         /* Now swap the 32 bit fields */
3243         for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
3244                 dip[i] = be32_to_cpu(sip[i]);
3245 }
3246
3247 static void
3248 bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3249         struct bfa_fcoe_stats_s *s)
3250 {
3251         u32     *dip = (u32 *) d;
3252         __be32  *sip = (__be32 *) s;
3253         int             i;
3254
3255         for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
3256              i = i + 2) {
3257 #ifdef __BIG_ENDIAN
3258                 dip[i] = be32_to_cpu(sip[i]);
3259                 dip[i + 1] = be32_to_cpu(sip[i + 1]);
3260 #else
3261                 dip[i] = be32_to_cpu(sip[i + 1]);
3262                 dip[i + 1] = be32_to_cpu(sip[i]);
3263 #endif
3264         }
3265 }
3266
3267 static void
3268 __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3269 {
3270         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
3271         struct bfa_cb_pending_q_s *cb;
3272         struct list_head *qe, *qen;
3273         union bfa_fcport_stats_u *ret;
3274
3275         if (complete) {
3276                 time64_t time = ktime_get_seconds();
3277
3278                 list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
3279                         bfa_q_deq(&fcport->stats_pending_q, &qe);
3280                         cb = (struct bfa_cb_pending_q_s *)qe;
3281                         if (fcport->stats_status == BFA_STATUS_OK) {
3282                                 ret = (union bfa_fcport_stats_u *)cb->data;
3283                                 /* Swap FC QoS or FCoE stats */
3284                                 if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
3285                                         bfa_fcport_qos_stats_swap(&ret->fcqos,
3286                                                         &fcport->stats->fcqos);
3287                                 else {
3288                                         bfa_fcport_fcoe_stats_swap(&ret->fcoe,
3289                                                         &fcport->stats->fcoe);
3290                                         ret->fcoe.secs_reset =
3291                                                 time - fcport->stats_reset_time;
3292                                 }
3293                         }
3294                         bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3295                                         fcport->stats_status);
3296                 }
3297                 fcport->stats_status = BFA_STATUS_OK;
3298         } else {
3299                 INIT_LIST_HEAD(&fcport->stats_pending_q);
3300                 fcport->stats_status = BFA_STATUS_OK;
3301         }
3302 }
3303
3304 static void
3305 bfa_fcport_stats_get_timeout(void *cbarg)
3306 {
3307         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3308
3309         bfa_trc(fcport->bfa, fcport->stats_qfull);
3310
3311         if (fcport->stats_qfull) {
3312                 bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3313                 fcport->stats_qfull = BFA_FALSE;
3314         }
3315
3316         fcport->stats_status = BFA_STATUS_ETIMER;
3317         __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3318 }
3319
3320 static void
3321 bfa_fcport_send_stats_get(void *cbarg)
3322 {
3323         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3324         struct bfi_fcport_req_s *msg;
3325
3326         msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3327
3328         if (!msg) {
3329                 fcport->stats_qfull = BFA_TRUE;
3330                 bfa_reqq_winit(&fcport->stats_reqq_wait,
3331                                 bfa_fcport_send_stats_get, fcport);
3332                 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3333                                 &fcport->stats_reqq_wait);
3334                 return;
3335         }
3336         fcport->stats_qfull = BFA_FALSE;
3337
3338         memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3339         bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
3340                         bfa_fn_lpu(fcport->bfa));
3341         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3342 }
3343
3344 static void
3345 __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3346 {
3347         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3348         struct bfa_cb_pending_q_s *cb;
3349         struct list_head *qe, *qen;
3350
3351         if (complete) {
3352                 /*
3353                  * re-initialize time stamp for stats reset
3354                  */
3355                 fcport->stats_reset_time = ktime_get_seconds();
3356                 list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
3357                         bfa_q_deq(&fcport->statsclr_pending_q, &qe);
3358                         cb = (struct bfa_cb_pending_q_s *)qe;
3359                         bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3360                                                 fcport->stats_status);
3361                 }
3362                 fcport->stats_status = BFA_STATUS_OK;
3363         } else {
3364                 INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3365                 fcport->stats_status = BFA_STATUS_OK;
3366         }
3367 }
3368
3369 static void
3370 bfa_fcport_stats_clr_timeout(void *cbarg)
3371 {
3372         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3373
3374         bfa_trc(fcport->bfa, fcport->stats_qfull);
3375
3376         if (fcport->stats_qfull) {
3377                 bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3378                 fcport->stats_qfull = BFA_FALSE;
3379         }
3380
3381         fcport->stats_status = BFA_STATUS_ETIMER;
3382         __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3383 }
3384
3385 static void
3386 bfa_fcport_send_stats_clear(void *cbarg)
3387 {
3388         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3389         struct bfi_fcport_req_s *msg;
3390
3391         msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3392
3393         if (!msg) {
3394                 fcport->stats_qfull = BFA_TRUE;
3395                 bfa_reqq_winit(&fcport->stats_reqq_wait,
3396                                 bfa_fcport_send_stats_clear, fcport);
3397                 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3398                                                 &fcport->stats_reqq_wait);
3399                 return;
3400         }
3401         fcport->stats_qfull = BFA_FALSE;
3402
3403         memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3404         bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
3405                         bfa_fn_lpu(fcport->bfa));
3406         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3407 }
3408
3409 /*
3410  * Handle trunk SCN event from firmware.
3411  */
3412 static void
3413 bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
3414 {
3415         struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3416         struct bfi_fcport_trunk_link_s *tlink;
3417         struct bfa_trunk_link_attr_s *lattr;
3418         enum bfa_trunk_state state_prev;
3419         int i;
3420         int link_bm = 0;
3421
3422         bfa_trc(fcport->bfa, fcport->cfg.trunked);
3423         WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
3424                    scn->trunk_state != BFA_TRUNK_OFFLINE);
3425
3426         bfa_trc(fcport->bfa, trunk->attr.state);
3427         bfa_trc(fcport->bfa, scn->trunk_state);
3428         bfa_trc(fcport->bfa, scn->trunk_speed);
3429
3430         /*
3431          * Save off new state for trunk attribute query
3432          */
3433         state_prev = trunk->attr.state;
3434         if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
3435                 trunk->attr.state = scn->trunk_state;
3436         trunk->attr.speed = scn->trunk_speed;
3437         for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3438                 lattr = &trunk->attr.link_attr[i];
3439                 tlink = &scn->tlink[i];
3440
3441                 lattr->link_state = tlink->state;
3442                 lattr->trunk_wwn  = tlink->trunk_wwn;
3443                 lattr->fctl       = tlink->fctl;
3444                 lattr->speed      = tlink->speed;
3445                 lattr->deskew     = be32_to_cpu(tlink->deskew);
3446
3447                 if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
3448                         fcport->speed    = tlink->speed;
3449                         fcport->topology = BFA_PORT_TOPOLOGY_P2P;
3450                         link_bm |= 1 << i;
3451                 }
3452
3453                 bfa_trc(fcport->bfa, lattr->link_state);
3454                 bfa_trc(fcport->bfa, lattr->trunk_wwn);
3455                 bfa_trc(fcport->bfa, lattr->fctl);
3456                 bfa_trc(fcport->bfa, lattr->speed);
3457                 bfa_trc(fcport->bfa, lattr->deskew);
3458         }
3459
3460         switch (link_bm) {
3461         case 3:
3462                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3463                         BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
3464                 break;
3465         case 2:
3466                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3467                         BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
3468                 break;
3469         case 1:
3470                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3471                         BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
3472                 break;
3473         default:
3474                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3475                         BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
3476         }
3477
3478         /*
3479          * Notify upper layers if trunk state changed.
3480          */
3481         if ((state_prev != trunk->attr.state) ||
3482                 (scn->trunk_state == BFA_TRUNK_OFFLINE)) {
3483                 bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
3484                         BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
3485         }
3486 }
3487
3488 static void
3489 bfa_trunk_iocdisable(struct bfa_s *bfa)
3490 {
3491         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3492         int i = 0;
3493
3494         /*
3495          * In trunked mode, notify upper layers that link is down
3496          */
3497         if (fcport->cfg.trunked) {
3498                 if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
3499                         bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
3500
3501                 fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
3502                 fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
3503                 for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3504                         fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
3505                         fcport->trunk.attr.link_attr[i].fctl =
3506                                                 BFA_TRUNK_LINK_FCTL_NORMAL;
3507                         fcport->trunk.attr.link_attr[i].link_state =
3508                                                 BFA_TRUNK_LINK_STATE_DN_LINKDN;
3509                         fcport->trunk.attr.link_attr[i].speed =
3510                                                 BFA_PORT_SPEED_UNKNOWN;
3511                         fcport->trunk.attr.link_attr[i].deskew = 0;
3512                 }
3513         }
3514 }
3515
3516 /*
3517  * Called to initialize port attributes
3518  */
3519 void
3520 bfa_fcport_init(struct bfa_s *bfa)
3521 {
3522         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3523
3524         /*
3525          * Initialize port attributes from IOC hardware data.
3526          */
3527         bfa_fcport_set_wwns(fcport);
3528         if (fcport->cfg.maxfrsize == 0)
3529                 fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
3530         fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
3531         fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
3532
3533         if (bfa_fcport_is_pbcdisabled(bfa))
3534                 bfa->modules.port.pbc_disabled = BFA_TRUE;
3535
3536         WARN_ON(!fcport->cfg.maxfrsize);
3537         WARN_ON(!fcport->cfg.rx_bbcredit);
3538         WARN_ON(!fcport->speed_sup);
3539 }
3540
3541 /*
3542  * Firmware message handler.
3543  */
3544 void
3545 bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3546 {
3547         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3548         union bfi_fcport_i2h_msg_u i2hmsg;
3549
3550         i2hmsg.msg = msg;
3551         fcport->event_arg.i2hmsg = i2hmsg;
3552
3553         bfa_trc(bfa, msg->mhdr.msg_id);
3554         bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
3555
3556         switch (msg->mhdr.msg_id) {
3557         case BFI_FCPORT_I2H_ENABLE_RSP:
3558                 if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
3559
3560                         fcport->stats_dma_ready = BFA_TRUE;
3561                         if (fcport->use_flash_cfg) {
3562                                 fcport->cfg = i2hmsg.penable_rsp->port_cfg;
3563                                 fcport->cfg.maxfrsize =
3564                                         cpu_to_be16(fcport->cfg.maxfrsize);
3565                                 fcport->cfg.path_tov =
3566                                         cpu_to_be16(fcport->cfg.path_tov);
3567                                 fcport->cfg.q_depth =
3568                                         cpu_to_be16(fcport->cfg.q_depth);
3569
3570                                 if (fcport->cfg.trunked)
3571                                         fcport->trunk.attr.state =
3572                                                 BFA_TRUNK_OFFLINE;
3573                                 else
3574                                         fcport->trunk.attr.state =
3575                                                 BFA_TRUNK_DISABLED;
3576                                 fcport->qos_attr.qos_bw =
3577                                         i2hmsg.penable_rsp->port_cfg.qos_bw;
3578                                 fcport->use_flash_cfg = BFA_FALSE;
3579                         }
3580
3581                         if (fcport->cfg.qos_enabled)
3582                                 fcport->qos_attr.state = BFA_QOS_OFFLINE;
3583                         else
3584                                 fcport->qos_attr.state = BFA_QOS_DISABLED;
3585
3586                         fcport->qos_attr.qos_bw_op =
3587                                         i2hmsg.penable_rsp->port_cfg.qos_bw;
3588
3589                         if (fcport->cfg.bb_cr_enabled)
3590                                 fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3591                         else
3592                                 fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3593
3594                         bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3595                 }
3596                 break;
3597
3598         case BFI_FCPORT_I2H_DISABLE_RSP:
3599                 if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
3600                         bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3601                 break;
3602
3603         case BFI_FCPORT_I2H_EVENT:
3604                 if (fcport->cfg.bb_cr_enabled)
3605                         fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3606                 else
3607                         fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3608
3609                 if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
3610                         bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
3611                 else {
3612                         if (i2hmsg.event->link_state.linkstate_rsn ==
3613                             BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)
3614                                 bfa_sm_send_event(fcport,
3615                                                   BFA_FCPORT_SM_FAA_MISCONFIG);
3616                         else
3617                                 bfa_sm_send_event(fcport,
3618                                                   BFA_FCPORT_SM_LINKDOWN);
3619                 }
3620                 fcport->qos_attr.qos_bw_op =
3621                                 i2hmsg.event->link_state.qos_attr.qos_bw_op;
3622                 break;
3623
3624         case BFI_FCPORT_I2H_TRUNK_SCN:
3625                 bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
3626                 break;
3627
3628         case BFI_FCPORT_I2H_STATS_GET_RSP:
3629                 /*
3630                  * check for timer pop before processing the rsp
3631                  */
3632                 if (list_empty(&fcport->stats_pending_q) ||
3633                     (fcport->stats_status == BFA_STATUS_ETIMER))
3634                         break;
3635
3636                 bfa_timer_stop(&fcport->timer);
3637                 fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3638                 __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3639                 break;
3640
3641         case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3642                 /*
3643                  * check for timer pop before processing the rsp
3644                  */
3645                 if (list_empty(&fcport->statsclr_pending_q) ||
3646                     (fcport->stats_status == BFA_STATUS_ETIMER))
3647                         break;
3648
3649                 bfa_timer_stop(&fcport->timer);
3650                 fcport->stats_status = BFA_STATUS_OK;
3651                 __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3652                 break;
3653
3654         case BFI_FCPORT_I2H_ENABLE_AEN:
3655                 bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
3656                 break;
3657
3658         case BFI_FCPORT_I2H_DISABLE_AEN:
3659                 bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
3660                 break;
3661
3662         default:
3663                 WARN_ON(1);
3664         break;
3665         }
3666 }
3667
3668 /*
3669  * Registered callback for port events.
3670  */
3671 void
3672 bfa_fcport_event_register(struct bfa_s *bfa,
3673                                 void (*cbfn) (void *cbarg,
3674                                 enum bfa_port_linkstate event),
3675                                 void *cbarg)
3676 {
3677         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3678
3679         fcport->event_cbfn = cbfn;
3680         fcport->event_cbarg = cbarg;
3681 }
3682
3683 bfa_status_t
3684 bfa_fcport_enable(struct bfa_s *bfa)
3685 {
3686         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3687
3688         if (bfa_fcport_is_pbcdisabled(bfa))
3689                 return BFA_STATUS_PBC;
3690
3691         if (bfa_ioc_is_disabled(&bfa->ioc))
3692                 return BFA_STATUS_IOC_DISABLED;
3693
3694         if (fcport->diag_busy)
3695                 return BFA_STATUS_DIAG_BUSY;
3696
3697         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
3698         return BFA_STATUS_OK;
3699 }
3700
3701 bfa_status_t
3702 bfa_fcport_disable(struct bfa_s *bfa)
3703 {
3704         if (bfa_fcport_is_pbcdisabled(bfa))
3705                 return BFA_STATUS_PBC;
3706
3707         if (bfa_ioc_is_disabled(&bfa->ioc))
3708                 return BFA_STATUS_IOC_DISABLED;
3709
3710         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
3711         return BFA_STATUS_OK;
3712 }
3713
3714 /* If PBC is disabled on port, return error */
3715 bfa_status_t
3716 bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
3717 {
3718         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3719         struct bfa_iocfc_s *iocfc = &bfa->iocfc;
3720         struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
3721
3722         if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
3723                 bfa_trc(bfa, fcport->pwwn);
3724                 return BFA_STATUS_PBC;
3725         }
3726         return BFA_STATUS_OK;
3727 }
3728
3729 /*
3730  * Configure port speed.
3731  */
3732 bfa_status_t
3733 bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
3734 {
3735         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3736
3737         bfa_trc(bfa, speed);
3738
3739         if (fcport->cfg.trunked == BFA_TRUE)
3740                 return BFA_STATUS_TRUNK_ENABLED;
3741         if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
3742                         (speed == BFA_PORT_SPEED_16GBPS))
3743                 return BFA_STATUS_UNSUPP_SPEED;
3744         if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
3745                 bfa_trc(bfa, fcport->speed_sup);
3746                 return BFA_STATUS_UNSUPP_SPEED;
3747         }
3748
3749         /* Port speed entered needs to be checked */
3750         if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
3751                 /* For CT2, 1G is not supported */
3752                 if ((speed == BFA_PORT_SPEED_1GBPS) &&
3753                     (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
3754                         return BFA_STATUS_UNSUPP_SPEED;
3755
3756                 /* Already checked for Auto Speed and Max Speed supp */
3757                 if (!(speed == BFA_PORT_SPEED_1GBPS ||
3758                       speed == BFA_PORT_SPEED_2GBPS ||
3759                       speed == BFA_PORT_SPEED_4GBPS ||
3760                       speed == BFA_PORT_SPEED_8GBPS ||
3761                       speed == BFA_PORT_SPEED_16GBPS ||
3762                       speed == BFA_PORT_SPEED_AUTO))
3763                         return BFA_STATUS_UNSUPP_SPEED;
3764         } else {
3765                 if (speed != BFA_PORT_SPEED_10GBPS)
3766                         return BFA_STATUS_UNSUPP_SPEED;
3767         }
3768
3769         fcport->cfg.speed = speed;
3770
3771         return BFA_STATUS_OK;
3772 }
3773
3774 /*
3775  * Get current speed.
3776  */
3777 enum bfa_port_speed
3778 bfa_fcport_get_speed(struct bfa_s *bfa)
3779 {
3780         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3781
3782         return fcport->speed;
3783 }
3784
3785 /*
3786  * Configure port topology.
3787  */
3788 bfa_status_t
3789 bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
3790 {
3791         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3792
3793         bfa_trc(bfa, topology);
3794         bfa_trc(bfa, fcport->cfg.topology);
3795
3796         switch (topology) {
3797         case BFA_PORT_TOPOLOGY_P2P:
3798                 break;
3799
3800         case BFA_PORT_TOPOLOGY_LOOP:
3801                 if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
3802                         (fcport->qos_attr.state != BFA_QOS_DISABLED))
3803                         return BFA_STATUS_ERROR_QOS_ENABLED;
3804                 if (fcport->cfg.ratelimit != BFA_FALSE)
3805                         return BFA_STATUS_ERROR_TRL_ENABLED;
3806                 if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
3807                         (fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
3808                         return BFA_STATUS_ERROR_TRUNK_ENABLED;
3809                 if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
3810                         (fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
3811                         return BFA_STATUS_UNSUPP_SPEED;
3812                 if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
3813                         return BFA_STATUS_LOOP_UNSUPP_MEZZ;
3814                 if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
3815                         return BFA_STATUS_DPORT_ERR;
3816                 if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
3817                         return BFA_STATUS_DPORT_ERR;
3818                 break;
3819
3820         case BFA_PORT_TOPOLOGY_AUTO:
3821                 break;
3822
3823         default:
3824                 return BFA_STATUS_EINVAL;
3825         }
3826
3827         fcport->cfg.topology = topology;
3828         return BFA_STATUS_OK;
3829 }
3830
3831 /*
3832  * Get current topology.
3833  */
3834 enum bfa_port_topology
3835 bfa_fcport_get_topology(struct bfa_s *bfa)
3836 {
3837         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3838
3839         return fcport->topology;
3840 }
3841
3842 /*
3843  * Get config topology.
3844  */
3845 enum bfa_port_topology
3846 bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
3847 {
3848         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3849
3850         return fcport->cfg.topology;
3851 }
3852
3853 bfa_status_t
3854 bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
3855 {
3856         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3857
3858         bfa_trc(bfa, alpa);
3859         bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3860         bfa_trc(bfa, fcport->cfg.hardalpa);
3861
3862         fcport->cfg.cfg_hardalpa = BFA_TRUE;
3863         fcport->cfg.hardalpa = alpa;
3864
3865         return BFA_STATUS_OK;
3866 }
3867
3868 bfa_status_t
3869 bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
3870 {
3871         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3872
3873         bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3874         bfa_trc(bfa, fcport->cfg.hardalpa);
3875
3876         fcport->cfg.cfg_hardalpa = BFA_FALSE;
3877         return BFA_STATUS_OK;
3878 }
3879
3880 bfa_boolean_t
3881 bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
3882 {
3883         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3884
3885         *alpa = fcport->cfg.hardalpa;
3886         return fcport->cfg.cfg_hardalpa;
3887 }
3888
3889 u8
3890 bfa_fcport_get_myalpa(struct bfa_s *bfa)
3891 {
3892         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3893
3894         return fcport->myalpa;
3895 }
3896
3897 bfa_status_t
3898 bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
3899 {
3900         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3901
3902         bfa_trc(bfa, maxfrsize);
3903         bfa_trc(bfa, fcport->cfg.maxfrsize);
3904
3905         /* with in range */
3906         if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
3907                 return BFA_STATUS_INVLD_DFSZ;
3908
3909         /* power of 2, if not the max frame size of 2112 */
3910         if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
3911                 return BFA_STATUS_INVLD_DFSZ;
3912
3913         fcport->cfg.maxfrsize = maxfrsize;
3914         return BFA_STATUS_OK;
3915 }
3916
3917 u16
3918 bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
3919 {
3920         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3921
3922         return fcport->cfg.maxfrsize;
3923 }
3924
3925 u8
3926 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3927 {
3928         if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
3929                 return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
3930
3931         else
3932                 return 0;
3933 }
3934
3935 void
3936 bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
3937 {
3938         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3939
3940         fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
3941 }
3942
3943 /*
3944  * Get port attributes.
3945  */
3946
3947 wwn_t
3948 bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
3949 {
3950         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3951         if (node)
3952                 return fcport->nwwn;
3953         else
3954                 return fcport->pwwn;
3955 }
3956
3957 void
3958 bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3959 {
3960         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3961
3962         memset(attr, 0, sizeof(struct bfa_port_attr_s));
3963
3964         attr->nwwn = fcport->nwwn;
3965         attr->pwwn = fcport->pwwn;
3966
3967         attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;
3968         attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;
3969
3970         memcpy(&attr->pport_cfg, &fcport->cfg,
3971                 sizeof(struct bfa_port_cfg_s));
3972         /* speed attributes */
3973         attr->pport_cfg.speed = fcport->cfg.speed;
3974         attr->speed_supported = fcport->speed_sup;
3975         attr->speed = fcport->speed;
3976         attr->cos_supported = FC_CLASS_3;
3977
3978         /* topology attributes */
3979         attr->pport_cfg.topology = fcport->cfg.topology;
3980         attr->topology = fcport->topology;
3981         attr->pport_cfg.trunked = fcport->cfg.trunked;
3982
3983         /* beacon attributes */
3984         attr->beacon = fcport->beacon;
3985         attr->link_e2e_beacon = fcport->link_e2e_beacon;
3986
3987         attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
3988         attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
3989         attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
3990
3991         attr->fec_state = fcport->fec_state;
3992
3993         /* PBC Disabled State */
3994         if (bfa_fcport_is_pbcdisabled(bfa))
3995                 attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
3996         else {
3997                 if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
3998                         attr->port_state = BFA_PORT_ST_IOCDIS;
3999                 else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
4000                         attr->port_state = BFA_PORT_ST_FWMISMATCH;
4001         }
4002
4003         /* FCoE vlan */
4004         attr->fcoe_vlan = fcport->fcoe_vlan;
4005 }
4006
4007 #define BFA_FCPORT_STATS_TOV    1000
4008
4009 /*
4010  * Fetch port statistics (FCQoS or FCoE).
4011  */
4012 bfa_status_t
4013 bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4014 {
4015         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4016
4017         if (!bfa_iocfc_is_operational(bfa) ||
4018             !fcport->stats_dma_ready)
4019                 return BFA_STATUS_IOC_NON_OP;
4020
4021         if (!list_empty(&fcport->statsclr_pending_q))
4022                 return BFA_STATUS_DEVBUSY;
4023
4024         if (list_empty(&fcport->stats_pending_q)) {
4025                 list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4026                 bfa_fcport_send_stats_get(fcport);
4027                 bfa_timer_start(bfa, &fcport->timer,
4028                                 bfa_fcport_stats_get_timeout,
4029                                 fcport, BFA_FCPORT_STATS_TOV);
4030         } else
4031                 list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4032
4033         return BFA_STATUS_OK;
4034 }
4035
4036 /*
4037  * Reset port statistics (FCQoS or FCoE).
4038  */
4039 bfa_status_t
4040 bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4041 {
4042         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4043
4044         if (!bfa_iocfc_is_operational(bfa) ||
4045             !fcport->stats_dma_ready)
4046                 return BFA_STATUS_IOC_NON_OP;
4047
4048         if (!list_empty(&fcport->stats_pending_q))
4049                 return BFA_STATUS_DEVBUSY;
4050
4051         if (list_empty(&fcport->statsclr_pending_q)) {
4052                 list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4053                 bfa_fcport_send_stats_clear(fcport);
4054                 bfa_timer_start(bfa, &fcport->timer,
4055                                 bfa_fcport_stats_clr_timeout,
4056                                 fcport, BFA_FCPORT_STATS_TOV);
4057         } else
4058                 list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4059
4060         return BFA_STATUS_OK;
4061 }
4062
4063 /*
4064  * Fetch port attributes.
4065  */
4066 bfa_boolean_t
4067 bfa_fcport_is_disabled(struct bfa_s *bfa)
4068 {
4069         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4070
4071         return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4072                 BFA_PORT_ST_DISABLED;
4073
4074 }
4075
4076 bfa_boolean_t
4077 bfa_fcport_is_dport(struct bfa_s *bfa)
4078 {
4079         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4080
4081         return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4082                 BFA_PORT_ST_DPORT);
4083 }
4084
4085 bfa_boolean_t
4086 bfa_fcport_is_ddport(struct bfa_s *bfa)
4087 {
4088         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4089
4090         return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4091                 BFA_PORT_ST_DDPORT);
4092 }
4093
4094 bfa_status_t
4095 bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
4096 {
4097         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4098         enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
4099
4100         bfa_trc(bfa, ioc_type);
4101
4102         if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))
4103                 return BFA_STATUS_QOS_BW_INVALID;
4104
4105         if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)
4106                 return BFA_STATUS_QOS_BW_INVALID;
4107
4108         if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||
4109             (qos_bw->low > qos_bw->high))
4110                 return BFA_STATUS_QOS_BW_INVALID;
4111
4112         if ((ioc_type == BFA_IOC_TYPE_FC) &&
4113             (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))
4114                 fcport->cfg.qos_bw = *qos_bw;
4115
4116         return BFA_STATUS_OK;
4117 }
4118
4119 bfa_boolean_t
4120 bfa_fcport_is_ratelim(struct bfa_s *bfa)
4121 {
4122         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4123
4124         return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
4125
4126 }
4127
4128 /*
4129  *      Enable/Disable FAA feature in port config
4130  */
4131 void
4132 bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)
4133 {
4134         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4135
4136         bfa_trc(bfa, state);
4137         fcport->cfg.faa_state = state;
4138 }
4139
4140 /*
4141  * Get default minimum ratelim speed
4142  */
4143 enum bfa_port_speed
4144 bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
4145 {
4146         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4147
4148         bfa_trc(bfa, fcport->cfg.trl_def_speed);
4149         return fcport->cfg.trl_def_speed;
4150
4151 }
4152
4153 void
4154 bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
4155                   bfa_boolean_t link_e2e_beacon)
4156 {
4157         struct bfa_s *bfa = dev;
4158         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4159
4160         bfa_trc(bfa, beacon);
4161         bfa_trc(bfa, link_e2e_beacon);
4162         bfa_trc(bfa, fcport->beacon);
4163         bfa_trc(bfa, fcport->link_e2e_beacon);
4164
4165         fcport->beacon = beacon;
4166         fcport->link_e2e_beacon = link_e2e_beacon;
4167 }
4168
4169 bfa_boolean_t
4170 bfa_fcport_is_linkup(struct bfa_s *bfa)
4171 {
4172         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4173
4174         return  (!fcport->cfg.trunked &&
4175                  bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
4176                 (fcport->cfg.trunked &&
4177                  fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
4178 }
4179
4180 bfa_boolean_t
4181 bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
4182 {
4183         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4184
4185         return fcport->cfg.qos_enabled;
4186 }
4187
4188 bfa_boolean_t
4189 bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
4190 {
4191         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4192
4193         return fcport->cfg.trunked;
4194 }
4195
4196 bfa_status_t
4197 bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)
4198 {
4199         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4200
4201         bfa_trc(bfa, on_off);
4202
4203         if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4204                 return BFA_STATUS_BBCR_FC_ONLY;
4205
4206         if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&
4207                 (bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))
4208                 return BFA_STATUS_CMD_NOTSUPP_MEZZ;
4209
4210         if (on_off) {
4211                 if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4212                         return BFA_STATUS_TOPOLOGY_LOOP;
4213
4214                 if (fcport->cfg.qos_enabled)
4215                         return BFA_STATUS_ERROR_QOS_ENABLED;
4216
4217                 if (fcport->cfg.trunked)
4218                         return BFA_STATUS_TRUNK_ENABLED;
4219
4220                 if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&
4221                         (fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))
4222                         return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;
4223
4224                 if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)
4225                         return BFA_STATUS_FEATURE_NOT_SUPPORTED;
4226
4227                 if (fcport->cfg.bb_cr_enabled) {
4228                         if (bb_scn != fcport->cfg.bb_scn)
4229                                 return BFA_STATUS_BBCR_CFG_NO_CHANGE;
4230                         else
4231                                 return BFA_STATUS_NO_CHANGE;
4232                 }
4233
4234                 if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))
4235                         bb_scn = BFA_BB_SCN_DEF;
4236
4237                 fcport->cfg.bb_cr_enabled = on_off;
4238                 fcport->cfg.bb_scn = bb_scn;
4239         } else {
4240                 if (!fcport->cfg.bb_cr_enabled)
4241                         return BFA_STATUS_NO_CHANGE;
4242
4243                 fcport->cfg.bb_cr_enabled = on_off;
4244                 fcport->cfg.bb_scn = 0;
4245         }
4246
4247         return BFA_STATUS_OK;
4248 }
4249
4250 bfa_status_t
4251 bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
4252                 struct bfa_bbcr_attr_s *bbcr_attr)
4253 {
4254         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4255
4256         if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4257                 return BFA_STATUS_BBCR_FC_ONLY;
4258
4259         if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4260                 return BFA_STATUS_TOPOLOGY_LOOP;
4261
4262         *bbcr_attr = fcport->bbcr_attr;
4263
4264         return BFA_STATUS_OK;
4265 }
4266
4267 void
4268 bfa_fcport_dportenable(struct bfa_s *bfa)
4269 {
4270         /*
4271          * Assume caller check for port is in disable state
4272          */
4273         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
4274         bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
4275 }
4276
4277 void
4278 bfa_fcport_dportdisable(struct bfa_s *bfa)
4279 {
4280         /*
4281          * Assume caller check for port is in disable state
4282          */
4283         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
4284         bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
4285 }
4286
4287 static void
4288 bfa_fcport_ddportenable(struct bfa_s *bfa)
4289 {
4290         /*
4291          * Assume caller check for port is in disable state
4292          */
4293         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
4294 }
4295
4296 static void
4297 bfa_fcport_ddportdisable(struct bfa_s *bfa)
4298 {
4299         /*
4300          * Assume caller check for port is in disable state
4301          */
4302         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
4303 }
4304
4305 /*
4306  * Rport State machine functions
4307  */
4308 /*
4309  * Beginning state, only online event expected.
4310  */
4311 static void
4312 bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
4313 {
4314         bfa_trc(rp->bfa, rp->rport_tag);
4315         bfa_trc(rp->bfa, event);
4316
4317         switch (event) {
4318         case BFA_RPORT_SM_CREATE:
4319                 bfa_stats(rp, sm_un_cr);
4320                 bfa_sm_set_state(rp, bfa_rport_sm_created);
4321                 break;
4322
4323         default:
4324                 bfa_stats(rp, sm_un_unexp);
4325                 bfa_sm_fault(rp->bfa, event);
4326         }
4327 }
4328
4329 static void
4330 bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
4331 {
4332         bfa_trc(rp->bfa, rp->rport_tag);
4333         bfa_trc(rp->bfa, event);
4334
4335         switch (event) {
4336         case BFA_RPORT_SM_ONLINE:
4337                 bfa_stats(rp, sm_cr_on);
4338                 if (bfa_rport_send_fwcreate(rp))
4339                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4340                 else
4341                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4342                 break;
4343
4344         case BFA_RPORT_SM_DELETE:
4345                 bfa_stats(rp, sm_cr_del);
4346                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4347                 bfa_rport_free(rp);
4348                 break;
4349
4350         case BFA_RPORT_SM_HWFAIL:
4351                 bfa_stats(rp, sm_cr_hwf);
4352                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4353                 break;
4354
4355         default:
4356                 bfa_stats(rp, sm_cr_unexp);
4357                 bfa_sm_fault(rp->bfa, event);
4358         }
4359 }
4360
4361 /*
4362  * Waiting for rport create response from firmware.
4363  */
4364 static void
4365 bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
4366 {
4367         bfa_trc(rp->bfa, rp->rport_tag);
4368         bfa_trc(rp->bfa, event);
4369
4370         switch (event) {
4371         case BFA_RPORT_SM_FWRSP:
4372                 bfa_stats(rp, sm_fwc_rsp);
4373                 bfa_sm_set_state(rp, bfa_rport_sm_online);
4374                 bfa_rport_online_cb(rp);
4375                 break;
4376
4377         case BFA_RPORT_SM_DELETE:
4378                 bfa_stats(rp, sm_fwc_del);
4379                 bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4380                 break;
4381
4382         case BFA_RPORT_SM_OFFLINE:
4383                 bfa_stats(rp, sm_fwc_off);
4384                 bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
4385                 break;
4386
4387         case BFA_RPORT_SM_HWFAIL:
4388                 bfa_stats(rp, sm_fwc_hwf);
4389                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4390                 break;
4391
4392         default:
4393                 bfa_stats(rp, sm_fwc_unexp);
4394                 bfa_sm_fault(rp->bfa, event);
4395         }
4396 }
4397
4398 /*
4399  * Request queue is full, awaiting queue resume to send create request.
4400  */
4401 static void
4402 bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4403 {
4404         bfa_trc(rp->bfa, rp->rport_tag);
4405         bfa_trc(rp->bfa, event);
4406
4407         switch (event) {
4408         case BFA_RPORT_SM_QRESUME:
4409                 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4410                 bfa_rport_send_fwcreate(rp);
4411                 break;
4412
4413         case BFA_RPORT_SM_DELETE:
4414                 bfa_stats(rp, sm_fwc_del);
4415                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4416                 bfa_reqq_wcancel(&rp->reqq_wait);
4417                 bfa_rport_free(rp);
4418                 break;
4419
4420         case BFA_RPORT_SM_OFFLINE:
4421                 bfa_stats(rp, sm_fwc_off);
4422                 bfa_sm_set_state(rp, bfa_rport_sm_offline);
4423                 bfa_reqq_wcancel(&rp->reqq_wait);
4424                 bfa_rport_offline_cb(rp);
4425                 break;
4426
4427         case BFA_RPORT_SM_HWFAIL:
4428                 bfa_stats(rp, sm_fwc_hwf);
4429                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4430                 bfa_reqq_wcancel(&rp->reqq_wait);
4431                 break;
4432
4433         default:
4434                 bfa_stats(rp, sm_fwc_unexp);
4435                 bfa_sm_fault(rp->bfa, event);
4436         }
4437 }
4438
4439 /*
4440  * Online state - normal parking state.
4441  */
4442 static void
4443 bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
4444 {
4445         struct bfi_rport_qos_scn_s *qos_scn;
4446
4447         bfa_trc(rp->bfa, rp->rport_tag);
4448         bfa_trc(rp->bfa, event);
4449
4450         switch (event) {
4451         case BFA_RPORT_SM_OFFLINE:
4452                 bfa_stats(rp, sm_on_off);
4453                 if (bfa_rport_send_fwdelete(rp))
4454                         bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4455                 else
4456                         bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4457                 break;
4458
4459         case BFA_RPORT_SM_DELETE:
4460                 bfa_stats(rp, sm_on_del);
4461                 if (bfa_rport_send_fwdelete(rp))
4462                         bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4463                 else
4464                         bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4465                 break;
4466
4467         case BFA_RPORT_SM_HWFAIL:
4468                 bfa_stats(rp, sm_on_hwf);
4469                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4470                 break;
4471
4472         case BFA_RPORT_SM_SET_SPEED:
4473                 bfa_rport_send_fwspeed(rp);
4474                 break;
4475
4476         case BFA_RPORT_SM_QOS_SCN:
4477                 qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
4478                 rp->qos_attr = qos_scn->new_qos_attr;
4479                 bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
4480                 bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
4481                 bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
4482                 bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
4483
4484                 qos_scn->old_qos_attr.qos_flow_id  =
4485                         be32_to_cpu(qos_scn->old_qos_attr.qos_flow_id);
4486                 qos_scn->new_qos_attr.qos_flow_id  =
4487                         be32_to_cpu(qos_scn->new_qos_attr.qos_flow_id);
4488
4489                 if (qos_scn->old_qos_attr.qos_flow_id !=
4490                         qos_scn->new_qos_attr.qos_flow_id)
4491                         bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
4492                                                     qos_scn->old_qos_attr,
4493                                                     qos_scn->new_qos_attr);
4494                 if (qos_scn->old_qos_attr.qos_priority !=
4495                         qos_scn->new_qos_attr.qos_priority)
4496                         bfa_cb_rport_qos_scn_prio(rp->rport_drv,
4497                                                   qos_scn->old_qos_attr,
4498                                                   qos_scn->new_qos_attr);
4499                 break;
4500
4501         default:
4502                 bfa_stats(rp, sm_on_unexp);
4503                 bfa_sm_fault(rp->bfa, event);
4504         }
4505 }
4506
4507 /*
4508  * Firmware rport is being deleted - awaiting f/w response.
4509  */
4510 static void
4511 bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
4512 {
4513         bfa_trc(rp->bfa, rp->rport_tag);
4514         bfa_trc(rp->bfa, event);
4515
4516         switch (event) {
4517         case BFA_RPORT_SM_FWRSP:
4518                 bfa_stats(rp, sm_fwd_rsp);
4519                 bfa_sm_set_state(rp, bfa_rport_sm_offline);
4520                 bfa_rport_offline_cb(rp);
4521                 break;
4522
4523         case BFA_RPORT_SM_DELETE:
4524                 bfa_stats(rp, sm_fwd_del);
4525                 bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4526                 break;
4527
4528         case BFA_RPORT_SM_HWFAIL:
4529                 bfa_stats(rp, sm_fwd_hwf);
4530                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4531                 bfa_rport_offline_cb(rp);
4532                 break;
4533
4534         default:
4535                 bfa_stats(rp, sm_fwd_unexp);
4536                 bfa_sm_fault(rp->bfa, event);
4537         }
4538 }
4539
4540 static void
4541 bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4542 {
4543         bfa_trc(rp->bfa, rp->rport_tag);
4544         bfa_trc(rp->bfa, event);
4545
4546         switch (event) {
4547         case BFA_RPORT_SM_QRESUME:
4548                 bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4549                 bfa_rport_send_fwdelete(rp);
4550                 break;
4551
4552         case BFA_RPORT_SM_DELETE:
4553                 bfa_stats(rp, sm_fwd_del);
4554                 bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4555                 break;
4556
4557         case BFA_RPORT_SM_HWFAIL:
4558                 bfa_stats(rp, sm_fwd_hwf);
4559                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4560                 bfa_reqq_wcancel(&rp->reqq_wait);
4561                 bfa_rport_offline_cb(rp);
4562                 break;
4563
4564         default:
4565                 bfa_stats(rp, sm_fwd_unexp);
4566                 bfa_sm_fault(rp->bfa, event);
4567         }
4568 }
4569
4570 /*
4571  * Offline state.
4572  */
4573 static void
4574 bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
4575 {
4576         bfa_trc(rp->bfa, rp->rport_tag);
4577         bfa_trc(rp->bfa, event);
4578
4579         switch (event) {
4580         case BFA_RPORT_SM_DELETE:
4581                 bfa_stats(rp, sm_off_del);
4582                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4583                 bfa_rport_free(rp);
4584                 break;
4585
4586         case BFA_RPORT_SM_ONLINE:
4587                 bfa_stats(rp, sm_off_on);
4588                 if (bfa_rport_send_fwcreate(rp))
4589                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4590                 else
4591                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4592                 break;
4593
4594         case BFA_RPORT_SM_HWFAIL:
4595                 bfa_stats(rp, sm_off_hwf);
4596                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4597                 break;
4598
4599         case BFA_RPORT_SM_OFFLINE:
4600                 bfa_rport_offline_cb(rp);
4601                 break;
4602
4603         default:
4604                 bfa_stats(rp, sm_off_unexp);
4605                 bfa_sm_fault(rp->bfa, event);
4606         }
4607 }
4608
4609 /*
4610  * Rport is deleted, waiting for firmware response to delete.
4611  */
4612 static void
4613 bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
4614 {
4615         bfa_trc(rp->bfa, rp->rport_tag);
4616         bfa_trc(rp->bfa, event);
4617
4618         switch (event) {
4619         case BFA_RPORT_SM_FWRSP:
4620                 bfa_stats(rp, sm_del_fwrsp);
4621                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4622                 bfa_rport_free(rp);
4623                 break;
4624
4625         case BFA_RPORT_SM_HWFAIL:
4626                 bfa_stats(rp, sm_del_hwf);
4627                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4628                 bfa_rport_free(rp);
4629                 break;
4630
4631         default:
4632                 bfa_sm_fault(rp->bfa, event);
4633         }
4634 }
4635
4636 static void
4637 bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4638 {
4639         bfa_trc(rp->bfa, rp->rport_tag);
4640         bfa_trc(rp->bfa, event);
4641
4642         switch (event) {
4643         case BFA_RPORT_SM_QRESUME:
4644                 bfa_stats(rp, sm_del_fwrsp);
4645                 bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4646                 bfa_rport_send_fwdelete(rp);
4647                 break;
4648
4649         case BFA_RPORT_SM_HWFAIL:
4650                 bfa_stats(rp, sm_del_hwf);
4651                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4652                 bfa_reqq_wcancel(&rp->reqq_wait);
4653                 bfa_rport_free(rp);
4654                 break;
4655
4656         default:
4657                 bfa_sm_fault(rp->bfa, event);
4658         }
4659 }
4660
4661 /*
4662  * Waiting for rport create response from firmware. A delete is pending.
4663  */
4664 static void
4665 bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
4666                                 enum bfa_rport_event event)
4667 {
4668         bfa_trc(rp->bfa, rp->rport_tag);
4669         bfa_trc(rp->bfa, event);
4670
4671         switch (event) {
4672         case BFA_RPORT_SM_FWRSP:
4673                 bfa_stats(rp, sm_delp_fwrsp);
4674                 if (bfa_rport_send_fwdelete(rp))
4675                         bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4676                 else
4677                         bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4678                 break;
4679
4680         case BFA_RPORT_SM_HWFAIL:
4681                 bfa_stats(rp, sm_delp_hwf);
4682                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4683                 bfa_rport_free(rp);
4684                 break;
4685
4686         default:
4687                 bfa_stats(rp, sm_delp_unexp);
4688                 bfa_sm_fault(rp->bfa, event);
4689         }
4690 }
4691
4692 /*
4693  * Waiting for rport create response from firmware. Rport offline is pending.
4694  */
4695 static void
4696 bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
4697                                  enum bfa_rport_event event)
4698 {
4699         bfa_trc(rp->bfa, rp->rport_tag);
4700         bfa_trc(rp->bfa, event);
4701
4702         switch (event) {
4703         case BFA_RPORT_SM_FWRSP:
4704                 bfa_stats(rp, sm_offp_fwrsp);
4705                 if (bfa_rport_send_fwdelete(rp))
4706                         bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4707                 else
4708                         bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4709                 break;
4710
4711         case BFA_RPORT_SM_DELETE:
4712                 bfa_stats(rp, sm_offp_del);
4713                 bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4714                 break;
4715
4716         case BFA_RPORT_SM_HWFAIL:
4717                 bfa_stats(rp, sm_offp_hwf);
4718                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4719                 bfa_rport_offline_cb(rp);
4720                 break;
4721
4722         default:
4723                 bfa_stats(rp, sm_offp_unexp);
4724                 bfa_sm_fault(rp->bfa, event);
4725         }
4726 }
4727
4728 /*
4729  * IOC h/w failed.
4730  */
4731 static void
4732 bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
4733 {
4734         bfa_trc(rp->bfa, rp->rport_tag);
4735         bfa_trc(rp->bfa, event);
4736
4737         switch (event) {
4738         case BFA_RPORT_SM_OFFLINE:
4739                 bfa_stats(rp, sm_iocd_off);
4740                 bfa_rport_offline_cb(rp);
4741                 break;
4742
4743         case BFA_RPORT_SM_DELETE:
4744                 bfa_stats(rp, sm_iocd_del);
4745                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4746                 bfa_rport_free(rp);
4747                 break;
4748
4749         case BFA_RPORT_SM_ONLINE:
4750                 bfa_stats(rp, sm_iocd_on);
4751                 if (bfa_rport_send_fwcreate(rp))
4752                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4753                 else
4754                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4755                 break;
4756
4757         case BFA_RPORT_SM_HWFAIL:
4758                 break;
4759
4760         default:
4761                 bfa_stats(rp, sm_iocd_unexp);
4762                 bfa_sm_fault(rp->bfa, event);
4763         }
4764 }
4765
4766
4767
4768 /*
4769  *  bfa_rport_private BFA rport private functions
4770  */
4771
4772 static void
4773 __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
4774 {
4775         struct bfa_rport_s *rp = cbarg;
4776
4777         if (complete)
4778                 bfa_cb_rport_online(rp->rport_drv);
4779 }
4780
4781 static void
4782 __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
4783 {
4784         struct bfa_rport_s *rp = cbarg;
4785
4786         if (complete)
4787                 bfa_cb_rport_offline(rp->rport_drv);
4788 }
4789
4790 static void
4791 bfa_rport_qresume(void *cbarg)
4792 {
4793         struct bfa_rport_s      *rp = cbarg;
4794
4795         bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
4796 }
4797
4798 void
4799 bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
4800                 struct bfa_s *bfa)
4801 {
4802         struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa);
4803
4804         if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
4805                 cfg->fwcfg.num_rports = BFA_RPORT_MIN;
4806
4807         /* kva memory */
4808         bfa_mem_kva_setup(minfo, rport_kva,
4809                 cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));
4810 }
4811
4812 void
4813 bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4814                 struct bfa_pcidev_s *pcidev)
4815 {
4816         struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4817         struct bfa_rport_s *rp;
4818         u16 i;
4819
4820         INIT_LIST_HEAD(&mod->rp_free_q);
4821         INIT_LIST_HEAD(&mod->rp_active_q);
4822         INIT_LIST_HEAD(&mod->rp_unused_q);
4823
4824         rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);
4825         mod->rps_list = rp;
4826         mod->num_rports = cfg->fwcfg.num_rports;
4827
4828         WARN_ON(!mod->num_rports ||
4829                    (mod->num_rports & (mod->num_rports - 1)));
4830
4831         for (i = 0; i < mod->num_rports; i++, rp++) {
4832                 memset(rp, 0, sizeof(struct bfa_rport_s));
4833                 rp->bfa = bfa;
4834                 rp->rport_tag = i;
4835                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4836
4837                 /*
4838                  *  - is unused
4839                  */
4840                 if (i)
4841                         list_add_tail(&rp->qe, &mod->rp_free_q);
4842
4843                 bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
4844         }
4845
4846         /*
4847          * consume memory
4848          */
4849         bfa_mem_kva_curp(mod) = (u8 *) rp;
4850 }
4851
4852 void
4853 bfa_rport_iocdisable(struct bfa_s *bfa)
4854 {
4855         struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4856         struct bfa_rport_s *rport;
4857         struct list_head *qe, *qen;
4858
4859         /* Enqueue unused rport resources to free_q */
4860         list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);
4861
4862         list_for_each_safe(qe, qen, &mod->rp_active_q) {
4863                 rport = (struct bfa_rport_s *) qe;
4864                 bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
4865         }
4866 }
4867
4868 static struct bfa_rport_s *
4869 bfa_rport_alloc(struct bfa_rport_mod_s *mod)
4870 {
4871         struct bfa_rport_s *rport;
4872
4873         bfa_q_deq(&mod->rp_free_q, &rport);
4874         if (rport)
4875                 list_add_tail(&rport->qe, &mod->rp_active_q);
4876
4877         return rport;
4878 }
4879
4880 static void
4881 bfa_rport_free(struct bfa_rport_s *rport)
4882 {
4883         struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
4884
4885         WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
4886         list_del(&rport->qe);
4887         list_add_tail(&rport->qe, &mod->rp_free_q);
4888 }
4889
4890 static bfa_boolean_t
4891 bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
4892 {
4893         struct bfi_rport_create_req_s *m;
4894
4895         /*
4896          * check for room in queue to send request now
4897          */
4898         m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4899         if (!m) {
4900                 bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4901                 return BFA_FALSE;
4902         }
4903
4904         bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
4905                         bfa_fn_lpu(rp->bfa));
4906         m->bfa_handle = rp->rport_tag;
4907         m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
4908         m->pid = rp->rport_info.pid;
4909         m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);
4910         m->local_pid = rp->rport_info.local_pid;
4911         m->fc_class = rp->rport_info.fc_class;
4912         m->vf_en = rp->rport_info.vf_en;
4913         m->vf_id = rp->rport_info.vf_id;
4914         m->cisc = rp->rport_info.cisc;
4915
4916         /*
4917          * queue I/O message to firmware
4918          */
4919         bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4920         return BFA_TRUE;
4921 }
4922
4923 static bfa_boolean_t
4924 bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
4925 {
4926         struct bfi_rport_delete_req_s *m;
4927
4928         /*
4929          * check for room in queue to send request now
4930          */
4931         m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4932         if (!m) {
4933                 bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4934                 return BFA_FALSE;
4935         }
4936
4937         bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
4938                         bfa_fn_lpu(rp->bfa));
4939         m->fw_handle = rp->fw_handle;
4940
4941         /*
4942          * queue I/O message to firmware
4943          */
4944         bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4945         return BFA_TRUE;
4946 }
4947
4948 static bfa_boolean_t
4949 bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
4950 {
4951         struct bfa_rport_speed_req_s *m;
4952
4953         /*
4954          * check for room in queue to send request now
4955          */
4956         m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4957         if (!m) {
4958                 bfa_trc(rp->bfa, rp->rport_info.speed);
4959                 return BFA_FALSE;
4960         }
4961
4962         bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
4963                         bfa_fn_lpu(rp->bfa));
4964         m->fw_handle = rp->fw_handle;
4965         m->speed = (u8)rp->rport_info.speed;
4966
4967         /*
4968          * queue I/O message to firmware
4969          */
4970         bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4971         return BFA_TRUE;
4972 }
4973
4974
4975
4976 /*
4977  *  bfa_rport_public
4978  */
4979
4980 /*
4981  * Rport interrupt processing.
4982  */
4983 void
4984 bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
4985 {
4986         union bfi_rport_i2h_msg_u msg;
4987         struct bfa_rport_s *rp;
4988
4989         bfa_trc(bfa, m->mhdr.msg_id);
4990
4991         msg.msg = m;
4992
4993         switch (m->mhdr.msg_id) {
4994         case BFI_RPORT_I2H_CREATE_RSP:
4995                 rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
4996                 rp->fw_handle = msg.create_rsp->fw_handle;
4997                 rp->qos_attr = msg.create_rsp->qos_attr;
4998                 bfa_rport_set_lunmask(bfa, rp);
4999                 WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
5000                 bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
5001                 break;
5002
5003         case BFI_RPORT_I2H_DELETE_RSP:
5004                 rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
5005                 WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
5006                 bfa_rport_unset_lunmask(bfa, rp);
5007                 bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
5008                 break;
5009
5010         case BFI_RPORT_I2H_QOS_SCN:
5011                 rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
5012                 rp->event_arg.fw_msg = msg.qos_scn_evt;
5013                 bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
5014                 break;
5015
5016         case BFI_RPORT_I2H_LIP_SCN_ONLINE:
5017                 bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
5018                                 &msg.lip_scn->loop_info);
5019                 bfa_cb_rport_scn_online(bfa);
5020                 break;
5021
5022         case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
5023                 bfa_cb_rport_scn_offline(bfa);
5024                 break;
5025
5026         case BFI_RPORT_I2H_NO_DEV:
5027                 rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
5028                 bfa_cb_rport_scn_no_dev(rp->rport_drv);
5029                 break;
5030
5031         default:
5032                 bfa_trc(bfa, m->mhdr.msg_id);
5033                 WARN_ON(1);
5034         }
5035 }
5036
5037 void
5038 bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)
5039 {
5040         struct bfa_rport_mod_s  *mod = BFA_RPORT_MOD(bfa);
5041         struct list_head        *qe;
5042         int     i;
5043
5044         for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {
5045                 bfa_q_deq_tail(&mod->rp_free_q, &qe);
5046                 list_add_tail(qe, &mod->rp_unused_q);
5047         }
5048 }
5049
5050 /*
5051  *  bfa_rport_api
5052  */
5053
5054 struct bfa_rport_s *
5055 bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
5056 {
5057         struct bfa_rport_s *rp;
5058
5059         rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
5060
5061         if (rp == NULL)
5062                 return NULL;
5063
5064         rp->bfa = bfa;
5065         rp->rport_drv = rport_drv;
5066         memset(&rp->stats, 0, sizeof(rp->stats));
5067
5068         WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
5069         bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
5070
5071         return rp;
5072 }
5073
5074 void
5075 bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
5076 {
5077         WARN_ON(rport_info->max_frmsz == 0);
5078
5079         /*
5080          * Some JBODs are seen to be not setting PDU size correctly in PLOGI
5081          * responses. Default to minimum size.
5082          */
5083         if (rport_info->max_frmsz == 0) {
5084                 bfa_trc(rport->bfa, rport->rport_tag);
5085                 rport_info->max_frmsz = FC_MIN_PDUSZ;
5086         }
5087
5088         rport->rport_info = *rport_info;
5089         bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
5090 }
5091
5092 void
5093 bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
5094 {
5095         WARN_ON(speed == 0);
5096         WARN_ON(speed == BFA_PORT_SPEED_AUTO);
5097
5098         if (rport) {
5099                 rport->rport_info.speed = speed;
5100                 bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
5101         }
5102 }
5103
5104 /* Set Rport LUN Mask */
5105 void
5106 bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5107 {
5108         struct bfa_lps_mod_s    *lps_mod = BFA_LPS_MOD(bfa);
5109         wwn_t   lp_wwn, rp_wwn;
5110         u8 lp_tag = (u8)rp->rport_info.lp_tag;
5111
5112         rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5113         lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5114
5115         BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5116                                         rp->lun_mask = BFA_TRUE;
5117         bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag);
5118 }
5119
5120 /* Unset Rport LUN mask */
5121 void
5122 bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5123 {
5124         struct bfa_lps_mod_s    *lps_mod = BFA_LPS_MOD(bfa);
5125         wwn_t   lp_wwn, rp_wwn;
5126
5127         rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5128         lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5129
5130         BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5131                                 rp->lun_mask = BFA_FALSE;
5132         bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn,
5133                         BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID);
5134 }
5135
5136 /*
5137  * SGPG related functions
5138  */
5139
5140 /*
5141  * Compute and return memory needed by FCP(im) module.
5142  */
5143 void
5144 bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5145                 struct bfa_s *bfa)
5146 {
5147         struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa);
5148         struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa);
5149         struct bfa_mem_dma_s *seg_ptr;
5150         u16     nsegs, idx, per_seg_sgpg, num_sgpg;
5151         u32     sgpg_sz = sizeof(struct bfi_sgpg_s);
5152
5153         if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
5154                 cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
5155         else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX)
5156                 cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX;
5157
5158         num_sgpg = cfg->drvcfg.num_sgpgs;
5159
5160         nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5161         per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz);
5162
5163         bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) {
5164                 if (num_sgpg >= per_seg_sgpg) {
5165                         num_sgpg -= per_seg_sgpg;
5166                         bfa_mem_dma_setup(minfo, seg_ptr,
5167                                         per_seg_sgpg * sgpg_sz);
5168                 } else
5169                         bfa_mem_dma_setup(minfo, seg_ptr,
5170                                         num_sgpg * sgpg_sz);
5171         }
5172
5173         /* kva memory */
5174         bfa_mem_kva_setup(minfo, sgpg_kva,
5175                 cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));
5176 }
5177
5178 void
5179 bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5180                 struct bfa_pcidev_s *pcidev)
5181 {
5182         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5183         struct bfa_sgpg_s *hsgpg;
5184         struct bfi_sgpg_s *sgpg;
5185         u64 align_len;
5186         struct bfa_mem_dma_s *seg_ptr;
5187         u32     sgpg_sz = sizeof(struct bfi_sgpg_s);
5188         u16     i, idx, nsegs, per_seg_sgpg, num_sgpg;
5189
5190         union {
5191                 u64 pa;
5192                 union bfi_addr_u addr;
5193         } sgpg_pa, sgpg_pa_tmp;
5194
5195         INIT_LIST_HEAD(&mod->sgpg_q);
5196         INIT_LIST_HEAD(&mod->sgpg_wait_q);
5197
5198         bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
5199
5200         mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
5201
5202         num_sgpg = cfg->drvcfg.num_sgpgs;
5203         nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5204
5205         /* dma/kva mem claim */
5206         hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod);
5207
5208         bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) {
5209
5210                 if (!bfa_mem_dma_virt(seg_ptr))
5211                         break;
5212
5213                 align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) -
5214                                              bfa_mem_dma_phys(seg_ptr);
5215
5216                 sgpg = (struct bfi_sgpg_s *)
5217                         (((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len);
5218                 sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len;
5219                 WARN_ON(sgpg_pa.pa & (sgpg_sz - 1));
5220
5221                 per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz;
5222
5223                 for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) {
5224                         memset(hsgpg, 0, sizeof(*hsgpg));
5225                         memset(sgpg, 0, sizeof(*sgpg));
5226
5227                         hsgpg->sgpg = sgpg;
5228                         sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
5229                         hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
5230                         list_add_tail(&hsgpg->qe, &mod->sgpg_q);
5231
5232                         sgpg++;
5233                         hsgpg++;
5234                         sgpg_pa.pa += sgpg_sz;
5235                 }
5236         }
5237
5238         bfa_mem_kva_curp(mod) = (u8 *) hsgpg;
5239 }
5240
5241 bfa_status_t
5242 bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
5243 {
5244         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5245         struct bfa_sgpg_s *hsgpg;
5246         int i;
5247
5248         if (mod->free_sgpgs < nsgpgs)
5249                 return BFA_STATUS_ENOMEM;
5250
5251         for (i = 0; i < nsgpgs; i++) {
5252                 bfa_q_deq(&mod->sgpg_q, &hsgpg);
5253                 WARN_ON(!hsgpg);
5254                 list_add_tail(&hsgpg->qe, sgpg_q);
5255         }
5256
5257         mod->free_sgpgs -= nsgpgs;
5258         return BFA_STATUS_OK;
5259 }
5260
5261 void
5262 bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
5263 {
5264         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5265         struct bfa_sgpg_wqe_s *wqe;
5266
5267         mod->free_sgpgs += nsgpg;
5268         WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
5269
5270         list_splice_tail_init(sgpg_q, &mod->sgpg_q);
5271
5272         if (list_empty(&mod->sgpg_wait_q))
5273                 return;
5274
5275         /*
5276          * satisfy as many waiting requests as possible
5277          */
5278         do {
5279                 wqe = bfa_q_first(&mod->sgpg_wait_q);
5280                 if (mod->free_sgpgs < wqe->nsgpg)
5281                         nsgpg = mod->free_sgpgs;
5282                 else
5283                         nsgpg = wqe->nsgpg;
5284                 bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
5285                 wqe->nsgpg -= nsgpg;
5286                 if (wqe->nsgpg == 0) {
5287                         list_del(&wqe->qe);
5288                         wqe->cbfn(wqe->cbarg);
5289                 }
5290         } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
5291 }
5292
5293 void
5294 bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
5295 {
5296         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5297
5298         WARN_ON(nsgpg <= 0);
5299         WARN_ON(nsgpg <= mod->free_sgpgs);
5300
5301         wqe->nsgpg_total = wqe->nsgpg = nsgpg;
5302
5303         /*
5304          * allocate any left to this one first
5305          */
5306         if (mod->free_sgpgs) {
5307                 /*
5308                  * no one else is waiting for SGPG
5309                  */
5310                 WARN_ON(!list_empty(&mod->sgpg_wait_q));
5311                 list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
5312                 wqe->nsgpg -= mod->free_sgpgs;
5313                 mod->free_sgpgs = 0;
5314         }
5315
5316         list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
5317 }
5318
5319 void
5320 bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
5321 {
5322         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5323
5324         WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
5325         list_del(&wqe->qe);
5326
5327         if (wqe->nsgpg_total != wqe->nsgpg)
5328                 bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
5329                                    wqe->nsgpg_total - wqe->nsgpg);
5330 }
5331
5332 void
5333 bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
5334                    void *cbarg)
5335 {
5336         INIT_LIST_HEAD(&wqe->sgpg_q);
5337         wqe->cbfn = cbfn;
5338         wqe->cbarg = cbarg;
5339 }
5340
5341 /*
5342  *  UF related functions
5343  */
5344 /*
5345  *****************************************************************************
5346  * Internal functions
5347  *****************************************************************************
5348  */
5349 static void
5350 __bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
5351 {
5352         struct bfa_uf_s   *uf = cbarg;
5353         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
5354
5355         if (complete)
5356                 ufm->ufrecv(ufm->cbarg, uf);
5357 }
5358
5359 static void
5360 claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)
5361 {
5362         struct bfi_uf_buf_post_s *uf_bp_msg;
5363         u16 i;
5364         u16 buf_len;
5365
5366         ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);
5367         uf_bp_msg = ufm->uf_buf_posts;
5368
5369         for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
5370              i++, uf_bp_msg++) {
5371                 memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
5372
5373                 uf_bp_msg->buf_tag = i;
5374                 buf_len = sizeof(struct bfa_uf_buf_s);
5375                 uf_bp_msg->buf_len = cpu_to_be16(buf_len);
5376                 bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
5377                             bfa_fn_lpu(ufm->bfa));
5378                 bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));
5379         }
5380
5381         /*
5382          * advance pointer beyond consumed memory
5383          */
5384         bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;
5385 }
5386
5387 static void
5388 claim_ufs(struct bfa_uf_mod_s *ufm)
5389 {
5390         u16 i;
5391         struct bfa_uf_s   *uf;
5392
5393         /*
5394          * Claim block of memory for UF list
5395          */
5396         ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);
5397
5398         /*
5399          * Initialize UFs and queue it in UF free queue
5400          */
5401         for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
5402                 memset(uf, 0, sizeof(struct bfa_uf_s));
5403                 uf->bfa = ufm->bfa;
5404                 uf->uf_tag = i;
5405                 uf->pb_len = BFA_PER_UF_DMA_SZ;
5406                 uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);
5407                 uf->buf_pa = ufm_pbs_pa(ufm, i);
5408                 list_add_tail(&uf->qe, &ufm->uf_free_q);
5409         }
5410
5411         /*
5412          * advance memory pointer
5413          */
5414         bfa_mem_kva_curp(ufm) = (u8 *) uf;
5415 }
5416
5417 static void
5418 uf_mem_claim(struct bfa_uf_mod_s *ufm)
5419 {
5420         claim_ufs(ufm);
5421         claim_uf_post_msgs(ufm);
5422 }
5423
5424 void
5425 bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5426                 struct bfa_s *bfa)
5427 {
5428         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5429         struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa);
5430         u32     num_ufs = cfg->fwcfg.num_uf_bufs;
5431         struct bfa_mem_dma_s *seg_ptr;
5432         u16     nsegs, idx, per_seg_uf = 0;
5433
5434         nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ);
5435         per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ);
5436
5437         bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) {
5438                 if (num_ufs >= per_seg_uf) {
5439                         num_ufs -= per_seg_uf;
5440                         bfa_mem_dma_setup(minfo, seg_ptr,
5441                                 per_seg_uf * BFA_PER_UF_DMA_SZ);
5442                 } else
5443                         bfa_mem_dma_setup(minfo, seg_ptr,
5444                                 num_ufs * BFA_PER_UF_DMA_SZ);
5445         }
5446
5447         /* kva memory */
5448         bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs *
5449                 (sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));
5450 }
5451
5452 void
5453 bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5454                 struct bfa_pcidev_s *pcidev)
5455 {
5456         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5457
5458         ufm->bfa = bfa;
5459         ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
5460         INIT_LIST_HEAD(&ufm->uf_free_q);
5461         INIT_LIST_HEAD(&ufm->uf_posted_q);
5462         INIT_LIST_HEAD(&ufm->uf_unused_q);
5463
5464         uf_mem_claim(ufm);
5465 }
5466
5467 static struct bfa_uf_s *
5468 bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
5469 {
5470         struct bfa_uf_s   *uf;
5471
5472         bfa_q_deq(&uf_mod->uf_free_q, &uf);
5473         return uf;
5474 }
5475
5476 static void
5477 bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
5478 {
5479         list_add_tail(&uf->qe, &uf_mod->uf_free_q);
5480 }
5481
5482 static bfa_status_t
5483 bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
5484 {
5485         struct bfi_uf_buf_post_s *uf_post_msg;
5486
5487         uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
5488         if (!uf_post_msg)
5489                 return BFA_STATUS_FAILED;
5490
5491         memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
5492                       sizeof(struct bfi_uf_buf_post_s));
5493         bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);
5494
5495         bfa_trc(ufm->bfa, uf->uf_tag);
5496
5497         list_add_tail(&uf->qe, &ufm->uf_posted_q);
5498         return BFA_STATUS_OK;
5499 }
5500
5501 static void
5502 bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
5503 {
5504         struct bfa_uf_s   *uf;
5505
5506         while ((uf = bfa_uf_get(uf_mod)) != NULL) {
5507                 if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
5508                         break;
5509         }
5510 }
5511
5512 static void
5513 uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
5514 {
5515         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5516         u16 uf_tag = m->buf_tag;
5517         struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
5518         struct bfa_uf_buf_s *uf_buf;
5519         uint8_t *buf;
5520
5521         uf_buf = (struct bfa_uf_buf_s *)
5522                         bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);
5523         buf = &uf_buf->d[0];
5524
5525         m->frm_len = be16_to_cpu(m->frm_len);
5526         m->xfr_len = be16_to_cpu(m->xfr_len);
5527
5528         list_del(&uf->qe);      /* dequeue from posted queue */
5529
5530         uf->data_ptr = buf;
5531         uf->data_len = m->xfr_len;
5532
5533         WARN_ON(uf->data_len < sizeof(struct fchs_s));
5534
5535         if (uf->data_len == sizeof(struct fchs_s)) {
5536                 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
5537                                uf->data_len, (struct fchs_s *)buf);
5538         } else {
5539                 u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
5540                 bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
5541                                       BFA_PL_EID_RX, uf->data_len,
5542                                       (struct fchs_s *)buf, pld_w0);
5543         }
5544
5545         if (bfa->fcs)
5546                 __bfa_cb_uf_recv(uf, BFA_TRUE);
5547         else
5548                 bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
5549 }
5550
5551 void
5552 bfa_uf_iocdisable(struct bfa_s *bfa)
5553 {
5554         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5555         struct bfa_uf_s *uf;
5556         struct list_head *qe, *qen;
5557
5558         /* Enqueue unused uf resources to free_q */
5559         list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q);
5560
5561         list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
5562                 uf = (struct bfa_uf_s *) qe;
5563                 list_del(&uf->qe);
5564                 bfa_uf_put(ufm, uf);
5565         }
5566 }
5567
5568 void
5569 bfa_uf_start(struct bfa_s *bfa)
5570 {
5571         bfa_uf_post_all(BFA_UF_MOD(bfa));
5572 }
5573
5574 /*
5575  * Register handler for all unsolicted receive frames.
5576  *
5577  * @param[in]   bfa             BFA instance
5578  * @param[in]   ufrecv  receive handler function
5579  * @param[in]   cbarg   receive handler arg
5580  */
5581 void
5582 bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
5583 {
5584         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5585
5586         ufm->ufrecv = ufrecv;
5587         ufm->cbarg = cbarg;
5588 }
5589
5590 /*
5591  *      Free an unsolicited frame back to BFA.
5592  *
5593  * @param[in]           uf              unsolicited frame to be freed
5594  *
5595  * @return None
5596  */
5597 void
5598 bfa_uf_free(struct bfa_uf_s *uf)
5599 {
5600         bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
5601         bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
5602 }
5603
5604
5605
5606 /*
5607  *  uf_pub BFA uf module public functions
5608  */
5609 void
5610 bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5611 {
5612         bfa_trc(bfa, msg->mhdr.msg_id);
5613
5614         switch (msg->mhdr.msg_id) {
5615         case BFI_UF_I2H_FRM_RCVD:
5616                 uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
5617                 break;
5618
5619         default:
5620                 bfa_trc(bfa, msg->mhdr.msg_id);
5621                 WARN_ON(1);
5622         }
5623 }
5624
5625 void
5626 bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
5627 {
5628         struct bfa_uf_mod_s     *mod = BFA_UF_MOD(bfa);
5629         struct list_head        *qe;
5630         int     i;
5631
5632         for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {
5633                 bfa_q_deq_tail(&mod->uf_free_q, &qe);
5634                 list_add_tail(qe, &mod->uf_unused_q);
5635         }
5636 }
5637
5638 /*
5639  *      Dport forward declaration
5640  */
5641
5642 enum bfa_dport_test_state_e {
5643         BFA_DPORT_ST_DISABLED   = 0,    /*!< dport is disabled */
5644         BFA_DPORT_ST_INP        = 1,    /*!< test in progress */
5645         BFA_DPORT_ST_COMP       = 2,    /*!< test complete successfully */
5646         BFA_DPORT_ST_NO_SFP     = 3,    /*!< sfp is not present */
5647         BFA_DPORT_ST_NOTSTART   = 4,    /*!< test not start dport is enabled */
5648 };
5649
5650 /*
5651  * BFA DPORT state machine events
5652  */
5653 enum bfa_dport_sm_event {
5654         BFA_DPORT_SM_ENABLE     = 1,    /* dport enable event         */
5655         BFA_DPORT_SM_DISABLE    = 2,    /* dport disable event        */
5656         BFA_DPORT_SM_FWRSP      = 3,    /* fw enable/disable rsp      */
5657         BFA_DPORT_SM_QRESUME    = 4,    /* CQ space available         */
5658         BFA_DPORT_SM_HWFAIL     = 5,    /* IOC h/w failure            */
5659         BFA_DPORT_SM_START      = 6,    /* re-start dport test        */
5660         BFA_DPORT_SM_REQFAIL    = 7,    /* request failure            */
5661         BFA_DPORT_SM_SCN        = 8,    /* state change notify frm fw */
5662 };
5663
5664 static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
5665                                   enum bfa_dport_sm_event event);
5666 static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
5667                                   enum bfa_dport_sm_event event);
5668 static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,
5669                                   enum bfa_dport_sm_event event);
5670 static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,
5671                                  enum bfa_dport_sm_event event);
5672 static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
5673                                  enum bfa_dport_sm_event event);
5674 static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
5675                                    enum bfa_dport_sm_event event);
5676 static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
5677                                         enum bfa_dport_sm_event event);
5678 static void bfa_dport_sm_starting(struct bfa_dport_s *dport,
5679                                   enum bfa_dport_sm_event event);
5680 static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
5681                                    enum bfa_dport_sm_event event);
5682 static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
5683                                    enum bfa_dport_sm_event event);
5684 static void bfa_dport_qresume(void *cbarg);
5685 static void bfa_dport_req_comp(struct bfa_dport_s *dport,
5686                                 struct bfi_diag_dport_rsp_s *msg);
5687 static void bfa_dport_scn(struct bfa_dport_s *dport,
5688                                 struct bfi_diag_dport_scn_s *msg);
5689
5690 /*
5691  *      BFA fcdiag module
5692  */
5693 #define BFA_DIAG_QTEST_TOV      1000    /* msec */
5694
5695 /*
5696  *      Set port status to busy
5697  */
5698 static void
5699 bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
5700 {
5701         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);
5702
5703         if (fcdiag->lb.lock)
5704                 fcport->diag_busy = BFA_TRUE;
5705         else
5706                 fcport->diag_busy = BFA_FALSE;
5707 }
5708
5709 void
5710 bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5711                 struct bfa_pcidev_s *pcidev)
5712 {
5713         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5714         struct bfa_dport_s  *dport = &fcdiag->dport;
5715
5716         fcdiag->bfa             = bfa;
5717         fcdiag->trcmod  = bfa->trcmod;
5718         /* The common DIAG attach bfa_diag_attach() will do all memory claim */
5719         dport->bfa = bfa;
5720         bfa_sm_set_state(dport, bfa_dport_sm_disabled);
5721         bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
5722         dport->cbfn = NULL;
5723         dport->cbarg = NULL;
5724         dport->test_state = BFA_DPORT_ST_DISABLED;
5725         memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
5726 }
5727
5728 void
5729 bfa_fcdiag_iocdisable(struct bfa_s *bfa)
5730 {
5731         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5732         struct bfa_dport_s *dport = &fcdiag->dport;
5733
5734         bfa_trc(fcdiag, fcdiag->lb.lock);
5735         if (fcdiag->lb.lock) {
5736                 fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
5737                 fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5738                 fcdiag->lb.lock = 0;
5739                 bfa_fcdiag_set_busy_status(fcdiag);
5740         }
5741
5742         bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
5743 }
5744
5745 static void
5746 bfa_fcdiag_queuetest_timeout(void *cbarg)
5747 {
5748         struct bfa_fcdiag_s       *fcdiag = cbarg;
5749         struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5750
5751         bfa_trc(fcdiag, fcdiag->qtest.all);
5752         bfa_trc(fcdiag, fcdiag->qtest.count);
5753
5754         fcdiag->qtest.timer_active = 0;
5755
5756         res->status = BFA_STATUS_ETIMER;
5757         res->count  = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5758         if (fcdiag->qtest.all)
5759                 res->queue  = fcdiag->qtest.all;
5760
5761         bfa_trc(fcdiag, BFA_STATUS_ETIMER);
5762         fcdiag->qtest.status = BFA_STATUS_ETIMER;
5763         fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5764         fcdiag->qtest.lock = 0;
5765 }
5766
5767 static bfa_status_t
5768 bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)
5769 {
5770         u32     i;
5771         struct bfi_diag_qtest_req_s *req;
5772
5773         req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);
5774         if (!req)
5775                 return BFA_STATUS_DEVBUSY;
5776
5777         /* build host command */
5778         bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,
5779                 bfa_fn_lpu(fcdiag->bfa));
5780
5781         for (i = 0; i < BFI_LMSG_PL_WSZ; i++)
5782                 req->data[i] = QTEST_PAT_DEFAULT;
5783
5784         bfa_trc(fcdiag, fcdiag->qtest.queue);
5785         /* ring door bell */
5786         bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);
5787         return BFA_STATUS_OK;
5788 }
5789
5790 static void
5791 bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,
5792                         bfi_diag_qtest_rsp_t *rsp)
5793 {
5794         struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5795         bfa_status_t status = BFA_STATUS_OK;
5796         int i;
5797
5798         /* Check timer, should still be active   */
5799         if (!fcdiag->qtest.timer_active) {
5800                 bfa_trc(fcdiag, fcdiag->qtest.timer_active);
5801                 return;
5802         }
5803
5804         /* update count */
5805         fcdiag->qtest.count--;
5806
5807         /* Check result */
5808         for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {
5809                 if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {
5810                         res->status = BFA_STATUS_DATACORRUPTED;
5811                         break;
5812                 }
5813         }
5814
5815         if (res->status == BFA_STATUS_OK) {
5816                 if (fcdiag->qtest.count > 0) {
5817                         status = bfa_fcdiag_queuetest_send(fcdiag);
5818                         if (status == BFA_STATUS_OK)
5819                                 return;
5820                         else
5821                                 res->status = status;
5822                 } else if (fcdiag->qtest.all > 0 &&
5823                         fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {
5824                         fcdiag->qtest.count = QTEST_CNT_DEFAULT;
5825                         fcdiag->qtest.queue++;
5826                         status = bfa_fcdiag_queuetest_send(fcdiag);
5827                         if (status == BFA_STATUS_OK)
5828                                 return;
5829                         else
5830                                 res->status = status;
5831                 }
5832         }
5833
5834         /* Stop timer when we comp all queue */
5835         if (fcdiag->qtest.timer_active) {
5836                 bfa_timer_stop(&fcdiag->qtest.timer);
5837                 fcdiag->qtest.timer_active = 0;
5838         }
5839         res->queue = fcdiag->qtest.queue;
5840         res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5841         bfa_trc(fcdiag, res->count);
5842         bfa_trc(fcdiag, res->status);
5843         fcdiag->qtest.status = res->status;
5844         fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5845         fcdiag->qtest.lock = 0;
5846 }
5847
5848 static void
5849 bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,
5850                         struct bfi_diag_lb_rsp_s *rsp)
5851 {
5852         struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;
5853
5854         res->numtxmfrm  = be32_to_cpu(rsp->res.numtxmfrm);
5855         res->numosffrm  = be32_to_cpu(rsp->res.numosffrm);
5856         res->numrcvfrm  = be32_to_cpu(rsp->res.numrcvfrm);
5857         res->badfrminf  = be32_to_cpu(rsp->res.badfrminf);
5858         res->badfrmnum  = be32_to_cpu(rsp->res.badfrmnum);
5859         res->status     = rsp->res.status;
5860         fcdiag->lb.status = rsp->res.status;
5861         bfa_trc(fcdiag, fcdiag->lb.status);
5862         fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5863         fcdiag->lb.lock = 0;
5864         bfa_fcdiag_set_busy_status(fcdiag);
5865 }
5866
5867 static bfa_status_t
5868 bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,
5869                         struct bfa_diag_loopback_s *loopback)
5870 {
5871         struct bfi_diag_lb_req_s *lb_req;
5872
5873         lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);
5874         if (!lb_req)
5875                 return BFA_STATUS_DEVBUSY;
5876
5877         /* build host command */
5878         bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,
5879                 bfa_fn_lpu(fcdiag->bfa));
5880
5881         lb_req->lb_mode = loopback->lb_mode;
5882         lb_req->speed = loopback->speed;
5883         lb_req->loopcnt = loopback->loopcnt;
5884         lb_req->pattern = loopback->pattern;
5885
5886         /* ring door bell */
5887         bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);
5888
5889         bfa_trc(fcdiag, loopback->lb_mode);
5890         bfa_trc(fcdiag, loopback->speed);
5891         bfa_trc(fcdiag, loopback->loopcnt);
5892         bfa_trc(fcdiag, loopback->pattern);
5893         return BFA_STATUS_OK;
5894 }
5895
5896 /*
5897  *      cpe/rme intr handler
5898  */
5899 void
5900 bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5901 {
5902         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5903
5904         switch (msg->mhdr.msg_id) {
5905         case BFI_DIAG_I2H_LOOPBACK:
5906                 bfa_fcdiag_loopback_comp(fcdiag,
5907                                 (struct bfi_diag_lb_rsp_s *) msg);
5908                 break;
5909         case BFI_DIAG_I2H_QTEST:
5910                 bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
5911                 break;
5912         case BFI_DIAG_I2H_DPORT:
5913                 bfa_dport_req_comp(&fcdiag->dport,
5914                                 (struct bfi_diag_dport_rsp_s *)msg);
5915                 break;
5916         case BFI_DIAG_I2H_DPORT_SCN:
5917                 bfa_dport_scn(&fcdiag->dport,
5918                                 (struct bfi_diag_dport_scn_s *)msg);
5919                 break;
5920         default:
5921                 bfa_trc(fcdiag, msg->mhdr.msg_id);
5922                 WARN_ON(1);
5923         }
5924 }
5925
5926 /*
5927  *      Loopback test
5928  *
5929  *   @param[in] *bfa            - bfa data struct
5930  *   @param[in] opmode          - port operation mode
5931  *   @param[in] speed           - port speed
5932  *   @param[in] lpcnt           - loop count
5933  *   @param[in] pat                     - pattern to build packet
5934  *   @param[in] *result         - pt to bfa_diag_loopback_result_t data struct
5935  *   @param[in] cbfn            - callback function
5936  *   @param[in] cbarg           - callback functioin arg
5937  *
5938  *   @param[out]
5939  */
5940 bfa_status_t
5941 bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
5942                 enum bfa_port_speed speed, u32 lpcnt, u32 pat,
5943                 struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,
5944                 void *cbarg)
5945 {
5946         struct  bfa_diag_loopback_s loopback;
5947         struct bfa_port_attr_s attr;
5948         bfa_status_t status;
5949         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5950
5951         if (!bfa_iocfc_is_operational(bfa))
5952                 return BFA_STATUS_IOC_NON_OP;
5953
5954         /* if port is PBC disabled, return error */
5955         if (bfa_fcport_is_pbcdisabled(bfa)) {
5956                 bfa_trc(fcdiag, BFA_STATUS_PBC);
5957                 return BFA_STATUS_PBC;
5958         }
5959
5960         if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {
5961                 bfa_trc(fcdiag, opmode);
5962                 return BFA_STATUS_PORT_NOT_DISABLED;
5963         }
5964
5965         /*
5966          * Check if input speed is supported by the port mode
5967          */
5968         if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
5969                 if (!(speed == BFA_PORT_SPEED_1GBPS ||
5970                       speed == BFA_PORT_SPEED_2GBPS ||
5971                       speed == BFA_PORT_SPEED_4GBPS ||
5972                       speed == BFA_PORT_SPEED_8GBPS ||
5973                       speed == BFA_PORT_SPEED_16GBPS ||
5974                       speed == BFA_PORT_SPEED_AUTO)) {
5975                         bfa_trc(fcdiag, speed);
5976                         return BFA_STATUS_UNSUPP_SPEED;
5977                 }
5978                 bfa_fcport_get_attr(bfa, &attr);
5979                 bfa_trc(fcdiag, attr.speed_supported);
5980                 if (speed > attr.speed_supported)
5981                         return BFA_STATUS_UNSUPP_SPEED;
5982         } else {
5983                 if (speed != BFA_PORT_SPEED_10GBPS) {
5984                         bfa_trc(fcdiag, speed);
5985                         return BFA_STATUS_UNSUPP_SPEED;
5986                 }
5987         }
5988
5989         /*
5990          * For CT2, 1G is not supported
5991          */
5992         if ((speed == BFA_PORT_SPEED_1GBPS) &&
5993             (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {
5994                 bfa_trc(fcdiag, speed);
5995                 return BFA_STATUS_UNSUPP_SPEED;
5996         }
5997
5998         /* For Mezz card, port speed entered needs to be checked */
5999         if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
6000                 if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
6001                         if (!(speed == BFA_PORT_SPEED_1GBPS ||
6002                               speed == BFA_PORT_SPEED_2GBPS ||
6003                               speed == BFA_PORT_SPEED_4GBPS ||
6004                               speed == BFA_PORT_SPEED_8GBPS ||
6005                               speed == BFA_PORT_SPEED_16GBPS ||
6006                               speed == BFA_PORT_SPEED_AUTO))
6007                                 return BFA_STATUS_UNSUPP_SPEED;
6008                 } else {
6009                         if (speed != BFA_PORT_SPEED_10GBPS)
6010                                 return BFA_STATUS_UNSUPP_SPEED;
6011                 }
6012         }
6013         /* check to see if fcport is dport */
6014         if (bfa_fcport_is_dport(bfa)) {
6015                 bfa_trc(fcdiag, fcdiag->lb.lock);
6016                 return BFA_STATUS_DPORT_ENABLED;
6017         }
6018         /* check to see if there is another destructive diag cmd running */
6019         if (fcdiag->lb.lock) {
6020                 bfa_trc(fcdiag, fcdiag->lb.lock);
6021                 return BFA_STATUS_DEVBUSY;
6022         }
6023
6024         fcdiag->lb.lock = 1;
6025         loopback.lb_mode = opmode;
6026         loopback.speed = speed;
6027         loopback.loopcnt = lpcnt;
6028         loopback.pattern = pat;
6029         fcdiag->lb.result = result;
6030         fcdiag->lb.cbfn = cbfn;
6031         fcdiag->lb.cbarg = cbarg;
6032         memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));
6033         bfa_fcdiag_set_busy_status(fcdiag);
6034
6035         /* Send msg to fw */
6036         status = bfa_fcdiag_loopback_send(fcdiag, &loopback);
6037         return status;
6038 }
6039
6040 /*
6041  *      DIAG queue test command
6042  *
6043  *   @param[in] *bfa            - bfa data struct
6044  *   @param[in] force           - 1: don't do ioc op checking
6045  *   @param[in] queue           - queue no. to test
6046  *   @param[in] *result         - pt to bfa_diag_qtest_result_t data struct
6047  *   @param[in] cbfn            - callback function
6048  *   @param[in] *cbarg          - callback functioin arg
6049  *
6050  *   @param[out]
6051  */
6052 bfa_status_t
6053 bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,
6054                 struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,
6055                 void *cbarg)
6056 {
6057         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6058         bfa_status_t status;
6059         bfa_trc(fcdiag, force);
6060         bfa_trc(fcdiag, queue);
6061
6062         if (!force && !bfa_iocfc_is_operational(bfa))
6063                 return BFA_STATUS_IOC_NON_OP;
6064
6065         /* check to see if there is another destructive diag cmd running */
6066         if (fcdiag->qtest.lock) {
6067                 bfa_trc(fcdiag, fcdiag->qtest.lock);
6068                 return BFA_STATUS_DEVBUSY;
6069         }
6070
6071         /* Initialization */
6072         fcdiag->qtest.lock = 1;
6073         fcdiag->qtest.cbfn = cbfn;
6074         fcdiag->qtest.cbarg = cbarg;
6075         fcdiag->qtest.result = result;
6076         fcdiag->qtest.count = QTEST_CNT_DEFAULT;
6077
6078         /* Init test results */
6079         fcdiag->qtest.result->status = BFA_STATUS_OK;
6080         fcdiag->qtest.result->count  = 0;
6081
6082         /* send */
6083         if (queue < BFI_IOC_MAX_CQS) {
6084                 fcdiag->qtest.result->queue  = (u8)queue;
6085                 fcdiag->qtest.queue = (u8)queue;
6086                 fcdiag->qtest.all   = 0;
6087         } else {
6088                 fcdiag->qtest.result->queue  = 0;
6089                 fcdiag->qtest.queue = 0;
6090                 fcdiag->qtest.all   = 1;
6091         }
6092         status = bfa_fcdiag_queuetest_send(fcdiag);
6093
6094         /* Start a timer */
6095         if (status == BFA_STATUS_OK) {
6096                 bfa_timer_start(bfa, &fcdiag->qtest.timer,
6097                                 bfa_fcdiag_queuetest_timeout, fcdiag,
6098                                 BFA_DIAG_QTEST_TOV);
6099                 fcdiag->qtest.timer_active = 1;
6100         }
6101         return status;
6102 }
6103
6104 /*
6105  * DIAG PLB is running
6106  *
6107  *   @param[in] *bfa    - bfa data struct
6108  *
6109  *   @param[out]
6110  */
6111 bfa_status_t
6112 bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
6113 {
6114         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6115         return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
6116 }
6117
6118 /*
6119  *      D-port
6120  */
6121 #define bfa_dport_result_start(__dport, __mode) do {                            \
6122                 (__dport)->result.start_time = ktime_get_real_seconds();        \
6123                 (__dport)->result.status = DPORT_TEST_ST_INPRG;                 \
6124                 (__dport)->result.mode = (__mode);                              \
6125                 (__dport)->result.rp_pwwn = (__dport)->rp_pwwn;                 \
6126                 (__dport)->result.rp_nwwn = (__dport)->rp_nwwn;                 \
6127                 (__dport)->result.lpcnt = (__dport)->lpcnt;                     \
6128 } while (0)
6129
6130 static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
6131                                         enum bfi_dport_req req);
6132 static void
6133 bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)
6134 {
6135         if (dport->cbfn != NULL) {
6136                 dport->cbfn(dport->cbarg, bfa_status);
6137                 dport->cbfn = NULL;
6138                 dport->cbarg = NULL;
6139         }
6140 }
6141
6142 static void
6143 bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6144 {
6145         bfa_trc(dport->bfa, event);
6146
6147         switch (event) {
6148         case BFA_DPORT_SM_ENABLE:
6149                 bfa_fcport_dportenable(dport->bfa);
6150                 if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))
6151                         bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6152                 else
6153                         bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);
6154                 break;
6155
6156         case BFA_DPORT_SM_DISABLE:
6157                 /* Already disabled */
6158                 break;
6159
6160         case BFA_DPORT_SM_HWFAIL:
6161                 /* ignore */
6162                 break;
6163
6164         case BFA_DPORT_SM_SCN:
6165                 if (dport->i2hmsg.scn.state ==  BFI_DPORT_SCN_DDPORT_ENABLE) {
6166                         bfa_fcport_ddportenable(dport->bfa);
6167                         dport->dynamic = BFA_TRUE;
6168                         dport->test_state = BFA_DPORT_ST_NOTSTART;
6169                         bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6170                 } else {
6171                         bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6172                         WARN_ON(1);
6173                 }
6174                 break;
6175
6176         default:
6177                 bfa_sm_fault(dport->bfa, event);
6178         }
6179 }
6180
6181 static void
6182 bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
6183                             enum bfa_dport_sm_event event)
6184 {
6185         bfa_trc(dport->bfa, event);
6186
6187         switch (event) {
6188         case BFA_DPORT_SM_QRESUME:
6189                 bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6190                 bfa_dport_send_req(dport, BFI_DPORT_ENABLE);
6191                 break;
6192
6193         case BFA_DPORT_SM_HWFAIL:
6194                 bfa_reqq_wcancel(&dport->reqq_wait);
6195                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6196                 bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6197                 break;
6198
6199         default:
6200                 bfa_sm_fault(dport->bfa, event);
6201         }
6202 }
6203
6204 static void
6205 bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6206 {
6207         bfa_trc(dport->bfa, event);
6208
6209         switch (event) {
6210         case BFA_DPORT_SM_FWRSP:
6211                 memset(&dport->result, 0,
6212                                 sizeof(struct bfa_diag_dport_result_s));
6213                 if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6214                         dport->test_state = BFA_DPORT_ST_NO_SFP;
6215                 } else {
6216                         dport->test_state = BFA_DPORT_ST_INP;
6217                         bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
6218                 }
6219                 bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6220                 break;
6221
6222         case BFA_DPORT_SM_REQFAIL:
6223                 dport->test_state = BFA_DPORT_ST_DISABLED;
6224                 bfa_fcport_dportdisable(dport->bfa);
6225                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6226                 break;
6227
6228         case BFA_DPORT_SM_HWFAIL:
6229                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6230                 bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6231                 break;
6232
6233         default:
6234                 bfa_sm_fault(dport->bfa, event);
6235         }
6236 }
6237
6238 static void
6239 bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6240 {
6241         bfa_trc(dport->bfa, event);
6242
6243         switch (event) {
6244         case BFA_DPORT_SM_START:
6245                 if (bfa_dport_send_req(dport, BFI_DPORT_START))
6246                         bfa_sm_set_state(dport, bfa_dport_sm_starting);
6247                 else
6248                         bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);
6249                 break;
6250
6251         case BFA_DPORT_SM_DISABLE:
6252                 bfa_fcport_dportdisable(dport->bfa);
6253                 if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))
6254                         bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6255                 else
6256                         bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);
6257                 break;
6258
6259         case BFA_DPORT_SM_HWFAIL:
6260                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6261                 break;
6262
6263         case BFA_DPORT_SM_SCN:
6264                 switch (dport->i2hmsg.scn.state) {
6265                 case BFI_DPORT_SCN_TESTCOMP:
6266                         dport->test_state = BFA_DPORT_ST_COMP;
6267                         break;
6268
6269                 case BFI_DPORT_SCN_TESTSTART:
6270                         dport->test_state = BFA_DPORT_ST_INP;
6271                         break;
6272
6273                 case BFI_DPORT_SCN_TESTSKIP:
6274                 case BFI_DPORT_SCN_SUBTESTSTART:
6275                         /* no state change */
6276                         break;
6277
6278                 case BFI_DPORT_SCN_SFP_REMOVED:
6279                         dport->test_state = BFA_DPORT_ST_NO_SFP;
6280                         break;
6281
6282                 case BFI_DPORT_SCN_DDPORT_DISABLE:
6283                         bfa_fcport_ddportdisable(dport->bfa);
6284
6285                         if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))
6286                                 bfa_sm_set_state(dport,
6287                                          bfa_dport_sm_dynamic_disabling);
6288                         else
6289                                 bfa_sm_set_state(dport,
6290                                          bfa_dport_sm_dynamic_disabling_qwait);
6291                         break;
6292
6293                 case BFI_DPORT_SCN_FCPORT_DISABLE:
6294                         bfa_fcport_ddportdisable(dport->bfa);
6295
6296                         bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6297                         dport->dynamic = BFA_FALSE;
6298                         break;
6299
6300                 default:
6301                         bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6302                         bfa_sm_fault(dport->bfa, event);
6303                 }
6304                 break;
6305         default:
6306                 bfa_sm_fault(dport->bfa, event);
6307         }
6308 }
6309
6310 static void
6311 bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
6312                              enum bfa_dport_sm_event event)
6313 {
6314         bfa_trc(dport->bfa, event);
6315
6316         switch (event) {
6317         case BFA_DPORT_SM_QRESUME:
6318                 bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6319                 bfa_dport_send_req(dport, BFI_DPORT_DISABLE);
6320                 break;
6321
6322         case BFA_DPORT_SM_HWFAIL:
6323                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6324                 bfa_reqq_wcancel(&dport->reqq_wait);
6325                 bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6326                 break;
6327
6328         case BFA_DPORT_SM_SCN:
6329                 /* ignore */
6330                 break;
6331
6332         default:
6333                 bfa_sm_fault(dport->bfa, event);
6334         }
6335 }
6336
6337 static void
6338 bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6339 {
6340         bfa_trc(dport->bfa, event);
6341
6342         switch (event) {
6343         case BFA_DPORT_SM_FWRSP:
6344                 dport->test_state = BFA_DPORT_ST_DISABLED;
6345                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6346                 break;
6347
6348         case BFA_DPORT_SM_HWFAIL:
6349                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6350                 bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6351                 break;
6352
6353         case BFA_DPORT_SM_SCN:
6354                 /* no state change */
6355                 break;
6356
6357         default:
6358                 bfa_sm_fault(dport->bfa, event);
6359         }
6360 }
6361
6362 static void
6363 bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
6364                             enum bfa_dport_sm_event event)
6365 {
6366         bfa_trc(dport->bfa, event);
6367
6368         switch (event) {
6369         case BFA_DPORT_SM_QRESUME:
6370                 bfa_sm_set_state(dport, bfa_dport_sm_starting);
6371                 bfa_dport_send_req(dport, BFI_DPORT_START);
6372                 break;
6373
6374         case BFA_DPORT_SM_HWFAIL:
6375                 bfa_reqq_wcancel(&dport->reqq_wait);
6376                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6377                 bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6378                 break;
6379
6380         default:
6381                 bfa_sm_fault(dport->bfa, event);
6382         }
6383 }
6384
6385 static void
6386 bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6387 {
6388         bfa_trc(dport->bfa, event);
6389
6390         switch (event) {
6391         case BFA_DPORT_SM_FWRSP:
6392                 memset(&dport->result, 0,
6393                                 sizeof(struct bfa_diag_dport_result_s));
6394                 if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6395                         dport->test_state = BFA_DPORT_ST_NO_SFP;
6396                 } else {
6397                         dport->test_state = BFA_DPORT_ST_INP;
6398                         bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
6399                 }
6400                 fallthrough;
6401
6402         case BFA_DPORT_SM_REQFAIL:
6403                 bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6404                 break;
6405
6406         case BFA_DPORT_SM_HWFAIL:
6407                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6408                 bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6409                 break;
6410
6411         default:
6412                 bfa_sm_fault(dport->bfa, event);
6413         }
6414 }
6415
6416 static void
6417 bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
6418                                enum bfa_dport_sm_event event)
6419 {
6420         bfa_trc(dport->bfa, event);
6421
6422         switch (event) {
6423         case BFA_DPORT_SM_SCN:
6424                 switch (dport->i2hmsg.scn.state) {
6425                 case BFI_DPORT_SCN_DDPORT_DISABLED:
6426                         bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6427                         dport->dynamic = BFA_FALSE;
6428                         bfa_fcport_enable(dport->bfa);
6429                         break;
6430
6431                 default:
6432                         bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6433                         bfa_sm_fault(dport->bfa, event);
6434
6435                 }
6436                 break;
6437
6438         case BFA_DPORT_SM_HWFAIL:
6439                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6440                 bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6441                 break;
6442
6443         default:
6444                 bfa_sm_fault(dport->bfa, event);
6445         }
6446 }
6447
6448 static void
6449 bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
6450                             enum bfa_dport_sm_event event)
6451 {
6452         bfa_trc(dport->bfa, event);
6453
6454         switch (event) {
6455         case BFA_DPORT_SM_QRESUME:
6456                 bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling);
6457                 bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE);
6458                 break;
6459
6460         case BFA_DPORT_SM_HWFAIL:
6461                 bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6462                 bfa_reqq_wcancel(&dport->reqq_wait);
6463                 bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6464                 break;
6465
6466         case BFA_DPORT_SM_SCN:
6467                 /* ignore */
6468                 break;
6469
6470         default:
6471                 bfa_sm_fault(dport->bfa, event);
6472         }
6473 }
6474
6475 static bfa_boolean_t
6476 bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
6477 {
6478         struct bfi_diag_dport_req_s *m;
6479
6480         /*
6481          * check for room in queue to send request now
6482          */
6483         m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
6484         if (!m) {
6485                 bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);
6486                 return BFA_FALSE;
6487         }
6488
6489         bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
6490                     bfa_fn_lpu(dport->bfa));
6491         m->req  = req;
6492         if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {
6493                 m->lpcnt = cpu_to_be32(dport->lpcnt);
6494                 m->payload = cpu_to_be32(dport->payload);
6495         }
6496
6497         /*
6498          * queue I/O message to firmware
6499          */
6500         bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);
6501
6502         return BFA_TRUE;
6503 }
6504
6505 static void
6506 bfa_dport_qresume(void *cbarg)
6507 {
6508         struct bfa_dport_s *dport = cbarg;
6509
6510         bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);
6511 }
6512
6513 static void
6514 bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)
6515 {
6516         msg->status = cpu_to_be32(msg->status);
6517         dport->i2hmsg.rsp.status = msg->status;
6518         dport->rp_pwwn = msg->pwwn;
6519         dport->rp_nwwn = msg->nwwn;
6520
6521         if ((msg->status == BFA_STATUS_OK) ||
6522             (msg->status == BFA_STATUS_DPORT_NO_SFP)) {
6523                 bfa_trc(dport->bfa, msg->status);
6524                 bfa_trc(dport->bfa, dport->rp_pwwn);
6525                 bfa_trc(dport->bfa, dport->rp_nwwn);
6526                 bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
6527
6528         } else {
6529                 bfa_trc(dport->bfa, msg->status);
6530                 bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);
6531         }
6532         bfa_cb_fcdiag_dport(dport, msg->status);
6533 }
6534
6535 static bfa_boolean_t
6536 bfa_dport_is_sending_req(struct bfa_dport_s *dport)
6537 {
6538         if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling)      ||
6539             bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
6540             bfa_sm_cmp_state(dport, bfa_dport_sm_disabling)     ||
6541             bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) ||
6542             bfa_sm_cmp_state(dport, bfa_dport_sm_starting)      ||
6543             bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {
6544                 return BFA_TRUE;
6545         } else {
6546                 return BFA_FALSE;
6547         }
6548 }
6549
6550 static void
6551 bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)
6552 {
6553         int i;
6554         uint8_t subtesttype;
6555
6556         bfa_trc(dport->bfa, msg->state);
6557         dport->i2hmsg.scn.state = msg->state;
6558
6559         switch (dport->i2hmsg.scn.state) {
6560         case BFI_DPORT_SCN_TESTCOMP:
6561                 dport->result.end_time = ktime_get_real_seconds();
6562                 bfa_trc(dport->bfa, dport->result.end_time);
6563
6564                 dport->result.status = msg->info.testcomp.status;
6565                 bfa_trc(dport->bfa, dport->result.status);
6566
6567                 dport->result.roundtrip_latency =
6568                         cpu_to_be32(msg->info.testcomp.latency);
6569                 dport->result.est_cable_distance =
6570                         cpu_to_be32(msg->info.testcomp.distance);
6571                 dport->result.buffer_required =
6572                         be16_to_cpu(msg->info.testcomp.numbuffer);
6573
6574                 dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);
6575                 dport->result.speed = msg->info.testcomp.speed;
6576
6577                 bfa_trc(dport->bfa, dport->result.roundtrip_latency);
6578                 bfa_trc(dport->bfa, dport->result.est_cable_distance);
6579                 bfa_trc(dport->bfa, dport->result.buffer_required);
6580                 bfa_trc(dport->bfa, dport->result.frmsz);
6581                 bfa_trc(dport->bfa, dport->result.speed);
6582
6583                 for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {
6584                         dport->result.subtest[i].status =
6585                                 msg->info.testcomp.subtest_status[i];
6586                         bfa_trc(dport->bfa, dport->result.subtest[i].status);
6587                 }
6588                 break;
6589
6590         case BFI_DPORT_SCN_TESTSKIP:
6591         case BFI_DPORT_SCN_DDPORT_ENABLE:
6592                 memset(&dport->result, 0,
6593                                 sizeof(struct bfa_diag_dport_result_s));
6594                 break;
6595
6596         case BFI_DPORT_SCN_TESTSTART:
6597                 memset(&dport->result, 0,
6598                                 sizeof(struct bfa_diag_dport_result_s));
6599                 dport->rp_pwwn = msg->info.teststart.pwwn;
6600                 dport->rp_nwwn = msg->info.teststart.nwwn;
6601                 dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);
6602                 bfa_dport_result_start(dport, msg->info.teststart.mode);
6603                 break;
6604
6605         case BFI_DPORT_SCN_SUBTESTSTART:
6606                 subtesttype = msg->info.teststart.type;
6607                 dport->result.subtest[subtesttype].start_time =
6608                         ktime_get_real_seconds();
6609                 dport->result.subtest[subtesttype].status =
6610                         DPORT_TEST_ST_INPRG;
6611
6612                 bfa_trc(dport->bfa, subtesttype);
6613                 bfa_trc(dport->bfa,
6614                         dport->result.subtest[subtesttype].start_time);
6615                 break;
6616
6617         case BFI_DPORT_SCN_SFP_REMOVED:
6618         case BFI_DPORT_SCN_DDPORT_DISABLED:
6619         case BFI_DPORT_SCN_DDPORT_DISABLE:
6620         case BFI_DPORT_SCN_FCPORT_DISABLE:
6621                 dport->result.status = DPORT_TEST_ST_IDLE;
6622                 break;
6623
6624         default:
6625                 bfa_sm_fault(dport->bfa, msg->state);
6626         }
6627
6628         bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);
6629 }
6630
6631 /*
6632  * Dport enable
6633  *
6634  * @param[in] *bfa            - bfa data struct
6635  */
6636 bfa_status_t
6637 bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6638                                 bfa_cb_diag_t cbfn, void *cbarg)
6639 {
6640         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6641         struct bfa_dport_s  *dport = &fcdiag->dport;
6642
6643         /*
6644          * Dport is not support in MEZZ card
6645          */
6646         if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {
6647                 bfa_trc(dport->bfa, BFA_STATUS_PBC);
6648                 return BFA_STATUS_CMD_NOTSUPP_MEZZ;
6649         }
6650
6651         /*
6652          * Dport is supported in CT2 or above
6653          */
6654         if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {
6655                 bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);
6656                 return BFA_STATUS_FEATURE_NOT_SUPPORTED;
6657         }
6658
6659         /*
6660          * Check to see if IOC is down
6661         */
6662         if (!bfa_iocfc_is_operational(bfa))
6663                 return BFA_STATUS_IOC_NON_OP;
6664
6665         /* if port is PBC disabled, return error */
6666         if (bfa_fcport_is_pbcdisabled(bfa)) {
6667                 bfa_trc(dport->bfa, BFA_STATUS_PBC);
6668                 return BFA_STATUS_PBC;
6669         }
6670
6671         /*
6672          * Check if port mode is FC port
6673          */
6674         if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {
6675                 bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));
6676                 return BFA_STATUS_CMD_NOTSUPP_CNA;
6677         }
6678
6679         /*
6680          * Check if port is in LOOP mode
6681          */
6682         if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||
6683             (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {
6684                 bfa_trc(dport->bfa, 0);
6685                 return BFA_STATUS_TOPOLOGY_LOOP;
6686         }
6687
6688         /*
6689          * Check if port is TRUNK mode
6690          */
6691         if (bfa_fcport_is_trunk_enabled(bfa)) {
6692                 bfa_trc(dport->bfa, 0);
6693                 return BFA_STATUS_ERROR_TRUNK_ENABLED;
6694         }
6695
6696         /*
6697          * Check if diag loopback is running
6698          */
6699         if (bfa_fcdiag_lb_is_running(bfa)) {
6700                 bfa_trc(dport->bfa, 0);
6701                 return BFA_STATUS_DIAG_BUSY;
6702         }
6703
6704         /*
6705          * Check to see if port is disable or in dport state
6706          */
6707         if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6708             (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6709                 bfa_trc(dport->bfa, 0);
6710                 return BFA_STATUS_PORT_NOT_DISABLED;
6711         }
6712
6713         /*
6714          * Check if dport is in dynamic mode
6715          */
6716         if (dport->dynamic)
6717                 return BFA_STATUS_DDPORT_ERR;
6718
6719         /*
6720          * Check if dport is busy
6721          */
6722         if (bfa_dport_is_sending_req(dport))
6723                 return BFA_STATUS_DEVBUSY;
6724
6725         /*
6726          * Check if dport is already enabled
6727          */
6728         if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6729                 bfa_trc(dport->bfa, 0);
6730                 return BFA_STATUS_DPORT_ENABLED;
6731         }
6732
6733         bfa_trc(dport->bfa, lpcnt);
6734         bfa_trc(dport->bfa, pat);
6735         dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6736         dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6737         dport->cbfn = cbfn;
6738         dport->cbarg = cbarg;
6739
6740         bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);
6741         return BFA_STATUS_OK;
6742 }
6743
6744 /*
6745  *      Dport disable
6746  *
6747  *      @param[in] *bfa            - bfa data struct
6748  */
6749 bfa_status_t
6750 bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
6751 {
6752         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6753         struct bfa_dport_s *dport = &fcdiag->dport;
6754
6755         if (bfa_ioc_is_disabled(&bfa->ioc))
6756                 return BFA_STATUS_IOC_DISABLED;
6757
6758         /* if port is PBC disabled, return error */
6759         if (bfa_fcport_is_pbcdisabled(bfa)) {
6760                 bfa_trc(dport->bfa, BFA_STATUS_PBC);
6761                 return BFA_STATUS_PBC;
6762         }
6763
6764         /*
6765          * Check if dport is in dynamic mode
6766          */
6767         if (dport->dynamic) {
6768                 return BFA_STATUS_DDPORT_ERR;
6769         }
6770
6771         /*
6772          * Check to see if port is disable or in dport state
6773          */
6774         if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6775             (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6776                 bfa_trc(dport->bfa, 0);
6777                 return BFA_STATUS_PORT_NOT_DISABLED;
6778         }
6779
6780         /*
6781          * Check if dport is busy
6782          */
6783         if (bfa_dport_is_sending_req(dport))
6784                 return BFA_STATUS_DEVBUSY;
6785
6786         /*
6787          * Check if dport is already disabled
6788          */
6789         if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {
6790                 bfa_trc(dport->bfa, 0);
6791                 return BFA_STATUS_DPORT_DISABLED;
6792         }
6793
6794         dport->cbfn = cbfn;
6795         dport->cbarg = cbarg;
6796
6797         bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);
6798         return BFA_STATUS_OK;
6799 }
6800
6801 /*
6802  * Dport start -- restart dport test
6803  *
6804  *   @param[in] *bfa            - bfa data struct
6805  */
6806 bfa_status_t
6807 bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6808                         bfa_cb_diag_t cbfn, void *cbarg)
6809 {
6810         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6811         struct bfa_dport_s *dport = &fcdiag->dport;
6812
6813         /*
6814          * Check to see if IOC is down
6815          */
6816         if (!bfa_iocfc_is_operational(bfa))
6817                 return BFA_STATUS_IOC_NON_OP;
6818
6819         /*
6820          * Check if dport is in dynamic mode
6821          */
6822         if (dport->dynamic)
6823                 return BFA_STATUS_DDPORT_ERR;
6824
6825         /*
6826          * Check if dport is busy
6827          */
6828         if (bfa_dport_is_sending_req(dport))
6829                 return BFA_STATUS_DEVBUSY;
6830
6831         /*
6832          * Check if dport is in enabled state.
6833          * Test can only be restart when previous test has completed
6834          */
6835         if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6836                 bfa_trc(dport->bfa, 0);
6837                 return BFA_STATUS_DPORT_DISABLED;
6838
6839         } else {
6840                 if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6841                         return BFA_STATUS_DPORT_INV_SFP;
6842
6843                 if (dport->test_state == BFA_DPORT_ST_INP)
6844                         return BFA_STATUS_DEVBUSY;
6845
6846                 WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);
6847         }
6848
6849         bfa_trc(dport->bfa, lpcnt);
6850         bfa_trc(dport->bfa, pat);
6851
6852         dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6853         dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6854
6855         dport->cbfn = cbfn;
6856         dport->cbarg = cbarg;
6857
6858         bfa_sm_send_event(dport, BFA_DPORT_SM_START);
6859         return BFA_STATUS_OK;
6860 }
6861
6862 /*
6863  * Dport show -- return dport test result
6864  *
6865  *   @param[in] *bfa            - bfa data struct
6866  */
6867 bfa_status_t
6868 bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)
6869 {
6870         struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6871         struct bfa_dport_s *dport = &fcdiag->dport;
6872
6873         /*
6874          * Check to see if IOC is down
6875          */
6876         if (!bfa_iocfc_is_operational(bfa))
6877                 return BFA_STATUS_IOC_NON_OP;
6878
6879         /*
6880          * Check if dport is busy
6881          */
6882         if (bfa_dport_is_sending_req(dport))
6883                 return BFA_STATUS_DEVBUSY;
6884
6885         /*
6886          * Check if dport is in enabled state.
6887          */
6888         if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6889                 bfa_trc(dport->bfa, 0);
6890                 return BFA_STATUS_DPORT_DISABLED;
6891
6892         }
6893
6894         /*
6895          * Check if there is SFP
6896          */
6897         if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6898                 return BFA_STATUS_DPORT_INV_SFP;
6899
6900         memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));
6901
6902         return BFA_STATUS_OK;
6903 }