]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/scsi/bfa/bfa_fcxp.c
Merge branches 'gemini' and 'misc' into devel
[mv-sheeva.git] / drivers / scsi / bfa / bfa_fcxp.c
1 /*
2  * Copyright (c) 2005-2009 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 <bfa.h>
19 #include <bfi/bfi_uf.h>
20 #include <cs/bfa_debug.h>
21
22 BFA_TRC_FILE(HAL, FCXP);
23 BFA_MODULE(fcxp);
24
25 /**
26  * forward declarations
27  */
28 static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
29 static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
30                                  struct bfi_fcxp_send_rsp_s *fcxp_rsp);
31 static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
32                                  struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
33 static void     bfa_fcxp_qresume(void *cbarg);
34 static void     bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
35                                struct bfi_fcxp_send_req_s *send_req);
36
37 /**
38  *  fcxp_pvt BFA FCXP private functions
39  */
40
41 static void
42 claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
43 {
44         u8        *dm_kva = NULL;
45         u64        dm_pa;
46         u32        buf_pool_sz;
47
48         dm_kva = bfa_meminfo_dma_virt(mi);
49         dm_pa = bfa_meminfo_dma_phys(mi);
50
51         buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
52
53         /*
54          * Initialize the fcxp req payload list
55          */
56         mod->req_pld_list_kva = dm_kva;
57         mod->req_pld_list_pa = dm_pa;
58         dm_kva += buf_pool_sz;
59         dm_pa += buf_pool_sz;
60         bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
61
62         /*
63          * Initialize the fcxp rsp payload list
64          */
65         buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
66         mod->rsp_pld_list_kva = dm_kva;
67         mod->rsp_pld_list_pa = dm_pa;
68         dm_kva += buf_pool_sz;
69         dm_pa += buf_pool_sz;
70         bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
71
72         bfa_meminfo_dma_virt(mi) = dm_kva;
73         bfa_meminfo_dma_phys(mi) = dm_pa;
74 }
75
76 static void
77 claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
78 {
79         u16        i;
80         struct bfa_fcxp_s *fcxp;
81
82         fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
83         bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
84
85         INIT_LIST_HEAD(&mod->fcxp_free_q);
86         INIT_LIST_HEAD(&mod->fcxp_active_q);
87
88         mod->fcxp_list = fcxp;
89
90         for (i = 0; i < mod->num_fcxps; i++) {
91                 fcxp->fcxp_mod = mod;
92                 fcxp->fcxp_tag = i;
93
94                 list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
95                 bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
96                 fcxp->reqq_waiting = BFA_FALSE;
97
98                 fcxp = fcxp + 1;
99         }
100
101         bfa_meminfo_kva(mi) = (void *)fcxp;
102 }
103
104 static void
105 bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
106                 u32 *dm_len)
107 {
108         u16        num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
109
110         if (num_fcxp_reqs == 0)
111                 return;
112
113         /*
114          * Account for req/rsp payload
115          */
116         *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
117         if (cfg->drvcfg.min_cfg)
118                 *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
119         else
120                 *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
121
122         /*
123          * Account for fcxp structs
124          */
125         *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
126 }
127
128 static void
129 bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
130                     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
131 {
132         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
133
134         bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
135         mod->bfa = bfa;
136         mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
137
138         /**
139          * Initialize FCXP request and response payload sizes.
140          */
141         mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
142         if (!cfg->drvcfg.min_cfg)
143                 mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
144
145         INIT_LIST_HEAD(&mod->wait_q);
146
147         claim_fcxp_req_rsp_mem(mod, meminfo);
148         claim_fcxps_mem(mod, meminfo);
149 }
150
151 static void
152 bfa_fcxp_detach(struct bfa_s *bfa)
153 {
154 }
155
156 static void
157 bfa_fcxp_start(struct bfa_s *bfa)
158 {
159 }
160
161 static void
162 bfa_fcxp_stop(struct bfa_s *bfa)
163 {
164 }
165
166 static void
167 bfa_fcxp_iocdisable(struct bfa_s *bfa)
168 {
169         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
170         struct bfa_fcxp_s *fcxp;
171         struct list_head        *qe, *qen;
172
173         list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
174                 fcxp = (struct bfa_fcxp_s *) qe;
175                 if (fcxp->caller == NULL) {
176                         fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
177                                         BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
178                         bfa_fcxp_free(fcxp);
179                 } else {
180                         fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
181                         bfa_cb_queue(bfa, &fcxp->hcb_qe,
182                                       __bfa_fcxp_send_cbfn, fcxp);
183                 }
184         }
185 }
186
187 static struct bfa_fcxp_s *
188 bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
189 {
190         struct bfa_fcxp_s *fcxp;
191
192         bfa_q_deq(&fm->fcxp_free_q, &fcxp);
193
194         if (fcxp)
195                 list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
196
197         return fcxp;
198 }
199
200 static void
201 bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
202 {
203         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
204         struct bfa_fcxp_wqe_s *wqe;
205
206         bfa_q_deq(&mod->wait_q, &wqe);
207         if (wqe) {
208                 bfa_trc(mod->bfa, fcxp->fcxp_tag);
209                 wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
210                 return;
211         }
212
213         bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
214         list_del(&fcxp->qe);
215         list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
216 }
217
218 static void
219 bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
220                        bfa_status_t req_status, u32 rsp_len,
221                        u32 resid_len, struct fchs_s *rsp_fchs)
222 {
223         /* discarded fcxp completion */
224 }
225
226 static void
227 __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
228 {
229         struct bfa_fcxp_s *fcxp = cbarg;
230
231         if (complete) {
232                 fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
233                                 fcxp->rsp_status, fcxp->rsp_len,
234                                 fcxp->residue_len, &fcxp->rsp_fchs);
235         } else {
236                 bfa_fcxp_free(fcxp);
237         }
238 }
239
240 static void
241 hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
242 {
243         struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
244         struct bfa_fcxp_s       *fcxp;
245         u16             fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
246
247         bfa_trc(bfa, fcxp_tag);
248
249         fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
250
251         /**
252          * @todo f/w should not set residue to non-0 when everything
253          *       is received.
254          */
255         if (fcxp_rsp->req_status == BFA_STATUS_OK)
256                 fcxp_rsp->residue_len = 0;
257         else
258                 fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
259
260         fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
261
262         bfa_assert(fcxp->send_cbfn != NULL);
263
264         hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
265
266         if (fcxp->send_cbfn != NULL) {
267                 if (fcxp->caller == NULL) {
268                         bfa_trc(mod->bfa, fcxp->fcxp_tag);
269
270                         fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
271                                         fcxp_rsp->req_status, fcxp_rsp->rsp_len,
272                                         fcxp_rsp->residue_len, &fcxp_rsp->fchs);
273                         /*
274                          * fcxp automatically freed on return from the callback
275                          */
276                         bfa_fcxp_free(fcxp);
277                 } else {
278                         bfa_trc(mod->bfa, fcxp->fcxp_tag);
279                         fcxp->rsp_status = fcxp_rsp->req_status;
280                         fcxp->rsp_len = fcxp_rsp->rsp_len;
281                         fcxp->residue_len = fcxp_rsp->residue_len;
282                         fcxp->rsp_fchs = fcxp_rsp->fchs;
283
284                         bfa_cb_queue(bfa, &fcxp->hcb_qe,
285                                       __bfa_fcxp_send_cbfn, fcxp);
286                 }
287         } else {
288                 bfa_trc(bfa, fcxp_tag);
289         }
290 }
291
292 static void
293 hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
294 {
295         union bfi_addr_u      sga_zero = { {0} };
296
297         sge->sg_len = reqlen;
298         sge->flags = BFI_SGE_DATA_LAST;
299         bfa_dma_addr_set(sge[0].sga, req_pa);
300         bfa_sge_to_be(sge);
301         sge++;
302
303         sge->sga = sga_zero;
304         sge->sg_len = reqlen;
305         sge->flags = BFI_SGE_PGDLEN;
306         bfa_sge_to_be(sge);
307 }
308
309 static void
310 hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
311                  struct fchs_s *fchs)
312 {
313         /*
314          * TODO: TX ox_id
315          */
316         if (reqlen > 0) {
317                 if (fcxp->use_ireqbuf) {
318                         u32        pld_w0 =
319                                 *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
320
321                         bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
322                                 BFA_PL_EID_TX,
323                                 reqlen + sizeof(struct fchs_s), fchs, pld_w0);
324                 } else {
325                         bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
326                                 BFA_PL_EID_TX, reqlen + sizeof(struct fchs_s),
327                                 fchs);
328                 }
329         } else {
330                 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
331                                reqlen + sizeof(struct fchs_s), fchs);
332         }
333 }
334
335 static void
336 hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
337                  struct bfi_fcxp_send_rsp_s *fcxp_rsp)
338 {
339         if (fcxp_rsp->rsp_len > 0) {
340                 if (fcxp->use_irspbuf) {
341                         u32        pld_w0 =
342                                 *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
343
344                         bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
345                                               BFA_PL_EID_RX,
346                                               (u16) fcxp_rsp->rsp_len,
347                                               &fcxp_rsp->fchs, pld_w0);
348                 } else {
349                         bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
350                                        BFA_PL_EID_RX,
351                                        (u16) fcxp_rsp->rsp_len,
352                                        &fcxp_rsp->fchs);
353                 }
354         } else {
355                 bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
356                                (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
357         }
358 }
359
360 /**
361  * Handler to resume sending fcxp when space in available in cpe queue.
362  */
363 static void
364 bfa_fcxp_qresume(void *cbarg)
365 {
366         struct bfa_fcxp_s               *fcxp = cbarg;
367         struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
368         struct bfi_fcxp_send_req_s      *send_req;
369
370         fcxp->reqq_waiting = BFA_FALSE;
371         send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
372         bfa_fcxp_queue(fcxp, send_req);
373 }
374
375 /**
376  * Queue fcxp send request to foimrware.
377  */
378 static void
379 bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
380 {
381         struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
382         struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
383         struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
384         struct bfa_rport_s              *rport = reqi->bfa_rport;
385
386         bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
387                         bfa_lpuid(bfa));
388
389         send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
390         if (rport) {
391                 send_req->rport_fw_hndl = rport->fw_handle;
392                 send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
393                 if (send_req->max_frmsz == 0)
394                         send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
395         } else {
396                 send_req->rport_fw_hndl = 0;
397                 send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
398         }
399
400         send_req->vf_id = bfa_os_htons(reqi->vf_id);
401         send_req->lp_tag = reqi->lp_tag;
402         send_req->class = reqi->class;
403         send_req->rsp_timeout = rspi->rsp_timeout;
404         send_req->cts = reqi->cts;
405         send_req->fchs = reqi->fchs;
406
407         send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
408         send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
409
410         /*
411          * setup req sgles
412          */
413         if (fcxp->use_ireqbuf == 1) {
414                 hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
415                                         BFA_FCXP_REQ_PLD_PA(fcxp));
416         } else {
417                 if (fcxp->nreq_sgles > 0) {
418                         bfa_assert(fcxp->nreq_sgles == 1);
419                         hal_fcxp_set_local_sges(send_req->req_sge,
420                                                 reqi->req_tot_len,
421                                                 fcxp->req_sga_cbfn(fcxp->caller,
422                                                                    0));
423                 } else {
424                         bfa_assert(reqi->req_tot_len == 0);
425                         hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
426                 }
427         }
428
429         /*
430          * setup rsp sgles
431          */
432         if (fcxp->use_irspbuf == 1) {
433                 bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
434
435                 hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
436                                         BFA_FCXP_RSP_PLD_PA(fcxp));
437
438         } else {
439                 if (fcxp->nrsp_sgles > 0) {
440                         bfa_assert(fcxp->nrsp_sgles == 1);
441                         hal_fcxp_set_local_sges(send_req->rsp_sge,
442                                                 rspi->rsp_maxlen,
443                                                 fcxp->rsp_sga_cbfn(fcxp->caller,
444                                                                    0));
445                 } else {
446                         bfa_assert(rspi->rsp_maxlen == 0);
447                         hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
448                 }
449         }
450
451         hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
452
453         bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
454
455         bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
456         bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
457 }
458
459
460 /**
461  *  hal_fcxp_api BFA FCXP API
462  */
463
464 /**
465  * Allocate an FCXP instance to send a response or to send a request
466  * that has a response. Request/response buffers are allocated by caller.
467  *
468  * @param[in]   bfa             BFA bfa instance
469  * @param[in]   nreq_sgles      Number of SG elements required for request
470  *                              buffer. 0, if fcxp internal buffers are used.
471  *                              Use bfa_fcxp_get_reqbuf() to get the
472  *                              internal req buffer.
473  * @param[in]   req_sgles       SG elements describing request buffer. Will be
474  *                              copied in by BFA and hence can be freed on
475  *                              return from this function.
476  * @param[in]   get_req_sga     function ptr to be called to get a request SG
477  *                              Address (given the sge index).
478  * @param[in]   get_req_sglen   function ptr to be called to get a request SG
479  *                              len (given the sge index).
480  * @param[in]   get_rsp_sga     function ptr to be called to get a response SG
481  *                              Address (given the sge index).
482  * @param[in]   get_rsp_sglen   function ptr to be called to get a response SG
483  *                              len (given the sge index).
484  *
485  * @return FCXP instance. NULL on failure.
486  */
487 struct bfa_fcxp_s *
488 bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
489                         int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
490                         bfa_fcxp_get_sglen_t req_sglen_cbfn,
491                         bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
492                         bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
493 {
494         struct bfa_fcxp_s *fcxp = NULL;
495         u32        nreq_sgpg, nrsp_sgpg;
496
497         bfa_assert(bfa != NULL);
498
499         fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
500         if (fcxp == NULL)
501                 return NULL;
502
503         bfa_trc(bfa, fcxp->fcxp_tag);
504
505         fcxp->caller = caller;
506
507         if (nreq_sgles == 0) {
508                 fcxp->use_ireqbuf = 1;
509         } else {
510                 bfa_assert(req_sga_cbfn != NULL);
511                 bfa_assert(req_sglen_cbfn != NULL);
512
513                 fcxp->use_ireqbuf = 0;
514                 fcxp->req_sga_cbfn = req_sga_cbfn;
515                 fcxp->req_sglen_cbfn = req_sglen_cbfn;
516
517                 fcxp->nreq_sgles = nreq_sgles;
518
519                 /*
520                  * alloc required sgpgs
521                  */
522                 if (nreq_sgles > BFI_SGE_INLINE) {
523                         nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
524
525                         if (bfa_sgpg_malloc(bfa, &fcxp->req_sgpg_q, nreq_sgpg)
526                             != BFA_STATUS_OK) {
527                                 /*
528                                  * TODO
529                                  */
530                         }
531                 }
532         }
533
534         if (nrsp_sgles == 0) {
535                 fcxp->use_irspbuf = 1;
536         } else {
537                 bfa_assert(rsp_sga_cbfn != NULL);
538                 bfa_assert(rsp_sglen_cbfn != NULL);
539
540                 fcxp->use_irspbuf = 0;
541                 fcxp->rsp_sga_cbfn = rsp_sga_cbfn;
542                 fcxp->rsp_sglen_cbfn = rsp_sglen_cbfn;
543
544                 fcxp->nrsp_sgles = nrsp_sgles;
545                 /*
546                  * alloc required sgpgs
547                  */
548                 if (nrsp_sgles > BFI_SGE_INLINE) {
549                         nrsp_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
550
551                         if (bfa_sgpg_malloc
552                             (bfa, &fcxp->rsp_sgpg_q, nrsp_sgpg)
553                             != BFA_STATUS_OK) {
554                                 /* bfa_sgpg_wait(bfa, &fcxp->rsp_sgpg_wqe,
555                                 nrsp_sgpg); */
556                                 /*
557                                  * TODO
558                                  */
559                         }
560                 }
561         }
562
563         return fcxp;
564 }
565
566 /**
567  * Get the internal request buffer pointer
568  *
569  * @param[in]   fcxp    BFA fcxp pointer
570  *
571  * @return              pointer to the internal request buffer
572  */
573 void *
574 bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
575 {
576         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
577         void    *reqbuf;
578
579         bfa_assert(fcxp->use_ireqbuf == 1);
580         reqbuf = ((u8 *)mod->req_pld_list_kva) +
581                         fcxp->fcxp_tag * mod->req_pld_sz;
582         return reqbuf;
583 }
584
585 u32
586 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
587 {
588         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
589
590         return mod->req_pld_sz;
591 }
592
593 /**
594  * Get the internal response buffer pointer
595  *
596  * @param[in]   fcxp    BFA fcxp pointer
597  *
598  * @return              pointer to the internal request buffer
599  */
600 void *
601 bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
602 {
603         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
604         void    *rspbuf;
605
606         bfa_assert(fcxp->use_irspbuf == 1);
607
608         rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
609                         fcxp->fcxp_tag * mod->rsp_pld_sz;
610         return rspbuf;
611 }
612
613 /**
614  *              Free the BFA FCXP
615  *
616  * @param[in]   fcxp                    BFA fcxp pointer
617  *
618  * @return              void
619  */
620 void
621 bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
622 {
623         struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
624
625         bfa_assert(fcxp != NULL);
626         bfa_trc(mod->bfa, fcxp->fcxp_tag);
627         bfa_fcxp_put(fcxp);
628 }
629
630 /**
631  * Send a FCXP request
632  *
633  * @param[in]   fcxp    BFA fcxp pointer
634  * @param[in]   rport   BFA rport pointer. Could be left NULL for WKA rports
635  * @param[in]   vf_id   virtual Fabric ID
636  * @param[in]   lp_tag  lport tag
637  * @param[in]   cts     use Continous sequence
638  * @param[in]   cos     fc Class of Service
639  * @param[in]   reqlen  request length, does not include FCHS length
640  * @param[in]   fchs    fc Header Pointer. The header content will be copied
641  *                      in by BFA.
642  *
643  * @param[in]   cbfn    call back function to be called on receiving
644  *                                                              the response
645  * @param[in]   cbarg   arg for cbfn
646  * @param[in]   rsp_timeout
647  *                      response timeout
648  *
649  * @return              bfa_status_t
650  */
651 void
652 bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
653                 u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
654                 u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
655                 void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
656 {
657         struct bfa_s                    *bfa  = fcxp->fcxp_mod->bfa;
658         struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
659         struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
660         struct bfi_fcxp_send_req_s      *send_req;
661
662         bfa_trc(bfa, fcxp->fcxp_tag);
663
664         /**
665          * setup request/response info
666          */
667         reqi->bfa_rport = rport;
668         reqi->vf_id = vf_id;
669         reqi->lp_tag = lp_tag;
670         reqi->class = cos;
671         rspi->rsp_timeout = rsp_timeout;
672         reqi->cts = cts;
673         reqi->fchs = *fchs;
674         reqi->req_tot_len = reqlen;
675         rspi->rsp_maxlen = rsp_maxlen;
676         fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
677         fcxp->send_cbarg = cbarg;
678
679         /**
680          * If no room in CPE queue, wait for space in request queue
681          */
682         send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
683         if (!send_req) {
684                 bfa_trc(bfa, fcxp->fcxp_tag);
685                 fcxp->reqq_waiting = BFA_TRUE;
686                 bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
687                 return;
688         }
689
690         bfa_fcxp_queue(fcxp, send_req);
691 }
692
693 /**
694  * Abort a BFA FCXP
695  *
696  * @param[in]   fcxp    BFA fcxp pointer
697  *
698  * @return              void
699  */
700 bfa_status_t
701 bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
702 {
703         bfa_assert(0);
704         return BFA_STATUS_OK;
705 }
706
707 void
708 bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
709                         bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg)
710 {
711         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
712
713         bfa_assert(list_empty(&mod->fcxp_free_q));
714
715         wqe->alloc_cbfn = alloc_cbfn;
716         wqe->alloc_cbarg = alloc_cbarg;
717         list_add_tail(&wqe->qe, &mod->wait_q);
718 }
719
720 void
721 bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
722 {
723         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
724
725         bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
726         list_del(&wqe->qe);
727 }
728
729 void
730 bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
731 {
732         /**
733          * If waiting for room in request queue, cancel reqq wait
734          * and free fcxp.
735          */
736         if (fcxp->reqq_waiting) {
737                 fcxp->reqq_waiting = BFA_FALSE;
738                 bfa_reqq_wcancel(&fcxp->reqq_wqe);
739                 bfa_fcxp_free(fcxp);
740                 return;
741         }
742
743         fcxp->send_cbfn = bfa_fcxp_null_comp;
744 }
745
746
747
748 /**
749  *  hal_fcxp_public BFA FCXP public functions
750  */
751
752 void
753 bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
754 {
755         switch (msg->mhdr.msg_id) {
756         case BFI_FCXP_I2H_SEND_RSP:
757                 hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
758                 break;
759
760         default:
761                 bfa_trc(bfa, msg->mhdr.msg_id);
762                 bfa_assert(0);
763         }
764 }
765
766 u32
767 bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
768 {
769         struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
770
771         return mod->rsp_pld_sz;
772 }
773
774