Skip to content

Commit 577f0d1

Browse files
vburrudavem330
authored andcommitted
octeon_ep: add separate mailbox command and response queues
Enhance control mailbox protocol to support following - separate command and response queues * command queue to send control commands to firmware. * response queue to receive responses and notifications from firmware. - variable size messages using scatter/gather Signed-off-by: Abhijit Ayarekar <[email protected]> Signed-off-by: Veerasenareddy Burru <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7c05d3d commit 577f0d1

File tree

6 files changed

+529
-411
lines changed

6 files changed

+529
-411
lines changed

drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c

Lines changed: 150 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -24,41 +24,49 @@
2424
/* Time in msecs to wait for message response */
2525
#define OCTEP_CTRL_MBOX_MSG_WAIT_MS 10
2626

27-
#define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET(m) (m)
28-
#define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET(m) ((m) + 8)
29-
#define OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(m) ((m) + 24)
30-
#define OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET(m) ((m) + 144)
31-
32-
#define OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m) ((m) + OCTEP_CTRL_MBOX_INFO_SZ)
33-
#define OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET(m) (OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m))
34-
#define OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 4)
35-
#define OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 8)
36-
#define OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 12)
37-
38-
#define OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m) ((m) + \
39-
OCTEP_CTRL_MBOX_INFO_SZ + \
40-
OCTEP_CTRL_MBOX_H2FQ_INFO_SZ)
41-
#define OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET(m) (OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m))
42-
#define OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 4)
43-
#define OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 8)
44-
#define OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 12)
45-
46-
#define OCTEP_CTRL_MBOX_Q_OFFSET(m, i) ((m) + \
47-
(sizeof(struct octep_ctrl_mbox_msg) * (i)))
48-
49-
static u32 octep_ctrl_mbox_circq_inc(u32 index, u32 mask)
27+
/* Size of mbox info in bytes */
28+
#define OCTEP_CTRL_MBOX_INFO_SZ 256
29+
/* Size of mbox host to fw queue info in bytes */
30+
#define OCTEP_CTRL_MBOX_H2FQ_INFO_SZ 16
31+
/* Size of mbox fw to host queue info in bytes */
32+
#define OCTEP_CTRL_MBOX_F2HQ_INFO_SZ 16
33+
34+
#define OCTEP_CTRL_MBOX_TOTAL_INFO_SZ (OCTEP_CTRL_MBOX_INFO_SZ + \
35+
OCTEP_CTRL_MBOX_H2FQ_INFO_SZ + \
36+
OCTEP_CTRL_MBOX_F2HQ_INFO_SZ)
37+
38+
#define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM(m) (m)
39+
#define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ(m) ((m) + 8)
40+
#define OCTEP_CTRL_MBOX_INFO_HOST_STATUS(m) ((m) + 24)
41+
#define OCTEP_CTRL_MBOX_INFO_FW_STATUS(m) ((m) + 144)
42+
43+
#define OCTEP_CTRL_MBOX_H2FQ_INFO(m) ((m) + OCTEP_CTRL_MBOX_INFO_SZ)
44+
#define OCTEP_CTRL_MBOX_H2FQ_PROD(m) (OCTEP_CTRL_MBOX_H2FQ_INFO(m))
45+
#define OCTEP_CTRL_MBOX_H2FQ_CONS(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO(m)) + 4)
46+
#define OCTEP_CTRL_MBOX_H2FQ_SZ(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO(m)) + 8)
47+
48+
#define OCTEP_CTRL_MBOX_F2HQ_INFO(m) ((m) + \
49+
OCTEP_CTRL_MBOX_INFO_SZ + \
50+
OCTEP_CTRL_MBOX_H2FQ_INFO_SZ)
51+
#define OCTEP_CTRL_MBOX_F2HQ_PROD(m) (OCTEP_CTRL_MBOX_F2HQ_INFO(m))
52+
#define OCTEP_CTRL_MBOX_F2HQ_CONS(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO(m)) + 4)
53+
#define OCTEP_CTRL_MBOX_F2HQ_SZ(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO(m)) + 8)
54+
55+
static const u32 mbox_hdr_sz = sizeof(union octep_ctrl_mbox_msg_hdr);
56+
57+
static u32 octep_ctrl_mbox_circq_inc(u32 index, u32 inc, u32 sz)
5058
{
51-
return (index + 1) & mask;
59+
return (index + inc) % sz;
5260
}
5361

54-
static u32 octep_ctrl_mbox_circq_space(u32 pi, u32 ci, u32 mask)
62+
static u32 octep_ctrl_mbox_circq_space(u32 pi, u32 ci, u32 sz)
5563
{
56-
return mask - ((pi - ci) & mask);
64+
return sz - (abs(pi - ci) % sz);
5765
}
5866

59-
static u32 octep_ctrl_mbox_circq_depth(u32 pi, u32 ci, u32 mask)
67+
static u32 octep_ctrl_mbox_circq_depth(u32 pi, u32 ci, u32 sz)
6068
{
61-
return ((pi - ci) & mask);
69+
return (abs(pi - ci) % sz);
6270
}
6371

6472
int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
@@ -73,172 +81,188 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
7381
return -EINVAL;
7482
}
7583

76-
magic_num = readq(OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET(mbox->barmem));
84+
magic_num = readq(OCTEP_CTRL_MBOX_INFO_MAGIC_NUM(mbox->barmem));
7785
if (magic_num != OCTEP_CTRL_MBOX_MAGIC_NUMBER) {
7886
pr_info("octep_ctrl_mbox : Invalid magic number %llx\n", magic_num);
7987
return -EINVAL;
8088
}
8189

82-
status = readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET(mbox->barmem));
90+
status = readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS(mbox->barmem));
8391
if (status != OCTEP_CTRL_MBOX_STATUS_READY) {
8492
pr_info("octep_ctrl_mbox : Firmware is not ready.\n");
8593
return -EINVAL;
8694
}
8795

88-
mbox->barmem_sz = readl(OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET(mbox->barmem));
96+
mbox->barmem_sz = readl(OCTEP_CTRL_MBOX_INFO_BARMEM_SZ(mbox->barmem));
8997

90-
writeq(OCTEP_CTRL_MBOX_STATUS_INIT, OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
98+
writeq(OCTEP_CTRL_MBOX_STATUS_INIT,
99+
OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
91100

92-
mbox->h2fq.elem_cnt = readl(OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET(mbox->barmem));
93-
mbox->h2fq.elem_sz = readl(OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET(mbox->barmem));
94-
mbox->h2fq.mask = (mbox->h2fq.elem_cnt - 1);
95-
mutex_init(&mbox->h2fq_lock);
101+
mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem));
102+
mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem);
103+
mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS(mbox->barmem);
104+
mbox->h2fq.hw_q = mbox->barmem + OCTEP_CTRL_MBOX_TOTAL_INFO_SZ;
96105

97-
mbox->f2hq.elem_cnt = readl(OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET(mbox->barmem));
98-
mbox->f2hq.elem_sz = readl(OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET(mbox->barmem));
99-
mbox->f2hq.mask = (mbox->f2hq.elem_cnt - 1);
100-
mutex_init(&mbox->f2hq_lock);
101-
102-
mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET(mbox->barmem);
103-
mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET(mbox->barmem);
104-
mbox->h2fq.hw_q = mbox->barmem +
105-
OCTEP_CTRL_MBOX_INFO_SZ +
106-
OCTEP_CTRL_MBOX_H2FQ_INFO_SZ +
107-
OCTEP_CTRL_MBOX_F2HQ_INFO_SZ;
108-
109-
mbox->f2hq.hw_prod = OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET(mbox->barmem);
110-
mbox->f2hq.hw_cons = OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET(mbox->barmem);
111-
mbox->f2hq.hw_q = mbox->h2fq.hw_q +
112-
((mbox->h2fq.elem_sz + sizeof(union octep_ctrl_mbox_msg_hdr)) *
113-
mbox->h2fq.elem_cnt);
106+
mbox->f2hq.sz = readl(OCTEP_CTRL_MBOX_F2HQ_SZ(mbox->barmem));
107+
mbox->f2hq.hw_prod = OCTEP_CTRL_MBOX_F2HQ_PROD(mbox->barmem);
108+
mbox->f2hq.hw_cons = OCTEP_CTRL_MBOX_F2HQ_CONS(mbox->barmem);
109+
mbox->f2hq.hw_q = mbox->barmem +
110+
OCTEP_CTRL_MBOX_TOTAL_INFO_SZ +
111+
mbox->h2fq.sz;
114112

115113
/* ensure ready state is seen after everything is initialized */
116114
wmb();
117-
writeq(OCTEP_CTRL_MBOX_STATUS_READY, OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
115+
writeq(OCTEP_CTRL_MBOX_STATUS_READY,
116+
OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
118117

119118
pr_info("Octep ctrl mbox : Init successful.\n");
120119

121120
return 0;
122121
}
123122

123+
static void
124+
octep_write_mbox_data(struct octep_ctrl_mbox_q *q, u32 *pi, u32 ci, void *buf, u32 w_sz)
125+
{
126+
u8 __iomem *qbuf;
127+
u32 cp_sz;
128+
129+
/* Assumption: Caller has ensured enough write space */
130+
qbuf = (q->hw_q + *pi);
131+
if (*pi < ci) {
132+
/* copy entire w_sz */
133+
memcpy_toio(qbuf, buf, w_sz);
134+
*pi = octep_ctrl_mbox_circq_inc(*pi, w_sz, q->sz);
135+
} else {
136+
/* copy up to end of queue */
137+
cp_sz = min((q->sz - *pi), w_sz);
138+
memcpy_toio(qbuf, buf, cp_sz);
139+
w_sz -= cp_sz;
140+
*pi = octep_ctrl_mbox_circq_inc(*pi, cp_sz, q->sz);
141+
if (w_sz) {
142+
/* roll over and copy remaining w_sz */
143+
buf += cp_sz;
144+
qbuf = (q->hw_q + *pi);
145+
memcpy_toio(qbuf, buf, w_sz);
146+
*pi = octep_ctrl_mbox_circq_inc(*pi, w_sz, q->sz);
147+
}
148+
}
149+
}
150+
124151
int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg)
125152
{
126-
unsigned long timeout = msecs_to_jiffies(OCTEP_CTRL_MBOX_MSG_TIMEOUT_MS);
127-
unsigned long period = msecs_to_jiffies(OCTEP_CTRL_MBOX_MSG_WAIT_MS);
153+
struct octep_ctrl_mbox_msg_buf *sg;
128154
struct octep_ctrl_mbox_q *q;
129-
unsigned long expire;
130-
u64 *mbuf, *word0;
131-
u8 __iomem *qidx;
132-
u16 pi, ci;
133-
int i;
155+
u32 pi, ci, buf_sz, w_sz;
156+
int s;
134157

135158
if (!mbox || !msg)
136159
return -EINVAL;
137160

161+
if (readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS(mbox->barmem)) != OCTEP_CTRL_MBOX_STATUS_READY)
162+
return -EIO;
163+
164+
mutex_lock(&mbox->h2fq_lock);
138165
q = &mbox->h2fq;
139166
pi = readl(q->hw_prod);
140167
ci = readl(q->hw_cons);
141168

142-
if (!octep_ctrl_mbox_circq_space(pi, ci, q->mask))
143-
return -ENOMEM;
144-
145-
qidx = OCTEP_CTRL_MBOX_Q_OFFSET(q->hw_q, pi);
146-
mbuf = (u64 *)msg->msg;
147-
word0 = &msg->hdr.word0;
148-
149-
mutex_lock(&mbox->h2fq_lock);
150-
for (i = 1; i <= msg->hdr.sizew; i++)
151-
writeq(*mbuf++, (qidx + (i * 8)));
152-
153-
writeq(*word0, qidx);
169+
if (octep_ctrl_mbox_circq_space(pi, ci, q->sz) < (msg->hdr.s.sz + mbox_hdr_sz)) {
170+
mutex_unlock(&mbox->f2hq_lock);
171+
return -EAGAIN;
172+
}
154173

155-
pi = octep_ctrl_mbox_circq_inc(pi, q->mask);
174+
octep_write_mbox_data(q, &pi, ci, (void *)&msg->hdr, mbox_hdr_sz);
175+
buf_sz = msg->hdr.s.sz;
176+
for (s = 0; ((s < msg->sg_num) && (buf_sz > 0)); s++) {
177+
sg = &msg->sg_list[s];
178+
w_sz = (sg->sz <= buf_sz) ? sg->sz : buf_sz;
179+
octep_write_mbox_data(q, &pi, ci, sg->msg, w_sz);
180+
buf_sz -= w_sz;
181+
}
156182
writel(pi, q->hw_prod);
157183
mutex_unlock(&mbox->h2fq_lock);
158184

159-
/* don't check for notification response */
160-
if (msg->hdr.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY)
161-
return 0;
162-
163-
expire = jiffies + timeout;
164-
while (true) {
165-
*word0 = readq(qidx);
166-
if (msg->hdr.flags == OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP)
167-
break;
168-
schedule_timeout_interruptible(period);
169-
if (signal_pending(current) || time_after(jiffies, expire)) {
170-
pr_info("octep_ctrl_mbox: Timed out\n");
171-
return -EBUSY;
185+
return 0;
186+
}
187+
188+
static void
189+
octep_read_mbox_data(struct octep_ctrl_mbox_q *q, u32 pi, u32 *ci, void *buf, u32 r_sz)
190+
{
191+
u8 __iomem *qbuf;
192+
u32 cp_sz;
193+
194+
/* Assumption: Caller has ensured enough read space */
195+
qbuf = (q->hw_q + *ci);
196+
if (*ci < pi) {
197+
/* copy entire r_sz */
198+
memcpy_fromio(buf, qbuf, r_sz);
199+
*ci = octep_ctrl_mbox_circq_inc(*ci, r_sz, q->sz);
200+
} else {
201+
/* copy up to end of queue */
202+
cp_sz = min((q->sz - *ci), r_sz);
203+
memcpy_fromio(buf, qbuf, cp_sz);
204+
r_sz -= cp_sz;
205+
*ci = octep_ctrl_mbox_circq_inc(*ci, cp_sz, q->sz);
206+
if (r_sz) {
207+
/* roll over and copy remaining r_sz */
208+
buf += cp_sz;
209+
qbuf = (q->hw_q + *ci);
210+
memcpy_fromio(buf, qbuf, r_sz);
211+
*ci = octep_ctrl_mbox_circq_inc(*ci, r_sz, q->sz);
172212
}
173213
}
174-
mbuf = (u64 *)msg->msg;
175-
for (i = 1; i <= msg->hdr.sizew; i++)
176-
*mbuf++ = readq(qidx + (i * 8));
177-
178-
return 0;
179214
}
180215

181216
int octep_ctrl_mbox_recv(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg)
182217
{
218+
struct octep_ctrl_mbox_msg_buf *sg;
219+
u32 pi, ci, r_sz, buf_sz, q_depth;
183220
struct octep_ctrl_mbox_q *q;
184-
u32 count, pi, ci;
185-
u8 __iomem *qidx;
186-
u64 *mbuf;
187-
int i;
221+
int s;
188222

189-
if (!mbox || !msg)
190-
return -EINVAL;
223+
if (readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS(mbox->barmem)) != OCTEP_CTRL_MBOX_STATUS_READY)
224+
return -EIO;
191225

226+
mutex_lock(&mbox->f2hq_lock);
192227
q = &mbox->f2hq;
193228
pi = readl(q->hw_prod);
194229
ci = readl(q->hw_cons);
195-
count = octep_ctrl_mbox_circq_depth(pi, ci, q->mask);
196-
if (!count)
197-
return -EAGAIN;
198-
199-
qidx = OCTEP_CTRL_MBOX_Q_OFFSET(q->hw_q, ci);
200-
mbuf = (u64 *)msg->msg;
201230

202-
mutex_lock(&mbox->f2hq_lock);
203-
204-
msg->hdr.word0 = readq(qidx);
205-
for (i = 1; i <= msg->hdr.sizew; i++)
206-
*mbuf++ = readq(qidx + (i * 8));
231+
q_depth = octep_ctrl_mbox_circq_depth(pi, ci, q->sz);
232+
if (q_depth < mbox_hdr_sz) {
233+
mutex_unlock(&mbox->f2hq_lock);
234+
return -EAGAIN;
235+
}
207236

208-
ci = octep_ctrl_mbox_circq_inc(ci, q->mask);
237+
octep_read_mbox_data(q, pi, &ci, (void *)&msg->hdr, mbox_hdr_sz);
238+
buf_sz = msg->hdr.s.sz;
239+
for (s = 0; ((s < msg->sg_num) && (buf_sz > 0)); s++) {
240+
sg = &msg->sg_list[s];
241+
r_sz = (sg->sz <= buf_sz) ? sg->sz : buf_sz;
242+
octep_read_mbox_data(q, pi, &ci, sg->msg, r_sz);
243+
buf_sz -= r_sz;
244+
}
209245
writel(ci, q->hw_cons);
210-
211246
mutex_unlock(&mbox->f2hq_lock);
212247

213-
if (msg->hdr.flags != OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ || !mbox->process_req)
214-
return 0;
215-
216-
mbox->process_req(mbox->user_ctx, msg);
217-
mbuf = (u64 *)msg->msg;
218-
for (i = 1; i <= msg->hdr.sizew; i++)
219-
writeq(*mbuf++, (qidx + (i * 8)));
220-
221-
writeq(msg->hdr.word0, qidx);
222-
223248
return 0;
224249
}
225250

226251
int octep_ctrl_mbox_uninit(struct octep_ctrl_mbox *mbox)
227252
{
228253
if (!mbox)
229254
return -EINVAL;
255+
if (!mbox->barmem)
256+
return -EINVAL;
230257

231-
writeq(OCTEP_CTRL_MBOX_STATUS_UNINIT,
232-
OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
258+
writeq(OCTEP_CTRL_MBOX_STATUS_INVALID,
259+
OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
233260
/* ensure uninit state is written before uninitialization */
234261
wmb();
235262

236263
mutex_destroy(&mbox->h2fq_lock);
237264
mutex_destroy(&mbox->f2hq_lock);
238265

239-
writeq(OCTEP_CTRL_MBOX_STATUS_INVALID,
240-
OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
241-
242266
pr_info("Octep ctrl mbox : Uninit successful.\n");
243267

244268
return 0;

0 commit comments

Comments
 (0)