1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Linux network driver for QLogic BR-series Converged Network Adapter.
4 */
5/*
6 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
7 * Copyright (c) 2014-2015 QLogic Corporation
8 * All rights reserved
9 * www.qlogic.com
10 */
11
12/* MSGQ module source file. */
13
14#include "bfi.h"
15#include "bfa_msgq.h"
16#include "bfa_ioc.h"
17
18#define call_cmdq_ent_cbfn(_cmdq_ent, _status)				\
19{									\
20	bfa_msgq_cmdcbfn_t cbfn;					\
21	void *cbarg;							\
22	cbfn = (_cmdq_ent)->cbfn;					\
23	cbarg = (_cmdq_ent)->cbarg;					\
24	(_cmdq_ent)->cbfn = NULL;					\
25	(_cmdq_ent)->cbarg = NULL;					\
26	if (cbfn) {							\
27		cbfn(cbarg, (_status));					\
28	}								\
29}
30
31static void bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq);
32static void bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq);
33
34enum cmdq_event {
35	CMDQ_E_START			= 1,
36	CMDQ_E_STOP			= 2,
37	CMDQ_E_FAIL			= 3,
38	CMDQ_E_POST			= 4,
39	CMDQ_E_INIT_RESP		= 5,
40	CMDQ_E_DB_READY			= 6,
41};
42
43bfa_fsm_state_decl(cmdq, stopped, struct bfa_msgq_cmdq, enum cmdq_event);
44bfa_fsm_state_decl(cmdq, init_wait, struct bfa_msgq_cmdq, enum cmdq_event);
45bfa_fsm_state_decl(cmdq, ready, struct bfa_msgq_cmdq, enum cmdq_event);
46bfa_fsm_state_decl(cmdq, dbell_wait, struct bfa_msgq_cmdq,
47			enum cmdq_event);
48
49static void
50cmdq_sm_stopped_entry(struct bfa_msgq_cmdq *cmdq)
51{
52	struct bfa_msgq_cmd_entry *cmdq_ent;
53
54	cmdq->producer_index = 0;
55	cmdq->consumer_index = 0;
56	cmdq->flags = 0;
57	cmdq->token = 0;
58	cmdq->offset = 0;
59	cmdq->bytes_to_copy = 0;
60	while (!list_empty(&cmdq->pending_q)) {
61		cmdq_ent = list_first_entry(&cmdq->pending_q,
62					    struct bfa_msgq_cmd_entry, qe);
63		list_del(&cmdq_ent->qe);
64		call_cmdq_ent_cbfn(cmdq_ent, BFA_STATUS_FAILED);
65	}
66}
67
68static void
69cmdq_sm_stopped(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
70{
71	switch (event) {
72	case CMDQ_E_START:
73		bfa_fsm_set_state(cmdq, cmdq_sm_init_wait);
74		break;
75
76	case CMDQ_E_STOP:
77	case CMDQ_E_FAIL:
78		/* No-op */
79		break;
80
81	case CMDQ_E_POST:
82		cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
83		break;
84
85	default:
86		bfa_sm_fault(event);
87	}
88}
89
90static void
91cmdq_sm_init_wait_entry(struct bfa_msgq_cmdq *cmdq)
92{
93	bfa_wc_down(&cmdq->msgq->init_wc);
94}
95
96static void
97cmdq_sm_init_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
98{
99	switch (event) {
100	case CMDQ_E_STOP:
101	case CMDQ_E_FAIL:
102		bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
103		break;
104
105	case CMDQ_E_POST:
106		cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
107		break;
108
109	case CMDQ_E_INIT_RESP:
110		if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
111			cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
112			bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
113		} else
114			bfa_fsm_set_state(cmdq, cmdq_sm_ready);
115		break;
116
117	default:
118		bfa_sm_fault(event);
119	}
120}
121
122static void
123cmdq_sm_ready_entry(struct bfa_msgq_cmdq *cmdq)
124{
125}
126
127static void
128cmdq_sm_ready(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
129{
130	switch (event) {
131	case CMDQ_E_STOP:
132	case CMDQ_E_FAIL:
133		bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
134		break;
135
136	case CMDQ_E_POST:
137		bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
138		break;
139
140	default:
141		bfa_sm_fault(event);
142	}
143}
144
145static void
146cmdq_sm_dbell_wait_entry(struct bfa_msgq_cmdq *cmdq)
147{
148	bfa_msgq_cmdq_dbell(cmdq);
149}
150
151static void
152cmdq_sm_dbell_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
153{
154	switch (event) {
155	case CMDQ_E_STOP:
156	case CMDQ_E_FAIL:
157		bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
158		break;
159
160	case CMDQ_E_POST:
161		cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
162		break;
163
164	case CMDQ_E_DB_READY:
165		if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
166			cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
167			bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
168		} else
169			bfa_fsm_set_state(cmdq, cmdq_sm_ready);
170		break;
171
172	default:
173		bfa_sm_fault(event);
174	}
175}
176
177static void
178bfa_msgq_cmdq_dbell_ready(void *arg)
179{
180	struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
181	bfa_fsm_send_event(cmdq, CMDQ_E_DB_READY);
182}
183
184static void
185bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq)
186{
187	struct bfi_msgq_h2i_db *dbell =
188		(struct bfi_msgq_h2i_db *)(&cmdq->dbell_mb.msg[0]);
189
190	memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
191	bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_PI, 0);
192	dbell->mh.mtag.i2htok = 0;
193	dbell->idx.cmdq_pi = htons(cmdq->producer_index);
194
195	if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->dbell_mb,
196				bfa_msgq_cmdq_dbell_ready, cmdq)) {
197		bfa_msgq_cmdq_dbell_ready(cmdq);
198	}
199}
200
201static void
202__cmd_copy(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq_cmd_entry *cmd)
203{
204	size_t len = cmd->msg_size;
205	size_t to_copy;
206	u8 *src, *dst;
207
208	src = (u8 *)cmd->msg_hdr;
209	dst = (u8 *)cmdq->addr.kva;
210	dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
211
212	while (len) {
213		to_copy = (len < BFI_MSGQ_CMD_ENTRY_SIZE) ?
214				len : BFI_MSGQ_CMD_ENTRY_SIZE;
215		memcpy(dst, src, to_copy);
216		len -= to_copy;
217		src += BFI_MSGQ_CMD_ENTRY_SIZE;
218		BFA_MSGQ_INDX_ADD(cmdq->producer_index, 1, cmdq->depth);
219		dst = (u8 *)cmdq->addr.kva;
220		dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
221	}
222
223}
224
225static void
226bfa_msgq_cmdq_ci_update(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
227{
228	struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
229	struct bfa_msgq_cmd_entry *cmd;
230	int posted = 0;
231
232	cmdq->consumer_index = ntohs(dbell->idx.cmdq_ci);
233
234	/* Walk through pending list to see if the command can be posted */
235	while (!list_empty(&cmdq->pending_q)) {
236		cmd = list_first_entry(&cmdq->pending_q,
237				       struct bfa_msgq_cmd_entry, qe);
238		if (ntohs(cmd->msg_hdr->num_entries) <=
239			BFA_MSGQ_FREE_CNT(cmdq)) {
240			list_del(&cmd->qe);
241			__cmd_copy(cmdq, cmd);
242			posted = 1;
243			call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
244		} else {
245			break;
246		}
247	}
248
249	if (posted)
250		bfa_fsm_send_event(cmdq, CMDQ_E_POST);
251}
252
253static void
254bfa_msgq_cmdq_copy_next(void *arg)
255{
256	struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
257
258	if (cmdq->bytes_to_copy)
259		bfa_msgq_cmdq_copy_rsp(cmdq);
260}
261
262static void
263bfa_msgq_cmdq_copy_req(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
264{
265	struct bfi_msgq_i2h_cmdq_copy_req *req =
266		(struct bfi_msgq_i2h_cmdq_copy_req *)mb;
267
268	cmdq->token = 0;
269	cmdq->offset = ntohs(req->offset);
270	cmdq->bytes_to_copy = ntohs(req->len);
271	bfa_msgq_cmdq_copy_rsp(cmdq);
272}
273
274static void
275bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq)
276{
277	struct bfi_msgq_h2i_cmdq_copy_rsp *rsp =
278		(struct bfi_msgq_h2i_cmdq_copy_rsp *)&cmdq->copy_mb.msg[0];
279	int copied;
280	u8 *addr = (u8 *)cmdq->addr.kva;
281
282	memset(rsp, 0, sizeof(struct bfi_msgq_h2i_cmdq_copy_rsp));
283	bfi_h2i_set(rsp->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_CMDQ_COPY_RSP, 0);
284	rsp->mh.mtag.i2htok = htons(cmdq->token);
285	copied = (cmdq->bytes_to_copy >= BFI_CMD_COPY_SZ) ? BFI_CMD_COPY_SZ :
286		cmdq->bytes_to_copy;
287	addr += cmdq->offset;
288	memcpy(rsp->data, addr, copied);
289
290	cmdq->token++;
291	cmdq->offset += copied;
292	cmdq->bytes_to_copy -= copied;
293
294	if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->copy_mb,
295				bfa_msgq_cmdq_copy_next, cmdq)) {
296		bfa_msgq_cmdq_copy_next(cmdq);
297	}
298}
299
300static void
301bfa_msgq_cmdq_attach(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq *msgq)
302{
303	cmdq->depth = BFA_MSGQ_CMDQ_NUM_ENTRY;
304	INIT_LIST_HEAD(&cmdq->pending_q);
305	cmdq->msgq = msgq;
306	bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
307}
308
309static void bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq);
310
311enum rspq_event {
312	RSPQ_E_START			= 1,
313	RSPQ_E_STOP			= 2,
314	RSPQ_E_FAIL			= 3,
315	RSPQ_E_RESP			= 4,
316	RSPQ_E_INIT_RESP		= 5,
317	RSPQ_E_DB_READY			= 6,
318};
319
320bfa_fsm_state_decl(rspq, stopped, struct bfa_msgq_rspq, enum rspq_event);
321bfa_fsm_state_decl(rspq, init_wait, struct bfa_msgq_rspq,
322			enum rspq_event);
323bfa_fsm_state_decl(rspq, ready, struct bfa_msgq_rspq, enum rspq_event);
324bfa_fsm_state_decl(rspq, dbell_wait, struct bfa_msgq_rspq,
325			enum rspq_event);
326
327static void
328rspq_sm_stopped_entry(struct bfa_msgq_rspq *rspq)
329{
330	rspq->producer_index = 0;
331	rspq->consumer_index = 0;
332	rspq->flags = 0;
333}
334
335static void
336rspq_sm_stopped(struct bfa_msgq_rspq *rspq, enum rspq_event event)
337{
338	switch (event) {
339	case RSPQ_E_START:
340		bfa_fsm_set_state(rspq, rspq_sm_init_wait);
341		break;
342
343	case RSPQ_E_STOP:
344	case RSPQ_E_FAIL:
345		/* No-op */
346		break;
347
348	default:
349		bfa_sm_fault(event);
350	}
351}
352
353static void
354rspq_sm_init_wait_entry(struct bfa_msgq_rspq *rspq)
355{
356	bfa_wc_down(&rspq->msgq->init_wc);
357}
358
359static void
360rspq_sm_init_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
361{
362	switch (event) {
363	case RSPQ_E_FAIL:
364	case RSPQ_E_STOP:
365		bfa_fsm_set_state(rspq, rspq_sm_stopped);
366		break;
367
368	case RSPQ_E_INIT_RESP:
369		bfa_fsm_set_state(rspq, rspq_sm_ready);
370		break;
371
372	default:
373		bfa_sm_fault(event);
374	}
375}
376
377static void
378rspq_sm_ready_entry(struct bfa_msgq_rspq *rspq)
379{
380}
381
382static void
383rspq_sm_ready(struct bfa_msgq_rspq *rspq, enum rspq_event event)
384{
385	switch (event) {
386	case RSPQ_E_STOP:
387	case RSPQ_E_FAIL:
388		bfa_fsm_set_state(rspq, rspq_sm_stopped);
389		break;
390
391	case RSPQ_E_RESP:
392		bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
393		break;
394
395	default:
396		bfa_sm_fault(event);
397	}
398}
399
400static void
401rspq_sm_dbell_wait_entry(struct bfa_msgq_rspq *rspq)
402{
403	if (!bfa_nw_ioc_is_disabled(rspq->msgq->ioc))
404		bfa_msgq_rspq_dbell(rspq);
405}
406
407static void
408rspq_sm_dbell_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
409{
410	switch (event) {
411	case RSPQ_E_STOP:
412	case RSPQ_E_FAIL:
413		bfa_fsm_set_state(rspq, rspq_sm_stopped);
414		break;
415
416	case RSPQ_E_RESP:
417		rspq->flags |= BFA_MSGQ_RSPQ_F_DB_UPDATE;
418		break;
419
420	case RSPQ_E_DB_READY:
421		if (rspq->flags & BFA_MSGQ_RSPQ_F_DB_UPDATE) {
422			rspq->flags &= ~BFA_MSGQ_RSPQ_F_DB_UPDATE;
423			bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
424		} else
425			bfa_fsm_set_state(rspq, rspq_sm_ready);
426		break;
427
428	default:
429		bfa_sm_fault(event);
430	}
431}
432
433static void
434bfa_msgq_rspq_dbell_ready(void *arg)
435{
436	struct bfa_msgq_rspq *rspq = (struct bfa_msgq_rspq *)arg;
437	bfa_fsm_send_event(rspq, RSPQ_E_DB_READY);
438}
439
440static void
441bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq)
442{
443	struct bfi_msgq_h2i_db *dbell =
444		(struct bfi_msgq_h2i_db *)(&rspq->dbell_mb.msg[0]);
445
446	memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
447	bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_CI, 0);
448	dbell->mh.mtag.i2htok = 0;
449	dbell->idx.rspq_ci = htons(rspq->consumer_index);
450
451	if (!bfa_nw_ioc_mbox_queue(rspq->msgq->ioc, &rspq->dbell_mb,
452				bfa_msgq_rspq_dbell_ready, rspq)) {
453		bfa_msgq_rspq_dbell_ready(rspq);
454	}
455}
456
457static void
458bfa_msgq_rspq_pi_update(struct bfa_msgq_rspq *rspq, struct bfi_mbmsg *mb)
459{
460	struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
461	struct bfi_msgq_mhdr *msghdr;
462	int num_entries;
463	int mc;
464	u8 *rspq_qe;
465
466	rspq->producer_index = ntohs(dbell->idx.rspq_pi);
467
468	while (rspq->consumer_index != rspq->producer_index) {
469		rspq_qe = (u8 *)rspq->addr.kva;
470		rspq_qe += (rspq->consumer_index * BFI_MSGQ_RSP_ENTRY_SIZE);
471		msghdr = (struct bfi_msgq_mhdr *)rspq_qe;
472
473		mc = msghdr->msg_class;
474		num_entries = ntohs(msghdr->num_entries);
475
476		if ((mc >= BFI_MC_MAX) || (rspq->rsphdlr[mc].cbfn == NULL))
477			break;
478
479		(rspq->rsphdlr[mc].cbfn)(rspq->rsphdlr[mc].cbarg, msghdr);
480
481		BFA_MSGQ_INDX_ADD(rspq->consumer_index, num_entries,
482				rspq->depth);
483	}
484
485	bfa_fsm_send_event(rspq, RSPQ_E_RESP);
486}
487
488static void
489bfa_msgq_rspq_attach(struct bfa_msgq_rspq *rspq, struct bfa_msgq *msgq)
490{
491	rspq->depth = BFA_MSGQ_RSPQ_NUM_ENTRY;
492	rspq->msgq = msgq;
493	bfa_fsm_set_state(rspq, rspq_sm_stopped);
494}
495
496static void
497bfa_msgq_init_rsp(struct bfa_msgq *msgq,
498		 struct bfi_mbmsg *mb)
499{
500	bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_INIT_RESP);
501	bfa_fsm_send_event(&msgq->rspq, RSPQ_E_INIT_RESP);
502}
503
504static void
505bfa_msgq_init(void *arg)
506{
507	struct bfa_msgq *msgq = (struct bfa_msgq *)arg;
508	struct bfi_msgq_cfg_req *msgq_cfg =
509		(struct bfi_msgq_cfg_req *)&msgq->init_mb.msg[0];
510
511	memset(msgq_cfg, 0, sizeof(struct bfi_msgq_cfg_req));
512	bfi_h2i_set(msgq_cfg->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_INIT_REQ, 0);
513	msgq_cfg->mh.mtag.i2htok = 0;
514
515	bfa_dma_be_addr_set(msgq_cfg->cmdq.addr, msgq->cmdq.addr.pa);
516	msgq_cfg->cmdq.q_depth = htons(msgq->cmdq.depth);
517	bfa_dma_be_addr_set(msgq_cfg->rspq.addr, msgq->rspq.addr.pa);
518	msgq_cfg->rspq.q_depth = htons(msgq->rspq.depth);
519
520	bfa_nw_ioc_mbox_queue(msgq->ioc, &msgq->init_mb, NULL, NULL);
521}
522
523static void
524bfa_msgq_isr(void *cbarg, struct bfi_mbmsg *msg)
525{
526	struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
527
528	switch (msg->mh.msg_id) {
529	case BFI_MSGQ_I2H_INIT_RSP:
530		bfa_msgq_init_rsp(msgq, msg);
531		break;
532
533	case BFI_MSGQ_I2H_DOORBELL_PI:
534		bfa_msgq_rspq_pi_update(&msgq->rspq, msg);
535		break;
536
537	case BFI_MSGQ_I2H_DOORBELL_CI:
538		bfa_msgq_cmdq_ci_update(&msgq->cmdq, msg);
539		break;
540
541	case BFI_MSGQ_I2H_CMDQ_COPY_REQ:
542		bfa_msgq_cmdq_copy_req(&msgq->cmdq, msg);
543		break;
544
545	default:
546		BUG_ON(1);
547	}
548}
549
550static void
551bfa_msgq_notify(void *cbarg, enum bfa_ioc_event event)
552{
553	struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
554
555	switch (event) {
556	case BFA_IOC_E_ENABLED:
557		bfa_wc_init(&msgq->init_wc, bfa_msgq_init, msgq);
558		bfa_wc_up(&msgq->init_wc);
559		bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_START);
560		bfa_wc_up(&msgq->init_wc);
561		bfa_fsm_send_event(&msgq->rspq, RSPQ_E_START);
562		bfa_wc_wait(&msgq->init_wc);
563		break;
564
565	case BFA_IOC_E_DISABLED:
566		bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_STOP);
567		bfa_fsm_send_event(&msgq->rspq, RSPQ_E_STOP);
568		break;
569
570	case BFA_IOC_E_FAILED:
571		bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_FAIL);
572		bfa_fsm_send_event(&msgq->rspq, RSPQ_E_FAIL);
573		break;
574
575	default:
576		break;
577	}
578}
579
580u32
581bfa_msgq_meminfo(void)
582{
583	return roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ) +
584		roundup(BFA_MSGQ_RSPQ_SIZE, BFA_DMA_ALIGN_SZ);
585}
586
587void
588bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa)
589{
590	msgq->cmdq.addr.kva = kva;
591	msgq->cmdq.addr.pa  = pa;
592
593	kva += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
594	pa += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
595
596	msgq->rspq.addr.kva = kva;
597	msgq->rspq.addr.pa = pa;
598}
599
600void
601bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc)
602{
603	msgq->ioc    = ioc;
604
605	bfa_msgq_cmdq_attach(&msgq->cmdq, msgq);
606	bfa_msgq_rspq_attach(&msgq->rspq, msgq);
607
608	bfa_nw_ioc_mbox_regisr(msgq->ioc, BFI_MC_MSGQ, bfa_msgq_isr, msgq);
609	bfa_ioc_notify_init(&msgq->ioc_notify, bfa_msgq_notify, msgq);
610	bfa_nw_ioc_notify_register(msgq->ioc, &msgq->ioc_notify);
611}
612
613void
614bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
615		bfa_msgq_mcfunc_t cbfn, void *cbarg)
616{
617	msgq->rspq.rsphdlr[mc].cbfn	= cbfn;
618	msgq->rspq.rsphdlr[mc].cbarg	= cbarg;
619}
620
621void
622bfa_msgq_cmd_post(struct bfa_msgq *msgq,  struct bfa_msgq_cmd_entry *cmd)
623{
624	if (ntohs(cmd->msg_hdr->num_entries) <=
625		BFA_MSGQ_FREE_CNT(&msgq->cmdq)) {
626		__cmd_copy(&msgq->cmdq, cmd);
627		call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
628		bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_POST);
629	} else {
630		list_add_tail(&cmd->qe, &msgq->cmdq.pending_q);
631	}
632}
633
634void
635bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len)
636{
637	struct bfa_msgq_rspq *rspq = &msgq->rspq;
638	size_t len = buf_len;
639	size_t to_copy;
640	int ci;
641	u8 *src, *dst;
642
643	ci = rspq->consumer_index;
644	src = (u8 *)rspq->addr.kva;
645	src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
646	dst = buf;
647
648	while (len) {
649		to_copy = (len < BFI_MSGQ_RSP_ENTRY_SIZE) ?
650				len : BFI_MSGQ_RSP_ENTRY_SIZE;
651		memcpy(dst, src, to_copy);
652		len -= to_copy;
653		dst += BFI_MSGQ_RSP_ENTRY_SIZE;
654		BFA_MSGQ_INDX_ADD(ci, 1, rspq->depth);
655		src = (u8 *)rspq->addr.kva;
656		src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
657	}
658}
659