aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorRasesh Mody <rmody@brocade.com>2011-08-08 12:21:35 -0400
committerDavid S. Miller <davem@davemloft.net>2011-08-11 10:30:12 -0400
commitaf027a34f34a8c0794a72dae8367e268eae89dbb (patch)
tree4af30be7fe275e1cb2b360c01e0d04a1ba81ad75 /drivers/net/ethernet
parenta6a5580c4d90788d67a77c689d3ab22aa5eecfc3 (diff)
bna: MSGQ Implementation
Change details: - Currently modules communicate with the FW using 32 byte command and response register. This limits the size of the command and response messages exchanged with the FW to 32 bytes. We need a mechanism to exchange the comamnds and responses exchange with FW that exceeds 32 bytes. - MSGQ implementation provides that facility. It removes the assumption that command/response queue size is precisely calculated to accommodate all concurrent FW commands/responses. The queue depth is made variable now, defined by a macro. A waiting command list is implemented to hold all the commands when there is no place in the command queue. Callback is implemented for each command entry to invoke the module posting the command, when there is space in the command queue and the command was finally posted to the queue. Module/Object information is embedded in the response for tracking purpose. Signed-off-by: Rasesh Mody <rmody@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/brocade/bna/Makefile3
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c14
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.h4
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_msgq.c669
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_msgq.h130
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi.h101
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_ctrl.c6
7 files changed, 918 insertions, 9 deletions
diff --git a/drivers/net/ethernet/brocade/bna/Makefile b/drivers/net/ethernet/brocade/bna/Makefile
index a5d604de7fea..d501f520b0bc 100644
--- a/drivers/net/ethernet/brocade/bna/Makefile
+++ b/drivers/net/ethernet/brocade/bna/Makefile
@@ -6,6 +6,7 @@
6obj-$(CONFIG_BNA) += bna.o 6obj-$(CONFIG_BNA) += bna.o
7 7
8bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o 8bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o
9bna-objs += bfa_ioc.o bfa_ioc_ct.o bfa_cee.o cna_fwimg.o 9bna-objs += bfa_msgq.o bfa_ioc.o bfa_ioc_ct.o bfa_cee.o
10bna-objs += cna_fwimg.o
10 11
11EXTRA_CFLAGS := -Idrivers/net/bna 12EXTRA_CFLAGS := -Idrivers/net/bna
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 3cdea65aee12..2d5c4fd778ee 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -1968,18 +1968,22 @@ bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
1968 * @param[in] ioc IOC instance 1968 * @param[in] ioc IOC instance
1969 * @param[i] cmd Mailbox command 1969 * @param[i] cmd Mailbox command
1970 */ 1970 */
1971void 1971bool
1972bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd) 1972bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd,
1973 bfa_mbox_cmd_cbfn_t cbfn, void *cbarg)
1973{ 1974{
1974 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; 1975 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1975 u32 stat; 1976 u32 stat;
1976 1977
1978 cmd->cbfn = cbfn;
1979 cmd->cbarg = cbarg;
1980
1977 /** 1981 /**
1978 * If a previous command is pending, queue new command 1982 * If a previous command is pending, queue new command
1979 */ 1983 */
1980 if (!list_empty(&mod->cmd_q)) { 1984 if (!list_empty(&mod->cmd_q)) {
1981 list_add_tail(&cmd->qe, &mod->cmd_q); 1985 list_add_tail(&cmd->qe, &mod->cmd_q);
1982 return; 1986 return true;
1983 } 1987 }
1984 1988
1985 /** 1989 /**
@@ -1988,7 +1992,7 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
1988 stat = readl(ioc->ioc_regs.hfn_mbox_cmd); 1992 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
1989 if (stat) { 1993 if (stat) {
1990 list_add_tail(&cmd->qe, &mod->cmd_q); 1994 list_add_tail(&cmd->qe, &mod->cmd_q);
1991 return; 1995 return true;
1992 } 1996 }
1993 1997
1994 /** 1998 /**
@@ -1996,7 +2000,7 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
1996 */ 2000 */
1997 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg)); 2001 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1998 2002
1999 return; 2003 return false;
2000} 2004}
2001 2005
2002/** 2006/**
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.h b/drivers/net/ethernet/brocade/bna/bfa_ioc.h
index bda866ba6e90..33ba5f40ca37 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.h
@@ -253,7 +253,9 @@ struct bfa_ioc_hwif {
253/** 253/**
254 * IOC mailbox interface 254 * IOC mailbox interface
255 */ 255 */
256void bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd); 256bool bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc,
257 struct bfa_mbox_cmd *cmd,
258 bfa_mbox_cmd_cbfn_t cbfn, void *cbarg);
257void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc); 259void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc);
258void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, 260void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
259 bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg); 261 bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
diff --git a/drivers/net/ethernet/brocade/bna/bfa_msgq.c b/drivers/net/ethernet/brocade/bna/bfa_msgq.c
new file mode 100644
index 000000000000..ed5218782787
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bfa_msgq.c
@@ -0,0 +1,669 @@
1/*
2 * Linux network driver for Brocade 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-2011 Brocade Communications Systems, Inc.
15 * All rights reserved
16 * www.brocade.com
17 */
18
19/**
20 * @file bfa_msgq.c MSGQ module source file.
21 */
22
23#include "bfi.h"
24#include "bfa_msgq.h"
25#include "bfa_ioc.h"
26
27#define call_cmdq_ent_cbfn(_cmdq_ent, _status) \
28{ \
29 bfa_msgq_cmdcbfn_t cbfn; \
30 void *cbarg; \
31 cbfn = (_cmdq_ent)->cbfn; \
32 cbarg = (_cmdq_ent)->cbarg; \
33 (_cmdq_ent)->cbfn = NULL; \
34 (_cmdq_ent)->cbarg = NULL; \
35 if (cbfn) { \
36 cbfn(cbarg, (_status)); \
37 } \
38}
39
40static void bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq);
41static void bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq);
42
43enum cmdq_event {
44 CMDQ_E_START = 1,
45 CMDQ_E_STOP = 2,
46 CMDQ_E_FAIL = 3,
47 CMDQ_E_POST = 4,
48 CMDQ_E_INIT_RESP = 5,
49 CMDQ_E_DB_READY = 6,
50};
51
52bfa_fsm_state_decl(cmdq, stopped, struct bfa_msgq_cmdq, enum cmdq_event);
53bfa_fsm_state_decl(cmdq, init_wait, struct bfa_msgq_cmdq, enum cmdq_event);
54bfa_fsm_state_decl(cmdq, ready, struct bfa_msgq_cmdq, enum cmdq_event);
55bfa_fsm_state_decl(cmdq, dbell_wait, struct bfa_msgq_cmdq,
56 enum cmdq_event);
57
58static void
59cmdq_sm_stopped_entry(struct bfa_msgq_cmdq *cmdq)
60{
61 struct bfa_msgq_cmd_entry *cmdq_ent;
62
63 cmdq->producer_index = 0;
64 cmdq->consumer_index = 0;
65 cmdq->flags = 0;
66 cmdq->token = 0;
67 cmdq->offset = 0;
68 cmdq->bytes_to_copy = 0;
69 while (!list_empty(&cmdq->pending_q)) {
70 bfa_q_deq(&cmdq->pending_q, &cmdq_ent);
71 bfa_q_qe_init(&cmdq_ent->qe);
72 call_cmdq_ent_cbfn(cmdq_ent, BFA_STATUS_FAILED);
73 }
74}
75
76static void
77cmdq_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
98static void
99cmdq_sm_init_wait_entry(struct bfa_msgq_cmdq *cmdq)
100{
101 bfa_wc_down(&cmdq->msgq->init_wc);
102}
103
104static void
105cmdq_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
130static void
131cmdq_sm_ready_entry(struct bfa_msgq_cmdq *cmdq)
132{
133}
134
135static void
136cmdq_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
153static void
154cmdq_sm_dbell_wait_entry(struct bfa_msgq_cmdq *cmdq)
155{
156 bfa_msgq_cmdq_dbell(cmdq);
157}
158
159static void
160cmdq_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
185static void
186bfa_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
192static void
193bfa_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
209static 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
235static void
236bfa_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 =
247 (struct bfa_msgq_cmd_entry *)bfa_q_first(&cmdq->pending_q);
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
263static void
264bfa_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
272static void
273bfa_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
284static void
285bfa_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
310static void
311bfa_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
319static void bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq);
320
321enum 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
330bfa_fsm_state_decl(rspq, stopped, struct bfa_msgq_rspq, enum rspq_event);
331bfa_fsm_state_decl(rspq, init_wait, struct bfa_msgq_rspq,
332 enum rspq_event);
333bfa_fsm_state_decl(rspq, ready, struct bfa_msgq_rspq, enum rspq_event);
334bfa_fsm_state_decl(rspq, dbell_wait, struct bfa_msgq_rspq,
335 enum rspq_event);
336
337static void
338rspq_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
345static void
346rspq_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
363static void
364rspq_sm_init_wait_entry(struct bfa_msgq_rspq *rspq)
365{
366 bfa_wc_down(&rspq->msgq->init_wc);
367}
368
369static void
370rspq_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
387static void
388rspq_sm_ready_entry(struct bfa_msgq_rspq *rspq)
389{
390}
391
392static void
393rspq_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
410static void
411rspq_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
417static void
418rspq_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
443static void
444bfa_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
450static void
451bfa_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
467static void
468bfa_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
498static void
499bfa_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
506static void
507bfa_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
514static void
515bfa_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
533static void
534bfa_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
560static void
561bfa_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
590u32
591bfa_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
597void
598bfa_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
610void
611bfa_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_q_qe_init(&msgq->ioc_notify);
620 bfa_ioc_notify_init(&msgq->ioc_notify, bfa_msgq_notify, msgq);
621 bfa_nw_ioc_notify_register(msgq->ioc, &msgq->ioc_notify);
622}
623
624void
625bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
626 bfa_msgq_mcfunc_t cbfn, void *cbarg)
627{
628 msgq->rspq.rsphdlr[mc].cbfn = cbfn;
629 msgq->rspq.rsphdlr[mc].cbarg = cbarg;
630}
631
632void
633bfa_msgq_cmd_post(struct bfa_msgq *msgq, struct bfa_msgq_cmd_entry *cmd)
634{
635 if (ntohs(cmd->msg_hdr->num_entries) <=
636 BFA_MSGQ_FREE_CNT(&msgq->cmdq)) {
637 __cmd_copy(&msgq->cmdq, cmd);
638 call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
639 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_POST);
640 } else {
641 list_add_tail(&cmd->qe, &msgq->cmdq.pending_q);
642 }
643}
644
645void
646bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len)
647{
648 struct bfa_msgq_rspq *rspq = &msgq->rspq;
649 size_t len = buf_len;
650 size_t to_copy;
651 int ci;
652 u8 *src, *dst;
653
654 ci = rspq->consumer_index;
655 src = (u8 *)rspq->addr.kva;
656 src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
657 dst = buf;
658
659 while (len) {
660 to_copy = (len < BFI_MSGQ_RSP_ENTRY_SIZE) ?
661 len : BFI_MSGQ_RSP_ENTRY_SIZE;
662 memcpy(dst, src, to_copy);
663 len -= to_copy;
664 dst += BFI_MSGQ_RSP_ENTRY_SIZE;
665 BFA_MSGQ_INDX_ADD(ci, 1, rspq->depth);
666 src = (u8 *)rspq->addr.kva;
667 src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
668 }
669}
diff --git a/drivers/net/ethernet/brocade/bna/bfa_msgq.h b/drivers/net/ethernet/brocade/bna/bfa_msgq.h
new file mode 100644
index 000000000000..a6a565a366dc
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bfa_msgq.h
@@ -0,0 +1,130 @@
1/*
2 * Linux network driver for Brocade 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-2011 Brocade Communications Systems, Inc.
15 * All rights reserved
16 * www.brocade.com
17 */
18
19#ifndef __BFA_MSGQ_H__
20#define __BFA_MSGQ_H__
21
22#include "bfa_defs.h"
23#include "bfi.h"
24#include "bfa_ioc.h"
25#include "bfa_cs.h"
26
27#define BFA_MSGQ_FREE_CNT(_q) \
28 (((_q)->consumer_index - (_q)->producer_index - 1) & ((_q)->depth - 1))
29
30#define BFA_MSGQ_INDX_ADD(_q_indx, _qe_num, _q_depth) \
31 ((_q_indx) = (((_q_indx) + (_qe_num)) & ((_q_depth) - 1)))
32
33#define BFA_MSGQ_CMDQ_NUM_ENTRY 128
34#define BFA_MSGQ_CMDQ_SIZE \
35 (BFI_MSGQ_CMD_ENTRY_SIZE * BFA_MSGQ_CMDQ_NUM_ENTRY)
36
37#define BFA_MSGQ_RSPQ_NUM_ENTRY 128
38#define BFA_MSGQ_RSPQ_SIZE \
39 (BFI_MSGQ_RSP_ENTRY_SIZE * BFA_MSGQ_RSPQ_NUM_ENTRY)
40
41#define bfa_msgq_cmd_set(_cmd, _cbfn, _cbarg, _msg_size, _msg_hdr) \
42do { \
43 (_cmd)->cbfn = (_cbfn); \
44 (_cmd)->cbarg = (_cbarg); \
45 (_cmd)->msg_size = (_msg_size); \
46 (_cmd)->msg_hdr = (_msg_hdr); \
47} while (0)
48
49struct bfa_msgq;
50
51typedef void (*bfa_msgq_cmdcbfn_t)(void *cbarg, enum bfa_status status);
52
53struct bfa_msgq_cmd_entry {
54 struct list_head qe;
55 bfa_msgq_cmdcbfn_t cbfn;
56 void *cbarg;
57 size_t msg_size;
58 struct bfi_msgq_mhdr *msg_hdr;
59};
60
61enum bfa_msgq_cmdq_flags {
62 BFA_MSGQ_CMDQ_F_DB_UPDATE = 1,
63};
64
65struct bfa_msgq_cmdq {
66 bfa_fsm_t fsm;
67 enum bfa_msgq_cmdq_flags flags;
68
69 u16 producer_index;
70 u16 consumer_index;
71 u16 depth; /* FW Q depth is 16 bits */
72 struct bfa_dma addr;
73 struct bfa_mbox_cmd dbell_mb;
74
75 u16 token;
76 int offset;
77 int bytes_to_copy;
78 struct bfa_mbox_cmd copy_mb;
79
80 struct list_head pending_q; /* pending command queue */
81
82 struct bfa_msgq *msgq;
83};
84
85enum bfa_msgq_rspq_flags {
86 BFA_MSGQ_RSPQ_F_DB_UPDATE = 1,
87};
88
89typedef void (*bfa_msgq_mcfunc_t)(void *cbarg, struct bfi_msgq_mhdr *mhdr);
90
91struct bfa_msgq_rspq {
92 bfa_fsm_t fsm;
93 enum bfa_msgq_rspq_flags flags;
94
95 u16 producer_index;
96 u16 consumer_index;
97 u16 depth; /* FW Q depth is 16 bits */
98 struct bfa_dma addr;
99 struct bfa_mbox_cmd dbell_mb;
100
101 int nmclass;
102 struct {
103 bfa_msgq_mcfunc_t cbfn;
104 void *cbarg;
105 } rsphdlr[BFI_MC_MAX];
106
107 struct bfa_msgq *msgq;
108};
109
110struct bfa_msgq {
111 struct bfa_msgq_cmdq cmdq;
112 struct bfa_msgq_rspq rspq;
113
114 struct bfa_wc init_wc;
115 struct bfa_mbox_cmd init_mb;
116
117 struct bfa_ioc_notify ioc_notify;
118 struct bfa_ioc *ioc;
119};
120
121u32 bfa_msgq_meminfo(void);
122void bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa);
123void bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc);
124void bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
125 bfa_msgq_mcfunc_t cbfn, void *cbarg);
126void bfa_msgq_cmd_post(struct bfa_msgq *msgq,
127 struct bfa_msgq_cmd_entry *cmd);
128void bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len);
129
130#endif
diff --git a/drivers/net/ethernet/brocade/bna/bfi.h b/drivers/net/ethernet/brocade/bna/bfi.h
index 088211c2724f..6a53183e411e 100644
--- a/drivers/net/ethernet/brocade/bna/bfi.h
+++ b/drivers/net/ethernet/brocade/bna/bfi.h
@@ -192,6 +192,8 @@ enum bfi_mclass {
192 192
193#define BFI_BOOT_LOADER_OS 0 193#define BFI_BOOT_LOADER_OS 0
194 194
195#define BFI_FWBOOT_ENV_OS 0
196
195#define BFI_BOOT_MEMTEST_RES_ADDR 0x900 197#define BFI_BOOT_MEMTEST_RES_ADDR 0x900
196#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3 198#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3
197 199
@@ -395,6 +397,105 @@ union bfi_ioc_i2h_msg_u {
395 u32 mboxmsg[BFI_IOC_MSGSZ]; 397 u32 mboxmsg[BFI_IOC_MSGSZ];
396}; 398};
397 399
400/**
401 *----------------------------------------------------------------------
402 * MSGQ
403 *----------------------------------------------------------------------
404 */
405
406enum bfi_msgq_h2i_msgs {
407 BFI_MSGQ_H2I_INIT_REQ = 1,
408 BFI_MSGQ_H2I_DOORBELL_PI = 2,
409 BFI_MSGQ_H2I_DOORBELL_CI = 3,
410 BFI_MSGQ_H2I_CMDQ_COPY_RSP = 4,
411};
412
413enum bfi_msgq_i2h_msgs {
414 BFI_MSGQ_I2H_INIT_RSP = BFA_I2HM(BFI_MSGQ_H2I_INIT_REQ),
415 BFI_MSGQ_I2H_DOORBELL_PI = BFA_I2HM(BFI_MSGQ_H2I_DOORBELL_PI),
416 BFI_MSGQ_I2H_DOORBELL_CI = BFA_I2HM(BFI_MSGQ_H2I_DOORBELL_CI),
417 BFI_MSGQ_I2H_CMDQ_COPY_REQ = BFA_I2HM(BFI_MSGQ_H2I_CMDQ_COPY_RSP),
418};
419
420/* Messages(commands/responsed/AENS will have the following header */
421struct bfi_msgq_mhdr {
422 u8 msg_class;
423 u8 msg_id;
424 u16 msg_token;
425 u16 num_entries;
426 u8 enet_id;
427 u8 rsvd[1];
428};
429
430#define bfi_msgq_mhdr_set(_mh, _mc, _mid, _tok, _enet_id) do { \
431 (_mh).msg_class = (_mc); \
432 (_mh).msg_id = (_mid); \
433 (_mh).msg_token = (_tok); \
434 (_mh).enet_id = (_enet_id); \
435} while (0)
436
437/*
438 * Mailbox for messaging interface
439 */
440#define BFI_MSGQ_CMD_ENTRY_SIZE (64) /* TBD */
441#define BFI_MSGQ_RSP_ENTRY_SIZE (64) /* TBD */
442
443#define bfi_msgq_num_cmd_entries(_size) \
444 (((_size) + BFI_MSGQ_CMD_ENTRY_SIZE - 1) / BFI_MSGQ_CMD_ENTRY_SIZE)
445
446struct bfi_msgq {
447 union bfi_addr_u addr;
448 u16 q_depth; /* Total num of entries in the queue */
449 u8 rsvd[2];
450};
451
452/* BFI_ENET_MSGQ_CFG_REQ TBD init or cfg? */
453struct bfi_msgq_cfg_req {
454 struct bfi_mhdr mh;
455 struct bfi_msgq cmdq;
456 struct bfi_msgq rspq;
457};
458
459/* BFI_ENET_MSGQ_CFG_RSP */
460struct bfi_msgq_cfg_rsp {
461 struct bfi_mhdr mh;
462 u8 cmd_status;
463 u8 rsvd[3];
464};
465
466/* BFI_MSGQ_H2I_DOORBELL */
467struct bfi_msgq_h2i_db {
468 struct bfi_mhdr mh;
469 union {
470 u16 cmdq_pi;
471 u16 rspq_ci;
472 } idx;
473};
474
475/* BFI_MSGQ_I2H_DOORBELL */
476struct bfi_msgq_i2h_db {
477 struct bfi_mhdr mh;
478 union {
479 u16 rspq_pi;
480 u16 cmdq_ci;
481 } idx;
482};
483
484#define BFI_CMD_COPY_SZ 28
485
486/* BFI_MSGQ_H2I_CMD_COPY_RSP */
487struct bfi_msgq_h2i_cmdq_copy_rsp {
488 struct bfi_mhdr mh;
489 u8 data[BFI_CMD_COPY_SZ];
490};
491
492/* BFI_MSGQ_I2H_CMD_COPY_REQ */
493struct bfi_msgq_i2h_cmdq_copy_req {
494 struct bfi_mhdr mh;
495 u16 offset;
496 u16 len;
497};
498
398#pragma pack() 499#pragma pack()
399 500
400#endif /* __BFI_H__ */ 501#endif /* __BFI_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bna_ctrl.c b/drivers/net/ethernet/brocade/bna/bna_ctrl.c
index cb2594c564dc..7d9551778274 100644
--- a/drivers/net/ethernet/brocade/bna/bna_ctrl.c
+++ b/drivers/net/ethernet/brocade/bna/bna_ctrl.c
@@ -183,7 +183,8 @@ bna_ll_isr(void *llarg, struct bfi_mbmsg *msg)
183 if (to_post) { 183 if (to_post) {
184 mb_qe = bfa_q_first(&bna->mbox_mod.posted_q); 184 mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
185 bfa_nw_ioc_mbox_queue(&bna->device.ioc, 185 bfa_nw_ioc_mbox_queue(&bna->device.ioc,
186 &mb_qe->cmd); 186 &mb_qe->cmd, NULL,
187 NULL);
187 } 188 }
188 } else { 189 } else {
189 snprintf(message, BNA_MESSAGE_SIZE, 190 snprintf(message, BNA_MESSAGE_SIZE,
@@ -234,7 +235,8 @@ bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe)
234 bna->mbox_mod.msg_pending++; 235 bna->mbox_mod.msg_pending++;
235 if (bna->mbox_mod.state == BNA_MBOX_FREE) { 236 if (bna->mbox_mod.state == BNA_MBOX_FREE) {
236 list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q); 237 list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
237 bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd); 238 bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd,
239 NULL, NULL);
238 bna->mbox_mod.state = BNA_MBOX_POSTED; 240 bna->mbox_mod.state = BNA_MBOX_POSTED;
239 } else { 241 } else {
240 list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q); 242 list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);