Commit 577f0d1b authored by Veerasenareddy Burru's avatar Veerasenareddy Burru Committed by David S. Miller
Browse files

octeon_ep: add separate mailbox command and response queues



Enhance control mailbox protocol to support following
 - separate command and response queues
    * command queue to send control commands to firmware.
    * response queue to receive responses and notifications from
      firmware.
 - variable size messages using scatter/gather

Signed-off-by: default avatarAbhijit Ayarekar <aayarekar@marvell.com>
Signed-off-by: default avatarVeerasenareddy Burru <vburru@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c05d3d0
Loading
Loading
Loading
Loading
+150 −126
Original line number Diff line number Diff line
@@ -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) + \
/* 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_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_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)

#define OCTEP_CTRL_MBOX_Q_OFFSET(m, i)			((m) + \
							 (sizeof(struct octep_ctrl_mbox_msg) * (i)))
static const u32 mbox_hdr_sz = sizeof(union octep_ctrl_mbox_msg_hdr);

static u32 octep_ctrl_mbox_circq_inc(u32 index, u32 mask)
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,153 +81,170 @@ 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);
		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;
}

static void
octep_write_mbox_data(struct octep_ctrl_mbox_q *q, u32 *pi, u32 ci, void *buf, u32 w_sz)
{
	u8 __iomem *qbuf;
	u32 cp_sz;

	/* 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);
		}
	}
}

int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg)
{
	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_q *q;
	unsigned long expire;
	u64 *mbuf, *word0;
	u8 __iomem *qidx;
	u16 pi, ci;
	int i;
	u32 pi, ci, buf_sz, w_sz;
	int s;

	if (!mbox || !msg)
		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);

	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);
	if (octep_ctrl_mbox_circq_space(pi, ci, q->sz) < (msg->hdr.s.sz + mbox_hdr_sz)) {
		mutex_unlock(&mbox->f2hq_lock);
		return -EAGAIN;
	}

	pi = octep_ctrl_mbox_circq_inc(pi, q->mask);
	octep_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;
		octep_write_mbox_data(q, &pi, ci, sg->msg, w_sz);
		buf_sz -= w_sz;
	}
	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;
}

	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 void
octep_read_mbox_data(struct octep_ctrl_mbox_q *q, u32 pi, u32 *ci, void *buf, u32 r_sz)
{
	u8 __iomem *qbuf;
	u32 cp_sz;

	/* 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)
{
	struct octep_ctrl_mbox_msg_buf *sg;
	u32 pi, ci, r_sz, buf_sz, q_depth;
	struct octep_ctrl_mbox_q *q;
	u32 count, pi, ci;
	u8 __iomem *qidx;
	u64 *mbuf;
	int i;
	int s;

	if (!mbox || !msg)
		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);

	msg->hdr.word0 = readq(qidx);
	for (i = 1; i <= msg->hdr.sizew; i++)
		*mbuf++ = readq(qidx + (i * 8));
	q_depth = octep_ctrl_mbox_circq_depth(pi, ci, q->sz);
	if (q_depth < mbox_hdr_sz) {
		mutex_unlock(&mbox->f2hq_lock);
		return -EAGAIN;
	}

	ci = octep_ctrl_mbox_circq_inc(ci, q->mask);
	octep_read_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];
		r_sz = (sg->sz <= buf_sz) ? sg->sz : buf_sz;
		octep_read_mbox_data(q, pi, &ci, sg->msg, r_sz);
		buf_sz -= r_sz;
	}
	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;
}

@@ -227,18 +252,17 @@ 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;
+46 −42
Original line number Diff line number Diff line
@@ -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,6 +146,8 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox);
/* Send mbox message.
 *
 * @param mbox: non-null pointer to struct octep_ctrl_mbox.
 * @param msg:  non-null pointer to struct octep_ctrl_mbox_msg.
 *              Caller should fill msg.sz and msg.desc.sz for each message.
 *
 * return value: 0 on success, -errno on failure.
 */
@@ -154,6 +156,8 @@ int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_ms
/* Retrieve mbox message.
 *
 * @param mbox: non-null pointer to struct octep_ctrl_mbox.
 * @param msg:  non-null pointer to struct octep_ctrl_mbox_msg.
 *              Caller should fill msg.sz and msg.desc.sz for each message.
 *
 * return value: 0 on success, -errno on failure.
 */
@@ -161,7 +165,7 @@ int octep_ctrl_mbox_recv(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_ms

/* 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.
 */
+220 −110

File changed.

Preview size limit exceeded, changes collapsed.

+92 −72
Original line number Diff line number Diff line
@@ -45,7 +45,9 @@ enum octep_ctrl_net_f2h_cmd {
	OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS,
};

struct octep_ctrl_net_req_hdr {
union octep_ctrl_net_req_hdr {
	u64 words[1];
	struct {
		/* sender id */
		u16 sender;
		/* receiver id */
@@ -54,6 +56,7 @@ struct octep_ctrl_net_req_hdr {
		u16 cmd;
		/* reserved */
		u16 rsvd0;
	} s;
};

/* get/set mtu request */
@@ -110,7 +113,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,7 +124,9 @@ struct octep_ctrl_net_h2f_req {
	};
} __packed;

struct octep_ctrl_net_resp_hdr {
union octep_ctrl_net_resp_hdr {
	u64 words[1];
	struct {
		/* sender id */
		u16 sender;
		/* receiver id */
@@ -130,6 +135,7 @@ struct octep_ctrl_net_resp_hdr {
		u16 cmd;
		/* octep_ctrl_net_reply */
		u16 reply;
	} s;
};

/* get mtu response */
@@ -152,7 +158,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 +176,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,56 +184,34 @@ 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.
 *
@@ -235,21 +219,29 @@ union octep_ctrl_net_f2h_data_sz {
 *
 * 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);

/** Set link status in firmware.
 *
 * @param oct: non-null pointer to struct octep_device.
 * @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, bool up,
				   bool wait_for_response);

/** Set rx state in firmware.
 *
 * @param oct: non-null pointer to struct octep_device.
 * @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, bool up,
				bool wait_for_response);

/** Get mac address from firmware.
 *
@@ -258,21 +250,29 @@ void octep_set_rx_state(struct octep_device *oct, bool up);
 *
 * 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, u8 *addr);

/** Set mac address in firmware.
 *
 * @param oct: non-null pointer to struct octep_device.
 * @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, u8 *addr,
				bool wait_for_response);

/** Set mtu in firmware.
 *
 * @param oct: non-null pointer to struct octep_device.
 * @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 mtu,
			   bool wait_for_response);

/** Get interface statistics from firmware.
 *
@@ -280,7 +280,7 @@ int octep_set_mtu(struct octep_device *oct, int mtu);
 *
 * 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);

/** Get link info from firmware.
 *
@@ -288,12 +288,32 @@ int octep_get_if_stats(struct octep_device *oct);
 *
 * 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);

/** Set link info in firmware.
 *
 * @param oct: non-null pointer to struct octep_device.
 * @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,
				 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.
 */
void 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__ */
+3 −3
Original line number Diff line number Diff line
@@ -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);
	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);

	advertised_modes = oct->link_info.advertised_modes;
	supported_modes = oct->link_info.supported_modes;
@@ -439,7 +439,7 @@ 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, &link_info_new, true);
	if (err)
		return err;

Loading