1d34921f88bf97348f0e086a71b338c5ecdce8c6
[linux-flexiantxendom0-3.2.10.git] / drivers / scsi / bfa / bfa_svc.c
1 /*
2  * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 #include "bfad_drv.h"
19 #include "bfa_plog.h"
20 #include "bfa_cs.h"
21 #include "bfa_modules.h"
22
23 BFA_TRC_FILE(HAL, FCXP);
24 BFA_MODULE(fcxp);
25 BFA_MODULE(sgpg);
26 BFA_MODULE(lps);
27 BFA_MODULE(fcport);
28 BFA_MODULE(rport);
29 BFA_MODULE(uf);
30
31 /*
32  * LPS related definitions
33  */
34 #define BFA_LPS_MIN_LPORTS      (1)
35 #define BFA_LPS_MAX_LPORTS      (256)
36
37 /*
38  * Maximum Vports supported per physical port or vf.
39  */
40 #define BFA_LPS_MAX_VPORTS_SUPP_CB  255
41 #define BFA_LPS_MAX_VPORTS_SUPP_CT  190
42
43
44 /*
45  * FC PORT related definitions
46  */
47 /*
48  * The port is considered disabled if corresponding physical port or IOC are
49  * disabled explicitly
50  */
51 #define BFA_PORT_IS_DISABLED(bfa) \
52         ((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
53         (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
54
55 /*
56  * BFA port state machine events
57  */
58 enum bfa_fcport_sm_event {
59         BFA_FCPORT_SM_START     = 1,    /*  start port state machine    */
60         BFA_FCPORT_SM_STOP      = 2,    /*  stop port state machine     */
61         BFA_FCPORT_SM_ENABLE    = 3,    /*  enable port         */
62         BFA_FCPORT_SM_DISABLE   = 4,    /*  disable port state machine */
63         BFA_FCPORT_SM_FWRSP     = 5,    /*  firmware enable/disable rsp */
64         BFA_FCPORT_SM_LINKUP    = 6,    /*  firmware linkup event       */
65         BFA_FCPORT_SM_LINKDOWN  = 7,    /*  firmware linkup down        */
66         BFA_FCPORT_SM_QRESUME   = 8,    /*  CQ space available  */
67         BFA_FCPORT_SM_HWFAIL    = 9,    /*  IOC h/w failure             */
68 };
69
70 /*
71  * BFA port link notification state machine events
72  */
73
74 enum bfa_fcport_ln_sm_event {
75         BFA_FCPORT_LN_SM_LINKUP         = 1,    /*  linkup event        */
76         BFA_FCPORT_LN_SM_LINKDOWN       = 2,    /*  linkdown event      */
77         BFA_FCPORT_LN_SM_NOTIFICATION   = 3     /*  done notification   */
78 };
79
80 /*
81  * RPORT related definitions
82  */
83 #define bfa_rport_offline_cb(__rp) do {                                 \
84         if ((__rp)->bfa->fcs)                                           \
85                 bfa_cb_rport_offline((__rp)->rport_drv);      \
86         else {                                                          \
87                 bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,              \
88                                 __bfa_cb_rport_offline, (__rp));      \
89         }                                                               \
90 } while (0)
91
92 #define bfa_rport_online_cb(__rp) do {                                  \
93         if ((__rp)->bfa->fcs)                                           \
94                 bfa_cb_rport_online((__rp)->rport_drv);      \
95         else {                                                          \
96                 bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,              \
97                                   __bfa_cb_rport_online, (__rp));      \
98                 }                                                       \
99 } while (0)
100
101 /*
102  * forward declarations FCXP related functions
103  */
104 static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
105 static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
106                                 struct bfi_fcxp_send_rsp_s *fcxp_rsp);
107 static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
108                                 struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
109 static void     bfa_fcxp_qresume(void *cbarg);
110 static void     bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
111                                 struct bfi_fcxp_send_req_s *send_req);
112
113 /*
114  * forward declarations for LPS functions
115  */
116 static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
117                                 u32 *dm_len);
118 static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
119                                 struct bfa_iocfc_cfg_s *cfg,
120                                 struct bfa_meminfo_s *meminfo,
121                                 struct bfa_pcidev_s *pcidev);
122 static void bfa_lps_detach(struct bfa_s *bfa);
123 static void bfa_lps_start(struct bfa_s *bfa);
124 static void bfa_lps_stop(struct bfa_s *bfa);
125 static void bfa_lps_iocdisable(struct bfa_s *bfa);
126 static void bfa_lps_login_rsp(struct bfa_s *bfa,
127                                 struct bfi_lps_login_rsp_s *rsp);
128 static void bfa_lps_logout_rsp(struct bfa_s *bfa,
129                                 struct bfi_lps_logout_rsp_s *rsp);
130 static void bfa_lps_reqq_resume(void *lps_arg);
131 static void bfa_lps_free(struct bfa_lps_s *lps);
132 static void bfa_lps_send_login(struct bfa_lps_s *lps);
133 static void bfa_lps_send_logout(struct bfa_lps_s *lps);
134 static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
135 static void bfa_lps_login_comp(struct bfa_lps_s *lps);
136 static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
137 static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
138
139 /*
140  * forward declaration for LPS state machine
141  */
142 static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
143 static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
144 static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
145                                         event);
146 static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
147 static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
148                                         enum bfa_lps_event event);
149 static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
150 static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
151                                         event);
152
153 /*
154  * forward declaration for FC Port functions
155  */
156 static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
157 static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
158 static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
159 static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
160 static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
161 static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
162 static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
163                         enum bfa_port_linkstate event, bfa_boolean_t trunk);
164 static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
165                                 enum bfa_port_linkstate event);
166 static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
167 static void bfa_fcport_stats_get_timeout(void *cbarg);
168 static void bfa_fcport_stats_clr_timeout(void *cbarg);
169 static void bfa_trunk_iocdisable(struct bfa_s *bfa);
170
171 /*
172  * forward declaration for FC PORT state machine
173  */
174 static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
175                                         enum bfa_fcport_sm_event event);
176 static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
177                                         enum bfa_fcport_sm_event event);
178 static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
179                                         enum bfa_fcport_sm_event event);
180 static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
181                                         enum bfa_fcport_sm_event event);
182 static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
183                                         enum bfa_fcport_sm_event event);
184 static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
185                                         enum bfa_fcport_sm_event event);
186 static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
187                                         enum bfa_fcport_sm_event event);
188 static void     bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
189                                         enum bfa_fcport_sm_event event);
190 static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
191                                         enum bfa_fcport_sm_event event);
192 static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
193                                         enum bfa_fcport_sm_event event);
194 static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
195                                         enum bfa_fcport_sm_event event);
196 static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
197                                         enum bfa_fcport_sm_event event);
198
199 static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
200                                         enum bfa_fcport_ln_sm_event event);
201 static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
202                                         enum bfa_fcport_ln_sm_event event);
203 static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
204                                         enum bfa_fcport_ln_sm_event event);
205 static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
206                                         enum bfa_fcport_ln_sm_event event);
207 static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
208                                         enum bfa_fcport_ln_sm_event event);
209 static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
210                                         enum bfa_fcport_ln_sm_event event);
211 static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
212                                         enum bfa_fcport_ln_sm_event event);
213
214 static struct bfa_sm_table_s hal_port_sm_table[] = {
215         {BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
216         {BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
217         {BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
218         {BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
219         {BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
220         {BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
221         {BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
222         {BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
223         {BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
224         {BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
225         {BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
226         {BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
227 };
228
229
230 /*
231  * forward declaration for RPORT related functions
232  */
233 static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
234 static void             bfa_rport_free(struct bfa_rport_s *rport);
235 static bfa_boolean_t    bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
236 static bfa_boolean_t    bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
237 static bfa_boolean_t    bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
238 static void             __bfa_cb_rport_online(void *cbarg,
239                                                 bfa_boolean_t complete);
240 static void             __bfa_cb_rport_offline(void *cbarg,
241                                                 bfa_boolean_t complete);
242
243 /*
244  * forward declaration for RPORT state machine
245  */
246 static void     bfa_rport_sm_uninit(struct bfa_rport_s *rp,
247                                         enum bfa_rport_event event);
248 static void     bfa_rport_sm_created(struct bfa_rport_s *rp,
249                                         enum bfa_rport_event event);
250 static void     bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
251                                         enum bfa_rport_event event);
252 static void     bfa_rport_sm_online(struct bfa_rport_s *rp,
253                                         enum bfa_rport_event event);
254 static void     bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
255                                         enum bfa_rport_event event);
256 static void     bfa_rport_sm_offline(struct bfa_rport_s *rp,
257                                         enum bfa_rport_event event);
258 static void     bfa_rport_sm_deleting(struct bfa_rport_s *rp,
259                                         enum bfa_rport_event event);
260 static void     bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
261                                         enum bfa_rport_event event);
262 static void     bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
263                                         enum bfa_rport_event event);
264 static void     bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
265                                         enum bfa_rport_event event);
266 static void     bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
267                                         enum bfa_rport_event event);
268 static void     bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
269                                         enum bfa_rport_event event);
270 static void     bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
271                                         enum bfa_rport_event event);
272
273 /*
274  * PLOG related definitions
275  */
276 static int
277 plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
278 {
279         if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
280                 (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
281                 return 1;
282
283         if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
284                 (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
285                 return 1;
286
287         return 0;
288 }
289
290 static u64
291 bfa_get_log_time(void)
292 {
293         u64 system_time = 0;
294         struct timeval tv;
295         do_gettimeofday(&tv);
296
297         /* We are interested in seconds only. */
298         system_time = tv.tv_sec;
299         return system_time;
300 }
301
302 static void
303 bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
304 {
305         u16 tail;
306         struct bfa_plog_rec_s *pl_recp;
307
308         if (plog->plog_enabled == 0)
309                 return;
310
311         if (plkd_validate_logrec(pl_rec)) {
312                 WARN_ON(1);
313                 return;
314         }
315
316         tail = plog->tail;
317
318         pl_recp = &(plog->plog_recs[tail]);
319
320         memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
321
322         pl_recp->tv = bfa_get_log_time();
323         BFA_PL_LOG_REC_INCR(plog->tail);
324
325         if (plog->head == plog->tail)
326                 BFA_PL_LOG_REC_INCR(plog->head);
327 }
328
329 void
330 bfa_plog_init(struct bfa_plog_s *plog)
331 {
332         memset((char *)plog, 0, sizeof(struct bfa_plog_s));
333
334         memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
335         plog->head = plog->tail = 0;
336         plog->plog_enabled = 1;
337 }
338
339 void
340 bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
341                 enum bfa_plog_eid event,
342                 u16 misc, char *log_str)
343 {
344         struct bfa_plog_rec_s  lp;
345
346         if (plog->plog_enabled) {
347                 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
348                 lp.mid = mid;
349                 lp.eid = event;
350                 lp.log_type = BFA_PL_LOG_TYPE_STRING;
351                 lp.misc = misc;
352                 strncpy(lp.log_entry.string_log, log_str,
353                         BFA_PL_STRING_LOG_SZ - 1);
354                 lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
355                 bfa_plog_add(plog, &lp);
356         }
357 }
358
359 void
360 bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
361                 enum bfa_plog_eid event,
362                 u16 misc, u32 *intarr, u32 num_ints)
363 {
364         struct bfa_plog_rec_s  lp;
365         u32 i;
366
367         if (num_ints > BFA_PL_INT_LOG_SZ)
368                 num_ints = BFA_PL_INT_LOG_SZ;
369
370         if (plog->plog_enabled) {
371                 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
372                 lp.mid = mid;
373                 lp.eid = event;
374                 lp.log_type = BFA_PL_LOG_TYPE_INT;
375                 lp.misc = misc;
376
377                 for (i = 0; i < num_ints; i++)
378                         lp.log_entry.int_log[i] = intarr[i];
379
380                 lp.log_num_ints = (u8) num_ints;
381
382                 bfa_plog_add(plog, &lp);
383         }
384 }
385
386 void
387 bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
388                         enum bfa_plog_eid event,
389                         u16 misc, struct fchs_s *fchdr)
390 {
391         struct bfa_plog_rec_s  lp;
392         u32     *tmp_int = (u32 *) fchdr;
393         u32     ints[BFA_PL_INT_LOG_SZ];
394
395         if (plog->plog_enabled) {
396                 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
397
398                 ints[0] = tmp_int[0];
399                 ints[1] = tmp_int[1];
400                 ints[2] = tmp_int[4];
401
402                 bfa_plog_intarr(plog, mid, event, misc, ints, 3);
403         }
404 }
405
406 void
407 bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
408                       enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
409                       u32 pld_w0)
410 {
411         struct bfa_plog_rec_s  lp;
412         u32     *tmp_int = (u32 *) fchdr;
413         u32     ints[BFA_PL_INT_LOG_SZ];
414
415         if (plog->plog_enabled) {
416                 memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
417
418                 ints[0] = tmp_int[0];
419                 ints[1] = tmp_int[1];
420                 ints[2] = tmp_int[4];
421                 ints[3] = pld_w0;
422
423                 bfa_plog_intarr(plog, mid, event, misc, ints, 4);
424         }
425 }
426
427
428 /*
429  *  fcxp_pvt BFA FCXP private functions
430  */
431
432 static void
433 claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
434 {
435         u8             *dm_kva = NULL;
436         u64     dm_pa;
437         u32     buf_pool_sz;
438
439         dm_kva = bfa_meminfo_dma_virt(mi);
440         dm_pa = bfa_meminfo_dma_phys(mi);
441
442         buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
443
444         /*
445          * Initialize the fcxp req payload list
446          */
447         mod->req_pld_list_kva = dm_kva;
448         mod->req_pld_list_pa = dm_pa;
449         dm_kva += buf_pool_sz;
450         dm_pa += buf_pool_sz;
451         memset(mod->req_pld_list_kva, 0, buf_pool_sz);
452
453         /*
454          * Initialize the fcxp rsp payload list
455          */
456         buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
457         mod->rsp_pld_list_kva = dm_kva;
458         mod->rsp_pld_list_pa = dm_pa;
459         dm_kva += buf_pool_sz;
460         dm_pa += buf_pool_sz;
461         memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
462
463         bfa_meminfo_dma_virt(mi) = dm_kva;
464         bfa_meminfo_dma_phys(mi) = dm_pa;
465 }
466
467 static void
468 claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
469 {
470         u16     i;
471         struct bfa_fcxp_s *fcxp;
472
473         fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
474         memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
475
476         INIT_LIST_HEAD(&mod->fcxp_free_q);
477         INIT_LIST_HEAD(&mod->fcxp_active_q);
478
479         mod->fcxp_list = fcxp;
480
481         for (i = 0; i < mod->num_fcxps; i++) {
482                 fcxp->fcxp_mod = mod;
483                 fcxp->fcxp_tag = i;
484
485                 list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
486                 bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
487                 fcxp->reqq_waiting = BFA_FALSE;
488
489                 fcxp = fcxp + 1;
490         }
491
492         bfa_meminfo_kva(mi) = (void *)fcxp;
493 }
494
495 static void
496 bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
497                  u32 *dm_len)
498 {
499         u16     num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
500
501         if (num_fcxp_reqs == 0)
502                 return;
503
504         /*
505          * Account for req/rsp payload
506          */
507         *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
508         if (cfg->drvcfg.min_cfg)
509                 *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
510         else
511                 *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
512
513         /*
514          * Account for fcxp structs
515          */
516         *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
517 }
518
519 static void
520 bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
521                 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
522 {
523         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
524
525         memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
526         mod->bfa = bfa;
527         mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
528
529         /*
530          * Initialize FCXP request and response payload sizes.
531          */
532         mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
533         if (!cfg->drvcfg.min_cfg)
534                 mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
535
536         INIT_LIST_HEAD(&mod->wait_q);
537
538         claim_fcxp_req_rsp_mem(mod, meminfo);
539         claim_fcxps_mem(mod, meminfo);
540 }
541
542 static void
543 bfa_fcxp_detach(struct bfa_s *bfa)
544 {
545 }
546
547 static void
548 bfa_fcxp_start(struct bfa_s *bfa)
549 {
550 }
551
552 static void
553 bfa_fcxp_stop(struct bfa_s *bfa)
554 {
555 }
556
557 static void
558 bfa_fcxp_iocdisable(struct bfa_s *bfa)
559 {
560         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
561         struct bfa_fcxp_s *fcxp;
562         struct list_head              *qe, *qen;
563
564         list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
565                 fcxp = (struct bfa_fcxp_s *) qe;
566                 if (fcxp->caller == NULL) {
567                         fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
568                                         BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
569                         bfa_fcxp_free(fcxp);
570                 } else {
571                         fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
572                         bfa_cb_queue(bfa, &fcxp->hcb_qe,
573                                      __bfa_fcxp_send_cbfn, fcxp);
574                 }
575         }
576 }
577
578 static struct bfa_fcxp_s *
579 bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
580 {
581         struct bfa_fcxp_s *fcxp;
582
583         bfa_q_deq(&fm->fcxp_free_q, &fcxp);
584
585         if (fcxp)
586                 list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
587
588         return fcxp;
589 }
590
591 static void
592 bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
593                struct bfa_s *bfa,
594                u8 *use_ibuf,
595                u32 *nr_sgles,
596                bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
597                bfa_fcxp_get_sglen_t *r_sglen_cbfn,
598                struct list_head *r_sgpg_q,
599                int n_sgles,
600                bfa_fcxp_get_sgaddr_t sga_cbfn,
601                bfa_fcxp_get_sglen_t sglen_cbfn)
602 {
603
604         WARN_ON(bfa == NULL);
605
606         bfa_trc(bfa, fcxp->fcxp_tag);
607
608         if (n_sgles == 0) {
609                 *use_ibuf = 1;
610         } else {
611                 WARN_ON(*sga_cbfn == NULL);
612                 WARN_ON(*sglen_cbfn == NULL);
613
614                 *use_ibuf = 0;
615                 *r_sga_cbfn = sga_cbfn;
616                 *r_sglen_cbfn = sglen_cbfn;
617
618                 *nr_sgles = n_sgles;
619
620                 /*
621                  * alloc required sgpgs
622                  */
623                 if (n_sgles > BFI_SGE_INLINE)
624                         WARN_ON(1);
625         }
626
627 }
628
629 static void
630 bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
631                void *caller, struct bfa_s *bfa, int nreq_sgles,
632                int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
633                bfa_fcxp_get_sglen_t req_sglen_cbfn,
634                bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
635                bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
636 {
637
638         WARN_ON(bfa == NULL);
639
640         bfa_trc(bfa, fcxp->fcxp_tag);
641
642         fcxp->caller = caller;
643
644         bfa_fcxp_init_reqrsp(fcxp, bfa,
645                 &fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
646                 &fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
647                 nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
648
649         bfa_fcxp_init_reqrsp(fcxp, bfa,
650                 &fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
651                 &fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
652                 nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
653
654 }
655
656 static void
657 bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
658 {
659         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
660         struct bfa_fcxp_wqe_s *wqe;
661
662         bfa_q_deq(&mod->wait_q, &wqe);
663         if (wqe) {
664                 bfa_trc(mod->bfa, fcxp->fcxp_tag);
665
666                 bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
667                         wqe->nrsp_sgles, wqe->req_sga_cbfn,
668                         wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
669                         wqe->rsp_sglen_cbfn);
670
671                 wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
672                 return;
673         }
674
675         WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
676         list_del(&fcxp->qe);
677         list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
678 }
679
680 static void
681 bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
682                    bfa_status_t req_status, u32 rsp_len,
683                    u32 resid_len, struct fchs_s *rsp_fchs)
684 {
685         /* discarded fcxp completion */
686 }
687
688 static void
689 __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
690 {
691         struct bfa_fcxp_s *fcxp = cbarg;
692
693         if (complete) {
694                 fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
695                                 fcxp->rsp_status, fcxp->rsp_len,
696                                 fcxp->residue_len, &fcxp->rsp_fchs);
697         } else {
698                 bfa_fcxp_free(fcxp);
699         }
700 }
701
702 static void
703 hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
704 {
705         struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
706         struct bfa_fcxp_s       *fcxp;
707         u16             fcxp_tag = be16_to_cpu(fcxp_rsp->fcxp_tag);
708
709         bfa_trc(bfa, fcxp_tag);
710
711         fcxp_rsp->rsp_len = be32_to_cpu(fcxp_rsp->rsp_len);
712
713         /*
714          * @todo f/w should not set residue to non-0 when everything
715          *       is received.
716          */
717         if (fcxp_rsp->req_status == BFA_STATUS_OK)
718                 fcxp_rsp->residue_len = 0;
719         else
720                 fcxp_rsp->residue_len = be32_to_cpu(fcxp_rsp->residue_len);
721
722         fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
723
724         WARN_ON(fcxp->send_cbfn == NULL);
725
726         hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
727
728         if (fcxp->send_cbfn != NULL) {
729                 bfa_trc(mod->bfa, (NULL == fcxp->caller));
730                 if (fcxp->caller == NULL) {
731                         fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
732                                         fcxp_rsp->req_status, fcxp_rsp->rsp_len,
733                                         fcxp_rsp->residue_len, &fcxp_rsp->fchs);
734                         /*
735                          * fcxp automatically freed on return from the callback
736                          */
737                         bfa_fcxp_free(fcxp);
738                 } else {
739                         fcxp->rsp_status = fcxp_rsp->req_status;
740                         fcxp->rsp_len = fcxp_rsp->rsp_len;
741                         fcxp->residue_len = fcxp_rsp->residue_len;
742                         fcxp->rsp_fchs = fcxp_rsp->fchs;
743
744                         bfa_cb_queue(bfa, &fcxp->hcb_qe,
745                                         __bfa_fcxp_send_cbfn, fcxp);
746                 }
747         } else {
748                 bfa_trc(bfa, (NULL == fcxp->send_cbfn));
749         }
750 }
751
752 static void
753 hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
754 {
755         union bfi_addr_u      sga_zero = { {0} };
756
757         sge->sg_len = reqlen;
758         sge->flags = BFI_SGE_DATA_LAST;
759         bfa_dma_addr_set(sge[0].sga, req_pa);
760         bfa_sge_to_be(sge);
761         sge++;
762
763         sge->sga = sga_zero;
764         sge->sg_len = reqlen;
765         sge->flags = BFI_SGE_PGDLEN;
766         bfa_sge_to_be(sge);
767 }
768
769 static void
770 hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
771                  struct fchs_s *fchs)
772 {
773         /*
774          * TODO: TX ox_id
775          */
776         if (reqlen > 0) {
777                 if (fcxp->use_ireqbuf) {
778                         u32     pld_w0 =
779                                 *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
780
781                         bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
782                                         BFA_PL_EID_TX,
783                                         reqlen + sizeof(struct fchs_s), fchs,
784                                         pld_w0);
785                 } else {
786                         bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
787                                         BFA_PL_EID_TX,
788                                         reqlen + sizeof(struct fchs_s),
789                                         fchs);
790                 }
791         } else {
792                 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
793                                reqlen + sizeof(struct fchs_s), fchs);
794         }
795 }
796
797 static void
798 hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
799                  struct bfi_fcxp_send_rsp_s *fcxp_rsp)
800 {
801         if (fcxp_rsp->rsp_len > 0) {
802                 if (fcxp->use_irspbuf) {
803                         u32     pld_w0 =
804                                 *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
805
806                         bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
807                                               BFA_PL_EID_RX,
808                                               (u16) fcxp_rsp->rsp_len,
809                                               &fcxp_rsp->fchs, pld_w0);
810                 } else {
811                         bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
812                                        BFA_PL_EID_RX,
813                                        (u16) fcxp_rsp->rsp_len,
814                                        &fcxp_rsp->fchs);
815                 }
816         } else {
817                 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
818                                (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
819         }
820 }
821
822 /*
823  * Handler to resume sending fcxp when space in available in cpe queue.
824  */
825 static void
826 bfa_fcxp_qresume(void *cbarg)
827 {
828         struct bfa_fcxp_s               *fcxp = cbarg;
829         struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
830         struct bfi_fcxp_send_req_s      *send_req;
831
832         fcxp->reqq_waiting = BFA_FALSE;
833         send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
834         bfa_fcxp_queue(fcxp, send_req);
835 }
836
837 /*
838  * Queue fcxp send request to foimrware.
839  */
840 static void
841 bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
842 {
843         struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
844         struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
845         struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
846         struct bfa_rport_s              *rport = reqi->bfa_rport;
847
848         bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
849                     bfa_lpuid(bfa));
850
851         send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
852         if (rport) {
853                 send_req->rport_fw_hndl = rport->fw_handle;
854                 send_req->max_frmsz = cpu_to_be16(rport->rport_info.max_frmsz);
855                 if (send_req->max_frmsz == 0)
856                         send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
857         } else {
858                 send_req->rport_fw_hndl = 0;
859                 send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
860         }
861
862         send_req->vf_id = cpu_to_be16(reqi->vf_id);
863         send_req->lp_tag = reqi->lp_tag;
864         send_req->class = reqi->class;
865         send_req->rsp_timeout = rspi->rsp_timeout;
866         send_req->cts = reqi->cts;
867         send_req->fchs = reqi->fchs;
868
869         send_req->req_len = cpu_to_be32(reqi->req_tot_len);
870         send_req->rsp_maxlen = cpu_to_be32(rspi->rsp_maxlen);
871
872         /*
873          * setup req sgles
874          */
875         if (fcxp->use_ireqbuf == 1) {
876                 hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
877                                         BFA_FCXP_REQ_PLD_PA(fcxp));
878         } else {
879                 if (fcxp->nreq_sgles > 0) {
880                         WARN_ON(fcxp->nreq_sgles != 1);
881                         hal_fcxp_set_local_sges(send_req->req_sge,
882                                                 reqi->req_tot_len,
883                                                 fcxp->req_sga_cbfn(fcxp->caller,
884                                                                    0));
885                 } else {
886                         WARN_ON(reqi->req_tot_len != 0);
887                         hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
888                 }
889         }
890
891         /*
892          * setup rsp sgles
893          */
894         if (fcxp->use_irspbuf == 1) {
895                 WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
896
897                 hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
898                                         BFA_FCXP_RSP_PLD_PA(fcxp));
899
900         } else {
901                 if (fcxp->nrsp_sgles > 0) {
902                         WARN_ON(fcxp->nrsp_sgles != 1);
903                         hal_fcxp_set_local_sges(send_req->rsp_sge,
904                                                 rspi->rsp_maxlen,
905                                                 fcxp->rsp_sga_cbfn(fcxp->caller,
906                                                                    0));
907                 } else {
908                         WARN_ON(rspi->rsp_maxlen != 0);
909                         hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
910                 }
911         }
912
913         hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
914
915         bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
916
917         bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
918         bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
919 }
920
921 /*
922  * Allocate an FCXP instance to send a response or to send a request
923  * that has a response. Request/response buffers are allocated by caller.
924  *
925  * @param[in]   bfa             BFA bfa instance
926  * @param[in]   nreq_sgles      Number of SG elements required for request
927  *                              buffer. 0, if fcxp internal buffers are used.
928  *                              Use bfa_fcxp_get_reqbuf() to get the
929  *                              internal req buffer.
930  * @param[in]   req_sgles       SG elements describing request buffer. Will be
931  *                              copied in by BFA and hence can be freed on
932  *                              return from this function.
933  * @param[in]   get_req_sga     function ptr to be called to get a request SG
934  *                              Address (given the sge index).
935  * @param[in]   get_req_sglen   function ptr to be called to get a request SG
936  *                              len (given the sge index).
937  * @param[in]   get_rsp_sga     function ptr to be called to get a response SG
938  *                              Address (given the sge index).
939  * @param[in]   get_rsp_sglen   function ptr to be called to get a response SG
940  *                              len (given the sge index).
941  *
942  * @return FCXP instance. NULL on failure.
943  */
944 struct bfa_fcxp_s *
945 bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
946                int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
947                bfa_fcxp_get_sglen_t req_sglen_cbfn,
948                bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
949                bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
950 {
951         struct bfa_fcxp_s *fcxp = NULL;
952
953         WARN_ON(bfa == NULL);
954
955         fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
956         if (fcxp == NULL)
957                 return NULL;
958
959         bfa_trc(bfa, fcxp->fcxp_tag);
960
961         bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
962                         req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
963
964         return fcxp;
965 }
966
967 /*
968  * Get the internal request buffer pointer
969  *
970  * @param[in]   fcxp    BFA fcxp pointer
971  *
972  * @return              pointer to the internal request buffer
973  */
974 void *
975 bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
976 {
977         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
978         void    *reqbuf;
979
980         WARN_ON(fcxp->use_ireqbuf != 1);
981         reqbuf = ((u8 *)mod->req_pld_list_kva) +
982                 fcxp->fcxp_tag * mod->req_pld_sz;
983         return reqbuf;
984 }
985
986 u32
987 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
988 {
989         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
990
991         return mod->req_pld_sz;
992 }
993
994 /*
995  * Get the internal response buffer pointer
996  *
997  * @param[in]   fcxp    BFA fcxp pointer
998  *
999  * @return              pointer to the internal request buffer
1000  */
1001 void *
1002 bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
1003 {
1004         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
1005         void    *rspbuf;
1006
1007         WARN_ON(fcxp->use_irspbuf != 1);
1008
1009         rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
1010                 fcxp->fcxp_tag * mod->rsp_pld_sz;
1011         return rspbuf;
1012 }
1013
1014 /*
1015  * Free the BFA FCXP
1016  *
1017  * @param[in]   fcxp                    BFA fcxp pointer
1018  *
1019  * @return              void
1020  */
1021 void
1022 bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
1023 {
1024         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
1025
1026         WARN_ON(fcxp == NULL);
1027         bfa_trc(mod->bfa, fcxp->fcxp_tag);
1028         bfa_fcxp_put(fcxp);
1029 }
1030
1031 /*
1032  * Send a FCXP request
1033  *
1034  * @param[in]   fcxp    BFA fcxp pointer
1035  * @param[in]   rport   BFA rport pointer. Could be left NULL for WKA rports
1036  * @param[in]   vf_id   virtual Fabric ID
1037  * @param[in]   lp_tag  lport tag
1038  * @param[in]   cts     use Continous sequence
1039  * @param[in]   cos     fc Class of Service
1040  * @param[in]   reqlen  request length, does not include FCHS length
1041  * @param[in]   fchs    fc Header Pointer. The header content will be copied
1042  *                      in by BFA.
1043  *
1044  * @param[in]   cbfn    call back function to be called on receiving
1045  *                                                              the response
1046  * @param[in]   cbarg   arg for cbfn
1047  * @param[in]   rsp_timeout
1048  *                      response timeout
1049  *
1050  * @return              bfa_status_t
1051  */
1052 void
1053 bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
1054               u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
1055               u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
1056               void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
1057 {
1058         struct bfa_s                    *bfa  = fcxp->fcxp_mod->bfa;
1059         struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
1060         struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
1061         struct bfi_fcxp_send_req_s      *send_req;
1062
1063         bfa_trc(bfa, fcxp->fcxp_tag);
1064
1065         /*
1066          * setup request/response info
1067          */
1068         reqi->bfa_rport = rport;
1069         reqi->vf_id = vf_id;
1070         reqi->lp_tag = lp_tag;
1071         reqi->class = cos;
1072         rspi->rsp_timeout = rsp_timeout;
1073         reqi->cts = cts;
1074         reqi->fchs = *fchs;
1075         reqi->req_tot_len = reqlen;
1076         rspi->rsp_maxlen = rsp_maxlen;
1077         fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
1078         fcxp->send_cbarg = cbarg;
1079
1080         /*
1081          * If no room in CPE queue, wait for space in request queue
1082          */
1083         send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
1084         if (!send_req) {
1085                 bfa_trc(bfa, fcxp->fcxp_tag);
1086                 fcxp->reqq_waiting = BFA_TRUE;
1087                 bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
1088                 return;
1089         }
1090
1091         bfa_fcxp_queue(fcxp, send_req);
1092 }
1093
1094 /*
1095  * Abort a BFA FCXP
1096  *
1097  * @param[in]   fcxp    BFA fcxp pointer
1098  *
1099  * @return              void
1100  */
1101 bfa_status_t
1102 bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
1103 {
1104         bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
1105         WARN_ON(1);
1106         return BFA_STATUS_OK;
1107 }
1108
1109 void
1110 bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1111                bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1112                void *caller, int nreq_sgles,
1113                int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1114                bfa_fcxp_get_sglen_t req_sglen_cbfn,
1115                bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1116                bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
1117 {
1118         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1119
1120         WARN_ON(!list_empty(&mod->fcxp_free_q));
1121
1122         wqe->alloc_cbfn = alloc_cbfn;
1123         wqe->alloc_cbarg = alloc_cbarg;
1124         wqe->caller = caller;
1125         wqe->bfa = bfa;
1126         wqe->nreq_sgles = nreq_sgles;
1127         wqe->nrsp_sgles = nrsp_sgles;
1128         wqe->req_sga_cbfn = req_sga_cbfn;
1129         wqe->req_sglen_cbfn = req_sglen_cbfn;
1130         wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1131         wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1132
1133         list_add_tail(&wqe->qe, &mod->wait_q);
1134 }
1135
1136 void
1137 bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1138 {
1139         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1140
1141         WARN_ON(!bfa_q_is_on_q(&mod->wait_q, wqe));
1142         list_del(&wqe->qe);
1143 }
1144
1145 void
1146 bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
1147 {
1148         /*
1149          * If waiting for room in request queue, cancel reqq wait
1150          * and free fcxp.
1151          */
1152         if (fcxp->reqq_waiting) {
1153                 fcxp->reqq_waiting = BFA_FALSE;
1154                 bfa_reqq_wcancel(&fcxp->reqq_wqe);
1155                 bfa_fcxp_free(fcxp);
1156                 return;
1157         }
1158
1159         fcxp->send_cbfn = bfa_fcxp_null_comp;
1160 }
1161
1162 void
1163 bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
1164 {
1165         switch (msg->mhdr.msg_id) {
1166         case BFI_FCXP_I2H_SEND_RSP:
1167                 hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
1168                 break;
1169
1170         default:
1171                 bfa_trc(bfa, msg->mhdr.msg_id);
1172                 WARN_ON(1);
1173         }
1174 }
1175
1176 u32
1177 bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
1178 {
1179         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1180
1181         return mod->rsp_pld_sz;
1182 }
1183
1184
1185 /*
1186  *  BFA LPS state machine functions
1187  */
1188
1189 /*
1190  * Init state -- no login
1191  */
1192 static void
1193 bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
1194 {
1195         bfa_trc(lps->bfa, lps->lp_tag);
1196         bfa_trc(lps->bfa, event);
1197
1198         switch (event) {
1199         case BFA_LPS_SM_LOGIN:
1200                 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1201                         bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
1202                         bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1203                 } else {
1204                         bfa_sm_set_state(lps, bfa_lps_sm_login);
1205                         bfa_lps_send_login(lps);
1206                 }
1207
1208                 if (lps->fdisc)
1209                         bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1210                                 BFA_PL_EID_LOGIN, 0, "FDISC Request");
1211                 else
1212                         bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1213                                 BFA_PL_EID_LOGIN, 0, "FLOGI Request");
1214                 break;
1215
1216         case BFA_LPS_SM_LOGOUT:
1217                 bfa_lps_logout_comp(lps);
1218                 break;
1219
1220         case BFA_LPS_SM_DELETE:
1221                 bfa_lps_free(lps);
1222                 break;
1223
1224         case BFA_LPS_SM_RX_CVL:
1225         case BFA_LPS_SM_OFFLINE:
1226                 break;
1227
1228         case BFA_LPS_SM_FWRSP:
1229                 /*
1230                  * Could happen when fabric detects loopback and discards
1231                  * the lps request. Fw will eventually sent out the timeout
1232                  * Just ignore
1233                  */
1234                 break;
1235
1236         default:
1237                 bfa_sm_fault(lps->bfa, event);
1238         }
1239 }
1240
1241 /*
1242  * login is in progress -- awaiting response from firmware
1243  */
1244 static void
1245 bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1246 {
1247         bfa_trc(lps->bfa, lps->lp_tag);
1248         bfa_trc(lps->bfa, event);
1249
1250         switch (event) {
1251         case BFA_LPS_SM_FWRSP:
1252                 if (lps->status == BFA_STATUS_OK) {
1253                         bfa_sm_set_state(lps, bfa_lps_sm_online);
1254                         if (lps->fdisc)
1255                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1256                                         BFA_PL_EID_LOGIN, 0, "FDISC Accept");
1257                         else
1258                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1259                                         BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
1260                         /* If N2N, send the assigned PID to FW */
1261                         bfa_trc(lps->bfa, lps->fport);
1262                         bfa_trc(lps->bfa, lps->lp_pid);
1263
1264                         if (!lps->fport && lps->lp_pid)
1265                                 bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1266                 } else {
1267                         bfa_sm_set_state(lps, bfa_lps_sm_init);
1268                         if (lps->fdisc)
1269                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1270                                         BFA_PL_EID_LOGIN, 0,
1271                                         "FDISC Fail (RJT or timeout)");
1272                         else
1273                                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1274                                         BFA_PL_EID_LOGIN, 0,
1275                                         "FLOGI Fail (RJT or timeout)");
1276                 }
1277                 bfa_lps_login_comp(lps);
1278                 break;
1279
1280         case BFA_LPS_SM_OFFLINE:
1281                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1282                 break;
1283
1284         case BFA_LPS_SM_SET_N2N_PID:
1285                 bfa_trc(lps->bfa, lps->fport);
1286                 bfa_trc(lps->bfa, lps->lp_pid);
1287                 break;
1288
1289         default:
1290                 bfa_sm_fault(lps->bfa, event);
1291         }
1292 }
1293
1294 /*
1295  * login pending - awaiting space in request queue
1296  */
1297 static void
1298 bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1299 {
1300         bfa_trc(lps->bfa, lps->lp_tag);
1301         bfa_trc(lps->bfa, event);
1302
1303         switch (event) {
1304         case BFA_LPS_SM_RESUME:
1305                 bfa_sm_set_state(lps, bfa_lps_sm_login);
1306                 break;
1307
1308         case BFA_LPS_SM_OFFLINE:
1309                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1310                 bfa_reqq_wcancel(&lps->wqe);
1311                 break;
1312
1313         case BFA_LPS_SM_RX_CVL:
1314                 /*
1315                  * Login was not even sent out; so when getting out
1316                  * of this state, it will appear like a login retry
1317                  * after Clear virtual link
1318                  */
1319                 break;
1320
1321         default:
1322                 bfa_sm_fault(lps->bfa, event);
1323         }
1324 }
1325
1326 /*
1327  * login complete
1328  */
1329 static void
1330 bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
1331 {
1332         bfa_trc(lps->bfa, lps->lp_tag);
1333         bfa_trc(lps->bfa, event);
1334
1335         switch (event) {
1336         case BFA_LPS_SM_LOGOUT:
1337                 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1338                         bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1339                         bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1340                 } else {
1341                         bfa_sm_set_state(lps, bfa_lps_sm_logout);
1342                         bfa_lps_send_logout(lps);
1343                 }
1344                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1345                         BFA_PL_EID_LOGO, 0, "Logout");
1346                 break;
1347
1348         case BFA_LPS_SM_RX_CVL:
1349                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1350
1351                 /* Let the vport module know about this event */
1352                 bfa_lps_cvl_event(lps);
1353                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1354                         BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1355                 break;
1356
1357         case BFA_LPS_SM_SET_N2N_PID:
1358                 if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1359                         bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
1360                         bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1361                 } else
1362                         bfa_lps_send_set_n2n_pid(lps);
1363                 break;
1364
1365         case BFA_LPS_SM_OFFLINE:
1366         case BFA_LPS_SM_DELETE:
1367                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1368                 break;
1369
1370         default:
1371                 bfa_sm_fault(lps->bfa, event);
1372         }
1373 }
1374
1375 /*
1376  * login complete
1377  */
1378 static void
1379 bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1380 {
1381         bfa_trc(lps->bfa, lps->lp_tag);
1382         bfa_trc(lps->bfa, event);
1383
1384         switch (event) {
1385         case BFA_LPS_SM_RESUME:
1386                 bfa_sm_set_state(lps, bfa_lps_sm_online);
1387                 bfa_lps_send_set_n2n_pid(lps);
1388                 break;
1389
1390         case BFA_LPS_SM_LOGOUT:
1391                 bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1392                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1393                         BFA_PL_EID_LOGO, 0, "Logout");
1394                 break;
1395
1396         case BFA_LPS_SM_RX_CVL:
1397                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1398                 bfa_reqq_wcancel(&lps->wqe);
1399
1400                 /* Let the vport module know about this event */
1401                 bfa_lps_cvl_event(lps);
1402                 bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1403                         BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1404                 break;
1405
1406         case BFA_LPS_SM_OFFLINE:
1407         case BFA_LPS_SM_DELETE:
1408                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1409                 bfa_reqq_wcancel(&lps->wqe);
1410                 break;
1411
1412         default:
1413                 bfa_sm_fault(lps->bfa, event);
1414         }
1415 }
1416
1417 /*
1418  * logout in progress - awaiting firmware response
1419  */
1420 static void
1421 bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1422 {
1423         bfa_trc(lps->bfa, lps->lp_tag);
1424         bfa_trc(lps->bfa, event);
1425
1426         switch (event) {
1427         case BFA_LPS_SM_FWRSP:
1428                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1429                 bfa_lps_logout_comp(lps);
1430                 break;
1431
1432         case BFA_LPS_SM_OFFLINE:
1433                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1434                 break;
1435
1436         default:
1437                 bfa_sm_fault(lps->bfa, event);
1438         }
1439 }
1440
1441 /*
1442  * logout pending -- awaiting space in request queue
1443  */
1444 static void
1445 bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1446 {
1447         bfa_trc(lps->bfa, lps->lp_tag);
1448         bfa_trc(lps->bfa, event);
1449
1450         switch (event) {
1451         case BFA_LPS_SM_RESUME:
1452                 bfa_sm_set_state(lps, bfa_lps_sm_logout);
1453                 bfa_lps_send_logout(lps);
1454                 break;
1455
1456         case BFA_LPS_SM_OFFLINE:
1457                 bfa_sm_set_state(lps, bfa_lps_sm_init);
1458                 bfa_reqq_wcancel(&lps->wqe);
1459                 break;
1460
1461         default:
1462                 bfa_sm_fault(lps->bfa, event);
1463         }
1464 }
1465
1466
1467
1468 /*
1469  *  lps_pvt BFA LPS private functions
1470  */
1471
1472 /*
1473  * return memory requirement
1474  */
1475 static void
1476 bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
1477         u32 *dm_len)
1478 {
1479         if (cfg->drvcfg.min_cfg)
1480                 *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
1481         else
1482                 *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
1483 }
1484
1485 /*
1486  * bfa module attach at initialization time
1487  */
1488 static void
1489 bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1490         struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
1491 {
1492         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1493         struct bfa_lps_s        *lps;
1494         int                     i;
1495
1496         memset(mod, 0, sizeof(struct bfa_lps_mod_s));
1497         mod->num_lps = BFA_LPS_MAX_LPORTS;
1498         if (cfg->drvcfg.min_cfg)
1499                 mod->num_lps = BFA_LPS_MIN_LPORTS;
1500         else
1501                 mod->num_lps = BFA_LPS_MAX_LPORTS;
1502         mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
1503
1504         bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
1505
1506         INIT_LIST_HEAD(&mod->lps_free_q);
1507         INIT_LIST_HEAD(&mod->lps_active_q);
1508
1509         for (i = 0; i < mod->num_lps; i++, lps++) {
1510                 lps->bfa        = bfa;
1511                 lps->lp_tag     = (u8) i;
1512                 lps->reqq       = BFA_REQQ_LPS;
1513                 bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
1514                 list_add_tail(&lps->qe, &mod->lps_free_q);
1515         }
1516 }
1517
1518 static void
1519 bfa_lps_detach(struct bfa_s *bfa)
1520 {
1521 }
1522
1523 static void
1524 bfa_lps_start(struct bfa_s *bfa)
1525 {
1526 }
1527
1528 static void
1529 bfa_lps_stop(struct bfa_s *bfa)
1530 {
1531 }
1532
1533 /*
1534  * IOC in disabled state -- consider all lps offline
1535  */
1536 static void
1537 bfa_lps_iocdisable(struct bfa_s *bfa)
1538 {
1539         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1540         struct bfa_lps_s        *lps;
1541         struct list_head                *qe, *qen;
1542
1543         list_for_each_safe(qe, qen, &mod->lps_active_q) {
1544                 lps = (struct bfa_lps_s *) qe;
1545                 bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1546         }
1547 }
1548
1549 /*
1550  * Firmware login response
1551  */
1552 static void
1553 bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1554 {
1555         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1556         struct bfa_lps_s        *lps;
1557
1558         WARN_ON(rsp->lp_tag >= mod->num_lps);
1559         lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
1560
1561         lps->status = rsp->status;
1562         switch (rsp->status) {
1563         case BFA_STATUS_OK:
1564                 lps->fport      = rsp->f_port;
1565                 if (lps->fport)
1566                         lps->lp_pid = rsp->lp_pid;
1567                 lps->npiv_en    = rsp->npiv_en;
1568                 lps->pr_bbcred  = be16_to_cpu(rsp->bb_credit);
1569                 lps->pr_pwwn    = rsp->port_name;
1570                 lps->pr_nwwn    = rsp->node_name;
1571                 lps->auth_req   = rsp->auth_req;
1572                 lps->lp_mac     = rsp->lp_mac;
1573                 lps->brcd_switch = rsp->brcd_switch;
1574                 lps->fcf_mac    = rsp->fcf_mac;
1575
1576                 break;
1577
1578         case BFA_STATUS_FABRIC_RJT:
1579                 lps->lsrjt_rsn = rsp->lsrjt_rsn;
1580                 lps->lsrjt_expl = rsp->lsrjt_expl;
1581
1582                 break;
1583
1584         case BFA_STATUS_EPROTOCOL:
1585                 lps->ext_status = rsp->ext_status;
1586
1587                 break;
1588
1589         default:
1590                 /* Nothing to do with other status */
1591                 break;
1592         }
1593
1594         bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1595 }
1596
1597 /*
1598  * Firmware logout response
1599  */
1600 static void
1601 bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
1602 {
1603         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1604         struct bfa_lps_s        *lps;
1605
1606         WARN_ON(rsp->lp_tag >= mod->num_lps);
1607         lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
1608
1609         bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1610 }
1611
1612 /*
1613  * Firmware received a Clear virtual link request (for FCoE)
1614  */
1615 static void
1616 bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
1617 {
1618         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1619         struct bfa_lps_s        *lps;
1620
1621         lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
1622
1623         bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
1624 }
1625
1626 /*
1627  * Space is available in request queue, resume queueing request to firmware.
1628  */
1629 static void
1630 bfa_lps_reqq_resume(void *lps_arg)
1631 {
1632         struct bfa_lps_s        *lps = lps_arg;
1633
1634         bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
1635 }
1636
1637 /*
1638  * lps is freed -- triggered by vport delete
1639  */
1640 static void
1641 bfa_lps_free(struct bfa_lps_s *lps)
1642 {
1643         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
1644
1645         lps->lp_pid = 0;
1646         list_del(&lps->qe);
1647         list_add_tail(&lps->qe, &mod->lps_free_q);
1648 }
1649
1650 /*
1651  * send login request to firmware
1652  */
1653 static void
1654 bfa_lps_send_login(struct bfa_lps_s *lps)
1655 {
1656         struct bfi_lps_login_req_s      *m;
1657
1658         m = bfa_reqq_next(lps->bfa, lps->reqq);
1659         WARN_ON(!m);
1660
1661         bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
1662                 bfa_lpuid(lps->bfa));
1663
1664         m->lp_tag       = lps->lp_tag;
1665         m->alpa         = lps->alpa;
1666         m->pdu_size     = cpu_to_be16(lps->pdusz);
1667         m->pwwn         = lps->pwwn;
1668         m->nwwn         = lps->nwwn;
1669         m->fdisc        = lps->fdisc;
1670         m->auth_en      = lps->auth_en;
1671
1672         bfa_reqq_produce(lps->bfa, lps->reqq);
1673 }
1674
1675 /*
1676  * send logout request to firmware
1677  */
1678 static void
1679 bfa_lps_send_logout(struct bfa_lps_s *lps)
1680 {
1681         struct bfi_lps_logout_req_s *m;
1682
1683         m = bfa_reqq_next(lps->bfa, lps->reqq);
1684         WARN_ON(!m);
1685
1686         bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
1687                 bfa_lpuid(lps->bfa));
1688
1689         m->lp_tag    = lps->lp_tag;
1690         m->port_name = lps->pwwn;
1691         bfa_reqq_produce(lps->bfa, lps->reqq);
1692 }
1693
1694 /*
1695  * send n2n pid set request to firmware
1696  */
1697 static void
1698 bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
1699 {
1700         struct bfi_lps_n2n_pid_req_s *m;
1701
1702         m = bfa_reqq_next(lps->bfa, lps->reqq);
1703         WARN_ON(!m);
1704
1705         bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
1706                 bfa_lpuid(lps->bfa));
1707
1708         m->lp_tag = lps->lp_tag;
1709         m->lp_pid = lps->lp_pid;
1710         bfa_reqq_produce(lps->bfa, lps->reqq);
1711 }
1712
1713 /*
1714  * Indirect login completion handler for non-fcs
1715  */
1716 static void
1717 bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
1718 {
1719         struct bfa_lps_s *lps   = arg;
1720
1721         if (!complete)
1722                 return;
1723
1724         if (lps->fdisc)
1725                 bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1726         else
1727                 bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1728 }
1729
1730 /*
1731  * Login completion handler -- direct call for fcs, queue for others
1732  */
1733 static void
1734 bfa_lps_login_comp(struct bfa_lps_s *lps)
1735 {
1736         if (!lps->bfa->fcs) {
1737                 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
1738                         lps);
1739                 return;
1740         }
1741
1742         if (lps->fdisc)
1743                 bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1744         else
1745                 bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1746 }
1747
1748 /*
1749  * Indirect logout completion handler for non-fcs
1750  */
1751 static void
1752 bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1753 {
1754         struct bfa_lps_s *lps   = arg;
1755
1756         if (!complete)
1757                 return;
1758
1759         if (lps->fdisc)
1760                 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1761 }
1762
1763 /*
1764  * Logout completion handler -- direct call for fcs, queue for others
1765  */
1766 static void
1767 bfa_lps_logout_comp(struct bfa_lps_s *lps)
1768 {
1769         if (!lps->bfa->fcs) {
1770                 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
1771                         lps);
1772                 return;
1773         }
1774         if (lps->fdisc)
1775                 bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1776 }
1777
1778 /*
1779  * Clear virtual link completion handler for non-fcs
1780  */
1781 static void
1782 bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
1783 {
1784         struct bfa_lps_s *lps   = arg;
1785
1786         if (!complete)
1787                 return;
1788
1789         /* Clear virtual link to base port will result in link down */
1790         if (lps->fdisc)
1791                 bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1792 }
1793
1794 /*
1795  * Received Clear virtual link event --direct call for fcs,
1796  * queue for others
1797  */
1798 static void
1799 bfa_lps_cvl_event(struct bfa_lps_s *lps)
1800 {
1801         if (!lps->bfa->fcs) {
1802                 bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
1803                         lps);
1804                 return;
1805         }
1806
1807         /* Clear virtual link to base port will result in link down */
1808         if (lps->fdisc)
1809                 bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1810 }
1811
1812
1813
1814 /*
1815  *  lps_public BFA LPS public functions
1816  */
1817
1818 u32
1819 bfa_lps_get_max_vport(struct bfa_s *bfa)
1820 {
1821         if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
1822                 return BFA_LPS_MAX_VPORTS_SUPP_CT;
1823         else
1824                 return BFA_LPS_MAX_VPORTS_SUPP_CB;
1825 }
1826
1827 /*
1828  * Allocate a lport srvice tag.
1829  */
1830 struct bfa_lps_s  *
1831 bfa_lps_alloc(struct bfa_s *bfa)
1832 {
1833         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1834         struct bfa_lps_s        *lps = NULL;
1835
1836         bfa_q_deq(&mod->lps_free_q, &lps);
1837
1838         if (lps == NULL)
1839                 return NULL;
1840
1841         list_add_tail(&lps->qe, &mod->lps_active_q);
1842
1843         bfa_sm_set_state(lps, bfa_lps_sm_init);
1844         return lps;
1845 }
1846
1847 /*
1848  * Free lport service tag. This can be called anytime after an alloc.
1849  * No need to wait for any pending login/logout completions.
1850  */
1851 void
1852 bfa_lps_delete(struct bfa_lps_s *lps)
1853 {
1854         bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
1855 }
1856
1857 /*
1858  * Initiate a lport login.
1859  */
1860 void
1861 bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1862         wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
1863 {
1864         lps->uarg       = uarg;
1865         lps->alpa       = alpa;
1866         lps->pdusz      = pdusz;
1867         lps->pwwn       = pwwn;
1868         lps->nwwn       = nwwn;
1869         lps->fdisc      = BFA_FALSE;
1870         lps->auth_en    = auth_en;
1871         bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1872 }
1873
1874 /*
1875  * Initiate a lport fdisc login.
1876  */
1877 void
1878 bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
1879         wwn_t nwwn)
1880 {
1881         lps->uarg       = uarg;
1882         lps->alpa       = 0;
1883         lps->pdusz      = pdusz;
1884         lps->pwwn       = pwwn;
1885         lps->nwwn       = nwwn;
1886         lps->fdisc      = BFA_TRUE;
1887         lps->auth_en    = BFA_FALSE;
1888         bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1889 }
1890
1891
1892 /*
1893  * Initiate a lport FDSIC logout.
1894  */
1895 void
1896 bfa_lps_fdisclogo(struct bfa_lps_s *lps)
1897 {
1898         bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
1899 }
1900
1901
1902 /*
1903  * Return lport services tag given the pid
1904  */
1905 u8
1906 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
1907 {
1908         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1909         struct bfa_lps_s        *lps;
1910         int                     i;
1911
1912         for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
1913                 if (lps->lp_pid == pid)
1914                         return lps->lp_tag;
1915         }
1916
1917         /* Return base port tag anyway */
1918         return 0;
1919 }
1920
1921
1922 /*
1923  * return port id assigned to the base lport
1924  */
1925 u32
1926 bfa_lps_get_base_pid(struct bfa_s *bfa)
1927 {
1928         struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1929
1930         return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
1931 }
1932
1933 /*
1934  * Set PID in case of n2n (which is assigned during PLOGI)
1935  */
1936 void
1937 bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
1938 {
1939         bfa_trc(lps->bfa, lps->lp_tag);
1940         bfa_trc(lps->bfa, n2n_pid);
1941
1942         lps->lp_pid = n2n_pid;
1943         bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1944 }
1945
1946 /*
1947  * LPS firmware message class handler.
1948  */
1949 void
1950 bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1951 {
1952         union bfi_lps_i2h_msg_u msg;
1953
1954         bfa_trc(bfa, m->mhdr.msg_id);
1955         msg.msg = m;
1956
1957         switch (m->mhdr.msg_id) {
1958         case BFI_LPS_H2I_LOGIN_RSP:
1959                 bfa_lps_login_rsp(bfa, msg.login_rsp);
1960                 break;
1961
1962         case BFI_LPS_H2I_LOGOUT_RSP:
1963                 bfa_lps_logout_rsp(bfa, msg.logout_rsp);
1964                 break;
1965
1966         case BFI_LPS_H2I_CVL_EVENT:
1967                 bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
1968                 break;
1969
1970         default:
1971                 bfa_trc(bfa, m->mhdr.msg_id);
1972                 WARN_ON(1);
1973         }
1974 }
1975
1976 /*
1977  * FC PORT state machine functions
1978  */
1979 static void
1980 bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
1981                         enum bfa_fcport_sm_event event)
1982 {
1983         bfa_trc(fcport->bfa, event);
1984
1985         switch (event) {
1986         case BFA_FCPORT_SM_START:
1987                 /*
1988                  * Start event after IOC is configured and BFA is started.
1989                  */
1990                 fcport->use_flash_cfg = BFA_TRUE;
1991
1992                 if (bfa_fcport_send_enable(fcport)) {
1993                         bfa_trc(fcport->bfa, BFA_TRUE);
1994                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
1995                 } else {
1996                         bfa_trc(fcport->bfa, BFA_FALSE);
1997                         bfa_sm_set_state(fcport,
1998                                         bfa_fcport_sm_enabling_qwait);
1999                 }
2000                 break;
2001
2002         case BFA_FCPORT_SM_ENABLE:
2003                 /*
2004                  * Port is persistently configured to be in enabled state. Do
2005                  * not change state. Port enabling is done when START event is
2006                  * received.
2007                  */
2008                 break;
2009
2010         case BFA_FCPORT_SM_DISABLE:
2011                 /*
2012                  * If a port is persistently configured to be disabled, the
2013                  * first event will a port disable request.
2014                  */
2015                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2016                 break;
2017
2018         case BFA_FCPORT_SM_HWFAIL:
2019                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2020                 break;
2021
2022         default:
2023                 bfa_sm_fault(fcport->bfa, event);
2024         }
2025 }
2026
2027 static void
2028 bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
2029                                 enum bfa_fcport_sm_event event)
2030 {
2031         char pwwn_buf[BFA_STRING_32];
2032         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2033         bfa_trc(fcport->bfa, event);
2034
2035         switch (event) {
2036         case BFA_FCPORT_SM_QRESUME:
2037                 bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2038                 bfa_fcport_send_enable(fcport);
2039                 break;
2040
2041         case BFA_FCPORT_SM_STOP:
2042                 bfa_reqq_wcancel(&fcport->reqq_wait);
2043                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2044                 break;
2045
2046         case BFA_FCPORT_SM_ENABLE:
2047                 /*
2048                  * Already enable is in progress.
2049                  */
2050                 break;
2051
2052         case BFA_FCPORT_SM_DISABLE:
2053                 /*
2054                  * Just send disable request to firmware when room becomes
2055                  * available in request queue.
2056                  */
2057                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2058                 bfa_reqq_wcancel(&fcport->reqq_wait);
2059                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2060                                 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2061                 wwn2str(pwwn_buf, fcport->pwwn);
2062                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2063                         "Base port disabled: WWN = %s\n", pwwn_buf);
2064                 break;
2065
2066         case BFA_FCPORT_SM_LINKUP:
2067         case BFA_FCPORT_SM_LINKDOWN:
2068                 /*
2069                  * Possible to get link events when doing back-to-back
2070                  * enable/disables.
2071                  */
2072                 break;
2073
2074         case BFA_FCPORT_SM_HWFAIL:
2075                 bfa_reqq_wcancel(&fcport->reqq_wait);
2076                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2077                 break;
2078
2079         default:
2080                 bfa_sm_fault(fcport->bfa, event);
2081         }
2082 }
2083
2084 static void
2085 bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
2086                                                 enum bfa_fcport_sm_event event)
2087 {
2088         char pwwn_buf[BFA_STRING_32];
2089         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2090         bfa_trc(fcport->bfa, event);
2091
2092         switch (event) {
2093         case BFA_FCPORT_SM_FWRSP:
2094         case BFA_FCPORT_SM_LINKDOWN:
2095                 bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2096                 break;
2097
2098         case BFA_FCPORT_SM_LINKUP:
2099                 bfa_fcport_update_linkinfo(fcport);
2100                 bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2101
2102                 WARN_ON(!fcport->event_cbfn);
2103                 bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2104                 break;
2105
2106         case BFA_FCPORT_SM_ENABLE:
2107                 /*
2108                  * Already being enabled.
2109                  */
2110                 break;
2111
2112         case BFA_FCPORT_SM_DISABLE:
2113                 if (bfa_fcport_send_disable(fcport))
2114                         bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2115                 else
2116                         bfa_sm_set_state(fcport,
2117                                          bfa_fcport_sm_disabling_qwait);
2118
2119                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2120                                 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2121                 wwn2str(pwwn_buf, fcport->pwwn);
2122                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2123                         "Base port disabled: WWN = %s\n", pwwn_buf);
2124                 break;
2125
2126         case BFA_FCPORT_SM_STOP:
2127                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2128                 break;
2129
2130         case BFA_FCPORT_SM_HWFAIL:
2131                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2132                 break;
2133
2134         default:
2135                 bfa_sm_fault(fcport->bfa, event);
2136         }
2137 }
2138
2139 static void
2140 bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
2141                                                 enum bfa_fcport_sm_event event)
2142 {
2143         struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2144         char pwwn_buf[BFA_STRING_32];
2145         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2146
2147         bfa_trc(fcport->bfa, event);
2148
2149         switch (event) {
2150         case BFA_FCPORT_SM_LINKUP:
2151                 bfa_fcport_update_linkinfo(fcport);
2152                 bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2153                 WARN_ON(!fcport->event_cbfn);
2154                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2155                                 BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
2156                 if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
2157
2158                         bfa_trc(fcport->bfa,
2159                                 pevent->link_state.vc_fcf.fcf.fipenabled);
2160                         bfa_trc(fcport->bfa,
2161                                 pevent->link_state.vc_fcf.fcf.fipfailed);
2162
2163                         if (pevent->link_state.vc_fcf.fcf.fipfailed)
2164                                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2165                                         BFA_PL_EID_FIP_FCF_DISC, 0,
2166                                         "FIP FCF Discovery Failed");
2167                         else
2168                                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2169                                         BFA_PL_EID_FIP_FCF_DISC, 0,
2170                                         "FIP FCF Discovered");
2171                 }
2172
2173                 bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2174                 wwn2str(pwwn_buf, fcport->pwwn);
2175                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2176                         "Base port online: WWN = %s\n", pwwn_buf);
2177                 break;
2178
2179         case BFA_FCPORT_SM_LINKDOWN:
2180                 /*
2181                  * Possible to get link down event.
2182                  */
2183                 break;
2184
2185         case BFA_FCPORT_SM_ENABLE:
2186                 /*
2187                  * Already enabled.
2188                  */
2189                 break;
2190
2191         case BFA_FCPORT_SM_DISABLE:
2192                 if (bfa_fcport_send_disable(fcport))
2193                         bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2194                 else
2195                         bfa_sm_set_state(fcport,
2196                                          bfa_fcport_sm_disabling_qwait);
2197
2198                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2199                                 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2200                 wwn2str(pwwn_buf, fcport->pwwn);
2201                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2202                         "Base port disabled: WWN = %s\n", pwwn_buf);
2203                 break;
2204
2205         case BFA_FCPORT_SM_STOP:
2206                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2207                 break;
2208
2209         case BFA_FCPORT_SM_HWFAIL:
2210                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2211                 break;
2212
2213         default:
2214                 bfa_sm_fault(fcport->bfa, event);
2215         }
2216 }
2217
2218 static void
2219 bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
2220         enum bfa_fcport_sm_event event)
2221 {
2222         char pwwn_buf[BFA_STRING_32];
2223         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2224
2225         bfa_trc(fcport->bfa, event);
2226
2227         switch (event) {
2228         case BFA_FCPORT_SM_ENABLE:
2229                 /*
2230                  * Already enabled.
2231                  */
2232                 break;
2233
2234         case BFA_FCPORT_SM_DISABLE:
2235                 if (bfa_fcport_send_disable(fcport))
2236                         bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2237                 else
2238                         bfa_sm_set_state(fcport,
2239                                          bfa_fcport_sm_disabling_qwait);
2240
2241                 bfa_fcport_reset_linkinfo(fcport);
2242                 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2243                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2244                                 BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2245                 wwn2str(pwwn_buf, fcport->pwwn);
2246                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2247                         "Base port offline: WWN = %s\n", pwwn_buf);
2248                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2249                         "Base port disabled: WWN = %s\n", pwwn_buf);
2250                 break;
2251
2252         case BFA_FCPORT_SM_LINKDOWN:
2253                 bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2254                 bfa_fcport_reset_linkinfo(fcport);
2255                 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2256                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2257                                 BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
2258                 wwn2str(pwwn_buf, fcport->pwwn);
2259                 if (BFA_PORT_IS_DISABLED(fcport->bfa))
2260                         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2261                                 "Base port offline: WWN = %s\n", pwwn_buf);
2262                 else
2263                         BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2264                                 "Base port (WWN = %s) "
2265                                 "lost fabric connectivity\n", pwwn_buf);
2266                 break;
2267
2268         case BFA_FCPORT_SM_STOP:
2269                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2270                 bfa_fcport_reset_linkinfo(fcport);
2271                 wwn2str(pwwn_buf, fcport->pwwn);
2272                 if (BFA_PORT_IS_DISABLED(fcport->bfa))
2273                         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2274                                 "Base port offline: WWN = %s\n", pwwn_buf);
2275                 else
2276                         BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2277                                 "Base port (WWN = %s) "
2278                                 "lost fabric connectivity\n", pwwn_buf);
2279                 break;
2280
2281         case BFA_FCPORT_SM_HWFAIL:
2282                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2283                 bfa_fcport_reset_linkinfo(fcport);
2284                 bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2285                 wwn2str(pwwn_buf, fcport->pwwn);
2286                 if (BFA_PORT_IS_DISABLED(fcport->bfa))
2287                         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2288                                 "Base port offline: WWN = %s\n", pwwn_buf);
2289                 else
2290                         BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2291                                 "Base port (WWN = %s) "
2292                                 "lost fabric connectivity\n", pwwn_buf);
2293                 break;
2294
2295         default:
2296                 bfa_sm_fault(fcport->bfa, event);
2297         }
2298 }
2299
2300 static void
2301 bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
2302                                  enum bfa_fcport_sm_event event)
2303 {
2304         bfa_trc(fcport->bfa, event);
2305
2306         switch (event) {
2307         case BFA_FCPORT_SM_QRESUME:
2308                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2309                 bfa_fcport_send_disable(fcport);
2310                 break;
2311
2312         case BFA_FCPORT_SM_STOP:
2313                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2314                 bfa_reqq_wcancel(&fcport->reqq_wait);
2315                 break;
2316
2317         case BFA_FCPORT_SM_ENABLE:
2318                 bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
2319                 break;
2320
2321         case BFA_FCPORT_SM_DISABLE:
2322                 /*
2323                  * Already being disabled.
2324                  */
2325                 break;
2326
2327         case BFA_FCPORT_SM_LINKUP:
2328         case BFA_FCPORT_SM_LINKDOWN:
2329                 /*
2330                  * Possible to get link events when doing back-to-back
2331                  * enable/disables.
2332                  */
2333                 break;
2334
2335         case BFA_FCPORT_SM_HWFAIL:
2336                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2337                 bfa_reqq_wcancel(&fcport->reqq_wait);
2338                 break;
2339
2340         default:
2341                 bfa_sm_fault(fcport->bfa, event);
2342         }
2343 }
2344
2345 static void
2346 bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
2347                                  enum bfa_fcport_sm_event event)
2348 {
2349         bfa_trc(fcport->bfa, event);
2350
2351         switch (event) {
2352         case BFA_FCPORT_SM_QRESUME:
2353                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2354                 bfa_fcport_send_disable(fcport);
2355                 if (bfa_fcport_send_enable(fcport))
2356                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2357                 else
2358                         bfa_sm_set_state(fcport,
2359                                          bfa_fcport_sm_enabling_qwait);
2360                 break;
2361
2362         case BFA_FCPORT_SM_STOP:
2363                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2364                 bfa_reqq_wcancel(&fcport->reqq_wait);
2365                 break;
2366
2367         case BFA_FCPORT_SM_ENABLE:
2368                 break;
2369
2370         case BFA_FCPORT_SM_DISABLE:
2371                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2372                 break;
2373
2374         case BFA_FCPORT_SM_LINKUP:
2375         case BFA_FCPORT_SM_LINKDOWN:
2376                 /*
2377                  * Possible to get link events when doing back-to-back
2378                  * enable/disables.
2379                  */
2380                 break;
2381
2382         case BFA_FCPORT_SM_HWFAIL:
2383                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2384                 bfa_reqq_wcancel(&fcport->reqq_wait);
2385                 break;
2386
2387         default:
2388                 bfa_sm_fault(fcport->bfa, event);
2389         }
2390 }
2391
2392 static void
2393 bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
2394                                                 enum bfa_fcport_sm_event event)
2395 {
2396         char pwwn_buf[BFA_STRING_32];
2397         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2398         bfa_trc(fcport->bfa, event);
2399
2400         switch (event) {
2401         case BFA_FCPORT_SM_FWRSP:
2402                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2403                 break;
2404
2405         case BFA_FCPORT_SM_DISABLE:
2406                 /*
2407                  * Already being disabled.
2408                  */
2409                 break;
2410
2411         case BFA_FCPORT_SM_ENABLE:
2412                 if (bfa_fcport_send_enable(fcport))
2413                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2414                 else
2415                         bfa_sm_set_state(fcport,
2416                                          bfa_fcport_sm_enabling_qwait);
2417
2418                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2419                                 BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2420                 wwn2str(pwwn_buf, fcport->pwwn);
2421                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2422                         "Base port enabled: WWN = %s\n", pwwn_buf);
2423                 break;
2424
2425         case BFA_FCPORT_SM_STOP:
2426                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2427                 break;
2428
2429         case BFA_FCPORT_SM_LINKUP:
2430         case BFA_FCPORT_SM_LINKDOWN:
2431                 /*
2432                  * Possible to get link events when doing back-to-back
2433                  * enable/disables.
2434                  */
2435                 break;
2436
2437         case BFA_FCPORT_SM_HWFAIL:
2438                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2439                 break;
2440
2441         default:
2442                 bfa_sm_fault(fcport->bfa, event);
2443         }
2444 }
2445
2446 static void
2447 bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
2448                                                 enum bfa_fcport_sm_event event)
2449 {
2450         char pwwn_buf[BFA_STRING_32];
2451         struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2452         bfa_trc(fcport->bfa, event);
2453
2454         switch (event) {
2455         case BFA_FCPORT_SM_START:
2456                 /*
2457                  * Ignore start event for a port that is disabled.
2458                  */
2459                 break;
2460
2461         case BFA_FCPORT_SM_STOP:
2462                 bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2463                 break;
2464
2465         case BFA_FCPORT_SM_ENABLE:
2466                 if (bfa_fcport_send_enable(fcport))
2467                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2468                 else
2469                         bfa_sm_set_state(fcport,
2470                                          bfa_fcport_sm_enabling_qwait);
2471
2472                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2473                                 BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2474                 wwn2str(pwwn_buf, fcport->pwwn);
2475                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2476                         "Base port enabled: WWN = %s\n", pwwn_buf);
2477                 break;
2478
2479         case BFA_FCPORT_SM_DISABLE:
2480                 /*
2481                  * Already disabled.
2482                  */
2483                 break;
2484
2485         case BFA_FCPORT_SM_HWFAIL:
2486                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2487                 break;
2488
2489         default:
2490                 bfa_sm_fault(fcport->bfa, event);
2491         }
2492 }
2493
2494 static void
2495 bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
2496                          enum bfa_fcport_sm_event event)
2497 {
2498         bfa_trc(fcport->bfa, event);
2499
2500         switch (event) {
2501         case BFA_FCPORT_SM_START:
2502                 if (bfa_fcport_send_enable(fcport))
2503                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2504                 else
2505                         bfa_sm_set_state(fcport,
2506                                          bfa_fcport_sm_enabling_qwait);
2507                 break;
2508
2509         default:
2510                 /*
2511                  * Ignore all other events.
2512                  */
2513                 ;
2514         }
2515 }
2516
2517 /*
2518  * Port is enabled. IOC is down/failed.
2519  */
2520 static void
2521 bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
2522                          enum bfa_fcport_sm_event event)
2523 {
2524         bfa_trc(fcport->bfa, event);
2525
2526         switch (event) {
2527         case BFA_FCPORT_SM_START:
2528                 if (bfa_fcport_send_enable(fcport))
2529                         bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2530                 else
2531                         bfa_sm_set_state(fcport,
2532                                          bfa_fcport_sm_enabling_qwait);
2533                 break;
2534
2535         default:
2536                 /*
2537                  * Ignore all events.
2538                  */
2539                 ;
2540         }
2541 }
2542
2543 /*
2544  * Port is disabled. IOC is down/failed.
2545  */
2546 static void
2547 bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
2548                          enum bfa_fcport_sm_event event)
2549 {
2550         bfa_trc(fcport->bfa, event);
2551
2552         switch (event) {
2553         case BFA_FCPORT_SM_START:
2554                 bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2555                 break;
2556
2557         case BFA_FCPORT_SM_ENABLE:
2558                 bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2559                 break;
2560
2561         default:
2562                 /*
2563                  * Ignore all events.
2564                  */
2565                 ;
2566         }
2567 }
2568
2569 /*
2570  * Link state is down
2571  */
2572 static void
2573 bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
2574                 enum bfa_fcport_ln_sm_event event)
2575 {
2576         bfa_trc(ln->fcport->bfa, event);
2577
2578         switch (event) {
2579         case BFA_FCPORT_LN_SM_LINKUP:
2580                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2581                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2582                 break;
2583
2584         default:
2585                 bfa_sm_fault(ln->fcport->bfa, event);
2586         }
2587 }
2588
2589 /*
2590  * Link state is waiting for down notification
2591  */
2592 static void
2593 bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
2594                 enum bfa_fcport_ln_sm_event event)
2595 {
2596         bfa_trc(ln->fcport->bfa, event);
2597
2598         switch (event) {
2599         case BFA_FCPORT_LN_SM_LINKUP:
2600                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2601                 break;
2602
2603         case BFA_FCPORT_LN_SM_NOTIFICATION:
2604                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2605                 break;
2606
2607         default:
2608                 bfa_sm_fault(ln->fcport->bfa, event);
2609         }
2610 }
2611
2612 /*
2613  * Link state is waiting for down notification and there is a pending up
2614  */
2615 static void
2616 bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
2617                 enum bfa_fcport_ln_sm_event event)
2618 {
2619         bfa_trc(ln->fcport->bfa, event);
2620
2621         switch (event) {
2622         case BFA_FCPORT_LN_SM_LINKDOWN:
2623                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2624                 break;
2625
2626         case BFA_FCPORT_LN_SM_NOTIFICATION:
2627                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2628                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2629                 break;
2630
2631         default:
2632                 bfa_sm_fault(ln->fcport->bfa, event);
2633         }
2634 }
2635
2636 /*
2637  * Link state is up
2638  */
2639 static void
2640 bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
2641                 enum bfa_fcport_ln_sm_event event)
2642 {
2643         bfa_trc(ln->fcport->bfa, event);
2644
2645         switch (event) {
2646         case BFA_FCPORT_LN_SM_LINKDOWN:
2647                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2648                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2649                 break;
2650
2651         default:
2652                 bfa_sm_fault(ln->fcport->bfa, event);
2653         }
2654 }
2655
2656 /*
2657  * Link state is waiting for up notification
2658  */
2659 static void
2660 bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
2661                 enum bfa_fcport_ln_sm_event event)
2662 {
2663         bfa_trc(ln->fcport->bfa, event);
2664
2665         switch (event) {
2666         case BFA_FCPORT_LN_SM_LINKDOWN:
2667                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2668                 break;
2669
2670         case BFA_FCPORT_LN_SM_NOTIFICATION:
2671                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
2672                 break;
2673
2674         default:
2675                 bfa_sm_fault(ln->fcport->bfa, event);
2676         }
2677 }
2678
2679 /*
2680  * Link state is waiting for up notification and there is a pending down
2681  */
2682 static void
2683 bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
2684                 enum bfa_fcport_ln_sm_event event)
2685 {
2686         bfa_trc(ln->fcport->bfa, event);
2687
2688         switch (event) {
2689         case BFA_FCPORT_LN_SM_LINKUP:
2690                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
2691                 break;
2692
2693         case BFA_FCPORT_LN_SM_NOTIFICATION:
2694                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2695                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2696                 break;
2697
2698         default:
2699                 bfa_sm_fault(ln->fcport->bfa, event);
2700         }
2701 }
2702
2703 /*
2704  * Link state is waiting for up notification and there are pending down and up
2705  */
2706 static void
2707 bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
2708                         enum bfa_fcport_ln_sm_event event)
2709 {
2710         bfa_trc(ln->fcport->bfa, event);
2711
2712         switch (event) {
2713         case BFA_FCPORT_LN_SM_LINKDOWN:
2714                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2715                 break;
2716
2717         case BFA_FCPORT_LN_SM_NOTIFICATION:
2718                 bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2719                 bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2720                 break;
2721
2722         default:
2723                 bfa_sm_fault(ln->fcport->bfa, event);
2724         }
2725 }
2726
2727 static void
2728 __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
2729 {
2730         struct bfa_fcport_ln_s *ln = cbarg;
2731
2732         if (complete)
2733                 ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
2734         else
2735                 bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2736 }
2737
2738 /*
2739  * Send SCN notification to upper layers.
2740  * trunk - false if caller is fcport to ignore fcport event in trunked mode
2741  */
2742 static void
2743 bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
2744         bfa_boolean_t trunk)
2745 {
2746         if (fcport->cfg.trunked && !trunk)
2747                 return;
2748
2749         switch (event) {
2750         case BFA_PORT_LINKUP:
2751                 bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
2752                 break;
2753         case BFA_PORT_LINKDOWN:
2754                 bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
2755                 break;
2756         default:
2757                 WARN_ON(1);
2758         }
2759 }
2760
2761 static void
2762 bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
2763 {
2764         struct bfa_fcport_s *fcport = ln->fcport;
2765
2766         if (fcport->bfa->fcs) {
2767                 fcport->event_cbfn(fcport->event_cbarg, event);
2768                 bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2769         } else {
2770                 ln->ln_event = event;
2771                 bfa_cb_queue(fcport->bfa, &ln->ln_qe,
2772                         __bfa_cb_fcport_event, ln);
2773         }
2774 }
2775
2776 #define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
2777                                                         BFA_CACHELINE_SZ))
2778
2779 static void
2780 bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
2781                 u32 *dm_len)
2782 {
2783         *dm_len += FCPORT_STATS_DMA_SZ;
2784 }
2785
2786 static void
2787 bfa_fcport_qresume(void *cbarg)
2788 {
2789         struct bfa_fcport_s *fcport = cbarg;
2790
2791         bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
2792 }
2793
2794 static void
2795 bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
2796 {
2797         u8              *dm_kva;
2798         u64     dm_pa;
2799
2800         dm_kva = bfa_meminfo_dma_virt(meminfo);
2801         dm_pa  = bfa_meminfo_dma_phys(meminfo);
2802
2803         fcport->stats_kva = dm_kva;
2804         fcport->stats_pa  = dm_pa;
2805         fcport->stats     = (union bfa_fcport_stats_u *) dm_kva;
2806
2807         dm_kva += FCPORT_STATS_DMA_SZ;
2808         dm_pa  += FCPORT_STATS_DMA_SZ;
2809
2810         bfa_meminfo_dma_virt(meminfo) = dm_kva;
2811         bfa_meminfo_dma_phys(meminfo) = dm_pa;
2812 }
2813
2814 /*
2815  * Memory initialization.
2816  */
2817 static void
2818 bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
2819                 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
2820 {
2821         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
2822         struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
2823         struct bfa_fcport_ln_s *ln = &fcport->ln;
2824         struct timeval tv;
2825
2826         memset(fcport, 0, sizeof(struct bfa_fcport_s));
2827         fcport->bfa = bfa;
2828         ln->fcport = fcport;
2829
2830         bfa_fcport_mem_claim(fcport, meminfo);
2831
2832         bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
2833         bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2834
2835         /*
2836          * initialize time stamp for stats reset
2837          */
2838         do_gettimeofday(&tv);
2839         fcport->stats_reset_time = tv.tv_sec;
2840
2841         /*
2842          * initialize and set default configuration
2843          */
2844         port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
2845         port_cfg->speed = BFA_PORT_SPEED_AUTO;
2846         port_cfg->trunked = BFA_FALSE;
2847         port_cfg->maxfrsize = 0;
2848
2849         port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
2850
2851         bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
2852 }
2853
2854 static void
2855 bfa_fcport_detach(struct bfa_s *bfa)
2856 {
2857 }
2858
2859 /*
2860  * Called when IOC is ready.
2861  */
2862 static void
2863 bfa_fcport_start(struct bfa_s *bfa)
2864 {
2865         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
2866 }
2867
2868 /*
2869  * Called before IOC is stopped.
2870  */
2871 static void
2872 bfa_fcport_stop(struct bfa_s *bfa)
2873 {
2874         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
2875         bfa_trunk_iocdisable(bfa);
2876 }
2877
2878 /*
2879  * Called when IOC failure is detected.
2880  */
2881 static void
2882 bfa_fcport_iocdisable(struct bfa_s *bfa)
2883 {
2884         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
2885
2886         bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
2887         bfa_trunk_iocdisable(bfa);
2888 }
2889
2890 static void
2891 bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
2892 {
2893         struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2894         struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
2895
2896         fcport->speed = pevent->link_state.speed;
2897         fcport->topology = pevent->link_state.topology;
2898
2899         if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
2900                 fcport->myalpa = 0;
2901
2902         /* QoS Details */
2903         fcport->qos_attr = pevent->link_state.qos_attr;
2904         fcport->qos_vc_attr = pevent->link_state.vc_fcf.qos_vc_attr;
2905
2906         /*
2907          * update trunk state if applicable
2908          */
2909         if (!fcport->cfg.trunked)
2910                 trunk->attr.state = BFA_TRUNK_DISABLED;
2911
2912         /* update FCoE specific */
2913         fcport->fcoe_vlan = be16_to_cpu(pevent->link_state.vc_fcf.fcf.vlan);
2914
2915         bfa_trc(fcport->bfa, fcport->speed);
2916         bfa_trc(fcport->bfa, fcport->topology);
2917 }
2918
2919 static void
2920 bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
2921 {
2922         fcport->speed = BFA_PORT_SPEED_UNKNOWN;
2923         fcport->topology = BFA_PORT_TOPOLOGY_NONE;
2924 }
2925
2926 /*
2927  * Send port enable message to firmware.
2928  */
2929 static bfa_boolean_t
2930 bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
2931 {
2932         struct bfi_fcport_enable_req_s *m;
2933
2934         /*
2935          * Increment message tag before queue check, so that responses to old
2936          * requests are discarded.
2937          */
2938         fcport->msgtag++;
2939
2940         /*
2941          * check for room in queue to send request now
2942          */
2943         m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
2944         if (!m) {
2945                 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
2946                                                         &fcport->reqq_wait);
2947                 return BFA_FALSE;
2948         }
2949
2950         bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
2951                         bfa_lpuid(fcport->bfa));
2952         m->nwwn = fcport->nwwn;
2953         m->pwwn = fcport->pwwn;
2954         m->port_cfg = fcport->cfg;
2955         m->msgtag = fcport->msgtag;
2956         m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
2957          m->use_flash_cfg = fcport->use_flash_cfg;
2958         bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
2959         bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
2960         bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
2961
2962         /*
2963          * queue I/O message to firmware
2964          */
2965         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
2966         return BFA_TRUE;
2967 }
2968
2969 /*
2970  * Send port disable message to firmware.
2971  */
2972 static  bfa_boolean_t
2973 bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
2974 {
2975         struct bfi_fcport_req_s *m;
2976
2977         /*
2978          * Increment message tag before queue check, so that responses to old
2979          * requests are discarded.
2980          */
2981         fcport->msgtag++;
2982
2983         /*
2984          * check for room in queue to send request now
2985          */
2986         m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
2987         if (!m) {
2988                 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
2989                                                         &fcport->reqq_wait);
2990                 return BFA_FALSE;
2991         }
2992
2993         bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
2994                         bfa_lpuid(fcport->bfa));
2995         m->msgtag = fcport->msgtag;
2996
2997         /*
2998          * queue I/O message to firmware
2999          */
3000         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
3001
3002         return BFA_TRUE;
3003 }
3004
3005 static void
3006 bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
3007 {
3008         fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
3009         fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
3010
3011         bfa_trc(fcport->bfa, fcport->pwwn);
3012         bfa_trc(fcport->bfa, fcport->nwwn);
3013 }
3014
3015 static void
3016 bfa_fcport_send_txcredit(void *port_cbarg)
3017 {
3018
3019         struct bfa_fcport_s *fcport = port_cbarg;
3020         struct bfi_fcport_set_svc_params_req_s *m;
3021
3022         /*
3023          * check for room in queue to send request now
3024          */
3025         m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3026         if (!m) {
3027                 bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit);
3028                 return;
3029         }
3030
3031         bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
3032                         bfa_lpuid(fcport->bfa));
3033         m->tx_bbcredit = cpu_to_be16((u16)fcport->cfg.tx_bbcredit);
3034
3035         /*
3036          * queue I/O message to firmware
3037          */
3038         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
3039 }
3040
3041 static void
3042 bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
3043         struct bfa_qos_stats_s *s)
3044 {
3045         u32     *dip = (u32 *) d;
3046         __be32  *sip = (__be32 *) s;
3047         int             i;
3048
3049         /* Now swap the 32 bit fields */
3050         for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
3051                 dip[i] = be32_to_cpu(sip[i]);
3052 }
3053
3054 static void
3055 bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3056         struct bfa_fcoe_stats_s *s)
3057 {
3058         u32     *dip = (u32 *) d;
3059         __be32  *sip = (__be32 *) s;
3060         int             i;
3061
3062         for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
3063              i = i + 2) {
3064 #ifdef __BIG_ENDIAN
3065                 dip[i] = be32_to_cpu(sip[i]);
3066                 dip[i + 1] = be32_to_cpu(sip[i + 1]);
3067 #else
3068                 dip[i] = be32_to_cpu(sip[i + 1]);
3069                 dip[i + 1] = be32_to_cpu(sip[i]);
3070 #endif
3071         }
3072 }
3073
3074 static void
3075 __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3076 {
3077         struct bfa_fcport_s *fcport = cbarg;
3078
3079         if (complete) {
3080                 if (fcport->stats_status == BFA_STATUS_OK) {
3081                         struct timeval tv;
3082
3083                         /* Swap FC QoS or FCoE stats */
3084                         if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
3085                                 bfa_fcport_qos_stats_swap(
3086                                         &fcport->stats_ret->fcqos,
3087                                         &fcport->stats->fcqos);
3088                         } else {
3089                                 bfa_fcport_fcoe_stats_swap(
3090                                         &fcport->stats_ret->fcoe,
3091                                         &fcport->stats->fcoe);
3092
3093                                 do_gettimeofday(&tv);
3094                                 fcport->stats_ret->fcoe.secs_reset =
3095                                         tv.tv_sec - fcport->stats_reset_time;
3096                         }
3097                 }
3098                 fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
3099         } else {
3100                 fcport->stats_busy = BFA_FALSE;
3101                 fcport->stats_status = BFA_STATUS_OK;
3102         }
3103 }
3104
3105 static void
3106 bfa_fcport_stats_get_timeout(void *cbarg)
3107 {
3108         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3109
3110         bfa_trc(fcport->bfa, fcport->stats_qfull);
3111
3112         if (fcport->stats_qfull) {
3113                 bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3114                 fcport->stats_qfull = BFA_FALSE;
3115         }
3116
3117         fcport->stats_status = BFA_STATUS_ETIMER;
3118         bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
3119                 fcport);
3120 }
3121
3122 static void
3123 bfa_fcport_send_stats_get(void *cbarg)
3124 {
3125         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3126         struct bfi_fcport_req_s *msg;
3127
3128         msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3129
3130         if (!msg) {
3131                 fcport->stats_qfull = BFA_TRUE;
3132                 bfa_reqq_winit(&fcport->stats_reqq_wait,
3133                                 bfa_fcport_send_stats_get, fcport);
3134                 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3135                                 &fcport->stats_reqq_wait);
3136                 return;
3137         }
3138         fcport->stats_qfull = BFA_FALSE;
3139
3140         memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3141         bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
3142                         bfa_lpuid(fcport->bfa));
3143         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
3144 }
3145
3146 static void
3147 __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3148 {
3149         struct bfa_fcport_s *fcport = cbarg;
3150
3151         if (complete) {
3152                 struct timeval tv;
3153
3154                 /*
3155                  * re-initialize time stamp for stats reset
3156                  */
3157                 do_gettimeofday(&tv);
3158                 fcport->stats_reset_time = tv.tv_sec;
3159
3160                 fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
3161         } else {
3162                 fcport->stats_busy = BFA_FALSE;
3163                 fcport->stats_status = BFA_STATUS_OK;
3164         }
3165 }
3166
3167 static void
3168 bfa_fcport_stats_clr_timeout(void *cbarg)
3169 {
3170         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3171
3172         bfa_trc(fcport->bfa, fcport->stats_qfull);
3173
3174         if (fcport->stats_qfull) {
3175                 bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3176                 fcport->stats_qfull = BFA_FALSE;
3177         }
3178
3179         fcport->stats_status = BFA_STATUS_ETIMER;
3180         bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
3181                         __bfa_cb_fcport_stats_clr, fcport);
3182 }
3183
3184 static void
3185 bfa_fcport_send_stats_clear(void *cbarg)
3186 {
3187         struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3188         struct bfi_fcport_req_s *msg;
3189
3190         msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3191
3192         if (!msg) {
3193                 fcport->stats_qfull = BFA_TRUE;
3194                 bfa_reqq_winit(&fcport->stats_reqq_wait,
3195                                 bfa_fcport_send_stats_clear, fcport);
3196                 bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3197                                                 &fcport->stats_reqq_wait);
3198                 return;
3199         }
3200         fcport->stats_qfull = BFA_FALSE;
3201
3202         memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3203         bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
3204                         bfa_lpuid(fcport->bfa));
3205         bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
3206 }
3207
3208 /*
3209  * Handle trunk SCN event from firmware.
3210  */
3211 static void
3212 bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
3213 {
3214         struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3215         struct bfi_fcport_trunk_link_s *tlink;
3216         struct bfa_trunk_link_attr_s *lattr;
3217         enum bfa_trunk_state state_prev;
3218         int i;
3219         int link_bm = 0;
3220
3221         bfa_trc(fcport->bfa, fcport->cfg.trunked);
3222         WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
3223                    scn->trunk_state != BFA_TRUNK_OFFLINE);
3224
3225         bfa_trc(fcport->bfa, trunk->attr.state);
3226         bfa_trc(fcport->bfa, scn->trunk_state);
3227         bfa_trc(fcport->bfa, scn->trunk_speed);
3228
3229         /*
3230          * Save off new state for trunk attribute query
3231          */
3232         state_prev = trunk->attr.state;
3233         if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
3234                 trunk->attr.state = scn->trunk_state;
3235         trunk->attr.speed = scn->trunk_speed;
3236         for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3237                 lattr = &trunk->attr.link_attr[i];
3238                 tlink = &scn->tlink[i];
3239
3240                 lattr->link_state = tlink->state;
3241                 lattr->trunk_wwn  = tlink->trunk_wwn;
3242                 lattr->fctl       = tlink->fctl;
3243                 lattr->speed      = tlink->speed;
3244                 lattr->deskew     = be32_to_cpu(tlink->deskew);
3245
3246                 if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
3247                         fcport->speed    = tlink->speed;
3248                         fcport->topology = BFA_PORT_TOPOLOGY_P2P;
3249                         link_bm |= 1 << i;
3250                 }
3251
3252                 bfa_trc(fcport->bfa, lattr->link_state);
3253                 bfa_trc(fcport->bfa, lattr->trunk_wwn);
3254                 bfa_trc(fcport->bfa, lattr->fctl);
3255                 bfa_trc(fcport->bfa, lattr->speed);
3256                 bfa_trc(fcport->bfa, lattr->deskew);
3257         }
3258
3259         switch (link_bm) {
3260         case 3:
3261                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3262                         BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
3263                 break;
3264         case 2:
3265                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3266                         BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
3267                 break;
3268         case 1:
3269                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3270                         BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
3271                 break;
3272         default:
3273                 bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3274                         BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
3275         }
3276
3277         /*
3278          * Notify upper layers if trunk state changed.
3279          */
3280         if ((state_prev != trunk->attr.state) ||
3281                 (scn->trunk_state == BFA_TRUNK_OFFLINE)) {
3282                 bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
3283                         BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
3284         }
3285 }
3286
3287 static void
3288 bfa_trunk_iocdisable(struct bfa_s *bfa)
3289 {
3290         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3291         int i = 0;
3292
3293         /*
3294          * In trunked mode, notify upper layers that link is down
3295          */
3296         if (fcport->cfg.trunked) {
3297                 if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
3298                         bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
3299
3300                 fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
3301                 fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
3302                 for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3303                         fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
3304                         fcport->trunk.attr.link_attr[i].fctl =
3305                                                 BFA_TRUNK_LINK_FCTL_NORMAL;
3306                         fcport->trunk.attr.link_attr[i].link_state =
3307                                                 BFA_TRUNK_LINK_STATE_DN_LINKDN;
3308                         fcport->trunk.attr.link_attr[i].speed =
3309                                                 BFA_PORT_SPEED_UNKNOWN;
3310                         fcport->trunk.attr.link_attr[i].deskew = 0;
3311                 }
3312         }
3313 }
3314
3315 /*
3316  * Called to initialize port attributes
3317  */
3318 void
3319 bfa_fcport_init(struct bfa_s *bfa)
3320 {
3321         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3322
3323         /*
3324          * Initialize port attributes from IOC hardware data.
3325          */
3326         bfa_fcport_set_wwns(fcport);
3327         if (fcport->cfg.maxfrsize == 0)
3328                 fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
3329         fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
3330         fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
3331
3332         WARN_ON(!fcport->cfg.maxfrsize);
3333         WARN_ON(!fcport->cfg.rx_bbcredit);
3334         WARN_ON(!fcport->speed_sup);
3335 }
3336
3337 /*
3338  * Firmware message handler.
3339  */
3340 void
3341 bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3342 {
3343         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3344         union bfi_fcport_i2h_msg_u i2hmsg;
3345
3346         i2hmsg.msg = msg;
3347         fcport->event_arg.i2hmsg = i2hmsg;
3348
3349         bfa_trc(bfa, msg->mhdr.msg_id);
3350         bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
3351
3352         switch (msg->mhdr.msg_id) {
3353         case BFI_FCPORT_I2H_ENABLE_RSP:
3354                 if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
3355
3356                         if (fcport->use_flash_cfg) {
3357                                 fcport->cfg = i2hmsg.penable_rsp->port_cfg;
3358                                 fcport->cfg.maxfrsize =
3359                                         cpu_to_be16(fcport->cfg.maxfrsize);
3360                                 fcport->cfg.path_tov =
3361                                         cpu_to_be16(fcport->cfg.path_tov);
3362                                 fcport->cfg.q_depth =
3363                                         cpu_to_be16(fcport->cfg.q_depth);
3364
3365                                 if (fcport->cfg.trunked)
3366                                         fcport->trunk.attr.state =
3367                                                 BFA_TRUNK_OFFLINE;
3368                                 else
3369                                         fcport->trunk.attr.state =
3370                                                 BFA_TRUNK_DISABLED;
3371                                 fcport->use_flash_cfg = BFA_FALSE;
3372                         }
3373
3374                         bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3375                 }
3376                 break;
3377
3378         case BFI_FCPORT_I2H_DISABLE_RSP:
3379                 if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
3380                         bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3381                 break;
3382
3383         case BFI_FCPORT_I2H_EVENT:
3384                 if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
3385                         bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
3386                 else
3387                         bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
3388                 break;
3389
3390         case BFI_FCPORT_I2H_TRUNK_SCN:
3391                 bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
3392                 break;
3393
3394         case BFI_FCPORT_I2H_STATS_GET_RSP:
3395                 /*
3396                  * check for timer pop before processing the rsp
3397                  */
3398                 if (fcport->stats_busy == BFA_FALSE ||
3399                     fcport->stats_status == BFA_STATUS_ETIMER)
3400                         break;
3401
3402                 bfa_timer_stop(&fcport->timer);
3403                 fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3404                 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
3405                                 __bfa_cb_fcport_stats_get, fcport);
3406                 break;
3407
3408         case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3409                 /*
3410                  * check for timer pop before processing the rsp
3411                  */
3412                 if (fcport->stats_busy == BFA_FALSE ||
3413                     fcport->stats_status == BFA_STATUS_ETIMER)
3414                         break;
3415
3416                 bfa_timer_stop(&fcport->timer);
3417                 fcport->stats_status = BFA_STATUS_OK;
3418                 bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
3419                                 __bfa_cb_fcport_stats_clr, fcport);
3420                 break;
3421
3422         case BFI_FCPORT_I2H_ENABLE_AEN:
3423                 bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
3424                 break;
3425
3426         case BFI_FCPORT_I2H_DISABLE_AEN:
3427                 bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
3428                 break;
3429
3430         default:
3431                 WARN_ON(1);
3432         break;
3433         }
3434 }
3435
3436 /*
3437  * Registered callback for port events.
3438  */
3439 void
3440 bfa_fcport_event_register(struct bfa_s *bfa,
3441                                 void (*cbfn) (void *cbarg,
3442                                 enum bfa_port_linkstate event),
3443                                 void *cbarg)
3444 {
3445         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3446
3447         fcport->event_cbfn = cbfn;
3448         fcport->event_cbarg = cbarg;
3449 }
3450
3451 bfa_status_t
3452 bfa_fcport_enable(struct bfa_s *bfa)
3453 {
3454         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3455
3456         if (bfa_ioc_is_disabled(&bfa->ioc))
3457                 return BFA_STATUS_IOC_DISABLED;
3458
3459         if (fcport->diag_busy)
3460                 return BFA_STATUS_DIAG_BUSY;
3461
3462         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
3463         return BFA_STATUS_OK;
3464 }
3465
3466 bfa_status_t
3467 bfa_fcport_disable(struct bfa_s *bfa)
3468 {
3469
3470         if (bfa_ioc_is_disabled(&bfa->ioc))
3471                 return BFA_STATUS_IOC_DISABLED;
3472
3473         bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
3474         return BFA_STATUS_OK;
3475 }
3476
3477 /*
3478  * Configure port speed.
3479  */
3480 bfa_status_t
3481 bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
3482 {
3483         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3484
3485         bfa_trc(bfa, speed);
3486
3487         if (fcport->cfg.trunked == BFA_TRUE)
3488                 return BFA_STATUS_TRUNK_ENABLED;
3489         if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
3490                 bfa_trc(bfa, fcport->speed_sup);
3491                 return BFA_STATUS_UNSUPP_SPEED;
3492         }
3493
3494         fcport->cfg.speed = speed;
3495
3496         return BFA_STATUS_OK;
3497 }
3498
3499 /*
3500  * Get current speed.
3501  */
3502 enum bfa_port_speed
3503 bfa_fcport_get_speed(struct bfa_s *bfa)
3504 {
3505         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3506
3507         return fcport->speed;
3508 }
3509
3510 /*
3511  * Configure port topology.
3512  */
3513 bfa_status_t
3514 bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
3515 {
3516         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3517
3518         bfa_trc(bfa, topology);
3519         bfa_trc(bfa, fcport->cfg.topology);
3520
3521         switch (topology) {
3522         case BFA_PORT_TOPOLOGY_P2P:
3523         case BFA_PORT_TOPOLOGY_LOOP:
3524         case BFA_PORT_TOPOLOGY_AUTO:
3525                 break;
3526
3527         default:
3528                 return BFA_STATUS_EINVAL;
3529         }
3530
3531         fcport->cfg.topology = topology;
3532         return BFA_STATUS_OK;
3533 }
3534
3535 /*
3536  * Get current topology.
3537  */
3538 enum bfa_port_topology
3539 bfa_fcport_get_topology(struct bfa_s *bfa)
3540 {
3541         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3542
3543         return fcport->topology;
3544 }
3545
3546 bfa_status_t
3547 bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
3548 {
3549         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3550
3551         bfa_trc(bfa, alpa);
3552         bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3553         bfa_trc(bfa, fcport->cfg.hardalpa);
3554
3555         fcport->cfg.cfg_hardalpa = BFA_TRUE;
3556         fcport->cfg.hardalpa = alpa;
3557
3558         return BFA_STATUS_OK;
3559 }
3560
3561 bfa_status_t
3562 bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
3563 {
3564         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3565
3566         bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3567         bfa_trc(bfa, fcport->cfg.hardalpa);
3568
3569         fcport->cfg.cfg_hardalpa = BFA_FALSE;
3570         return BFA_STATUS_OK;
3571 }
3572
3573 bfa_boolean_t
3574 bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
3575 {
3576         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3577
3578         *alpa = fcport->cfg.hardalpa;
3579         return fcport->cfg.cfg_hardalpa;
3580 }
3581
3582 u8
3583 bfa_fcport_get_myalpa(struct bfa_s *bfa)
3584 {
3585         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3586
3587         return fcport->myalpa;
3588 }
3589
3590 bfa_status_t
3591 bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
3592 {
3593         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3594
3595         bfa_trc(bfa, maxfrsize);
3596         bfa_trc(bfa, fcport->cfg.maxfrsize);
3597
3598         /* with in range */
3599         if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
3600                 return BFA_STATUS_INVLD_DFSZ;
3601
3602         /* power of 2, if not the max frame size of 2112 */
3603         if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
3604                 return BFA_STATUS_INVLD_DFSZ;
3605
3606         fcport->cfg.maxfrsize = maxfrsize;
3607         return BFA_STATUS_OK;
3608 }
3609
3610 u16
3611 bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
3612 {
3613         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3614
3615         return fcport->cfg.maxfrsize;
3616 }
3617
3618 u8
3619 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3620 {
3621         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3622
3623         return fcport->cfg.rx_bbcredit;
3624 }
3625
3626 void
3627 bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
3628 {
3629         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3630
3631         fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
3632         bfa_fcport_send_txcredit(fcport);
3633 }
3634
3635 /*
3636  * Get port attributes.
3637  */
3638
3639 wwn_t
3640 bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
3641 {
3642         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3643         if (node)
3644                 return fcport->nwwn;
3645         else
3646                 return fcport->pwwn;
3647 }
3648
3649 void
3650 bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3651 {
3652         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3653
3654         memset(attr, 0, sizeof(struct bfa_port_attr_s));
3655
3656         attr->nwwn = fcport->nwwn;
3657         attr->pwwn = fcport->pwwn;
3658
3659         attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;
3660         attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;
3661
3662         memcpy(&attr->pport_cfg, &fcport->cfg,
3663                 sizeof(struct bfa_port_cfg_s));
3664         /* speed attributes */
3665         attr->pport_cfg.speed = fcport->cfg.speed;
3666         attr->speed_supported = fcport->speed_sup;
3667         attr->speed = fcport->speed;
3668         attr->cos_supported = FC_CLASS_3;
3669
3670         /* topology attributes */
3671         attr->pport_cfg.topology = fcport->cfg.topology;
3672         attr->topology = fcport->topology;
3673         attr->pport_cfg.trunked = fcport->cfg.trunked;
3674
3675         /* beacon attributes */
3676         attr->beacon = fcport->beacon;
3677         attr->link_e2e_beacon = fcport->link_e2e_beacon;
3678         attr->plog_enabled = (bfa_boolean_t)fcport->bfa->plog->plog_enabled;
3679         attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
3680
3681         attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
3682         attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
3683         attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
3684         if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
3685                 attr->port_state = BFA_PORT_ST_IOCDIS;
3686         else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
3687                 attr->port_state = BFA_PORT_ST_FWMISMATCH;
3688
3689         /* FCoE vlan */
3690         attr->fcoe_vlan = fcport->fcoe_vlan;
3691 }
3692
3693 #define BFA_FCPORT_STATS_TOV    1000
3694
3695 /*
3696  * Fetch port statistics (FCQoS or FCoE).
3697  */
3698 bfa_status_t
3699 bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
3700         bfa_cb_port_t cbfn, void *cbarg)
3701 {
3702         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3703
3704         if (fcport->stats_busy) {
3705                 bfa_trc(bfa, fcport->stats_busy);
3706                 return BFA_STATUS_DEVBUSY;
3707         }
3708
3709         fcport->stats_busy  = BFA_TRUE;
3710         fcport->stats_ret   = stats;
3711         fcport->stats_cbfn  = cbfn;
3712         fcport->stats_cbarg = cbarg;
3713
3714         bfa_fcport_send_stats_get(fcport);
3715
3716         bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
3717                         fcport, BFA_FCPORT_STATS_TOV);
3718         return BFA_STATUS_OK;
3719 }
3720
3721 /*
3722  * Reset port statistics (FCQoS or FCoE).
3723  */
3724 bfa_status_t
3725 bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
3726 {
3727         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3728
3729         if (fcport->stats_busy) {
3730                 bfa_trc(bfa, fcport->stats_busy);
3731                 return BFA_STATUS_DEVBUSY;
3732         }
3733
3734         fcport->stats_busy  = BFA_TRUE;
3735         fcport->stats_cbfn  = cbfn;
3736         fcport->stats_cbarg = cbarg;
3737
3738         bfa_fcport_send_stats_clear(fcport);
3739
3740         bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
3741                         fcport, BFA_FCPORT_STATS_TOV);
3742         return BFA_STATUS_OK;
3743 }
3744
3745
3746 /*
3747  * Fetch port attributes.
3748  */
3749 bfa_boolean_t
3750 bfa_fcport_is_disabled(struct bfa_s *bfa)
3751 {
3752         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3753
3754         return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
3755                 BFA_PORT_ST_DISABLED;
3756
3757 }
3758
3759 bfa_boolean_t
3760 bfa_fcport_is_ratelim(struct bfa_s *bfa)
3761 {
3762         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3763
3764         return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
3765
3766 }
3767
3768 /*
3769  * Get default minimum ratelim speed
3770  */
3771 enum bfa_port_speed
3772 bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
3773 {
3774         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3775
3776         bfa_trc(bfa, fcport->cfg.trl_def_speed);
3777         return fcport->cfg.trl_def_speed;
3778
3779 }
3780
3781 bfa_boolean_t
3782 bfa_fcport_is_linkup(struct bfa_s *bfa)
3783 {
3784         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3785
3786         return  (!fcport->cfg.trunked &&
3787                  bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
3788                 (fcport->cfg.trunked &&
3789                  fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
3790 }
3791
3792 bfa_boolean_t
3793 bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
3794 {
3795         struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3796
3797         return fcport->cfg.qos_enabled;
3798 }
3799
3800 /*
3801  * Rport State machine functions
3802  */
3803 /*
3804  * Beginning state, only online event expected.
3805  */
3806 static void
3807 bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
3808 {
3809         bfa_trc(rp->bfa, rp->rport_tag);
3810         bfa_trc(rp->bfa, event);
3811
3812         switch (event) {
3813         case BFA_RPORT_SM_CREATE:
3814                 bfa_stats(rp, sm_un_cr);
3815                 bfa_sm_set_state(rp, bfa_rport_sm_created);
3816                 break;
3817
3818         default:
3819                 bfa_stats(rp, sm_un_unexp);
3820                 bfa_sm_fault(rp->bfa, event);
3821         }
3822 }
3823
3824 static void
3825 bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
3826 {
3827         bfa_trc(rp->bfa, rp->rport_tag);
3828         bfa_trc(rp->bfa, event);
3829
3830         switch (event) {
3831         case BFA_RPORT_SM_ONLINE:
3832                 bfa_stats(rp, sm_cr_on);
3833                 if (bfa_rport_send_fwcreate(rp))
3834                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
3835                 else
3836                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
3837                 break;
3838
3839         case BFA_RPORT_SM_DELETE:
3840                 bfa_stats(rp, sm_cr_del);
3841                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
3842                 bfa_rport_free(rp);
3843                 break;
3844
3845         case BFA_RPORT_SM_HWFAIL:
3846                 bfa_stats(rp, sm_cr_hwf);
3847                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
3848                 break;
3849
3850         default:
3851                 bfa_stats(rp, sm_cr_unexp);
3852                 bfa_sm_fault(rp->bfa, event);
3853         }
3854 }
3855
3856 /*
3857  * Waiting for rport create response from firmware.
3858  */
3859 static void
3860 bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
3861 {
3862         bfa_trc(rp->bfa, rp->rport_tag);
3863         bfa_trc(rp->bfa, event);
3864
3865         switch (event) {
3866         case BFA_RPORT_SM_FWRSP:
3867                 bfa_stats(rp, sm_fwc_rsp);
3868                 bfa_sm_set_state(rp, bfa_rport_sm_online);
3869                 bfa_rport_online_cb(rp);
3870                 break;
3871
3872         case BFA_RPORT_SM_DELETE:
3873                 bfa_stats(rp, sm_fwc_del);
3874                 bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
3875                 break;
3876
3877         case BFA_RPORT_SM_OFFLINE:
3878                 bfa_stats(rp, sm_fwc_off);
3879                 bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
3880                 break;
3881
3882         case BFA_RPORT_SM_HWFAIL:
3883                 bfa_stats(rp, sm_fwc_hwf);
3884                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
3885                 break;
3886
3887         default:
3888                 bfa_stats(rp, sm_fwc_unexp);
3889                 bfa_sm_fault(rp->bfa, event);
3890         }
3891 }
3892
3893 /*
3894  * Request queue is full, awaiting queue resume to send create request.
3895  */
3896 static void
3897 bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
3898 {
3899         bfa_trc(rp->bfa, rp->rport_tag);
3900         bfa_trc(rp->bfa, event);
3901
3902         switch (event) {
3903         case BFA_RPORT_SM_QRESUME:
3904                 bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
3905                 bfa_rport_send_fwcreate(rp);
3906                 break;
3907
3908         case BFA_RPORT_SM_DELETE:
3909                 bfa_stats(rp, sm_fwc_del);
3910                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
3911                 bfa_reqq_wcancel(&rp->reqq_wait);
3912                 bfa_rport_free(rp);
3913                 break;
3914
3915         case BFA_RPORT_SM_OFFLINE:
3916                 bfa_stats(rp, sm_fwc_off);
3917                 bfa_sm_set_state(rp, bfa_rport_sm_offline);
3918                 bfa_reqq_wcancel(&rp->reqq_wait);
3919                 bfa_rport_offline_cb(rp);
3920                 break;
3921
3922         case BFA_RPORT_SM_HWFAIL:
3923                 bfa_stats(rp, sm_fwc_hwf);
3924                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
3925                 bfa_reqq_wcancel(&rp->reqq_wait);
3926                 break;
3927
3928         default:
3929                 bfa_stats(rp, sm_fwc_unexp);
3930                 bfa_sm_fault(rp->bfa, event);
3931         }
3932 }
3933
3934 /*
3935  * Online state - normal parking state.
3936  */
3937 static void
3938 bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
3939 {
3940         struct bfi_rport_qos_scn_s *qos_scn;
3941
3942         bfa_trc(rp->bfa, rp->rport_tag);
3943         bfa_trc(rp->bfa, event);
3944
3945         switch (event) {
3946         case BFA_RPORT_SM_OFFLINE:
3947                 bfa_stats(rp, sm_on_off);
3948                 if (bfa_rport_send_fwdelete(rp))
3949                         bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
3950                 else
3951                         bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
3952                 break;
3953
3954         case BFA_RPORT_SM_DELETE:
3955                 bfa_stats(rp, sm_on_del);
3956                 if (bfa_rport_send_fwdelete(rp))
3957                         bfa_sm_set_state(rp, bfa_rport_sm_deleting);
3958                 else
3959                         bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
3960                 break;
3961
3962         case BFA_RPORT_SM_HWFAIL:
3963                 bfa_stats(rp, sm_on_hwf);
3964                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
3965                 break;
3966
3967         case BFA_RPORT_SM_SET_SPEED:
3968                 bfa_rport_send_fwspeed(rp);
3969                 break;
3970
3971         case BFA_RPORT_SM_QOS_SCN:
3972                 qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
3973                 rp->qos_attr = qos_scn->new_qos_attr;
3974                 bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
3975                 bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
3976                 bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
3977                 bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
3978
3979                 qos_scn->old_qos_attr.qos_flow_id  =
3980                         be32_to_cpu(qos_scn->old_qos_attr.qos_flow_id);
3981                 qos_scn->new_qos_attr.qos_flow_id  =
3982                         be32_to_cpu(qos_scn->new_qos_attr.qos_flow_id);
3983
3984                 if (qos_scn->old_qos_attr.qos_flow_id !=
3985                         qos_scn->new_qos_attr.qos_flow_id)
3986                         bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
3987                                                     qos_scn->old_qos_attr,
3988                                                     qos_scn->new_qos_attr);
3989                 if (qos_scn->old_qos_attr.qos_priority !=
3990                         qos_scn->new_qos_attr.qos_priority)
3991                         bfa_cb_rport_qos_scn_prio(rp->rport_drv,
3992                                                   qos_scn->old_qos_attr,
3993                                                   qos_scn->new_qos_attr);
3994                 break;
3995
3996         default:
3997                 bfa_stats(rp, sm_on_unexp);
3998                 bfa_sm_fault(rp->bfa, event);
3999         }
4000 }
4001
4002 /*
4003  * Firmware rport is being deleted - awaiting f/w response.
4004  */
4005 static void
4006 bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
4007 {
4008         bfa_trc(rp->bfa, rp->rport_tag);
4009         bfa_trc(rp->bfa, event);
4010
4011         switch (event) {
4012         case BFA_RPORT_SM_FWRSP:
4013                 bfa_stats(rp, sm_fwd_rsp);
4014                 bfa_sm_set_state(rp, bfa_rport_sm_offline);
4015                 bfa_rport_offline_cb(rp);
4016                 break;
4017
4018         case BFA_RPORT_SM_DELETE:
4019                 bfa_stats(rp, sm_fwd_del);
4020                 bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4021                 break;
4022
4023         case BFA_RPORT_SM_HWFAIL:
4024                 bfa_stats(rp, sm_fwd_hwf);
4025                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4026                 bfa_rport_offline_cb(rp);
4027                 break;
4028
4029         default:
4030                 bfa_stats(rp, sm_fwd_unexp);
4031                 bfa_sm_fault(rp->bfa, event);
4032         }
4033 }
4034
4035 static void
4036 bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4037 {
4038         bfa_trc(rp->bfa, rp->rport_tag);
4039         bfa_trc(rp->bfa, event);
4040
4041         switch (event) {
4042         case BFA_RPORT_SM_QRESUME:
4043                 bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4044                 bfa_rport_send_fwdelete(rp);
4045                 break;
4046
4047         case BFA_RPORT_SM_DELETE:
4048                 bfa_stats(rp, sm_fwd_del);
4049                 bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4050                 break;
4051
4052         case BFA_RPORT_SM_HWFAIL:
4053                 bfa_stats(rp, sm_fwd_hwf);
4054                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4055                 bfa_reqq_wcancel(&rp->reqq_wait);
4056                 bfa_rport_offline_cb(rp);
4057                 break;
4058
4059         default:
4060                 bfa_stats(rp, sm_fwd_unexp);
4061                 bfa_sm_fault(rp->bfa, event);
4062         }
4063 }
4064
4065 /*
4066  * Offline state.
4067  */
4068 static void
4069 bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
4070 {
4071         bfa_trc(rp->bfa, rp->rport_tag);
4072         bfa_trc(rp->bfa, event);
4073
4074         switch (event) {
4075         case BFA_RPORT_SM_DELETE:
4076                 bfa_stats(rp, sm_off_del);
4077                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4078                 bfa_rport_free(rp);
4079                 break;
4080
4081         case BFA_RPORT_SM_ONLINE:
4082                 bfa_stats(rp, sm_off_on);
4083                 if (bfa_rport_send_fwcreate(rp))
4084                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4085                 else
4086                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4087                 break;
4088
4089         case BFA_RPORT_SM_HWFAIL:
4090                 bfa_stats(rp, sm_off_hwf);
4091                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4092                 break;
4093
4094         default:
4095                 bfa_stats(rp, sm_off_unexp);
4096                 bfa_sm_fault(rp->bfa, event);
4097         }
4098 }
4099
4100 /*
4101  * Rport is deleted, waiting for firmware response to delete.
4102  */
4103 static void
4104 bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
4105 {
4106         bfa_trc(rp->bfa, rp->rport_tag);
4107         bfa_trc(rp->bfa, event);
4108
4109         switch (event) {
4110         case BFA_RPORT_SM_FWRSP:
4111                 bfa_stats(rp, sm_del_fwrsp);
4112                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4113                 bfa_rport_free(rp);
4114                 break;
4115
4116         case BFA_RPORT_SM_HWFAIL:
4117                 bfa_stats(rp, sm_del_hwf);
4118                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4119                 bfa_rport_free(rp);
4120                 break;
4121
4122         default:
4123                 bfa_sm_fault(rp->bfa, event);
4124         }
4125 }
4126
4127 static void
4128 bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4129 {
4130         bfa_trc(rp->bfa, rp->rport_tag);
4131         bfa_trc(rp->bfa, event);
4132
4133         switch (event) {
4134         case BFA_RPORT_SM_QRESUME:
4135                 bfa_stats(rp, sm_del_fwrsp);
4136                 bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4137                 bfa_rport_send_fwdelete(rp);
4138                 break;
4139
4140         case BFA_RPORT_SM_HWFAIL:
4141                 bfa_stats(rp, sm_del_hwf);
4142                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4143                 bfa_reqq_wcancel(&rp->reqq_wait);
4144                 bfa_rport_free(rp);
4145                 break;
4146
4147         default:
4148                 bfa_sm_fault(rp->bfa, event);
4149         }
4150 }
4151
4152 /*
4153  * Waiting for rport create response from firmware. A delete is pending.
4154  */
4155 static void
4156 bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
4157                                 enum bfa_rport_event event)
4158 {
4159         bfa_trc(rp->bfa, rp->rport_tag);
4160         bfa_trc(rp->bfa, event);
4161
4162         switch (event) {
4163         case BFA_RPORT_SM_FWRSP:
4164                 bfa_stats(rp, sm_delp_fwrsp);
4165                 if (bfa_rport_send_fwdelete(rp))
4166                         bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4167                 else
4168                         bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4169                 break;
4170
4171         case BFA_RPORT_SM_HWFAIL:
4172                 bfa_stats(rp, sm_delp_hwf);
4173                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4174                 bfa_rport_free(rp);
4175                 break;
4176
4177         default:
4178                 bfa_stats(rp, sm_delp_unexp);
4179                 bfa_sm_fault(rp->bfa, event);
4180         }
4181 }
4182
4183 /*
4184  * Waiting for rport create response from firmware. Rport offline is pending.
4185  */
4186 static void
4187 bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
4188                                  enum bfa_rport_event event)
4189 {
4190         bfa_trc(rp->bfa, rp->rport_tag);
4191         bfa_trc(rp->bfa, event);
4192
4193         switch (event) {
4194         case BFA_RPORT_SM_FWRSP:
4195                 bfa_stats(rp, sm_offp_fwrsp);
4196                 if (bfa_rport_send_fwdelete(rp))
4197                         bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4198                 else
4199                         bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4200                 break;
4201
4202         case BFA_RPORT_SM_DELETE:
4203                 bfa_stats(rp, sm_offp_del);
4204                 bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4205                 break;
4206
4207         case BFA_RPORT_SM_HWFAIL:
4208                 bfa_stats(rp, sm_offp_hwf);
4209                 bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4210                 break;
4211
4212         default:
4213                 bfa_stats(rp, sm_offp_unexp);
4214                 bfa_sm_fault(rp->bfa, event);
4215         }
4216 }
4217
4218 /*
4219  * IOC h/w failed.
4220  */
4221 static void
4222 bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
4223 {
4224         bfa_trc(rp->bfa, rp->rport_tag);
4225         bfa_trc(rp->bfa, event);
4226
4227         switch (event) {
4228         case BFA_RPORT_SM_OFFLINE:
4229                 bfa_stats(rp, sm_iocd_off);
4230                 bfa_rport_offline_cb(rp);
4231                 break;
4232
4233         case BFA_RPORT_SM_DELETE:
4234                 bfa_stats(rp, sm_iocd_del);
4235                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4236                 bfa_rport_free(rp);
4237                 break;
4238
4239         case BFA_RPORT_SM_ONLINE:
4240                 bfa_stats(rp, sm_iocd_on);
4241                 if (bfa_rport_send_fwcreate(rp))
4242                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4243                 else
4244                         bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4245                 break;
4246
4247         case BFA_RPORT_SM_HWFAIL:
4248                 break;
4249
4250         default:
4251                 bfa_stats(rp, sm_iocd_unexp);
4252                 bfa_sm_fault(rp->bfa, event);
4253         }
4254 }
4255
4256
4257
4258 /*
4259  *  bfa_rport_private BFA rport private functions
4260  */
4261
4262 static void
4263 __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
4264 {
4265         struct bfa_rport_s *rp = cbarg;
4266
4267         if (complete)
4268                 bfa_cb_rport_online(rp->rport_drv);
4269 }
4270
4271 static void
4272 __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
4273 {
4274         struct bfa_rport_s *rp = cbarg;
4275
4276         if (complete)
4277                 bfa_cb_rport_offline(rp->rport_drv);
4278 }
4279
4280 static void
4281 bfa_rport_qresume(void *cbarg)
4282 {
4283         struct bfa_rport_s      *rp = cbarg;
4284
4285         bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
4286 }
4287
4288 static void
4289 bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
4290                 u32 *dm_len)
4291 {
4292         if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
4293                 cfg->fwcfg.num_rports = BFA_RPORT_MIN;
4294
4295         *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
4296 }
4297
4298 static void
4299 bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4300                      struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
4301 {
4302         struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4303         struct bfa_rport_s *rp;
4304         u16 i;
4305
4306         INIT_LIST_HEAD(&mod->rp_free_q);
4307         INIT_LIST_HEAD(&mod->rp_active_q);
4308
4309         rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
4310         mod->rps_list = rp;
4311         mod->num_rports = cfg->fwcfg.num_rports;
4312
4313         WARN_ON(!mod->num_rports ||
4314                    (mod->num_rports & (mod->num_rports - 1)));
4315
4316         for (i = 0; i < mod->num_rports; i++, rp++) {
4317                 memset(rp, 0, sizeof(struct bfa_rport_s));
4318                 rp->bfa = bfa;
4319                 rp->rport_tag = i;
4320                 bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4321
4322                 /*
4323                  *  - is unused
4324                  */
4325                 if (i)
4326                         list_add_tail(&rp->qe, &mod->rp_free_q);
4327
4328                 bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
4329         }
4330
4331         /*
4332          * consume memory
4333          */
4334         bfa_meminfo_kva(meminfo) = (u8 *) rp;
4335 }
4336
4337 static void
4338 bfa_rport_detach(struct bfa_s *bfa)
4339 {
4340 }
4341
4342 static void
4343 bfa_rport_start(struct bfa_s *bfa)
4344 {
4345 }
4346
4347 static void
4348 bfa_rport_stop(struct bfa_s *bfa)
4349 {
4350 }
4351
4352 static void
4353 bfa_rport_iocdisable(struct bfa_s *bfa)
4354 {
4355         struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4356         struct bfa_rport_s *rport;
4357         struct list_head *qe, *qen;
4358
4359         list_for_each_safe(qe, qen, &mod->rp_active_q) {
4360                 rport = (struct bfa_rport_s *) qe;
4361                 bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
4362         }
4363 }
4364
4365 static struct bfa_rport_s *
4366 bfa_rport_alloc(struct bfa_rport_mod_s *mod)
4367 {
4368         struct bfa_rport_s *rport;
4369
4370         bfa_q_deq(&mod->rp_free_q, &rport);
4371         if (rport)
4372                 list_add_tail(&rport->qe, &mod->rp_active_q);
4373
4374         return rport;
4375 }
4376
4377 static void
4378 bfa_rport_free(struct bfa_rport_s *rport)
4379 {
4380         struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
4381
4382         WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
4383         list_del(&rport->qe);
4384         list_add_tail(&rport->qe, &mod->rp_free_q);
4385 }
4386
4387 static bfa_boolean_t
4388 bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
4389 {
4390         struct bfi_rport_create_req_s *m;
4391
4392         /*
4393          * check for room in queue to send request now
4394          */
4395         m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4396         if (!m) {
4397                 bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4398                 return BFA_FALSE;
4399         }
4400
4401         bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
4402                         bfa_lpuid(rp->bfa));
4403         m->bfa_handle = rp->rport_tag;
4404         m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
4405         m->pid = rp->rport_info.pid;
4406         m->lp_tag = rp->rport_info.lp_tag;
4407         m->local_pid = rp->rport_info.local_pid;
4408         m->fc_class = rp->rport_info.fc_class;
4409         m->vf_en = rp->rport_info.vf_en;
4410         m->vf_id = rp->rport_info.vf_id;
4411         m->cisc = rp->rport_info.cisc;
4412
4413         /*
4414          * queue I/O message to firmware
4415          */
4416         bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
4417         return BFA_TRUE;
4418 }
4419
4420 static bfa_boolean_t
4421 bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
4422 {
4423         struct bfi_rport_delete_req_s *m;
4424
4425         /*
4426          * check for room in queue to send request now
4427          */
4428         m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4429         if (!m) {
4430                 bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4431                 return BFA_FALSE;
4432         }
4433
4434         bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
4435                         bfa_lpuid(rp->bfa));
4436         m->fw_handle = rp->fw_handle;
4437
4438         /*
4439          * queue I/O message to firmware
4440          */
4441         bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
4442         return BFA_TRUE;
4443 }
4444
4445 static bfa_boolean_t
4446 bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
4447 {
4448         struct bfa_rport_speed_req_s *m;
4449
4450         /*
4451          * check for room in queue to send request now
4452          */
4453         m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4454         if (!m) {
4455                 bfa_trc(rp->bfa, rp->rport_info.speed);
4456                 return BFA_FALSE;
4457         }
4458
4459         bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
4460                         bfa_lpuid(rp->bfa));
4461         m->fw_handle = rp->fw_handle;
4462         m->speed = (u8)rp->rport_info.speed;
4463
4464         /*
4465          * queue I/O message to firmware
4466          */
4467         bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
4468         return BFA_TRUE;
4469 }
4470
4471
4472
4473 /*
4474  *  bfa_rport_public
4475  */
4476
4477 /*
4478  * Rport interrupt processing.
4479  */
4480 void
4481 bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
4482 {
4483         union bfi_rport_i2h_msg_u msg;
4484         struct bfa_rport_s *rp;
4485
4486         bfa_trc(bfa, m->mhdr.msg_id);
4487
4488         msg.msg = m;
4489
4490         switch (m->mhdr.msg_id) {
4491         case BFI_RPORT_I2H_CREATE_RSP:
4492                 rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
4493                 rp->fw_handle = msg.create_rsp->fw_handle;
4494                 rp->qos_attr = msg.create_rsp->qos_attr;
4495                 WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
4496                 bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
4497                 break;
4498
4499         case BFI_RPORT_I2H_DELETE_RSP:
4500                 rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
4501                 WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
4502                 bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
4503                 break;
4504
4505         case BFI_RPORT_I2H_QOS_SCN:
4506                 rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
4507                 rp->event_arg.fw_msg = msg.qos_scn_evt;
4508                 bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
4509                 break;
4510
4511         default:
4512                 bfa_trc(bfa, m->mhdr.msg_id);
4513                 WARN_ON(1);
4514         }
4515 }
4516
4517
4518
4519 /*
4520  *  bfa_rport_api
4521  */
4522
4523 struct bfa_rport_s *
4524 bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
4525 {
4526         struct bfa_rport_s *rp;
4527
4528         rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
4529
4530         if (rp == NULL)
4531                 return NULL;
4532
4533         rp->bfa = bfa;
4534         rp->rport_drv = rport_drv;
4535         memset(&rp->stats, 0, sizeof(rp->stats));
4536
4537         WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
4538         bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
4539
4540         return rp;
4541 }
4542
4543 void
4544 bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
4545 {
4546         WARN_ON(rport_info->max_frmsz == 0);
4547
4548         /*
4549          * Some JBODs are seen to be not setting PDU size correctly in PLOGI
4550          * responses. Default to minimum size.
4551          */
4552         if (rport_info->max_frmsz == 0) {
4553                 bfa_trc(rport->bfa, rport->rport_tag);
4554                 rport_info->max_frmsz = FC_MIN_PDUSZ;
4555         }
4556
4557         rport->rport_info = *rport_info;
4558         bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
4559 }
4560
4561 void
4562 bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
4563 {
4564         WARN_ON(speed == 0);
4565         WARN_ON(speed == BFA_PORT_SPEED_AUTO);
4566
4567         rport->rport_info.speed = speed;
4568         bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
4569 }
4570
4571
4572 /*
4573  * SGPG related functions
4574  */
4575
4576 /*
4577  * Compute and return memory needed by FCP(im) module.
4578  */
4579 static void
4580 bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
4581                 u32 *dm_len)
4582 {
4583         if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
4584                 cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
4585
4586         *km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
4587         *dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
4588 }
4589
4590
4591 static void
4592 bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4593                     struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
4594 {
4595         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4596         int i;
4597         struct bfa_sgpg_s *hsgpg;
4598         struct bfi_sgpg_s *sgpg;
4599         u64 align_len;
4600
4601         union {
4602                 u64 pa;
4603                 union bfi_addr_u addr;
4604         } sgpg_pa, sgpg_pa_tmp;
4605
4606         INIT_LIST_HEAD(&mod->sgpg_q);
4607         INIT_LIST_HEAD(&mod->sgpg_wait_q);
4608
4609         bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
4610
4611         mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
4612         mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
4613         align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
4614         mod->sgpg_arr_pa += align_len;
4615         mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
4616                                                 align_len);
4617         mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
4618                                                 align_len);
4619
4620         hsgpg = mod->hsgpg_arr;
4621         sgpg = mod->sgpg_arr;
4622         sgpg_pa.pa = mod->sgpg_arr_pa;
4623         mod->free_sgpgs = mod->num_sgpgs;
4624
4625         WARN_ON(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1));
4626
4627         for (i = 0; i < mod->num_sgpgs; i++) {
4628                 memset(hsgpg, 0, sizeof(*hsgpg));
4629                 memset(sgpg, 0, sizeof(*sgpg));
4630
4631                 hsgpg->sgpg = sgpg;
4632                 sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
4633                 hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
4634                 list_add_tail(&hsgpg->qe, &mod->sgpg_q);
4635
4636                 hsgpg++;
4637                 sgpg++;
4638                 sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
4639         }
4640
4641         bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
4642         bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
4643         bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
4644 }
4645
4646 static void
4647 bfa_sgpg_detach(struct bfa_s *bfa)
4648 {
4649 }
4650
4651 static void
4652 bfa_sgpg_start(struct bfa_s *bfa)
4653 {
4654 }
4655
4656 static void
4657 bfa_sgpg_stop(struct bfa_s *bfa)
4658 {
4659 }
4660
4661 static void
4662 bfa_sgpg_iocdisable(struct bfa_s *bfa)
4663 {
4664 }
4665
4666 bfa_status_t
4667 bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
4668 {
4669         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4670         struct bfa_sgpg_s *hsgpg;
4671         int i;
4672
4673         if (mod->free_sgpgs < nsgpgs)
4674                 return BFA_STATUS_ENOMEM;
4675
4676         for (i = 0; i < nsgpgs; i++) {
4677                 bfa_q_deq(&mod->sgpg_q, &hsgpg);
4678                 WARN_ON(!hsgpg);
4679                 list_add_tail(&hsgpg->qe, sgpg_q);
4680         }
4681
4682         mod->free_sgpgs -= nsgpgs;
4683         return BFA_STATUS_OK;
4684 }
4685
4686 void
4687 bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
4688 {
4689         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4690         struct bfa_sgpg_wqe_s *wqe;
4691
4692         mod->free_sgpgs += nsgpg;
4693         WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
4694
4695         list_splice_tail_init(sgpg_q, &mod->sgpg_q);
4696
4697         if (list_empty(&mod->sgpg_wait_q))
4698                 return;
4699
4700         /*
4701          * satisfy as many waiting requests as possible
4702          */
4703         do {
4704                 wqe = bfa_q_first(&mod->sgpg_wait_q);
4705                 if (mod->free_sgpgs < wqe->nsgpg)
4706                         nsgpg = mod->free_sgpgs;
4707                 else
4708                         nsgpg = wqe->nsgpg;
4709                 bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
4710                 wqe->nsgpg -= nsgpg;
4711                 if (wqe->nsgpg == 0) {
4712                         list_del(&wqe->qe);
4713                         wqe->cbfn(wqe->cbarg);
4714                 }
4715         } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
4716 }
4717
4718 void
4719 bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
4720 {
4721         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4722
4723         WARN_ON(nsgpg <= 0);
4724         WARN_ON(nsgpg <= mod->free_sgpgs);
4725
4726         wqe->nsgpg_total = wqe->nsgpg = nsgpg;
4727
4728         /*
4729          * allocate any left to this one first
4730          */
4731         if (mod->free_sgpgs) {
4732                 /*
4733                  * no one else is waiting for SGPG
4734                  */
4735                 WARN_ON(!list_empty(&mod->sgpg_wait_q));
4736                 list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
4737                 wqe->nsgpg -= mod->free_sgpgs;
4738                 mod->free_sgpgs = 0;
4739         }
4740
4741         list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
4742 }
4743
4744 void
4745 bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
4746 {
4747         struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
4748
4749         WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
4750         list_del(&wqe->qe);
4751
4752         if (wqe->nsgpg_total != wqe->nsgpg)
4753                 bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
4754                                    wqe->nsgpg_total - wqe->nsgpg);
4755 }
4756
4757 void
4758 bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
4759                    void *cbarg)
4760 {
4761         INIT_LIST_HEAD(&wqe->sgpg_q);
4762         wqe->cbfn = cbfn;
4763         wqe->cbarg = cbarg;
4764 }
4765
4766 /*
4767  *  UF related functions
4768  */
4769 /*
4770  *****************************************************************************
4771  * Internal functions
4772  *****************************************************************************
4773  */
4774 static void
4775 __bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
4776 {
4777         struct bfa_uf_s   *uf = cbarg;
4778         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
4779
4780         if (complete)
4781                 ufm->ufrecv(ufm->cbarg, uf);
4782 }
4783
4784 static void
4785 claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
4786 {
4787         u32 uf_pb_tot_sz;
4788
4789         ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
4790         ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
4791         uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
4792                                                         BFA_DMA_ALIGN_SZ);
4793
4794         bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
4795         bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
4796
4797         memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
4798 }
4799
4800 static void
4801 claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
4802 {
4803         struct bfi_uf_buf_post_s *uf_bp_msg;
4804         struct bfi_sge_s      *sge;
4805         union bfi_addr_u      sga_zero = { {0} };
4806         u16 i;
4807         u16 buf_len;
4808
4809         ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
4810         uf_bp_msg = ufm->uf_buf_posts;
4811
4812         for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
4813              i++, uf_bp_msg++) {
4814                 memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
4815
4816                 uf_bp_msg->buf_tag = i;
4817                 buf_len = sizeof(struct bfa_uf_buf_s);
4818                 uf_bp_msg->buf_len = cpu_to_be16(buf_len);
4819                 bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
4820                             bfa_lpuid(ufm->bfa));
4821
4822                 sge = uf_bp_msg->sge;
4823                 sge[0].sg_len = buf_len;
4824                 sge[0].flags = BFI_SGE_DATA_LAST;
4825                 bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
4826                 bfa_sge_to_be(sge);
4827
4828                 sge[1].sg_len = buf_len;
4829                 sge[1].flags = BFI_SGE_PGDLEN;
4830                 sge[1].sga = sga_zero;
4831                 bfa_sge_to_be(&sge[1]);
4832         }
4833
4834         /*
4835          * advance pointer beyond consumed memory
4836          */
4837         bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
4838 }
4839
4840 static void
4841 claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
4842 {
4843         u16 i;
4844         struct bfa_uf_s   *uf;
4845
4846         /*
4847          * Claim block of memory for UF list
4848          */
4849         ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
4850
4851         /*
4852          * Initialize UFs and queue it in UF free queue
4853          */
4854         for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
4855                 memset(uf, 0, sizeof(struct bfa_uf_s));
4856                 uf->bfa = ufm->bfa;
4857                 uf->uf_tag = i;
4858                 uf->pb_len = sizeof(struct bfa_uf_buf_s);
4859                 uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
4860                 uf->buf_pa = ufm_pbs_pa(ufm, i);
4861                 list_add_tail(&uf->qe, &ufm->uf_free_q);
4862         }
4863
4864         /*
4865          * advance memory pointer
4866          */
4867         bfa_meminfo_kva(mi) = (u8 *) uf;
4868 }
4869
4870 static void
4871 uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
4872 {
4873         claim_uf_pbs(ufm, mi);
4874         claim_ufs(ufm, mi);
4875         claim_uf_post_msgs(ufm, mi);
4876 }
4877
4878 static void
4879 bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
4880 {
4881         u32 num_ufs = cfg->fwcfg.num_uf_bufs;
4882
4883         /*
4884          * dma-able memory for UF posted bufs
4885          */
4886         *dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
4887                                                         BFA_DMA_ALIGN_SZ);
4888
4889         /*
4890          * kernel Virtual memory for UFs and UF buf post msg copies
4891          */
4892         *ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
4893         *ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
4894 }
4895
4896 static void
4897 bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4898                   struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
4899 {
4900         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
4901
4902         memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
4903         ufm->bfa = bfa;
4904         ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
4905         INIT_LIST_HEAD(&ufm->uf_free_q);
4906         INIT_LIST_HEAD(&ufm->uf_posted_q);
4907
4908         uf_mem_claim(ufm, meminfo);
4909 }
4910
4911 static void
4912 bfa_uf_detach(struct bfa_s *bfa)
4913 {
4914 }
4915
4916 static struct bfa_uf_s *
4917 bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
4918 {
4919         struct bfa_uf_s   *uf;
4920
4921         bfa_q_deq(&uf_mod->uf_free_q, &uf);
4922         return uf;
4923 }
4924
4925 static void
4926 bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
4927 {
4928         list_add_tail(&uf->qe, &uf_mod->uf_free_q);
4929 }
4930
4931 static bfa_status_t
4932 bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
4933 {
4934         struct bfi_uf_buf_post_s *uf_post_msg;
4935
4936         uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
4937         if (!uf_post_msg)
4938                 return BFA_STATUS_FAILED;
4939
4940         memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
4941                       sizeof(struct bfi_uf_buf_post_s));
4942         bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
4943
4944         bfa_trc(ufm->bfa, uf->uf_tag);
4945
4946         list_add_tail(&uf->qe, &ufm->uf_posted_q);
4947         return BFA_STATUS_OK;
4948 }
4949
4950 static void
4951 bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
4952 {
4953         struct bfa_uf_s   *uf;
4954
4955         while ((uf = bfa_uf_get(uf_mod)) != NULL) {
4956                 if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
4957                         break;
4958         }
4959 }
4960
4961 static void
4962 uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
4963 {
4964         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
4965         u16 uf_tag = m->buf_tag;
4966         struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
4967         struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
4968         u8 *buf = &uf_buf->d[0];
4969         struct fchs_s *fchs;
4970
4971         m->frm_len = be16_to_cpu(m->frm_len);
4972         m->xfr_len = be16_to_cpu(m->xfr_len);
4973
4974         fchs = (struct fchs_s *)uf_buf;
4975
4976         list_del(&uf->qe);      /* dequeue from posted queue */
4977
4978         uf->data_ptr = buf;
4979         uf->data_len = m->xfr_len;
4980
4981         WARN_ON(uf->data_len < sizeof(struct fchs_s));
4982
4983         if (uf->data_len == sizeof(struct fchs_s)) {
4984                 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
4985                                uf->data_len, (struct fchs_s *)buf);
4986         } else {
4987                 u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
4988                 bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
4989                                       BFA_PL_EID_RX, uf->data_len,
4990                                       (struct fchs_s *)buf, pld_w0);
4991         }
4992
4993         if (bfa->fcs)
4994                 __bfa_cb_uf_recv(uf, BFA_TRUE);
4995         else
4996                 bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
4997 }
4998
4999 static void
5000 bfa_uf_stop(struct bfa_s *bfa)
5001 {
5002 }
5003
5004 static void
5005 bfa_uf_iocdisable(struct bfa_s *bfa)
5006 {
5007         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5008         struct bfa_uf_s *uf;
5009         struct list_head *qe, *qen;
5010
5011         list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
5012                 uf = (struct bfa_uf_s *) qe;
5013                 list_del(&uf->qe);
5014                 bfa_uf_put(ufm, uf);
5015         }
5016 }
5017
5018 static void
5019 bfa_uf_start(struct bfa_s *bfa)
5020 {
5021         bfa_uf_post_all(BFA_UF_MOD(bfa));
5022 }
5023
5024 /*
5025  * Register handler for all unsolicted recieve frames.
5026  *
5027  * @param[in]   bfa             BFA instance
5028  * @param[in]   ufrecv  receive handler function
5029  * @param[in]   cbarg   receive handler arg
5030  */
5031 void
5032 bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
5033 {
5034         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5035
5036         ufm->ufrecv = ufrecv;
5037         ufm->cbarg = cbarg;
5038 }
5039
5040 /*
5041  *      Free an unsolicited frame back to BFA.
5042  *
5043  * @param[in]           uf              unsolicited frame to be freed
5044  *
5045  * @return None
5046  */
5047 void
5048 bfa_uf_free(struct bfa_uf_s *uf)
5049 {
5050         bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
5051         bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
5052 }
5053
5054
5055
5056 /*
5057  *  uf_pub BFA uf module public functions
5058  */
5059 void
5060 bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5061 {
5062         bfa_trc(bfa, msg->mhdr.msg_id);
5063
5064         switch (msg->mhdr.msg_id) {
5065         case BFI_UF_I2H_FRM_RCVD:
5066                 uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
5067                 break;
5068
5069         default:
5070                 bfa_trc(bfa, msg->mhdr.msg_id);
5071                 WARN_ON(1);
5072         }
5073 }
5074
5075