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