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