xref: /openbmc/linux/drivers/scsi/fnic/vnic_wq.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_WQ_H_
75df6d737SAbhijeet Joglekar #define _VNIC_WQ_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_wq_desc_avail fnic_wq_desc_avail
185df6d737SAbhijeet Joglekar #define vnic_wq_desc_used fnic_wq_desc_used
195df6d737SAbhijeet Joglekar #define vnic_wq_next_desc fni_cwq_next_desc
205df6d737SAbhijeet Joglekar #define vnic_wq_post fnic_wq_post
215df6d737SAbhijeet Joglekar #define vnic_wq_service fnic_wq_service
225df6d737SAbhijeet Joglekar #define vnic_wq_free fnic_wq_free
235df6d737SAbhijeet Joglekar #define vnic_wq_alloc fnic_wq_alloc
249d699c62SSatish Kharat #define vnic_wq_devcmd2_alloc fnic_wq_devcmd2_alloc
259d699c62SSatish Kharat #define vnic_wq_init_start fnic_wq_init_start
265df6d737SAbhijeet Joglekar #define vnic_wq_init fnic_wq_init
275df6d737SAbhijeet Joglekar #define vnic_wq_error_status fnic_wq_error_status
285df6d737SAbhijeet Joglekar #define vnic_wq_enable fnic_wq_enable
295df6d737SAbhijeet Joglekar #define vnic_wq_disable fnic_wq_disable
305df6d737SAbhijeet Joglekar #define vnic_wq_clean fnic_wq_clean
315df6d737SAbhijeet Joglekar 
325df6d737SAbhijeet Joglekar /* Work queue control */
335df6d737SAbhijeet Joglekar struct vnic_wq_ctrl {
345df6d737SAbhijeet Joglekar 	u64 ring_base;			/* 0x00 */
355df6d737SAbhijeet Joglekar 	u32 ring_size;			/* 0x08 */
365df6d737SAbhijeet Joglekar 	u32 pad0;
375df6d737SAbhijeet Joglekar 	u32 posted_index;		/* 0x10 */
385df6d737SAbhijeet Joglekar 	u32 pad1;
395df6d737SAbhijeet Joglekar 	u32 cq_index;			/* 0x18 */
405df6d737SAbhijeet Joglekar 	u32 pad2;
415df6d737SAbhijeet Joglekar 	u32 enable;			/* 0x20 */
425df6d737SAbhijeet Joglekar 	u32 pad3;
435df6d737SAbhijeet Joglekar 	u32 running;			/* 0x28 */
445df6d737SAbhijeet Joglekar 	u32 pad4;
455df6d737SAbhijeet Joglekar 	u32 fetch_index;		/* 0x30 */
465df6d737SAbhijeet Joglekar 	u32 pad5;
475df6d737SAbhijeet Joglekar 	u32 dca_value;			/* 0x38 */
485df6d737SAbhijeet Joglekar 	u32 pad6;
495df6d737SAbhijeet Joglekar 	u32 error_interrupt_enable;	/* 0x40 */
505df6d737SAbhijeet Joglekar 	u32 pad7;
515df6d737SAbhijeet Joglekar 	u32 error_interrupt_offset;	/* 0x48 */
525df6d737SAbhijeet Joglekar 	u32 pad8;
535df6d737SAbhijeet Joglekar 	u32 error_status;		/* 0x50 */
545df6d737SAbhijeet Joglekar 	u32 pad9;
555df6d737SAbhijeet Joglekar };
565df6d737SAbhijeet Joglekar 
575df6d737SAbhijeet Joglekar struct vnic_wq_buf {
585df6d737SAbhijeet Joglekar 	struct vnic_wq_buf *next;
595df6d737SAbhijeet Joglekar 	dma_addr_t dma_addr;
605df6d737SAbhijeet Joglekar 	void *os_buf;
615df6d737SAbhijeet Joglekar 	unsigned int len;
625df6d737SAbhijeet Joglekar 	unsigned int index;
635df6d737SAbhijeet Joglekar 	int sop;
645df6d737SAbhijeet Joglekar 	void *desc;
655df6d737SAbhijeet Joglekar };
665df6d737SAbhijeet Joglekar 
675df6d737SAbhijeet Joglekar /* Break the vnic_wq_buf allocations into blocks of 64 entries */
685df6d737SAbhijeet Joglekar #define VNIC_WQ_BUF_BLK_ENTRIES 64
695df6d737SAbhijeet Joglekar #define VNIC_WQ_BUF_BLK_SZ \
705df6d737SAbhijeet Joglekar 	(VNIC_WQ_BUF_BLK_ENTRIES * sizeof(struct vnic_wq_buf))
715df6d737SAbhijeet Joglekar #define VNIC_WQ_BUF_BLKS_NEEDED(entries) \
725df6d737SAbhijeet Joglekar 	DIV_ROUND_UP(entries, VNIC_WQ_BUF_BLK_ENTRIES)
735df6d737SAbhijeet Joglekar #define VNIC_WQ_BUF_BLKS_MAX VNIC_WQ_BUF_BLKS_NEEDED(4096)
745df6d737SAbhijeet Joglekar 
755df6d737SAbhijeet Joglekar struct vnic_wq {
765df6d737SAbhijeet Joglekar 	unsigned int index;
775df6d737SAbhijeet Joglekar 	struct vnic_dev *vdev;
785df6d737SAbhijeet Joglekar 	struct vnic_wq_ctrl __iomem *ctrl;	/* memory-mapped */
795df6d737SAbhijeet Joglekar 	struct vnic_dev_ring ring;
805df6d737SAbhijeet Joglekar 	struct vnic_wq_buf *bufs[VNIC_WQ_BUF_BLKS_MAX];
815df6d737SAbhijeet Joglekar 	struct vnic_wq_buf *to_use;
825df6d737SAbhijeet Joglekar 	struct vnic_wq_buf *to_clean;
835df6d737SAbhijeet Joglekar 	unsigned int pkts_outstanding;
845df6d737SAbhijeet Joglekar };
855df6d737SAbhijeet Joglekar 
vnic_wq_desc_avail(struct vnic_wq * wq)865df6d737SAbhijeet Joglekar static inline unsigned int vnic_wq_desc_avail(struct vnic_wq *wq)
875df6d737SAbhijeet Joglekar {
885df6d737SAbhijeet Joglekar 	/* how many does SW own? */
895df6d737SAbhijeet Joglekar 	return wq->ring.desc_avail;
905df6d737SAbhijeet Joglekar }
915df6d737SAbhijeet Joglekar 
vnic_wq_desc_used(struct vnic_wq * wq)925df6d737SAbhijeet Joglekar static inline unsigned int vnic_wq_desc_used(struct vnic_wq *wq)
935df6d737SAbhijeet Joglekar {
945df6d737SAbhijeet Joglekar 	/* how many does HW own? */
955df6d737SAbhijeet Joglekar 	return wq->ring.desc_count - wq->ring.desc_avail - 1;
965df6d737SAbhijeet Joglekar }
975df6d737SAbhijeet Joglekar 
vnic_wq_next_desc(struct vnic_wq * wq)985df6d737SAbhijeet Joglekar static inline void *vnic_wq_next_desc(struct vnic_wq *wq)
995df6d737SAbhijeet Joglekar {
1005df6d737SAbhijeet Joglekar 	return wq->to_use->desc;
1015df6d737SAbhijeet Joglekar }
1025df6d737SAbhijeet Joglekar 
vnic_wq_post(struct vnic_wq * wq,void * os_buf,dma_addr_t dma_addr,unsigned int len,int sop,int eop)1035df6d737SAbhijeet Joglekar static inline void vnic_wq_post(struct vnic_wq *wq,
1045df6d737SAbhijeet Joglekar 	void *os_buf, dma_addr_t dma_addr,
1055df6d737SAbhijeet Joglekar 	unsigned int len, int sop, int eop)
1065df6d737SAbhijeet Joglekar {
1075df6d737SAbhijeet Joglekar 	struct vnic_wq_buf *buf = wq->to_use;
1085df6d737SAbhijeet Joglekar 
1095df6d737SAbhijeet Joglekar 	buf->sop = sop;
1105df6d737SAbhijeet Joglekar 	buf->os_buf = eop ? os_buf : NULL;
1115df6d737SAbhijeet Joglekar 	buf->dma_addr = dma_addr;
1125df6d737SAbhijeet Joglekar 	buf->len = len;
1135df6d737SAbhijeet Joglekar 
1145df6d737SAbhijeet Joglekar 	buf = buf->next;
1155df6d737SAbhijeet Joglekar 	if (eop) {
1165df6d737SAbhijeet Joglekar 		/* Adding write memory barrier prevents compiler and/or CPU
1175df6d737SAbhijeet Joglekar 		 * reordering, thus avoiding descriptor posting before
1185df6d737SAbhijeet Joglekar 		 * descriptor is initialized. Otherwise, hardware can read
1195df6d737SAbhijeet Joglekar 		 * stale descriptor fields.
1205df6d737SAbhijeet Joglekar 		 */
1215df6d737SAbhijeet Joglekar 		wmb();
1225df6d737SAbhijeet Joglekar 		iowrite32(buf->index, &wq->ctrl->posted_index);
1235df6d737SAbhijeet Joglekar 	}
1245df6d737SAbhijeet Joglekar 	wq->to_use = buf;
1255df6d737SAbhijeet Joglekar 
1265df6d737SAbhijeet Joglekar 	wq->ring.desc_avail--;
1275df6d737SAbhijeet Joglekar }
1285df6d737SAbhijeet Joglekar 
vnic_wq_service(struct vnic_wq * wq,struct cq_desc * cq_desc,u16 completed_index,void (* buf_service)(struct vnic_wq * wq,struct cq_desc * cq_desc,struct vnic_wq_buf * buf,void * opaque),void * opaque)1295df6d737SAbhijeet Joglekar static inline void vnic_wq_service(struct vnic_wq *wq,
1305df6d737SAbhijeet Joglekar 	struct cq_desc *cq_desc, u16 completed_index,
1315df6d737SAbhijeet Joglekar 	void (*buf_service)(struct vnic_wq *wq,
1325df6d737SAbhijeet Joglekar 	struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque),
1335df6d737SAbhijeet Joglekar 	void *opaque)
1345df6d737SAbhijeet Joglekar {
1355df6d737SAbhijeet Joglekar 	struct vnic_wq_buf *buf;
1365df6d737SAbhijeet Joglekar 
1375df6d737SAbhijeet Joglekar 	buf = wq->to_clean;
1385df6d737SAbhijeet Joglekar 	while (1) {
1395df6d737SAbhijeet Joglekar 
1405df6d737SAbhijeet Joglekar 		(*buf_service)(wq, cq_desc, buf, opaque);
1415df6d737SAbhijeet Joglekar 
1425df6d737SAbhijeet Joglekar 		wq->ring.desc_avail++;
1435df6d737SAbhijeet Joglekar 
1445df6d737SAbhijeet Joglekar 		wq->to_clean = buf->next;
1455df6d737SAbhijeet Joglekar 
1465df6d737SAbhijeet Joglekar 		if (buf->index == completed_index)
1475df6d737SAbhijeet Joglekar 			break;
1485df6d737SAbhijeet Joglekar 
1495df6d737SAbhijeet Joglekar 		buf = wq->to_clean;
1505df6d737SAbhijeet Joglekar 	}
1515df6d737SAbhijeet Joglekar }
1525df6d737SAbhijeet Joglekar 
1535df6d737SAbhijeet Joglekar void vnic_wq_free(struct vnic_wq *wq);
1545df6d737SAbhijeet Joglekar int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
1555df6d737SAbhijeet Joglekar 	unsigned int desc_count, unsigned int desc_size);
1569d699c62SSatish Kharat int vnic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq,
1579d699c62SSatish Kharat 		unsigned int desc_count, unsigned int desc_size);
1589d699c62SSatish Kharat void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
1599d699c62SSatish Kharat 		unsigned int fetch_index, unsigned int posted_index,
1609d699c62SSatish Kharat 		unsigned int error_interrupt_enable,
1619d699c62SSatish Kharat 		unsigned int error_interrupt_offset);
1625df6d737SAbhijeet Joglekar void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
1635df6d737SAbhijeet Joglekar 	unsigned int error_interrupt_enable,
1645df6d737SAbhijeet Joglekar 	unsigned int error_interrupt_offset);
1655df6d737SAbhijeet Joglekar unsigned int vnic_wq_error_status(struct vnic_wq *wq);
1665df6d737SAbhijeet Joglekar void vnic_wq_enable(struct vnic_wq *wq);
1675df6d737SAbhijeet Joglekar int vnic_wq_disable(struct vnic_wq *wq);
1685df6d737SAbhijeet Joglekar void vnic_wq_clean(struct vnic_wq *wq,
1695df6d737SAbhijeet Joglekar 	void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf));
1705df6d737SAbhijeet Joglekar 
1715df6d737SAbhijeet Joglekar #endif /* _VNIC_WQ_H_ */
172