xref: /openbmc/linux/drivers/scsi/fnic/vnic_rq.h (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1*e6550b3eSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
25df6d737SAbhijeet Joglekar /*
35df6d737SAbhijeet Joglekar  * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
45df6d737SAbhijeet Joglekar  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
55df6d737SAbhijeet Joglekar  */
65df6d737SAbhijeet Joglekar #ifndef _VNIC_RQ_H_
75df6d737SAbhijeet Joglekar #define _VNIC_RQ_H_
85df6d737SAbhijeet Joglekar 
95df6d737SAbhijeet Joglekar #include <linux/pci.h>
105df6d737SAbhijeet Joglekar #include "vnic_dev.h"
115df6d737SAbhijeet Joglekar #include "vnic_cq.h"
125df6d737SAbhijeet Joglekar 
135df6d737SAbhijeet Joglekar /*
145df6d737SAbhijeet Joglekar  * These defines avoid symbol clash between fnic and enic (Cisco 10G Eth
155df6d737SAbhijeet Joglekar  * Driver) when both are built with CONFIG options =y
165df6d737SAbhijeet Joglekar  */
175df6d737SAbhijeet Joglekar #define vnic_rq_desc_avail fnic_rq_desc_avail
185df6d737SAbhijeet Joglekar #define vnic_rq_desc_used fnic_rq_desc_used
195df6d737SAbhijeet Joglekar #define vnic_rq_next_desc fnic_rq_next_desc
205df6d737SAbhijeet Joglekar #define vnic_rq_next_index fnic_rq_next_index
215df6d737SAbhijeet Joglekar #define vnic_rq_next_buf_index fnic_rq_next_buf_index
225df6d737SAbhijeet Joglekar #define vnic_rq_post fnic_rq_post
235df6d737SAbhijeet Joglekar #define vnic_rq_posting_soon fnic_rq_posting_soon
245df6d737SAbhijeet Joglekar #define vnic_rq_return_descs fnic_rq_return_descs
255df6d737SAbhijeet Joglekar #define vnic_rq_service fnic_rq_service
265df6d737SAbhijeet Joglekar #define vnic_rq_fill fnic_rq_fill
275df6d737SAbhijeet Joglekar #define vnic_rq_free fnic_rq_free
285df6d737SAbhijeet Joglekar #define vnic_rq_alloc fnic_rq_alloc
295df6d737SAbhijeet Joglekar #define vnic_rq_init fnic_rq_init
305df6d737SAbhijeet Joglekar #define vnic_rq_error_status fnic_rq_error_status
315df6d737SAbhijeet Joglekar #define vnic_rq_enable fnic_rq_enable
325df6d737SAbhijeet Joglekar #define vnic_rq_disable fnic_rq_disable
335df6d737SAbhijeet Joglekar #define vnic_rq_clean fnic_rq_clean
345df6d737SAbhijeet Joglekar 
355df6d737SAbhijeet Joglekar /* Receive queue control */
365df6d737SAbhijeet Joglekar struct vnic_rq_ctrl {
375df6d737SAbhijeet Joglekar 	u64 ring_base;			/* 0x00 */
385df6d737SAbhijeet Joglekar 	u32 ring_size;			/* 0x08 */
395df6d737SAbhijeet Joglekar 	u32 pad0;
405df6d737SAbhijeet Joglekar 	u32 posted_index;		/* 0x10 */
415df6d737SAbhijeet Joglekar 	u32 pad1;
425df6d737SAbhijeet Joglekar 	u32 cq_index;			/* 0x18 */
435df6d737SAbhijeet Joglekar 	u32 pad2;
445df6d737SAbhijeet Joglekar 	u32 enable;			/* 0x20 */
455df6d737SAbhijeet Joglekar 	u32 pad3;
465df6d737SAbhijeet Joglekar 	u32 running;			/* 0x28 */
475df6d737SAbhijeet Joglekar 	u32 pad4;
485df6d737SAbhijeet Joglekar 	u32 fetch_index;		/* 0x30 */
495df6d737SAbhijeet Joglekar 	u32 pad5;
505df6d737SAbhijeet Joglekar 	u32 error_interrupt_enable;	/* 0x38 */
515df6d737SAbhijeet Joglekar 	u32 pad6;
525df6d737SAbhijeet Joglekar 	u32 error_interrupt_offset;	/* 0x40 */
535df6d737SAbhijeet Joglekar 	u32 pad7;
545df6d737SAbhijeet Joglekar 	u32 error_status;		/* 0x48 */
555df6d737SAbhijeet Joglekar 	u32 pad8;
565df6d737SAbhijeet Joglekar 	u32 dropped_packet_count;	/* 0x50 */
575df6d737SAbhijeet Joglekar 	u32 pad9;
585df6d737SAbhijeet Joglekar 	u32 dropped_packet_count_rc;	/* 0x58 */
595df6d737SAbhijeet Joglekar 	u32 pad10;
605df6d737SAbhijeet Joglekar };
615df6d737SAbhijeet Joglekar 
625df6d737SAbhijeet Joglekar /* Break the vnic_rq_buf allocations into blocks of 64 entries */
635df6d737SAbhijeet Joglekar #define VNIC_RQ_BUF_BLK_ENTRIES 64
645df6d737SAbhijeet Joglekar #define VNIC_RQ_BUF_BLK_SZ \
655df6d737SAbhijeet Joglekar 	(VNIC_RQ_BUF_BLK_ENTRIES * sizeof(struct vnic_rq_buf))
665df6d737SAbhijeet Joglekar #define VNIC_RQ_BUF_BLKS_NEEDED(entries) \
675df6d737SAbhijeet Joglekar 	DIV_ROUND_UP(entries, VNIC_RQ_BUF_BLK_ENTRIES)
685df6d737SAbhijeet Joglekar #define VNIC_RQ_BUF_BLKS_MAX VNIC_RQ_BUF_BLKS_NEEDED(4096)
695df6d737SAbhijeet Joglekar 
705df6d737SAbhijeet Joglekar struct vnic_rq_buf {
715df6d737SAbhijeet Joglekar 	struct vnic_rq_buf *next;
725df6d737SAbhijeet Joglekar 	dma_addr_t dma_addr;
735df6d737SAbhijeet Joglekar 	void *os_buf;
745df6d737SAbhijeet Joglekar 	unsigned int os_buf_index;
755df6d737SAbhijeet Joglekar 	unsigned int len;
765df6d737SAbhijeet Joglekar 	unsigned int index;
775df6d737SAbhijeet Joglekar 	void *desc;
785df6d737SAbhijeet Joglekar };
795df6d737SAbhijeet Joglekar 
805df6d737SAbhijeet Joglekar struct vnic_rq {
815df6d737SAbhijeet Joglekar 	unsigned int index;
825df6d737SAbhijeet Joglekar 	struct vnic_dev *vdev;
835df6d737SAbhijeet Joglekar 	struct vnic_rq_ctrl __iomem *ctrl;	/* memory-mapped */
845df6d737SAbhijeet Joglekar 	struct vnic_dev_ring ring;
855df6d737SAbhijeet Joglekar 	struct vnic_rq_buf *bufs[VNIC_RQ_BUF_BLKS_MAX];
865df6d737SAbhijeet Joglekar 	struct vnic_rq_buf *to_use;
875df6d737SAbhijeet Joglekar 	struct vnic_rq_buf *to_clean;
885df6d737SAbhijeet Joglekar 	void *os_buf_head;
895df6d737SAbhijeet Joglekar 	unsigned int buf_index;
905df6d737SAbhijeet Joglekar 	unsigned int pkts_outstanding;
915df6d737SAbhijeet Joglekar };
925df6d737SAbhijeet Joglekar 
vnic_rq_desc_avail(struct vnic_rq * rq)935df6d737SAbhijeet Joglekar static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq)
945df6d737SAbhijeet Joglekar {
955df6d737SAbhijeet Joglekar 	/* how many does SW own? */
965df6d737SAbhijeet Joglekar 	return rq->ring.desc_avail;
975df6d737SAbhijeet Joglekar }
985df6d737SAbhijeet Joglekar 
vnic_rq_desc_used(struct vnic_rq * rq)995df6d737SAbhijeet Joglekar static inline unsigned int vnic_rq_desc_used(struct vnic_rq *rq)
1005df6d737SAbhijeet Joglekar {
1015df6d737SAbhijeet Joglekar 	/* how many does HW own? */
1025df6d737SAbhijeet Joglekar 	return rq->ring.desc_count - rq->ring.desc_avail - 1;
1035df6d737SAbhijeet Joglekar }
1045df6d737SAbhijeet Joglekar 
vnic_rq_next_desc(struct vnic_rq * rq)1055df6d737SAbhijeet Joglekar static inline void *vnic_rq_next_desc(struct vnic_rq *rq)
1065df6d737SAbhijeet Joglekar {
1075df6d737SAbhijeet Joglekar 	return rq->to_use->desc;
1085df6d737SAbhijeet Joglekar }
1095df6d737SAbhijeet Joglekar 
vnic_rq_next_index(struct vnic_rq * rq)1105df6d737SAbhijeet Joglekar static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)
1115df6d737SAbhijeet Joglekar {
1125df6d737SAbhijeet Joglekar 	return rq->to_use->index;
1135df6d737SAbhijeet Joglekar }
1145df6d737SAbhijeet Joglekar 
vnic_rq_next_buf_index(struct vnic_rq * rq)1155df6d737SAbhijeet Joglekar static inline unsigned int vnic_rq_next_buf_index(struct vnic_rq *rq)
1165df6d737SAbhijeet Joglekar {
1175df6d737SAbhijeet Joglekar 	return rq->buf_index++;
1185df6d737SAbhijeet Joglekar }
1195df6d737SAbhijeet Joglekar 
vnic_rq_post(struct vnic_rq * rq,void * os_buf,unsigned int os_buf_index,dma_addr_t dma_addr,unsigned int len)1205df6d737SAbhijeet Joglekar static inline void vnic_rq_post(struct vnic_rq *rq,
1215df6d737SAbhijeet Joglekar 	void *os_buf, unsigned int os_buf_index,
1225df6d737SAbhijeet Joglekar 	dma_addr_t dma_addr, unsigned int len)
1235df6d737SAbhijeet Joglekar {
1245df6d737SAbhijeet Joglekar 	struct vnic_rq_buf *buf = rq->to_use;
1255df6d737SAbhijeet Joglekar 
1265df6d737SAbhijeet Joglekar 	buf->os_buf = os_buf;
1275df6d737SAbhijeet Joglekar 	buf->os_buf_index = os_buf_index;
1285df6d737SAbhijeet Joglekar 	buf->dma_addr = dma_addr;
1295df6d737SAbhijeet Joglekar 	buf->len = len;
1305df6d737SAbhijeet Joglekar 
1315df6d737SAbhijeet Joglekar 	buf = buf->next;
1325df6d737SAbhijeet Joglekar 	rq->to_use = buf;
1335df6d737SAbhijeet Joglekar 	rq->ring.desc_avail--;
1345df6d737SAbhijeet Joglekar 
1355df6d737SAbhijeet Joglekar 	/* Move the posted_index every nth descriptor
1365df6d737SAbhijeet Joglekar 	 */
1375df6d737SAbhijeet Joglekar 
1385df6d737SAbhijeet Joglekar #ifndef VNIC_RQ_RETURN_RATE
1395df6d737SAbhijeet Joglekar #define VNIC_RQ_RETURN_RATE		0xf	/* keep 2^n - 1 */
1405df6d737SAbhijeet Joglekar #endif
1415df6d737SAbhijeet Joglekar 
1425df6d737SAbhijeet Joglekar 	if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) {
1435df6d737SAbhijeet Joglekar 		/* Adding write memory barrier prevents compiler and/or CPU
1445df6d737SAbhijeet Joglekar 		 * reordering, thus avoiding descriptor posting before
1455df6d737SAbhijeet Joglekar 		 * descriptor is initialized. Otherwise, hardware can read
1465df6d737SAbhijeet Joglekar 		 * stale descriptor fields.
1475df6d737SAbhijeet Joglekar 		 */
1485df6d737SAbhijeet Joglekar 		wmb();
1495df6d737SAbhijeet Joglekar 		iowrite32(buf->index, &rq->ctrl->posted_index);
1505df6d737SAbhijeet Joglekar 	}
1515df6d737SAbhijeet Joglekar }
1525df6d737SAbhijeet Joglekar 
vnic_rq_posting_soon(struct vnic_rq * rq)1535df6d737SAbhijeet Joglekar static inline int vnic_rq_posting_soon(struct vnic_rq *rq)
1545df6d737SAbhijeet Joglekar {
1555df6d737SAbhijeet Joglekar 	return (rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0;
1565df6d737SAbhijeet Joglekar }
1575df6d737SAbhijeet Joglekar 
vnic_rq_return_descs(struct vnic_rq * rq,unsigned int count)1585df6d737SAbhijeet Joglekar static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
1595df6d737SAbhijeet Joglekar {
1605df6d737SAbhijeet Joglekar 	rq->ring.desc_avail += count;
1615df6d737SAbhijeet Joglekar }
1625df6d737SAbhijeet Joglekar 
1635df6d737SAbhijeet Joglekar enum desc_return_options {
1645df6d737SAbhijeet Joglekar 	VNIC_RQ_RETURN_DESC,
1655df6d737SAbhijeet Joglekar 	VNIC_RQ_DEFER_RETURN_DESC,
1665df6d737SAbhijeet Joglekar };
1675df6d737SAbhijeet Joglekar 
vnic_rq_service(struct vnic_rq * rq,struct cq_desc * cq_desc,u16 completed_index,int desc_return,void (* buf_service)(struct vnic_rq * rq,struct cq_desc * cq_desc,struct vnic_rq_buf * buf,int skipped,void * opaque),void * opaque)1685df6d737SAbhijeet Joglekar static inline void vnic_rq_service(struct vnic_rq *rq,
1695df6d737SAbhijeet Joglekar 	struct cq_desc *cq_desc, u16 completed_index,
1705df6d737SAbhijeet Joglekar 	int desc_return, void (*buf_service)(struct vnic_rq *rq,
1715df6d737SAbhijeet Joglekar 	struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
1725df6d737SAbhijeet Joglekar 	int skipped, void *opaque), void *opaque)
1735df6d737SAbhijeet Joglekar {
1745df6d737SAbhijeet Joglekar 	struct vnic_rq_buf *buf;
1755df6d737SAbhijeet Joglekar 	int skipped;
1765df6d737SAbhijeet Joglekar 
1775df6d737SAbhijeet Joglekar 	buf = rq->to_clean;
1785df6d737SAbhijeet Joglekar 	while (1) {
1795df6d737SAbhijeet Joglekar 
1805df6d737SAbhijeet Joglekar 		skipped = (buf->index != completed_index);
1815df6d737SAbhijeet Joglekar 
1825df6d737SAbhijeet Joglekar 		(*buf_service)(rq, cq_desc, buf, skipped, opaque);
1835df6d737SAbhijeet Joglekar 
1845df6d737SAbhijeet Joglekar 		if (desc_return == VNIC_RQ_RETURN_DESC)
1855df6d737SAbhijeet Joglekar 			rq->ring.desc_avail++;
1865df6d737SAbhijeet Joglekar 
1875df6d737SAbhijeet Joglekar 		rq->to_clean = buf->next;
1885df6d737SAbhijeet Joglekar 
1895df6d737SAbhijeet Joglekar 		if (!skipped)
1905df6d737SAbhijeet Joglekar 			break;
1915df6d737SAbhijeet Joglekar 
1925df6d737SAbhijeet Joglekar 		buf = rq->to_clean;
1935df6d737SAbhijeet Joglekar 	}
1945df6d737SAbhijeet Joglekar }
1955df6d737SAbhijeet Joglekar 
vnic_rq_fill(struct vnic_rq * rq,int (* buf_fill)(struct vnic_rq * rq))1965df6d737SAbhijeet Joglekar static inline int vnic_rq_fill(struct vnic_rq *rq,
1975df6d737SAbhijeet Joglekar 	int (*buf_fill)(struct vnic_rq *rq))
1985df6d737SAbhijeet Joglekar {
1995df6d737SAbhijeet Joglekar 	int err;
2005df6d737SAbhijeet Joglekar 
2015df6d737SAbhijeet Joglekar 	while (vnic_rq_desc_avail(rq) > 1) {
2025df6d737SAbhijeet Joglekar 
2035df6d737SAbhijeet Joglekar 		err = (*buf_fill)(rq);
2045df6d737SAbhijeet Joglekar 		if (err)
2055df6d737SAbhijeet Joglekar 			return err;
2065df6d737SAbhijeet Joglekar 	}
2075df6d737SAbhijeet Joglekar 
2085df6d737SAbhijeet Joglekar 	return 0;
2095df6d737SAbhijeet Joglekar }
2105df6d737SAbhijeet Joglekar 
2115df6d737SAbhijeet Joglekar void vnic_rq_free(struct vnic_rq *rq);
2125df6d737SAbhijeet Joglekar int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
2135df6d737SAbhijeet Joglekar 	unsigned int desc_count, unsigned int desc_size);
2145df6d737SAbhijeet Joglekar void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
2155df6d737SAbhijeet Joglekar 	unsigned int error_interrupt_enable,
2165df6d737SAbhijeet Joglekar 	unsigned int error_interrupt_offset);
2175df6d737SAbhijeet Joglekar unsigned int vnic_rq_error_status(struct vnic_rq *rq);
2185df6d737SAbhijeet Joglekar void vnic_rq_enable(struct vnic_rq *rq);
2195df6d737SAbhijeet Joglekar int vnic_rq_disable(struct vnic_rq *rq);
2205df6d737SAbhijeet Joglekar void vnic_rq_clean(struct vnic_rq *rq,
2215df6d737SAbhijeet Joglekar 	void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf));
2225df6d737SAbhijeet Joglekar 
2235df6d737SAbhijeet Joglekar #endif /* _VNIC_RQ_H_ */
224