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
31 static void bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq);
32 static void bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq);
33
34 enum 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
43 bfa_fsm_state_decl(cmdq, stopped, struct bfa_msgq_cmdq, enum cmdq_event);
44 bfa_fsm_state_decl(cmdq, init_wait, struct bfa_msgq_cmdq, enum cmdq_event);
45 bfa_fsm_state_decl(cmdq, ready, struct bfa_msgq_cmdq, enum cmdq_event);
46 bfa_fsm_state_decl(cmdq, dbell_wait, struct bfa_msgq_cmdq,
47 enum cmdq_event);
48
49 static void
cmdq_sm_stopped_entry(struct bfa_msgq_cmdq * cmdq)50 cmdq_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
68 static void
cmdq_sm_stopped(struct bfa_msgq_cmdq * cmdq,enum cmdq_event event)69 cmdq_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
90 static void
cmdq_sm_init_wait_entry(struct bfa_msgq_cmdq * cmdq)91 cmdq_sm_init_wait_entry(struct bfa_msgq_cmdq *cmdq)
92 {
93 bfa_wc_down(&cmdq->msgq->init_wc);
94 }
95
96 static void
cmdq_sm_init_wait(struct bfa_msgq_cmdq * cmdq,enum cmdq_event event)97 cmdq_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
122 static void
cmdq_sm_ready_entry(struct bfa_msgq_cmdq * cmdq)123 cmdq_sm_ready_entry(struct bfa_msgq_cmdq *cmdq)
124 {
125 }
126
127 static void
cmdq_sm_ready(struct bfa_msgq_cmdq * cmdq,enum cmdq_event event)128 cmdq_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
145 static void
cmdq_sm_dbell_wait_entry(struct bfa_msgq_cmdq * cmdq)146 cmdq_sm_dbell_wait_entry(struct bfa_msgq_cmdq *cmdq)
147 {
148 bfa_msgq_cmdq_dbell(cmdq);
149 }
150
151 static void
cmdq_sm_dbell_wait(struct bfa_msgq_cmdq * cmdq,enum cmdq_event event)152 cmdq_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
177 static void
bfa_msgq_cmdq_dbell_ready(void * arg)178 bfa_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
184 static void
bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq * cmdq)185 bfa_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
201 static void
__cmd_copy(struct bfa_msgq_cmdq * cmdq,struct bfa_msgq_cmd_entry * cmd)202 __cmd_copy(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq_cmd_entry *cmd)
203 {
204 size_t len = cmd->msg_size;
205 int num_entries = 0;
206 size_t to_copy;
207 u8 *src, *dst;
208
209 src = (u8 *)cmd->msg_hdr;
210 dst = (u8 *)cmdq->addr.kva;
211 dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
212
213 while (len) {
214 to_copy = (len < BFI_MSGQ_CMD_ENTRY_SIZE) ?
215 len : BFI_MSGQ_CMD_ENTRY_SIZE;
216 memcpy(dst, src, to_copy);
217 len -= to_copy;
218 src += BFI_MSGQ_CMD_ENTRY_SIZE;
219 BFA_MSGQ_INDX_ADD(cmdq->producer_index, 1, cmdq->depth);
220 dst = (u8 *)cmdq->addr.kva;
221 dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
222 num_entries++;
223 }
224
225 }
226
227 static void
bfa_msgq_cmdq_ci_update(struct bfa_msgq_cmdq * cmdq,struct bfi_mbmsg * mb)228 bfa_msgq_cmdq_ci_update(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
229 {
230 struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
231 struct bfa_msgq_cmd_entry *cmd;
232 int posted = 0;
233
234 cmdq->consumer_index = ntohs(dbell->idx.cmdq_ci);
235
236 /* Walk through pending list to see if the command can be posted */
237 while (!list_empty(&cmdq->pending_q)) {
238 cmd = list_first_entry(&cmdq->pending_q,
239 struct bfa_msgq_cmd_entry, qe);
240 if (ntohs(cmd->msg_hdr->num_entries) <=
241 BFA_MSGQ_FREE_CNT(cmdq)) {
242 list_del(&cmd->qe);
243 __cmd_copy(cmdq, cmd);
244 posted = 1;
245 call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
246 } else {
247 break;
248 }
249 }
250
251 if (posted)
252 bfa_fsm_send_event(cmdq, CMDQ_E_POST);
253 }
254
255 static void
bfa_msgq_cmdq_copy_next(void * arg)256 bfa_msgq_cmdq_copy_next(void *arg)
257 {
258 struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
259
260 if (cmdq->bytes_to_copy)
261 bfa_msgq_cmdq_copy_rsp(cmdq);
262 }
263
264 static void
bfa_msgq_cmdq_copy_req(struct bfa_msgq_cmdq * cmdq,struct bfi_mbmsg * mb)265 bfa_msgq_cmdq_copy_req(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
266 {
267 struct bfi_msgq_i2h_cmdq_copy_req *req =
268 (struct bfi_msgq_i2h_cmdq_copy_req *)mb;
269
270 cmdq->token = 0;
271 cmdq->offset = ntohs(req->offset);
272 cmdq->bytes_to_copy = ntohs(req->len);
273 bfa_msgq_cmdq_copy_rsp(cmdq);
274 }
275
276 static void
bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq * cmdq)277 bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq)
278 {
279 struct bfi_msgq_h2i_cmdq_copy_rsp *rsp =
280 (struct bfi_msgq_h2i_cmdq_copy_rsp *)&cmdq->copy_mb.msg[0];
281 int copied;
282 u8 *addr = (u8 *)cmdq->addr.kva;
283
284 memset(rsp, 0, sizeof(struct bfi_msgq_h2i_cmdq_copy_rsp));
285 bfi_h2i_set(rsp->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_CMDQ_COPY_RSP, 0);
286 rsp->mh.mtag.i2htok = htons(cmdq->token);
287 copied = (cmdq->bytes_to_copy >= BFI_CMD_COPY_SZ) ? BFI_CMD_COPY_SZ :
288 cmdq->bytes_to_copy;
289 addr += cmdq->offset;
290 memcpy(rsp->data, addr, copied);
291
292 cmdq->token++;
293 cmdq->offset += copied;
294 cmdq->bytes_to_copy -= copied;
295
296 if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->copy_mb,
297 bfa_msgq_cmdq_copy_next, cmdq)) {
298 bfa_msgq_cmdq_copy_next(cmdq);
299 }
300 }
301
302 static void
bfa_msgq_cmdq_attach(struct bfa_msgq_cmdq * cmdq,struct bfa_msgq * msgq)303 bfa_msgq_cmdq_attach(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq *msgq)
304 {
305 cmdq->depth = BFA_MSGQ_CMDQ_NUM_ENTRY;
306 INIT_LIST_HEAD(&cmdq->pending_q);
307 cmdq->msgq = msgq;
308 bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
309 }
310
311 static void bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq);
312
313 enum rspq_event {
314 RSPQ_E_START = 1,
315 RSPQ_E_STOP = 2,
316 RSPQ_E_FAIL = 3,
317 RSPQ_E_RESP = 4,
318 RSPQ_E_INIT_RESP = 5,
319 RSPQ_E_DB_READY = 6,
320 };
321
322 bfa_fsm_state_decl(rspq, stopped, struct bfa_msgq_rspq, enum rspq_event);
323 bfa_fsm_state_decl(rspq, init_wait, struct bfa_msgq_rspq,
324 enum rspq_event);
325 bfa_fsm_state_decl(rspq, ready, struct bfa_msgq_rspq, enum rspq_event);
326 bfa_fsm_state_decl(rspq, dbell_wait, struct bfa_msgq_rspq,
327 enum rspq_event);
328
329 static void
rspq_sm_stopped_entry(struct bfa_msgq_rspq * rspq)330 rspq_sm_stopped_entry(struct bfa_msgq_rspq *rspq)
331 {
332 rspq->producer_index = 0;
333 rspq->consumer_index = 0;
334 rspq->flags = 0;
335 }
336
337 static void
rspq_sm_stopped(struct bfa_msgq_rspq * rspq,enum rspq_event event)338 rspq_sm_stopped(struct bfa_msgq_rspq *rspq, enum rspq_event event)
339 {
340 switch (event) {
341 case RSPQ_E_START:
342 bfa_fsm_set_state(rspq, rspq_sm_init_wait);
343 break;
344
345 case RSPQ_E_STOP:
346 case RSPQ_E_FAIL:
347 /* No-op */
348 break;
349
350 default:
351 bfa_sm_fault(event);
352 }
353 }
354
355 static void
rspq_sm_init_wait_entry(struct bfa_msgq_rspq * rspq)356 rspq_sm_init_wait_entry(struct bfa_msgq_rspq *rspq)
357 {
358 bfa_wc_down(&rspq->msgq->init_wc);
359 }
360
361 static void
rspq_sm_init_wait(struct bfa_msgq_rspq * rspq,enum rspq_event event)362 rspq_sm_init_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
363 {
364 switch (event) {
365 case RSPQ_E_FAIL:
366 case RSPQ_E_STOP:
367 bfa_fsm_set_state(rspq, rspq_sm_stopped);
368 break;
369
370 case RSPQ_E_INIT_RESP:
371 bfa_fsm_set_state(rspq, rspq_sm_ready);
372 break;
373
374 default:
375 bfa_sm_fault(event);
376 }
377 }
378
379 static void
rspq_sm_ready_entry(struct bfa_msgq_rspq * rspq)380 rspq_sm_ready_entry(struct bfa_msgq_rspq *rspq)
381 {
382 }
383
384 static void
rspq_sm_ready(struct bfa_msgq_rspq * rspq,enum rspq_event event)385 rspq_sm_ready(struct bfa_msgq_rspq *rspq, enum rspq_event event)
386 {
387 switch (event) {
388 case RSPQ_E_STOP:
389 case RSPQ_E_FAIL:
390 bfa_fsm_set_state(rspq, rspq_sm_stopped);
391 break;
392
393 case RSPQ_E_RESP:
394 bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
395 break;
396
397 default:
398 bfa_sm_fault(event);
399 }
400 }
401
402 static void
rspq_sm_dbell_wait_entry(struct bfa_msgq_rspq * rspq)403 rspq_sm_dbell_wait_entry(struct bfa_msgq_rspq *rspq)
404 {
405 if (!bfa_nw_ioc_is_disabled(rspq->msgq->ioc))
406 bfa_msgq_rspq_dbell(rspq);
407 }
408
409 static void
rspq_sm_dbell_wait(struct bfa_msgq_rspq * rspq,enum rspq_event event)410 rspq_sm_dbell_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
411 {
412 switch (event) {
413 case RSPQ_E_STOP:
414 case RSPQ_E_FAIL:
415 bfa_fsm_set_state(rspq, rspq_sm_stopped);
416 break;
417
418 case RSPQ_E_RESP:
419 rspq->flags |= BFA_MSGQ_RSPQ_F_DB_UPDATE;
420 break;
421
422 case RSPQ_E_DB_READY:
423 if (rspq->flags & BFA_MSGQ_RSPQ_F_DB_UPDATE) {
424 rspq->flags &= ~BFA_MSGQ_RSPQ_F_DB_UPDATE;
425 bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
426 } else
427 bfa_fsm_set_state(rspq, rspq_sm_ready);
428 break;
429
430 default:
431 bfa_sm_fault(event);
432 }
433 }
434
435 static void
bfa_msgq_rspq_dbell_ready(void * arg)436 bfa_msgq_rspq_dbell_ready(void *arg)
437 {
438 struct bfa_msgq_rspq *rspq = (struct bfa_msgq_rspq *)arg;
439 bfa_fsm_send_event(rspq, RSPQ_E_DB_READY);
440 }
441
442 static void
bfa_msgq_rspq_dbell(struct bfa_msgq_rspq * rspq)443 bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq)
444 {
445 struct bfi_msgq_h2i_db *dbell =
446 (struct bfi_msgq_h2i_db *)(&rspq->dbell_mb.msg[0]);
447
448 memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
449 bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_CI, 0);
450 dbell->mh.mtag.i2htok = 0;
451 dbell->idx.rspq_ci = htons(rspq->consumer_index);
452
453 if (!bfa_nw_ioc_mbox_queue(rspq->msgq->ioc, &rspq->dbell_mb,
454 bfa_msgq_rspq_dbell_ready, rspq)) {
455 bfa_msgq_rspq_dbell_ready(rspq);
456 }
457 }
458
459 static void
bfa_msgq_rspq_pi_update(struct bfa_msgq_rspq * rspq,struct bfi_mbmsg * mb)460 bfa_msgq_rspq_pi_update(struct bfa_msgq_rspq *rspq, struct bfi_mbmsg *mb)
461 {
462 struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
463 struct bfi_msgq_mhdr *msghdr;
464 int num_entries;
465 int mc;
466 u8 *rspq_qe;
467
468 rspq->producer_index = ntohs(dbell->idx.rspq_pi);
469
470 while (rspq->consumer_index != rspq->producer_index) {
471 rspq_qe = (u8 *)rspq->addr.kva;
472 rspq_qe += (rspq->consumer_index * BFI_MSGQ_RSP_ENTRY_SIZE);
473 msghdr = (struct bfi_msgq_mhdr *)rspq_qe;
474
475 mc = msghdr->msg_class;
476 num_entries = ntohs(msghdr->num_entries);
477
478 if ((mc >= BFI_MC_MAX) || (rspq->rsphdlr[mc].cbfn == NULL))
479 break;
480
481 (rspq->rsphdlr[mc].cbfn)(rspq->rsphdlr[mc].cbarg, msghdr);
482
483 BFA_MSGQ_INDX_ADD(rspq->consumer_index, num_entries,
484 rspq->depth);
485 }
486
487 bfa_fsm_send_event(rspq, RSPQ_E_RESP);
488 }
489
490 static void
bfa_msgq_rspq_attach(struct bfa_msgq_rspq * rspq,struct bfa_msgq * msgq)491 bfa_msgq_rspq_attach(struct bfa_msgq_rspq *rspq, struct bfa_msgq *msgq)
492 {
493 rspq->depth = BFA_MSGQ_RSPQ_NUM_ENTRY;
494 rspq->msgq = msgq;
495 bfa_fsm_set_state(rspq, rspq_sm_stopped);
496 }
497
498 static void
bfa_msgq_init_rsp(struct bfa_msgq * msgq,struct bfi_mbmsg * mb)499 bfa_msgq_init_rsp(struct bfa_msgq *msgq,
500 struct bfi_mbmsg *mb)
501 {
502 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_INIT_RESP);
503 bfa_fsm_send_event(&msgq->rspq, RSPQ_E_INIT_RESP);
504 }
505
506 static void
bfa_msgq_init(void * arg)507 bfa_msgq_init(void *arg)
508 {
509 struct bfa_msgq *msgq = (struct bfa_msgq *)arg;
510 struct bfi_msgq_cfg_req *msgq_cfg =
511 (struct bfi_msgq_cfg_req *)&msgq->init_mb.msg[0];
512
513 memset(msgq_cfg, 0, sizeof(struct bfi_msgq_cfg_req));
514 bfi_h2i_set(msgq_cfg->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_INIT_REQ, 0);
515 msgq_cfg->mh.mtag.i2htok = 0;
516
517 bfa_dma_be_addr_set(msgq_cfg->cmdq.addr, msgq->cmdq.addr.pa);
518 msgq_cfg->cmdq.q_depth = htons(msgq->cmdq.depth);
519 bfa_dma_be_addr_set(msgq_cfg->rspq.addr, msgq->rspq.addr.pa);
520 msgq_cfg->rspq.q_depth = htons(msgq->rspq.depth);
521
522 bfa_nw_ioc_mbox_queue(msgq->ioc, &msgq->init_mb, NULL, NULL);
523 }
524
525 static void
bfa_msgq_isr(void * cbarg,struct bfi_mbmsg * msg)526 bfa_msgq_isr(void *cbarg, struct bfi_mbmsg *msg)
527 {
528 struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
529
530 switch (msg->mh.msg_id) {
531 case BFI_MSGQ_I2H_INIT_RSP:
532 bfa_msgq_init_rsp(msgq, msg);
533 break;
534
535 case BFI_MSGQ_I2H_DOORBELL_PI:
536 bfa_msgq_rspq_pi_update(&msgq->rspq, msg);
537 break;
538
539 case BFI_MSGQ_I2H_DOORBELL_CI:
540 bfa_msgq_cmdq_ci_update(&msgq->cmdq, msg);
541 break;
542
543 case BFI_MSGQ_I2H_CMDQ_COPY_REQ:
544 bfa_msgq_cmdq_copy_req(&msgq->cmdq, msg);
545 break;
546
547 default:
548 BUG_ON(1);
549 }
550 }
551
552 static void
bfa_msgq_notify(void * cbarg,enum bfa_ioc_event event)553 bfa_msgq_notify(void *cbarg, enum bfa_ioc_event event)
554 {
555 struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
556
557 switch (event) {
558 case BFA_IOC_E_ENABLED:
559 bfa_wc_init(&msgq->init_wc, bfa_msgq_init, msgq);
560 bfa_wc_up(&msgq->init_wc);
561 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_START);
562 bfa_wc_up(&msgq->init_wc);
563 bfa_fsm_send_event(&msgq->rspq, RSPQ_E_START);
564 bfa_wc_wait(&msgq->init_wc);
565 break;
566
567 case BFA_IOC_E_DISABLED:
568 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_STOP);
569 bfa_fsm_send_event(&msgq->rspq, RSPQ_E_STOP);
570 break;
571
572 case BFA_IOC_E_FAILED:
573 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_FAIL);
574 bfa_fsm_send_event(&msgq->rspq, RSPQ_E_FAIL);
575 break;
576
577 default:
578 break;
579 }
580 }
581
582 u32
bfa_msgq_meminfo(void)583 bfa_msgq_meminfo(void)
584 {
585 return roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ) +
586 roundup(BFA_MSGQ_RSPQ_SIZE, BFA_DMA_ALIGN_SZ);
587 }
588
589 void
bfa_msgq_memclaim(struct bfa_msgq * msgq,u8 * kva,u64 pa)590 bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa)
591 {
592 msgq->cmdq.addr.kva = kva;
593 msgq->cmdq.addr.pa = pa;
594
595 kva += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
596 pa += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
597
598 msgq->rspq.addr.kva = kva;
599 msgq->rspq.addr.pa = pa;
600 }
601
602 void
bfa_msgq_attach(struct bfa_msgq * msgq,struct bfa_ioc * ioc)603 bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc)
604 {
605 msgq->ioc = ioc;
606
607 bfa_msgq_cmdq_attach(&msgq->cmdq, msgq);
608 bfa_msgq_rspq_attach(&msgq->rspq, msgq);
609
610 bfa_nw_ioc_mbox_regisr(msgq->ioc, BFI_MC_MSGQ, bfa_msgq_isr, msgq);
611 bfa_ioc_notify_init(&msgq->ioc_notify, bfa_msgq_notify, msgq);
612 bfa_nw_ioc_notify_register(msgq->ioc, &msgq->ioc_notify);
613 }
614
615 void
bfa_msgq_regisr(struct bfa_msgq * msgq,enum bfi_mclass mc,bfa_msgq_mcfunc_t cbfn,void * cbarg)616 bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
617 bfa_msgq_mcfunc_t cbfn, void *cbarg)
618 {
619 msgq->rspq.rsphdlr[mc].cbfn = cbfn;
620 msgq->rspq.rsphdlr[mc].cbarg = cbarg;
621 }
622
623 void
bfa_msgq_cmd_post(struct bfa_msgq * msgq,struct bfa_msgq_cmd_entry * cmd)624 bfa_msgq_cmd_post(struct bfa_msgq *msgq, struct bfa_msgq_cmd_entry *cmd)
625 {
626 if (ntohs(cmd->msg_hdr->num_entries) <=
627 BFA_MSGQ_FREE_CNT(&msgq->cmdq)) {
628 __cmd_copy(&msgq->cmdq, cmd);
629 call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
630 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_POST);
631 } else {
632 list_add_tail(&cmd->qe, &msgq->cmdq.pending_q);
633 }
634 }
635
636 void
bfa_msgq_rsp_copy(struct bfa_msgq * msgq,u8 * buf,size_t buf_len)637 bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len)
638 {
639 struct bfa_msgq_rspq *rspq = &msgq->rspq;
640 size_t len = buf_len;
641 size_t to_copy;
642 int ci;
643 u8 *src, *dst;
644
645 ci = rspq->consumer_index;
646 src = (u8 *)rspq->addr.kva;
647 src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
648 dst = buf;
649
650 while (len) {
651 to_copy = (len < BFI_MSGQ_RSP_ENTRY_SIZE) ?
652 len : BFI_MSGQ_RSP_ENTRY_SIZE;
653 memcpy(dst, src, to_copy);
654 len -= to_copy;
655 dst += BFI_MSGQ_RSP_ENTRY_SIZE;
656 BFA_MSGQ_INDX_ADD(ci, 1, rspq->depth);
657 src = (u8 *)rspq->addr.kva;
658 src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
659 }
660 }
661