Message ID | 20230214051422.13705-5-vburru@marvell.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | octeon_ep: deferred probe and mailbox | expand |
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@marvell.com> > Signed-off-by: Veerasenareddy Burru <vburru@marvell.com> > --- > 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 >
> -----Original Message----- > From: Maciej Fijalkowski <maciej.fijalkowski@intel.com> > Sent: Wednesday, February 15, 2023 7:55 AM > To: Veerasenareddy Burru <vburru@marvell.com> > Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Abhijit Ayarekar > <aayarekar@marvell.com>; Sathesh B Edara <sedara@marvell.com>; > Satananda Burla <sburla@marvell.com>; linux-doc@vger.kernel.org; David S. > Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; > Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com> > Subject: [EXT] Re: [PATCH net-next v3 4/7] octeon_ep: enhance control > mailbox for VF support > > External Email > > ---------------------------------------------------------------------- > 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@marvell.com> > > Signed-off-by: Veerasenareddy Burru <vburru@marvell.com> > > --- > > 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? > Will separate out the changes to the APIs to accept function ID > > > > 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. > OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET is renamed to OCTEP_CTRL_MBOX_INFO_MAGIC_NUM. > > +#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 ? Will rename in next revision. > > also, you only return 0 and don't check the retval, so s/static int/static void > Ack. Will make this change in next revision. > > +{ > > + 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? > Will remove this argument in next revision. Will bring it back when we have actual use case. > > { > > - 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 > Sorry for missing on this. Will fix RCT violations in next revision. > > + 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 > Ack > > +} > > > > - 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 > Will fix in next revision > > + 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 > Ack > > } > > > > 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_ ? > we should have had octep_ prefix. Will add in next revision. > > + 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. > Sure, will remove it in next revision. > > +} > > + > > +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 > will update in the next revision > > +{ > > + 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); > Agree; will fix in next revision. Thank you for the kind review comments and suggestions. > > > > 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 > >
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) +#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; } -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); 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) +{ + 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) { - 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; + 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; +} - 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, + 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; } 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; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h index 2dc5753cfec6..6ee0345d4436 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h @@ -27,50 +27,39 @@ * |-------------------------------------------| * |producer index (4 bytes) | * |consumer index (4 bytes) | - * |element size (4 bytes) | - * |element count (4 bytes) | + * |max element size (4 bytes) | + * |reserved (4 bytes) | * |===========================================| * |Fw to Host Queue info (16 bytes) | * |-------------------------------------------| * |producer index (4 bytes) | * |consumer index (4 bytes) | - * |element size (4 bytes) | - * |element count (4 bytes) | + * |max element size (4 bytes) | + * |reserved (4 bytes) | * |===========================================| - * |Host to Fw Queue | + * |Host to Fw Queue ((total size-288/2) bytes)| * |-------------------------------------------| - * |((elem_sz + hdr(8 bytes)) * elem_cnt) bytes| + * | | * |===========================================| * |===========================================| - * |Fw to Host Queue | + * |Fw to Host Queue ((total size-288/2) bytes)| * |-------------------------------------------| - * |((elem_sz + hdr(8 bytes)) * elem_cnt) bytes| + * | | * |===========================================| */ #define OCTEP_CTRL_MBOX_MAGIC_NUMBER 0xdeaddeadbeefbeefull -/* Size of mbox info in bytes */ -#define OCTEP_CTRL_MBOX_INFO_SZ 256 -/* Size of mbox host to target queue info in bytes */ -#define OCTEP_CTRL_MBOX_H2FQ_INFO_SZ 16 -/* Size of mbox target to host queue info in bytes */ -#define OCTEP_CTRL_MBOX_F2HQ_INFO_SZ 16 -/* Size of mbox queue in bytes */ -#define OCTEP_CTRL_MBOX_Q_SZ(sz, cnt) (((sz) + 8) * (cnt)) -/* Size of mbox in bytes */ -#define OCTEP_CTRL_MBOX_SZ(hsz, hcnt, fsz, fcnt) (OCTEP_CTRL_MBOX_INFO_SZ + \ - OCTEP_CTRL_MBOX_H2FQ_INFO_SZ + \ - OCTEP_CTRL_MBOX_F2HQ_INFO_SZ + \ - OCTEP_CTRL_MBOX_Q_SZ(hsz, hcnt) + \ - OCTEP_CTRL_MBOX_Q_SZ(fsz, fcnt)) - /* Valid request message */ #define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ BIT(0) /* Valid response message */ #define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP BIT(1) /* Valid notification, no response required */ #define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY BIT(2) +/* Valid custom message */ +#define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_CUSTOM BIT(3) + +#define OCTEP_CTRL_MBOX_MSG_DESC_MAX 4 enum octep_ctrl_mbox_status { OCTEP_CTRL_MBOX_STATUS_INVALID = 0, @@ -81,31 +70,48 @@ enum octep_ctrl_mbox_status { /* mbox message */ union octep_ctrl_mbox_msg_hdr { - u64 word0; + u64 words[2]; struct { + /* must be 0 */ + u16 reserved1:15; + /* vf_idx is valid if 1 */ + u16 is_vf:1; + /* sender vf index 0-(n-1), 0 if (is_vf==0) */ + u16 vf_idx; + /* total size of message excluding header */ + u32 sz; /* OCTEP_CTRL_MBOX_MSG_HDR_FLAG_* */ u32 flags; - /* size of message in words excluding header */ - u32 sizew; - }; + /* identifier to match responses */ + u16 msg_id; + u16 reserved2; + } s; +}; + +/* mbox message buffer */ +struct octep_ctrl_mbox_msg_buf { + u32 reserved1; + u16 reserved2; + /* size of buffer */ + u16 sz; + /* pointer to message buffer */ + void *msg; }; /* mbox message */ struct octep_ctrl_mbox_msg { /* mbox transaction header */ union octep_ctrl_mbox_msg_hdr hdr; - /* pointer to message buffer */ - void *msg; + /* number of sg buffer's */ + int sg_num; + /* message buffer's */ + struct octep_ctrl_mbox_msg_buf sg_list[OCTEP_CTRL_MBOX_MSG_DESC_MAX]; }; /* Mbox queue */ struct octep_ctrl_mbox_q { - /* q element size, should be aligned to unsigned long */ - u16 elem_sz; - /* q element count, should be power of 2 */ - u16 elem_cnt; - /* q mask */ - u16 mask; + /* size of queue buffer */ + u32 sz; /* producer address in bar mem */ u8 __iomem *hw_prod; /* consumer address in bar mem */ @@ -115,16 +121,10 @@ struct octep_ctrl_mbox_q { }; struct octep_ctrl_mbox { - /* host driver version */ - u64 version; /* size of bar memory */ u32 barmem_sz; /* pointer to BAR memory */ u8 __iomem *barmem; - /* user context for callback, can be null */ - void *user_ctx; - /* callback handler for processing request, called from octep_ctrl_mbox_recv */ - int (*process_req)(void *user_ctx, struct octep_ctrl_mbox_msg *msg); /* host-to-fw queue */ struct octep_ctrl_mbox_q h2fq; /* fw-to-host queue */ @@ -146,22 +146,32 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox); /* Send mbox message. * * @param mbox: non-null pointer to struct octep_ctrl_mbox. + * @param msgs: Array of non-null pointers to struct octep_ctrl_mbox_msg. + * Caller should fill msg.sz and msg.desc.sz for each message. + * @param num: Size of msg array. * - * return value: 0 on success, -errno on failure. + * return value: number of messages sent on success, -errno on failure. */ -int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg); +int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, + struct octep_ctrl_mbox_msg *msgs, + int num); /* Retrieve mbox message. * * @param mbox: non-null pointer to struct octep_ctrl_mbox. + * @param msgs: Array of non-null pointers to struct octep_ctrl_mbox_msg. + * Caller should fill msg.sz and msg.desc.sz for each message. + * @param num: Size of msg array. * - * return value: 0 on success, -errno on failure. + * return value: number of messages received on success, -errno on failure. */ -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); /* Uninitialize control mbox. * - * @param ep: non-null pointer to struct octep_ctrl_mbox. + * @param mbox: non-null pointer to struct octep_ctrl_mbox. * * return value: 0 on success, -errno on failure. */ diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c index 7c00c896ab98..715af1891d0d 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c @@ -8,134 +8,199 @@ #include <linux/types.h> #include <linux/etherdevice.h> #include <linux/pci.h> +#include <linux/wait.h> #include "octep_config.h" #include "octep_main.h" #include "octep_ctrl_net.h" -int octep_get_link_status(struct octep_device *oct) +static const u32 req_hdr_sz = sizeof(union octep_ctrl_net_req_hdr); +static const u32 mtu_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mtu); +static const u32 mac_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mac); +static const u32 state_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_state); +static const u32 link_info_sz = sizeof(struct octep_ctrl_net_link_info); +static const u32 get_stats_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_get_stats); +static atomic_t ctrl_net_msg_id; + +static void init_send_req(struct octep_ctrl_mbox_msg *msg, void *buf, + u16 sz, int vfid) { - 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, + 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; +} + +static int process_mbox_resp(struct octep_device *oct, + 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) +{ + 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; + + 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; +} + +int octep_ctrl_net_uninit(struct octep_device *oct) +{ + struct octep_ctrl_net_wait_data *pos, *n; + + list_for_each_entry_safe(pos, n, &oct->ctrl_req_wait_list, list) + pos->done = 1; - req.hdr.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; + wake_up_interruptible_all(&oct->ctrl_req_wait_q); - msg.hdr.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ; - msg.hdr.sizew = OCTEP_CTRL_NET_H2F_LINK_INFO_REQ_SZW; - msg.msg = &req; + octep_ctrl_mbox_uninit(&oct->ctrl_mbox); - return octep_ctrl_mbox_send(&oct->ctrl_mbox, &msg); + return 0; } diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h index f23b58381322..c68cdaa1738b 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h @@ -7,6 +7,8 @@ #ifndef __OCTEP_CTRL_NET_H__ #define __OCTEP_CTRL_NET_H__ +#define OCTEP_CTRL_NET_INVALID_VFID (-1) + /* Supported commands */ enum octep_ctrl_net_cmd { OCTEP_CTRL_NET_CMD_GET = 0, @@ -45,15 +47,18 @@ enum octep_ctrl_net_f2h_cmd { OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS, }; -struct octep_ctrl_net_req_hdr { - /* sender id */ - u16 sender; - /* receiver id */ - u16 receiver; - /* octep_ctrl_net_h2t_cmd */ - u16 cmd; - /* reserved */ - u16 rsvd0; +union octep_ctrl_net_req_hdr { + u64 words[1]; + struct { + /* sender id */ + u16 sender; + /* receiver id */ + u16 receiver; + /* octep_ctrl_net_h2t_cmd */ + u16 cmd; + /* reserved */ + u16 rsvd0; + } s; }; /* get/set mtu request */ @@ -110,7 +115,7 @@ struct octep_ctrl_net_h2f_req_cmd_link_info { /* Host to fw request data */ struct octep_ctrl_net_h2f_req { - struct octep_ctrl_net_req_hdr hdr; + union octep_ctrl_net_req_hdr hdr; union { struct octep_ctrl_net_h2f_req_cmd_mtu mtu; struct octep_ctrl_net_h2f_req_cmd_mac mac; @@ -121,15 +126,18 @@ struct octep_ctrl_net_h2f_req { }; } __packed; -struct octep_ctrl_net_resp_hdr { - /* sender id */ - u16 sender; - /* receiver id */ - u16 receiver; - /* octep_ctrl_net_h2t_cmd */ - u16 cmd; - /* octep_ctrl_net_reply */ - u16 reply; +union octep_ctrl_net_resp_hdr { + u64 words[1]; + struct { + /* sender id */ + u16 sender; + /* receiver id */ + u16 receiver; + /* octep_ctrl_net_h2t_cmd */ + u16 cmd; + /* octep_ctrl_net_reply */ + u16 reply; + } s; }; /* get mtu response */ @@ -152,7 +160,7 @@ struct octep_ctrl_net_h2f_resp_cmd_state { /* Host to fw response data */ struct octep_ctrl_net_h2f_resp { - struct octep_ctrl_net_resp_hdr hdr; + union octep_ctrl_net_resp_hdr hdr; union { struct octep_ctrl_net_h2f_resp_cmd_mtu mtu; struct octep_ctrl_net_h2f_resp_cmd_mac mac; @@ -170,7 +178,7 @@ struct octep_ctrl_net_f2h_req_cmd_state { /* Fw to host request data */ struct octep_ctrl_net_f2h_req { - struct octep_ctrl_net_req_hdr hdr; + union octep_ctrl_net_req_hdr hdr; union { struct octep_ctrl_net_f2h_req_cmd_state link; }; @@ -178,122 +186,146 @@ struct octep_ctrl_net_f2h_req { /* Fw to host response data */ struct octep_ctrl_net_f2h_resp { - struct octep_ctrl_net_resp_hdr hdr; + union octep_ctrl_net_resp_hdr hdr; }; -/* Size of host to fw octep_ctrl_mbox queue element */ -union octep_ctrl_net_h2f_data_sz { +/* Max data size to be transferred over mbox */ +union octep_ctrl_net_max_data { struct octep_ctrl_net_h2f_req h2f_req; struct octep_ctrl_net_h2f_resp h2f_resp; -}; - -/* Size of fw to host octep_ctrl_mbox queue element */ -union octep_ctrl_net_f2h_data_sz { struct octep_ctrl_net_f2h_req f2h_req; struct octep_ctrl_net_f2h_resp f2h_resp; }; -/* size of host to fw data in words */ -#define OCTEP_CTRL_NET_H2F_DATA_SZW ((sizeof(union octep_ctrl_net_h2f_data_sz)) / \ - (sizeof(unsigned long))) - -/* size of fw to host data in words */ -#define OCTEP_CTRL_NET_F2H_DATA_SZW ((sizeof(union octep_ctrl_net_f2h_data_sz)) / \ - (sizeof(unsigned long))) - -/* size in words of get/set mtu request */ -#define OCTEP_CTRL_NET_H2F_MTU_REQ_SZW 2 -/* size in words of get/set mac request */ -#define OCTEP_CTRL_NET_H2F_MAC_REQ_SZW 2 -/* size in words of get stats request */ -#define OCTEP_CTRL_NET_H2F_GET_STATS_REQ_SZW 2 -/* size in words of get/set state request */ -#define OCTEP_CTRL_NET_H2F_STATE_REQ_SZW 2 -/* size in words of get/set link info request */ -#define OCTEP_CTRL_NET_H2F_LINK_INFO_REQ_SZW 4 - -/* size in words of get mtu response */ -#define OCTEP_CTRL_NET_H2F_GET_MTU_RESP_SZW 2 -/* size in words of set mtu response */ -#define OCTEP_CTRL_NET_H2F_SET_MTU_RESP_SZW 1 -/* size in words of get mac response */ -#define OCTEP_CTRL_NET_H2F_GET_MAC_RESP_SZW 2 -/* size in words of set mac response */ -#define OCTEP_CTRL_NET_H2F_SET_MAC_RESP_SZW 1 -/* size in words of get state request */ -#define OCTEP_CTRL_NET_H2F_GET_STATE_RESP_SZW 2 -/* size in words of set state request */ -#define OCTEP_CTRL_NET_H2F_SET_STATE_RESP_SZW 1 -/* size in words of get link info request */ -#define OCTEP_CTRL_NET_H2F_GET_LINK_INFO_RESP_SZW 4 -/* size in words of set link info request */ -#define OCTEP_CTRL_NET_H2F_SET_LINK_INFO_RESP_SZW 1 +struct octep_ctrl_net_wait_data { + struct list_head list; + int done; + struct octep_ctrl_mbox_msg msg; + union { + struct octep_ctrl_net_h2f_req req; + struct octep_ctrl_net_h2f_resp resp; + } data; +}; + +/** Initialize data for ctrl net. + * + * @param oct: non-null pointer to struct octep_device. + * + * return value: 0 on success, -errno on error. + */ +int octep_ctrl_net_init(struct octep_device *oct); /** Get link status from firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. * * return value: link status 0=down, 1=up. */ -int octep_get_link_status(struct octep_device *oct); +int octep_ctrl_net_get_link_status(struct octep_device *oct, int vfid); /** Set link status in firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. * @param up: boolean status. + * @param wait_for_response: poll for response. + * + * return value: 0 on success, -errno on failure */ -void octep_set_link_status(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); /** Set rx state in firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. * @param up: boolean status. + * @param wait_for_response: poll for response. + * + * return value: 0 on success, -errno on failure. */ -void octep_set_rx_state(struct octep_device *oct, bool up); +int octep_ctrl_net_set_rx_state(struct octep_device *oct, int vfid, bool up, + bool wait_for_response); /** Get mac address from firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. * @param addr: non-null pointer to mac address. * * return value: 0 on success, -errno on failure. */ -int octep_get_mac_addr(struct octep_device *oct, u8 *addr); +int octep_ctrl_net_get_mac_addr(struct octep_device *oct, int vfid, u8 *addr); /** Set mac address in firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. * @param addr: non-null pointer to mac address. + * @param wait_for_response: poll for response. + * + * return value: 0 on success, -errno on failure. */ -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); /** Set mtu in firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. * @param mtu: mtu. + * @param wait_for_response: poll for response. + * + * return value: 0 on success, -errno on failure. */ -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); /** Get interface statistics from firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. * * return value: 0 on success, -errno on failure. */ -int octep_get_if_stats(struct octep_device *oct); +int octep_ctrl_net_get_if_stats(struct octep_device *oct, int vfid); /** Get link info from firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. * * return value: 0 on success, -errno on failure. */ -int octep_get_link_info(struct octep_device *oct); +int octep_ctrl_net_get_link_info(struct octep_device *oct, int vfid); /** Set link info in firmware. * * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. + * @param link_info: non-null pointer to struct octep_iface_link_info. + * @param wait_for_response: poll for response. + * + * return value: 0 on success, -errno on failure. + */ +int octep_ctrl_net_set_link_info(struct octep_device *oct, + int vfid, + struct octep_iface_link_info *link_info, + bool wait_for_response); + +/** Poll for firmware messages and process them. + * + * @param oct: non-null pointer to struct octep_device. + */ +int octep_ctrl_net_recv_fw_messages(struct octep_device *oct); + +/** Uninitialize data for ctrl net. + * + * @param oct: non-null pointer to struct octep_device. + * + * return value: 0 on success, -errno on error. */ -int octep_set_link_info(struct octep_device *oct, struct octep_iface_link_info *link_info); +int octep_ctrl_net_uninit(struct octep_device *oct); #endif /* __OCTEP_CTRL_NET_H__ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c index 87ef129b269a..389042b57787 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c @@ -150,7 +150,7 @@ octep_get_ethtool_stats(struct net_device *netdev, rx_packets = 0; rx_bytes = 0; - octep_get_if_stats(oct); + octep_ctrl_net_get_if_stats(oct, OCTEP_CTRL_NET_INVALID_VFID); iface_tx_stats = &oct->iface_tx_stats; iface_rx_stats = &oct->iface_rx_stats; @@ -283,7 +283,7 @@ static int octep_get_link_ksettings(struct net_device *netdev, ethtool_link_ksettings_zero_link_mode(cmd, supported); ethtool_link_ksettings_zero_link_mode(cmd, advertising); - octep_get_link_info(oct); + octep_ctrl_net_get_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID); advertised_modes = oct->link_info.advertised_modes; supported_modes = oct->link_info.supported_modes; @@ -439,7 +439,8 @@ static int octep_set_link_ksettings(struct net_device *netdev, link_info_new.speed = cmd->base.speed; link_info_new.autoneg = autoneg; - err = octep_set_link_info(oct, &link_info_new); + err = octep_ctrl_net_set_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID, + &link_info_new, true); if (err) return err; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c index 565a383f0c68..e3c7932b85ca 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c @@ -508,11 +508,10 @@ static int octep_open(struct net_device *netdev) octep_napi_enable(oct); oct->link_info.admin_up = 1; - octep_set_rx_state(oct, true); - - ret = octep_get_link_status(oct); - if (!ret) - octep_set_link_status(oct, true); + octep_ctrl_net_set_rx_state(oct, OCTEP_CTRL_NET_INVALID_VFID, true, + false); + octep_ctrl_net_set_link_status(oct, OCTEP_CTRL_NET_INVALID_VFID, true, + false); oct->poll_non_ioq_intr = false; /* Enable the input and output queues for this Octeon device */ @@ -523,7 +522,7 @@ static int octep_open(struct net_device *netdev) octep_oq_dbell_init(oct); - ret = octep_get_link_status(oct); + ret = octep_ctrl_net_get_link_status(oct, OCTEP_CTRL_NET_INVALID_VFID); if (ret > 0) octep_link_up(netdev); @@ -553,14 +552,16 @@ static int octep_stop(struct net_device *netdev) netdev_info(netdev, "Stopping the device ...\n"); + octep_ctrl_net_set_link_status(oct, OCTEP_CTRL_NET_INVALID_VFID, false, + false); + octep_ctrl_net_set_rx_state(oct, OCTEP_CTRL_NET_INVALID_VFID, false, + false); + /* Stop Tx from stack */ netif_tx_stop_all_queues(netdev); netif_carrier_off(netdev); netif_tx_disable(netdev); - octep_set_link_status(oct, false); - octep_set_rx_state(oct, false); - oct->link_info.admin_up = 0; oct->link_info.oper_up = 0; @@ -762,7 +763,9 @@ static void octep_get_stats64(struct net_device *netdev, struct octep_device *oct = netdev_priv(netdev); int q; - octep_get_if_stats(oct); + if (netif_running(netdev)) + octep_ctrl_net_get_if_stats(oct, OCTEP_CTRL_NET_INVALID_VFID); + tx_packets = 0; tx_bytes = 0; rx_packets = 0; @@ -833,7 +836,8 @@ static int octep_set_mac(struct net_device *netdev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - err = octep_set_mac_addr(oct, addr->sa_data); + err = octep_ctrl_net_set_mac_addr(oct, OCTEP_CTRL_NET_INVALID_VFID, + addr->sa_data, true); if (err) return err; @@ -853,7 +857,8 @@ static int octep_change_mtu(struct net_device *netdev, int new_mtu) if (link_info->mtu == new_mtu) return 0; - err = octep_set_mtu(oct, new_mtu); + err = octep_ctrl_net_set_mtu(oct, OCTEP_CTRL_NET_INVALID_VFID, new_mtu, + true); if (!err) { oct->link_info.mtu = new_mtu; netdev->mtu = new_mtu; @@ -905,34 +910,8 @@ static void octep_ctrl_mbox_task(struct work_struct *work) { struct octep_device *oct = container_of(work, struct octep_device, ctrl_mbox_task); - struct net_device *netdev = oct->netdev; - struct octep_ctrl_net_f2h_req req = {}; - struct octep_ctrl_mbox_msg msg; - int ret = 0; - - msg.msg = &req; - while (true) { - ret = octep_ctrl_mbox_recv(&oct->ctrl_mbox, &msg); - if (ret) - break; - - switch (req.hdr.cmd) { - case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS: - if (netif_running(netdev)) { - if (req.link.state) { - dev_info(&oct->pdev->dev, "netif_carrier_on\n"); - netif_carrier_on(netdev); - } else { - dev_info(&oct->pdev->dev, "netif_carrier_off\n"); - netif_carrier_off(netdev); - } - } - break; - default: - pr_info("Unknown mbox req : %u\n", req.hdr.cmd); - break; - } - } + + octep_ctrl_net_recv_fw_messages(oct); } 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; 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;