• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/scsi/bfa/
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
22BFA_TRC_FILE(HAL, FCXP);
23BFA_MODULE(fcxp);
24
25/**
26 * forward declarations
27 */
28static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
29static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
30				 struct bfi_fcxp_send_rsp_s *fcxp_rsp);
31static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
32				 struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
33static void	bfa_fcxp_qresume(void *cbarg);
34static 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
41static void
42claim_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
76static void
77claim_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
104static void
105bfa_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
128static void
129bfa_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
151static void
152bfa_fcxp_detach(struct bfa_s *bfa)
153{
154}
155
156static void
157bfa_fcxp_start(struct bfa_s *bfa)
158{
159}
160
161static void
162bfa_fcxp_stop(struct bfa_s *bfa)
163{
164}
165
166static void
167bfa_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
187static struct bfa_fcxp_s *
188bfa_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
200static void
201bfa_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
218static void
219bfa_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
226static 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
240static void
241hal_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
292static void
293hal_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
309static void
310hal_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
335static void
336hal_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 */
363static void
364bfa_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 */
378static void
379bfa_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 */
487struct bfa_fcxp_s *
488bfa_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 */
573void *
574bfa_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
585u32
586bfa_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 */
600void *
601bfa_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 */
620void
621bfa_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 */
651void
652bfa_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 */
700bfa_status_t
701bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
702{
703	bfa_assert(0);
704	return BFA_STATUS_OK;
705}
706
707void
708bfa_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
720void
721bfa_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
729void
730bfa_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
752void
753bfa_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
766u32
767bfa_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