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

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
Extension
.c
Size
8060 bytes
Lines
280
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

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)
{
	struct octep_ctrl_mbox_msg_buf *sg;
	struct octep_ctrl_mbox_q *q;
	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->sz) < (msg->hdr.s.sz + mbox_hdr_sz)) {
		mutex_unlock(&mbox->h2fq_lock);
		return -EAGAIN;
	}

	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);

	return 0;
}

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

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;
	int s;

	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);

Annotation

Implementation Notes