brintos

brintos / linux-shallow public Read only

0
0
Text · 4.8 KiB · 0bc595a Raw
207 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.4 * Copyright 2007 Nuova Systems, Inc.  All rights reserved.5 */6 7#ifndef _VNIC_RQ_H_8#define _VNIC_RQ_H_9 10#include <linux/pci.h>11#include <linux/netdevice.h>12 13#include "vnic_dev.h"14#include "vnic_cq.h"15 16/* Receive queue control */17struct vnic_rq_ctrl {18	u64 ring_base;			/* 0x00 */19	u32 ring_size;			/* 0x08 */20	u32 pad0;21	u32 posted_index;		/* 0x10 */22	u32 pad1;23	u32 cq_index;			/* 0x18 */24	u32 pad2;25	u32 enable;			/* 0x20 */26	u32 pad3;27	u32 running;			/* 0x28 */28	u32 pad4;29	u32 fetch_index;		/* 0x30 */30	u32 pad5;31	u32 error_interrupt_enable;	/* 0x38 */32	u32 pad6;33	u32 error_interrupt_offset;	/* 0x40 */34	u32 pad7;35	u32 error_status;		/* 0x48 */36	u32 pad8;37	u32 dropped_packet_count;	/* 0x50 */38	u32 pad9;39	u32 dropped_packet_count_rc;	/* 0x58 */40	u32 pad10;41};42 43/* Break the vnic_rq_buf allocations into blocks of 32/64 entries */44#define VNIC_RQ_BUF_MIN_BLK_ENTRIES 3245#define VNIC_RQ_BUF_DFLT_BLK_ENTRIES 6446#define VNIC_RQ_BUF_BLK_ENTRIES(entries) \47	((unsigned int)((entries < VNIC_RQ_BUF_DFLT_BLK_ENTRIES) ? \48	VNIC_RQ_BUF_MIN_BLK_ENTRIES : VNIC_RQ_BUF_DFLT_BLK_ENTRIES))49#define VNIC_RQ_BUF_BLK_SZ(entries) \50	(VNIC_RQ_BUF_BLK_ENTRIES(entries) * sizeof(struct vnic_rq_buf))51#define VNIC_RQ_BUF_BLKS_NEEDED(entries) \52	DIV_ROUND_UP(entries, VNIC_RQ_BUF_BLK_ENTRIES(entries))53#define VNIC_RQ_BUF_BLKS_MAX VNIC_RQ_BUF_BLKS_NEEDED(4096)54 55struct vnic_rq_buf {56	struct vnic_rq_buf *next;57	dma_addr_t dma_addr;58	void *os_buf;59	unsigned int os_buf_index;60	unsigned int len;61	unsigned int index;62	void *desc;63	uint64_t wr_id;64};65 66enum enic_poll_state {67	ENIC_POLL_STATE_IDLE,68	ENIC_POLL_STATE_NAPI,69	ENIC_POLL_STATE_POLL70};71 72struct vnic_rq {73	unsigned int index;74	struct vnic_dev *vdev;75	struct vnic_rq_ctrl __iomem *ctrl;              /* memory-mapped */76	struct vnic_dev_ring ring;77	struct vnic_rq_buf *bufs[VNIC_RQ_BUF_BLKS_MAX];78	struct vnic_rq_buf *to_use;79	struct vnic_rq_buf *to_clean;80	void *os_buf_head;81	unsigned int pkts_outstanding;82};83 84static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq)85{86	/* how many does SW own? */87	return rq->ring.desc_avail;88}89 90static inline unsigned int vnic_rq_desc_used(struct vnic_rq *rq)91{92	/* how many does HW own? */93	return rq->ring.desc_count - rq->ring.desc_avail - 1;94}95 96static inline void *vnic_rq_next_desc(struct vnic_rq *rq)97{98	return rq->to_use->desc;99}100 101static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)102{103	return rq->to_use->index;104}105 106static inline void vnic_rq_post(struct vnic_rq *rq,107	void *os_buf, unsigned int os_buf_index,108	dma_addr_t dma_addr, unsigned int len,109	uint64_t wrid)110{111	struct vnic_rq_buf *buf = rq->to_use;112 113	buf->os_buf = os_buf;114	buf->os_buf_index = os_buf_index;115	buf->dma_addr = dma_addr;116	buf->len = len;117	buf->wr_id = wrid;118 119	buf = buf->next;120	rq->to_use = buf;121	rq->ring.desc_avail--;122 123	/* Move the posted_index every nth descriptor124	 */125 126#ifndef VNIC_RQ_RETURN_RATE127#define VNIC_RQ_RETURN_RATE		0xf	/* keep 2^n - 1 */128#endif129 130	if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) {131		/* Adding write memory barrier prevents compiler and/or CPU132		 * reordering, thus avoiding descriptor posting before133		 * descriptor is initialized. Otherwise, hardware can read134		 * stale descriptor fields.135		 */136		wmb();137		iowrite32(buf->index, &rq->ctrl->posted_index);138	}139}140 141static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)142{143	rq->ring.desc_avail += count;144}145 146enum desc_return_options {147	VNIC_RQ_RETURN_DESC,148	VNIC_RQ_DEFER_RETURN_DESC,149};150 151static inline void vnic_rq_service(struct vnic_rq *rq,152	struct cq_desc *cq_desc, u16 completed_index,153	int desc_return, void (*buf_service)(struct vnic_rq *rq,154	struct cq_desc *cq_desc, struct vnic_rq_buf *buf,155	int skipped, void *opaque), void *opaque)156{157	struct vnic_rq_buf *buf;158	int skipped;159 160	buf = rq->to_clean;161	while (1) {162 163		skipped = (buf->index != completed_index);164 165		(*buf_service)(rq, cq_desc, buf, skipped, opaque);166 167		if (desc_return == VNIC_RQ_RETURN_DESC)168			rq->ring.desc_avail++;169 170		rq->to_clean = buf->next;171 172		if (!skipped)173			break;174 175		buf = rq->to_clean;176	}177}178 179static inline int vnic_rq_fill(struct vnic_rq *rq,180	int (*buf_fill)(struct vnic_rq *rq))181{182	int err;183 184	while (vnic_rq_desc_avail(rq) > 0) {185 186		err = (*buf_fill)(rq);187		if (err)188			return err;189	}190 191	return 0;192}193 194void vnic_rq_free(struct vnic_rq *rq);195int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,196	unsigned int desc_count, unsigned int desc_size);197void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,198	unsigned int error_interrupt_enable,199	unsigned int error_interrupt_offset);200unsigned int vnic_rq_error_status(struct vnic_rq *rq);201void vnic_rq_enable(struct vnic_rq *rq);202int vnic_rq_disable(struct vnic_rq *rq);203void vnic_rq_clean(struct vnic_rq *rq,204	void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf));205 206#endif /* _VNIC_RQ_H_ */207