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