Re: [PATCH net-next v3 4/7] octeon_ep: enhance control mailbox for VF support

From: Maciej Fijalkowski
Date: Wed Feb 15 2023 - 10:55:36 EST


On Mon, Feb 13, 2023 at 09:14:19PM -0800, Veerasenareddy Burru wrote:
> 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
> - VF support
> * extend control command structure to include vfid.
> * update APIs to accept VF ID.
>
> Signed-off-by: Abhijit Ayarekar <aayarekar@xxxxxxxxxxx>
> Signed-off-by: Veerasenareddy Burru <vburru@xxxxxxxxxxx>
> ---
> v2 -> v3:
> * no change
>
> v1 -> v2:
> * modified the patch to work with device status "oct->status" removed.
>
> .../marvell/octeon_ep/octep_ctrl_mbox.c | 318 +++++++++-------
> .../marvell/octeon_ep/octep_ctrl_mbox.h | 102 ++---
> .../marvell/octeon_ep/octep_ctrl_net.c | 349 ++++++++++++------
> .../marvell/octeon_ep/octep_ctrl_net.h | 176 +++++----
> .../marvell/octeon_ep/octep_ethtool.c | 7 +-
> .../ethernet/marvell/octeon_ep/octep_main.c | 80 ++--
> 6 files changed, 619 insertions(+), 413 deletions(-)

patch is big, any ways to split it up? for example, why couldn't the "VF
support" be pulled out to a sequent commit?

>
> diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
> index 39322e4dd100..cda252fc8f54 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
> +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
> @@ -24,41 +24,49 @@
> /* Time in msecs to wait for message response */
> #define OCTEP_CTRL_MBOX_MSG_WAIT_MS 10
>
> -#define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET(m) (m)
> -#define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET(m) ((m) + 8)
> -#define OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(m) ((m) + 24)
> -#define OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET(m) ((m) + 144)
> -
> -#define OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m) ((m) + OCTEP_CTRL_MBOX_INFO_SZ)
> -#define OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET(m) (OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m))
> -#define OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 4)
> -#define OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 8)
> -#define OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 12)
> -
> -#define OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m) ((m) + \
> - OCTEP_CTRL_MBOX_INFO_SZ + \
> - OCTEP_CTRL_MBOX_H2FQ_INFO_SZ)
> -#define OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET(m) (OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m))
> -#define OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 4)
> -#define OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 8)
> -#define OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 12)
> -
> -#define OCTEP_CTRL_MBOX_Q_OFFSET(m, i) ((m) + \
> - (sizeof(struct octep_ctrl_mbox_msg) * (i)))
> -
> -static u32 octep_ctrl_mbox_circq_inc(u32 index, u32 mask)
> +/* Size of mbox info in bytes */
> +#define OCTEP_CTRL_MBOX_INFO_SZ 256
> +/* Size of mbox host to fw queue info in bytes */
> +#define OCTEP_CTRL_MBOX_H2FQ_INFO_SZ 16
> +/* Size of mbox fw to host queue info in bytes */
> +#define OCTEP_CTRL_MBOX_F2HQ_INFO_SZ 16
> +
> +#define OCTEP_CTRL_MBOX_TOTAL_INFO_SZ (OCTEP_CTRL_MBOX_INFO_SZ + \
> + OCTEP_CTRL_MBOX_H2FQ_INFO_SZ + \
> + OCTEP_CTRL_MBOX_F2HQ_INFO_SZ)
> +
> +#define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM(m) (m)

This doesn't serve any purpose, does it? I know there was
OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET but i don't see any value in this
macro.

> +#define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ(m) ((m) + 8)
> +#define OCTEP_CTRL_MBOX_INFO_HOST_STATUS(m) ((m) + 24)
> +#define OCTEP_CTRL_MBOX_INFO_FW_STATUS(m) ((m) + 144)
> +
> +#define OCTEP_CTRL_MBOX_H2FQ_INFO(m) ((m) + OCTEP_CTRL_MBOX_INFO_SZ)
> +#define OCTEP_CTRL_MBOX_H2FQ_PROD(m) (OCTEP_CTRL_MBOX_H2FQ_INFO(m))
> +#define OCTEP_CTRL_MBOX_H2FQ_CONS(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO(m)) + 4)
> +#define OCTEP_CTRL_MBOX_H2FQ_SZ(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO(m)) + 8)
> +
> +#define OCTEP_CTRL_MBOX_F2HQ_INFO(m) ((m) + \
> + OCTEP_CTRL_MBOX_INFO_SZ + \
> + OCTEP_CTRL_MBOX_H2FQ_INFO_SZ)
> +#define OCTEP_CTRL_MBOX_F2HQ_PROD(m) (OCTEP_CTRL_MBOX_F2HQ_INFO(m))
> +#define OCTEP_CTRL_MBOX_F2HQ_CONS(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO(m)) + 4)
> +#define OCTEP_CTRL_MBOX_F2HQ_SZ(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO(m)) + 8)
> +
> +static const u32 mbox_hdr_sz = sizeof(union octep_ctrl_mbox_msg_hdr);
> +
> +static u32 octep_ctrl_mbox_circq_inc(u32 index, u32 inc, u32 sz)
> {
> - return (index + 1) & mask;
> + return (index + inc) % sz;

previously mbox len was power-of-2 sized?

> }
>
> -static u32 octep_ctrl_mbox_circq_space(u32 pi, u32 ci, u32 mask)
> +static u32 octep_ctrl_mbox_circq_space(u32 pi, u32 ci, u32 sz)
> {
> - return mask - ((pi - ci) & mask);
> + return sz - (abs(pi - ci) % sz);
> }
>
> -static u32 octep_ctrl_mbox_circq_depth(u32 pi, u32 ci, u32 mask)
> +static u32 octep_ctrl_mbox_circq_depth(u32 pi, u32 ci, u32 sz)
> {
> - return ((pi - ci) & mask);
> + return (abs(pi - ci) % sz);
> }
>
> int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
> @@ -73,172 +81,228 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
> return -EINVAL;
> }
>
> - magic_num = readq(OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET(mbox->barmem));
> + magic_num = readq(OCTEP_CTRL_MBOX_INFO_MAGIC_NUM(mbox->barmem));
> if (magic_num != OCTEP_CTRL_MBOX_MAGIC_NUMBER) {
> - pr_info("octep_ctrl_mbox : Invalid magic number %llx\n", magic_num);
> + pr_info("octep_ctrl_mbox : Invalid magic number %llx\n",
> + magic_num);

unneeded change

> return -EINVAL;
> }
>
> - status = readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET(mbox->barmem));
> + status = readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS(mbox->barmem));
> if (status != OCTEP_CTRL_MBOX_STATUS_READY) {
> pr_info("octep_ctrl_mbox : Firmware is not ready.\n");
> return -EINVAL;
> }
>
> - mbox->barmem_sz = readl(OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET(mbox->barmem));
> + mbox->barmem_sz = readl(OCTEP_CTRL_MBOX_INFO_BARMEM_SZ(mbox->barmem));
>
> - writeq(OCTEP_CTRL_MBOX_STATUS_INIT, OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
> + writeq(OCTEP_CTRL_MBOX_STATUS_INIT,
> + OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
>
> - mbox->h2fq.elem_cnt = readl(OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET(mbox->barmem));
> - mbox->h2fq.elem_sz = readl(OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET(mbox->barmem));
> - mbox->h2fq.mask = (mbox->h2fq.elem_cnt - 1);
> - mutex_init(&mbox->h2fq_lock);
> + mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem));
> + mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem);
> + mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS(mbox->barmem);
> + mbox->h2fq.hw_q = mbox->barmem + OCTEP_CTRL_MBOX_TOTAL_INFO_SZ;
>
> - mbox->f2hq.elem_cnt = readl(OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET(mbox->barmem));
> - mbox->f2hq.elem_sz = readl(OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET(mbox->barmem));
> - mbox->f2hq.mask = (mbox->f2hq.elem_cnt - 1);
> - mutex_init(&mbox->f2hq_lock);
> -
> - mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET(mbox->barmem);
> - mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET(mbox->barmem);
> - mbox->h2fq.hw_q = mbox->barmem +
> - OCTEP_CTRL_MBOX_INFO_SZ +
> - OCTEP_CTRL_MBOX_H2FQ_INFO_SZ +
> - OCTEP_CTRL_MBOX_F2HQ_INFO_SZ;
> -
> - mbox->f2hq.hw_prod = OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET(mbox->barmem);
> - mbox->f2hq.hw_cons = OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET(mbox->barmem);
> - mbox->f2hq.hw_q = mbox->h2fq.hw_q +
> - ((mbox->h2fq.elem_sz + sizeof(union octep_ctrl_mbox_msg_hdr)) *
> - mbox->h2fq.elem_cnt);
> + mbox->f2hq.sz = readl(OCTEP_CTRL_MBOX_F2HQ_SZ(mbox->barmem));
> + mbox->f2hq.hw_prod = OCTEP_CTRL_MBOX_F2HQ_PROD(mbox->barmem);
> + mbox->f2hq.hw_cons = OCTEP_CTRL_MBOX_F2HQ_CONS(mbox->barmem);
> + mbox->f2hq.hw_q = mbox->barmem +
> + OCTEP_CTRL_MBOX_TOTAL_INFO_SZ +
> + mbox->h2fq.sz;
>
> /* ensure ready state is seen after everything is initialized */
> wmb();
> - writeq(OCTEP_CTRL_MBOX_STATUS_READY, OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
> + writeq(OCTEP_CTRL_MBOX_STATUS_READY,
> + OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
>
> pr_info("Octep ctrl mbox : Init successful.\n");
>
> return 0;
> }
>
> -int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg)
> +static int write_mbox_data(struct octep_ctrl_mbox_q *q, u32 *pi,
> + u32 ci, void *buf, u32 w_sz)

octep_write_mbox_data ?

also, you only return 0 and don't check the retval, so
s/static int/static void

> +{
> + u32 cp_sz;
> + u8 __iomem *qbuf;
> +
> + /* Assumption: Caller has ensured enough write space */
> + qbuf = (q->hw_q + *pi);
> + if (*pi < ci) {
> + /* copy entire w_sz */
> + memcpy_toio(qbuf, buf, w_sz);
> + *pi = octep_ctrl_mbox_circq_inc(*pi, w_sz, q->sz);
> + } else {
> + /* copy up to end of queue */
> + cp_sz = min((q->sz - *pi), w_sz);
> + memcpy_toio(qbuf, buf, cp_sz);
> + w_sz -= cp_sz;
> + *pi = octep_ctrl_mbox_circq_inc(*pi, cp_sz, q->sz);
> + if (w_sz) {
> + /* roll over and copy remaining w_sz */
> + buf += cp_sz;
> + qbuf = (q->hw_q + *pi);
> + memcpy_toio(qbuf, buf, w_sz);
> + *pi = octep_ctrl_mbox_circq_inc(*pi, w_sz, q->sz);
> + }
> + }
> +
> + return 0;
> +}
> +
> +int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox,
> + struct octep_ctrl_mbox_msg *msgs,
> + int num)

only callsite that currently is present sets num to 1, what's the point
currently of having this arg?

> {
> - unsigned long timeout = msecs_to_jiffies(OCTEP_CTRL_MBOX_MSG_TIMEOUT_MS);
> - unsigned long period = msecs_to_jiffies(OCTEP_CTRL_MBOX_MSG_WAIT_MS);
> + struct octep_ctrl_mbox_msg_buf *sg;
> + struct octep_ctrl_mbox_msg *msg;
> struct octep_ctrl_mbox_q *q;
> - unsigned long expire;
> - u64 *mbuf, *word0;
> - u8 __iomem *qidx;
> - u16 pi, ci;
> - int i;
> + u32 pi, ci, prev_pi, buf_sz, w_sz;

RCT? you probably have this issue all over your patchset

> + int m, s;
>
> - if (!mbox || !msg)
> + if (!mbox || !msgs)
> return -EINVAL;
>
> + if (readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS(mbox->barmem)) !=
> + OCTEP_CTRL_MBOX_STATUS_READY)
> + return -EIO;
> +
> + mutex_lock(&mbox->h2fq_lock);
> q = &mbox->h2fq;
> pi = readl(q->hw_prod);
> ci = readl(q->hw_cons);
> + for (m = 0; m < num; m++) {
> + msg = &msgs[m];
> + if (!msg)
> + break;
>
> - if (!octep_ctrl_mbox_circq_space(pi, ci, q->mask))
> - return -ENOMEM;
> -
> - qidx = OCTEP_CTRL_MBOX_Q_OFFSET(q->hw_q, pi);
> - mbuf = (u64 *)msg->msg;
> - word0 = &msg->hdr.word0;
> -
> - mutex_lock(&mbox->h2fq_lock);
> - for (i = 1; i <= msg->hdr.sizew; i++)
> - writeq(*mbuf++, (qidx + (i * 8)));
> -
> - writeq(*word0, qidx);
> + /* not enough space for next message */
> + if (octep_ctrl_mbox_circq_space(pi, ci, q->sz) <
> + (msg->hdr.s.sz + mbox_hdr_sz))
> + break;
>
> - pi = octep_ctrl_mbox_circq_inc(pi, q->mask);
> + prev_pi = pi;
> + write_mbox_data(q, &pi, ci, (void *)&msg->hdr, mbox_hdr_sz);
> + buf_sz = msg->hdr.s.sz;
> + for (s = 0; ((s < msg->sg_num) && (buf_sz > 0)); s++) {
> + sg = &msg->sg_list[s];
> + w_sz = (sg->sz <= buf_sz) ? sg->sz : buf_sz;
> + write_mbox_data(q, &pi, ci, sg->msg, w_sz);
> + buf_sz -= w_sz;
> + }
> + if (buf_sz) {
> + /* we did not write entire message */
> + pi = prev_pi;
> + break;
> + }
> + }
> writel(pi, q->hw_prod);
> mutex_unlock(&mbox->h2fq_lock);
>
> - /* don't check for notification response */
> - if (msg->hdr.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY)
> - return 0;
> + return (m) ? m : -EAGAIN;

remove brackets

> +}
>
> - expire = jiffies + timeout;
> - while (true) {
> - *word0 = readq(qidx);
> - if (msg->hdr.flags == OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP)
> - break;
> - schedule_timeout_interruptible(period);
> - if (signal_pending(current) || time_after(jiffies, expire)) {
> - pr_info("octep_ctrl_mbox: Timed out\n");
> - return -EBUSY;
> +static int read_mbox_data(struct octep_ctrl_mbox_q *q, u32 pi,

same comment as for write func

> + u32 *ci, void *buf, u32 r_sz)
> +{
> + u32 cp_sz;
> + u8 __iomem *qbuf;
> +
> + /* Assumption: Caller has ensured enough read space */
> + qbuf = (q->hw_q + *ci);
> + if (*ci < pi) {
> + /* copy entire r_sz */
> + memcpy_fromio(buf, qbuf, r_sz);
> + *ci = octep_ctrl_mbox_circq_inc(*ci, r_sz, q->sz);
> + } else {
> + /* copy up to end of queue */
> + cp_sz = min((q->sz - *ci), r_sz);
> + memcpy_fromio(buf, qbuf, cp_sz);
> + r_sz -= cp_sz;
> + *ci = octep_ctrl_mbox_circq_inc(*ci, cp_sz, q->sz);
> + if (r_sz) {
> + /* roll over and copy remaining r_sz */
> + buf += cp_sz;
> + qbuf = (q->hw_q + *ci);
> + memcpy_fromio(buf, qbuf, r_sz);
> + *ci = octep_ctrl_mbox_circq_inc(*ci, r_sz, q->sz);
> }
> }
> - mbuf = (u64 *)msg->msg;
> - for (i = 1; i <= msg->hdr.sizew; i++)
> - *mbuf++ = readq(qidx + (i * 8));
>
> return 0;
> }
>
> -int octep_ctrl_mbox_recv(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg)
> +int octep_ctrl_mbox_recv(struct octep_ctrl_mbox *mbox,
> + struct octep_ctrl_mbox_msg *msgs,
> + int num)
> {
> + struct octep_ctrl_mbox_msg_buf *sg;
> + struct octep_ctrl_mbox_msg *msg;
> struct octep_ctrl_mbox_q *q;
> - u32 count, pi, ci;
> - u8 __iomem *qidx;
> - u64 *mbuf;
> - int i;
> + u32 pi, ci, q_depth, r_sz, buf_sz, prev_ci;
> + int s, m;
>
> - if (!mbox || !msg)
> + if (!mbox || !msgs)
> return -EINVAL;
>
> + if (readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS(mbox->barmem)) !=
> + OCTEP_CTRL_MBOX_STATUS_READY)
> + return -EIO;
> +
> + mutex_lock(&mbox->f2hq_lock);
> q = &mbox->f2hq;
> pi = readl(q->hw_prod);
> ci = readl(q->hw_cons);
> - count = octep_ctrl_mbox_circq_depth(pi, ci, q->mask);
> - if (!count)
> - return -EAGAIN;
> -
> - qidx = OCTEP_CTRL_MBOX_Q_OFFSET(q->hw_q, ci);
> - mbuf = (u64 *)msg->msg;
> -
> - mutex_lock(&mbox->f2hq_lock);
> + for (m = 0; m < num; m++) {
> + q_depth = octep_ctrl_mbox_circq_depth(pi, ci, q->sz);
> + if (q_depth < mbox_hdr_sz)
> + break;
>
> - msg->hdr.word0 = readq(qidx);
> - for (i = 1; i <= msg->hdr.sizew; i++)
> - *mbuf++ = readq(qidx + (i * 8));
> + msg = &msgs[m];
> + if (!msg)
> + break;
>
> - ci = octep_ctrl_mbox_circq_inc(ci, q->mask);
> + prev_ci = ci;
> + read_mbox_data(q, pi, &ci, (void *)&msg->hdr, mbox_hdr_sz);
> + buf_sz = msg->hdr.s.sz;
> + if (q_depth < (mbox_hdr_sz + buf_sz)) {
> + ci = prev_ci;
> + break;
> + }
> + for (s = 0; ((s < msg->sg_num) && (buf_sz > 0)); s++) {
> + sg = &msg->sg_list[s];
> + r_sz = (sg->sz <= buf_sz) ? sg->sz : buf_sz;
> + read_mbox_data(q, pi, &ci, sg->msg, r_sz);
> + buf_sz -= r_sz;
> + }
> + if (buf_sz) {
> + /* we did not read entire message */
> + ci = prev_ci;
> + break;
> + }
> + }
> writel(ci, q->hw_cons);
> -
> mutex_unlock(&mbox->f2hq_lock);
>
> - if (msg->hdr.flags != OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ || !mbox->process_req)
> - return 0;
> -
> - mbox->process_req(mbox->user_ctx, msg);
> - mbuf = (u64 *)msg->msg;
> - for (i = 1; i <= msg->hdr.sizew; i++)
> - writeq(*mbuf++, (qidx + (i * 8)));
> -
> - writeq(msg->hdr.word0, qidx);
> -
> - return 0;
> + return (m) ? m : -EAGAIN;

again remove brackets

> }
>
> int octep_ctrl_mbox_uninit(struct octep_ctrl_mbox *mbox)
> {
> if (!mbox)
> return -EINVAL;
> + if (!mbox->barmem)
> + return -EINVAL;
>
> - writeq(OCTEP_CTRL_MBOX_STATUS_UNINIT,
> - OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
> + writeq(OCTEP_CTRL_MBOX_STATUS_INVALID,
> + OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
> /* ensure uninit state is written before uninitialization */
> wmb();
>
> mutex_destroy(&mbox->h2fq_lock);
> mutex_destroy(&mbox->f2hq_lock);
>
> - writeq(OCTEP_CTRL_MBOX_STATUS_INVALID,
> - OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
> -
> pr_info("Octep ctrl mbox : Uninit successful.\n");
>
> return 0;

(...)

> {
> - struct octep_ctrl_net_h2f_req req = {};
> - struct octep_ctrl_net_h2f_resp *resp;
> - struct octep_ctrl_mbox_msg msg = {};
> - int err;
> + msg->hdr.s.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> + msg->hdr.s.msg_id = atomic_inc_return(&ctrl_net_msg_id) &
> + GENMASK(sizeof(msg->hdr.s.msg_id) * BITS_PER_BYTE, 0);
> + msg->hdr.s.sz = req_hdr_sz + sz;
> + msg->sg_num = 1;
> + msg->sg_list[0].msg = buf;
> + msg->sg_list[0].sz = msg->hdr.s.sz;
> + if (vfid != OCTEP_CTRL_NET_INVALID_VFID) {
> + msg->hdr.s.is_vf = 1;
> + msg->hdr.s.vf_idx = vfid;
> + }
> +}
>
> - req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
> - req.link.cmd = OCTEP_CTRL_NET_CMD_GET;
> +static int send_mbox_req(struct octep_device *oct,

why it's not prefixed with octep_ ?

> + struct octep_ctrl_net_wait_data *d,
> + bool wait_for_response)
> +{
> + int err, ret;
>
> - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_STATE_REQ_SZW;
> - msg.msg = &req;
> - err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
> - if (err)
> + err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &d->msg, 1);
> + if (err < 0)
> return err;
>
> - resp = (struct octep_ctrl_net_h2f_resp *)&req;
> - return resp->link.state;
> + if (!wait_for_response)
> + return 0;
> +
> + d->done = 0;
> + INIT_LIST_HEAD(&d->list);
> + list_add_tail(&d->list, &oct->ctrl_req_wait_list);
> + ret = wait_event_interruptible_timeout(oct->ctrl_req_wait_q,
> + (d->done != 0),
> + jiffies + msecs_to_jiffies(500));
> + list_del(&d->list);
> + if (ret == 0 || ret == 1)
> + return -EAGAIN;
> +
> + /**
> + * (ret == 0) cond = false && timeout, return 0
> + * (ret < 0) interrupted by signal, return 0
> + * (ret == 1) cond = true && timeout, return 1
> + * (ret >= 1) cond = true && !timeout, return 1
> + */
> +
> + if (d->data.resp.hdr.s.reply != OCTEP_CTRL_NET_REPLY_OK)
> + return -EAGAIN;
> +
> + return 0;
> }
>
> -void octep_set_link_status(struct octep_device *oct, bool up)
> +int octep_ctrl_net_init(struct octep_device *oct)
> {
> - struct octep_ctrl_net_h2f_req req = {};
> - struct octep_ctrl_mbox_msg msg = {};
> + struct pci_dev *pdev = oct->pdev;
> + struct octep_ctrl_mbox *ctrl_mbox;
> + int ret;
> +
> + init_waitqueue_head(&oct->ctrl_req_wait_q);
> + INIT_LIST_HEAD(&oct->ctrl_req_wait_list);
> +
> + /* Initialize control mbox */
> + ctrl_mbox = &oct->ctrl_mbox;
> + ctrl_mbox->barmem = CFG_GET_CTRL_MBOX_MEM_ADDR(oct->conf);
> + ret = octep_ctrl_mbox_init(ctrl_mbox);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to initialize control mbox\n");
> + return ret;
> + }
> + oct->ctrl_mbox_ifstats_offset = ctrl_mbox->barmem_sz;
> +
> + return 0;
> +}
>
> - req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
> - req.link.cmd = OCTEP_CTRL_NET_CMD_SET;
> - req.link.state = (up) ? OCTEP_CTRL_NET_STATE_UP : OCTEP_CTRL_NET_STATE_DOWN;
> +int octep_ctrl_net_get_link_status(struct octep_device *oct, int vfid)
> +{
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
> + int err;
>
> - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_STATE_REQ_SZW;
> - msg.msg = &req;
> - octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
> + init_send_req(&d.msg, (void *)req, state_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
> + req->link.cmd = OCTEP_CTRL_NET_CMD_GET;
> + err = send_mbox_req(oct, &d, true);
> + if (err < 0)
> + return err;
> +
> + return d.data.resp.link.state;
> }
>
> -void octep_set_rx_state(struct octep_device *oct, bool up)
> +int octep_ctrl_net_set_link_status(struct octep_device *oct, int vfid, bool up,
> + bool wait_for_response)
> {
> - struct octep_ctrl_net_h2f_req req = {};
> - struct octep_ctrl_mbox_msg msg = {};
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
>
> - req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_RX_STATE;
> - req.link.cmd = OCTEP_CTRL_NET_CMD_SET;
> - req.link.state = (up) ? OCTEP_CTRL_NET_STATE_UP : OCTEP_CTRL_NET_STATE_DOWN;
> + init_send_req(&d.msg, req, state_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;
> + req->link.cmd = OCTEP_CTRL_NET_CMD_SET;
> + req->link.state = (up) ? OCTEP_CTRL_NET_STATE_UP :
> + OCTEP_CTRL_NET_STATE_DOWN;
>
> - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_STATE_REQ_SZW;
> - msg.msg = &req;
> - octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
> + return send_mbox_req(oct, &d, wait_for_response);
> }
>
> -int octep_get_mac_addr(struct octep_device *oct, u8 *addr)
> +int octep_ctrl_net_set_rx_state(struct octep_device *oct, int vfid, bool up,
> + bool wait_for_response)
> {
> - struct octep_ctrl_net_h2f_req req = {};
> - struct octep_ctrl_net_h2f_resp *resp;
> - struct octep_ctrl_mbox_msg msg = {};
> - int err;
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
> +
> + init_send_req(&d.msg, req, state_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_RX_STATE;
> + req->link.cmd = OCTEP_CTRL_NET_CMD_SET;
> + req->link.state = (up) ? OCTEP_CTRL_NET_STATE_UP :
> + OCTEP_CTRL_NET_STATE_DOWN;
>
> - req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
> - req.link.cmd = OCTEP_CTRL_NET_CMD_GET;
> + return send_mbox_req(oct, &d, wait_for_response);
> +}
> +
> +int octep_ctrl_net_get_mac_addr(struct octep_device *oct, int vfid, u8 *addr)
> +{
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
> + int err;
>
> - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_MAC_REQ_SZW;
> - msg.msg = &req;
> - err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
> - if (err)
> + init_send_req(&d.msg, req, mac_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
> + req->link.cmd = OCTEP_CTRL_NET_CMD_GET;
> + err = send_mbox_req(oct, &d, true);
> + if (err < 0)
> return err;
>
> - resp = (struct octep_ctrl_net_h2f_resp *)&req;
> - memcpy(addr, resp->mac.addr, ETH_ALEN);
> + memcpy(addr, d.data.resp.mac.addr, ETH_ALEN);
>
> - return err;
> + return 0;
> }
>
> -int octep_set_mac_addr(struct octep_device *oct, u8 *addr)
> +int octep_ctrl_net_set_mac_addr(struct octep_device *oct, int vfid, u8 *addr,
> + bool wait_for_response)
> {
> - struct octep_ctrl_net_h2f_req req = {};
> - struct octep_ctrl_mbox_msg msg = {};
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
>
> - req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
> - req.mac.cmd = OCTEP_CTRL_NET_CMD_SET;
> - memcpy(&req.mac.addr, addr, ETH_ALEN);
> + init_send_req(&d.msg, req, mac_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;
> + req->mac.cmd = OCTEP_CTRL_NET_CMD_SET;
> + memcpy(&req->mac.addr, addr, ETH_ALEN);
>
> - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_MAC_REQ_SZW;
> - msg.msg = &req;
> -
> - return octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
> + return send_mbox_req(oct, &d, wait_for_response);
> }
>
> -int octep_set_mtu(struct octep_device *oct, int mtu)
> +int octep_ctrl_net_set_mtu(struct octep_device *oct, int vfid, int mtu,
> + bool wait_for_response)
> {
> - struct octep_ctrl_net_h2f_req req = {};
> - struct octep_ctrl_mbox_msg msg = {};
> -
> - req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_MTU;
> - req.mtu.cmd = OCTEP_CTRL_NET_CMD_SET;
> - req.mtu.val = mtu;
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
>
> - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_MTU_REQ_SZW;
> - msg.msg = &req;
> + init_send_req(&d.msg, req, mtu_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MTU;
> + req->mtu.cmd = OCTEP_CTRL_NET_CMD_SET;
> + req->mtu.val = mtu;
>
> - return octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
> + return send_mbox_req(oct, &d, wait_for_response);
> }
>
> -int octep_get_if_stats(struct octep_device *oct)
> +int octep_ctrl_net_get_if_stats(struct octep_device *oct, int vfid)
> {
> void __iomem *iface_rx_stats;
> void __iomem *iface_tx_stats;
> - struct octep_ctrl_net_h2f_req req = {};
> - struct octep_ctrl_mbox_msg msg = {};
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
> int err;
>
> - req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_IF_STATS;
> - req.mac.cmd = OCTEP_CTRL_NET_CMD_GET;
> - req.get_stats.offset = oct->ctrl_mbox_ifstats_offset;
> -
> - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_GET_STATS_REQ_SZW;
> - msg.msg = &req;
> - err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
> - if (err)
> + init_send_req(&d.msg, req, get_stats_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_IF_STATS;
> + req->get_stats.offset = oct->ctrl_mbox_ifstats_offset;
> + err = send_mbox_req(oct, &d, true);
> + if (err < 0)
> return err;
>
> iface_rx_stats = oct->ctrl_mbox.barmem + oct->ctrl_mbox_ifstats_offset;
> @@ -144,51 +209,115 @@ int octep_get_if_stats(struct octep_device *oct)
> memcpy_fromio(&oct->iface_rx_stats, iface_rx_stats, sizeof(struct octep_iface_rx_stats));
> memcpy_fromio(&oct->iface_tx_stats, iface_tx_stats, sizeof(struct octep_iface_tx_stats));
>
> - return err;
> + return 0;
> }
>
> -int octep_get_link_info(struct octep_device *oct)
> +int octep_ctrl_net_get_link_info(struct octep_device *oct, int vfid)
> {
> - struct octep_ctrl_net_h2f_req req = {};
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
> struct octep_ctrl_net_h2f_resp *resp;
> - struct octep_ctrl_mbox_msg msg = {};
> int err;
>
> - req.hdr.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
> - req.mac.cmd = OCTEP_CTRL_NET_CMD_GET;
> -
> - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;
> - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_LINK_INFO_REQ_SZW;
> - msg.msg = &req;
> - err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg);
> - if (err)
> + init_send_req(&d.msg, req, link_info_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
> + req->link_info.cmd = OCTEP_CTRL_NET_CMD_GET;
> + err = send_mbox_req(oct, &d, true);
> + if (err < 0)
> return err;
>
> - resp = (struct octep_ctrl_net_h2f_resp *)&req;
> + resp = &d.data.resp;
> oct->link_info.supported_modes = resp->link_info.supported_modes;
> oct->link_info.advertised_modes = resp->link_info.advertised_modes;
> oct->link_info.autoneg = resp->link_info.autoneg;
> oct->link_info.pause = resp->link_info.pause;
> oct->link_info.speed = resp->link_info.speed;
>
> - return err;
> + return 0;
> }
>
> -int octep_set_link_info(struct octep_device *oct, struct octep_iface_link_info *link_info)
> +int octep_ctrl_net_set_link_info(struct octep_device *oct, int vfid,
> + struct octep_iface_link_info *link_info,
> + bool wait_for_response)
> {
> - struct octep_ctrl_net_h2f_req req = {};
> - struct octep_ctrl_mbox_msg msg = {};
> + struct octep_ctrl_net_wait_data d = {0};
> + struct octep_ctrl_net_h2f_req *req = &d.data.req;
> +
> + init_send_req(&d.msg, req, link_info_sz, vfid);
> + req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;
> + req->link_info.cmd = OCTEP_CTRL_NET_CMD_SET;
> + req->link_info.info.advertised_modes = link_info->advertised_modes;
> + req->link_info.info.autoneg = link_info->autoneg;
> + req->link_info.info.pause = link_info->pause;
> + req->link_info.info.speed = link_info->speed;
> +
> + return send_mbox_req(oct, &d, wait_for_response);
> +}
> +
> +static int process_mbox_req(struct octep_device *oct,
> + struct octep_ctrl_mbox_msg *msg)
> +{
> + return 0;

? if it's going to be filled on later patch, add it there.

> +}
> +
> +static int process_mbox_resp(struct octep_device *oct,

s/int/void

> + struct octep_ctrl_mbox_msg *msg)
> +{
> + struct octep_ctrl_net_wait_data *pos, *n;
> +
> + list_for_each_entry_safe(pos, n, &oct->ctrl_req_wait_list, list) {
> + if (pos->msg.hdr.s.msg_id == msg->hdr.s.msg_id) {
> + memcpy(&pos->data.resp,
> + msg->sg_list[0].msg,
> + msg->hdr.s.sz);
> + pos->done = 1;
> + wake_up_interruptible_all(&oct->ctrl_req_wait_q);
> + break;
> + }
> + }
> +
> + return 0;
> +}
> +
> +int octep_ctrl_net_recv_fw_messages(struct octep_device *oct)

s/int/void

> +{
> + static u16 msg_sz = sizeof(union octep_ctrl_net_max_data);
> + union octep_ctrl_net_max_data data = {0};
> + struct octep_ctrl_mbox_msg msg = {0};
> + int ret;
> +
> + msg.hdr.s.sz = msg_sz;
> + msg.sg_num = 1;
> + msg.sg_list[0].sz = msg_sz;
> + msg.sg_list[0].msg = &data;
> + while (true) {
> + /* mbox will overwrite msg.hdr.s.sz so initialize it */
> + msg.hdr.s.sz = msg_sz;
> + ret = octep_ctrl_mbox_recv(&oct->ctrl_mbox,
> + (struct octep_ctrl_mbox_msg *)&msg,
> + 1);
> + if (ret <= 0)
> + break;

wouldn't it be better to return error and handle this accordingly on callsite?

> +
> + if (msg.hdr.s.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ)
> + process_mbox_req(oct, &msg);
> + else if (msg.hdr.s.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP)
> + process_mbox_resp(oct, &msg);
> + }
> +
> + return 0;
> +}
> +

(...)

> static const char *octep_devid_to_str(struct octep_device *oct)
> @@ -956,7 +935,6 @@ static const char *octep_devid_to_str(struct octep_device *oct)
> */
> int octep_device_setup(struct octep_device *oct)
> {
> - struct octep_ctrl_mbox *ctrl_mbox;
> struct pci_dev *pdev = oct->pdev;
> int i, ret;
>
> @@ -993,18 +971,9 @@ int octep_device_setup(struct octep_device *oct)
>
> oct->pkind = CFG_GET_IQ_PKIND(oct->conf);
>
> - /* Initialize control mbox */
> - ctrl_mbox = &oct->ctrl_mbox;
> - ctrl_mbox->barmem = CFG_GET_CTRL_MBOX_MEM_ADDR(oct->conf);
> - ret = octep_ctrl_mbox_init(ctrl_mbox);
> - if (ret) {
> - dev_err(&pdev->dev, "Failed to initialize control mbox\n");
> - goto unsupported_dev;
> - }
> - oct->ctrl_mbox_ifstats_offset = OCTEP_CTRL_MBOX_SZ(ctrl_mbox->h2fq.elem_sz,
> - ctrl_mbox->h2fq.elem_cnt,
> - ctrl_mbox->f2hq.elem_sz,
> - ctrl_mbox->f2hq.elem_cnt);
> + ret = octep_ctrl_net_init(oct);
> + if (ret)
> + return ret;

if it's the end of func then you could just

return octep_ctrl_net_init(oct);

>
> return 0;
>
> @@ -1034,7 +1003,7 @@ static void octep_device_cleanup(struct octep_device *oct)
> oct->mbox[i] = NULL;
> }
>
> - octep_ctrl_mbox_uninit(&oct->ctrl_mbox);
> + octep_ctrl_net_uninit(oct);
>
> oct->hw_ops.soft_reset(oct);
> for (i = 0; i < OCTEP_MMIO_REGIONS; i++) {
> @@ -1145,7 +1114,8 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> netdev->max_mtu = OCTEP_MAX_MTU;
> netdev->mtu = OCTEP_DEFAULT_MTU;
>
> - err = octep_get_mac_addr(octep_dev, octep_dev->mac_addr);
> + err = octep_ctrl_net_get_mac_addr(octep_dev, OCTEP_CTRL_NET_INVALID_VFID,
> + octep_dev->mac_addr);
> if (err) {
> dev_err(&pdev->dev, "Failed to get mac address\n");
> goto register_dev_err;
> --
> 2.36.0
>