cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vnic_wq.h (4832B)


      1/*
      2 * Copyright 2014 Cisco Systems, Inc.  All rights reserved.
      3 *
      4 * This program is free software; you may redistribute it and/or modify
      5 * it under the terms of the GNU General Public License as published by
      6 * the Free Software Foundation; version 2 of the License.
      7 *
      8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     15 * SOFTWARE.
     16 */
     17
     18#ifndef _VNIC_WQ_H_
     19#define _VNIC_WQ_H_
     20
     21#include <linux/pci.h>
     22#include "vnic_dev.h"
     23#include "vnic_cq.h"
     24
     25/* Work queue control */
     26struct vnic_wq_ctrl {
     27	u64 ring_base;			/* 0x00 */
     28	u32 ring_size;			/* 0x08 */
     29	u32 pad0;
     30	u32 posted_index;		/* 0x10 */
     31	u32 pad1;
     32	u32 cq_index;			/* 0x18 */
     33	u32 pad2;
     34	u32 enable;			/* 0x20 */
     35	u32 pad3;
     36	u32 running;			/* 0x28 */
     37	u32 pad4;
     38	u32 fetch_index;		/* 0x30 */
     39	u32 pad5;
     40	u32 dca_value;			/* 0x38 */
     41	u32 pad6;
     42	u32 error_interrupt_enable;	/* 0x40 */
     43	u32 pad7;
     44	u32 error_interrupt_offset;	/* 0x48 */
     45	u32 pad8;
     46	u32 error_status;		/* 0x50 */
     47	u32 pad9;
     48};
     49
     50struct vnic_wq_buf {
     51	struct vnic_wq_buf *next;
     52	dma_addr_t dma_addr;
     53	void *os_buf;
     54	unsigned int len;
     55	unsigned int index;
     56	int sop;
     57	void *desc;
     58};
     59
     60/* Break the vnic_wq_buf allocations into blocks of 64 entries */
     61#define VNIC_WQ_BUF_MIN_BLK_ENTRIES 32
     62#define VNIC_WQ_BUF_DFLT_BLK_ENTRIES 64
     63#define VNIC_WQ_BUF_BLK_ENTRIES(entries) \
     64	((unsigned int)(entries < VNIC_WQ_BUF_DFLT_BLK_ENTRIES) ? \
     65		VNIC_WQ_BUF_MIN_BLK_ENTRIES : VNIC_WQ_BUF_DFLT_BLK_ENTRIES)
     66#define VNIC_WQ_BUF_BLK_SZ \
     67	(VNIC_WQ_BUF_DFLT_BLK_ENTRIES * sizeof(struct vnic_wq_buf))
     68#define VNIC_WQ_BUF_BLKS_NEEDED(entries) \
     69	DIV_ROUND_UP(entries, VNIC_WQ_BUF_DFLT_BLK_ENTRIES)
     70#define VNIC_WQ_BUF_BLKS_NEEDED(entries) \
     71	DIV_ROUND_UP(entries, VNIC_WQ_BUF_DFLT_BLK_ENTRIES)
     72#define VNIC_WQ_BUF_BLKS_MAX VNIC_WQ_BUF_BLKS_NEEDED(4096)
     73
     74struct vnic_wq {
     75	unsigned int index;
     76	struct vnic_dev *vdev;
     77	struct vnic_wq_ctrl __iomem *ctrl;	/* memory-mapped */
     78	struct vnic_dev_ring ring;
     79	struct vnic_wq_buf *bufs[VNIC_WQ_BUF_BLKS_MAX];
     80	struct vnic_wq_buf *to_use;
     81	struct vnic_wq_buf *to_clean;
     82	unsigned int pkts_outstanding;
     83};
     84
     85static inline unsigned int svnic_wq_desc_avail(struct vnic_wq *wq)
     86{
     87	/* how many does SW own? */
     88	return wq->ring.desc_avail;
     89}
     90
     91static inline unsigned int svnic_wq_desc_used(struct vnic_wq *wq)
     92{
     93	/* how many does HW own? */
     94	return wq->ring.desc_count - wq->ring.desc_avail - 1;
     95}
     96
     97static inline void *svnic_wq_next_desc(struct vnic_wq *wq)
     98{
     99	return wq->to_use->desc;
    100}
    101
    102static inline void svnic_wq_post(struct vnic_wq *wq,
    103	void *os_buf, dma_addr_t dma_addr,
    104	unsigned int len, int sop, int eop)
    105{
    106	struct vnic_wq_buf *buf = wq->to_use;
    107
    108	buf->sop = sop;
    109	buf->os_buf = eop ? os_buf : NULL;
    110	buf->dma_addr = dma_addr;
    111	buf->len = len;
    112
    113	buf = buf->next;
    114	if (eop) {
    115		/* Adding write memory barrier prevents compiler and/or CPU
    116		 * reordering, thus avoiding descriptor posting before
    117		 * descriptor is initialized. Otherwise, hardware can read
    118		 * stale descriptor fields.
    119		 */
    120		wmb();
    121		iowrite32(buf->index, &wq->ctrl->posted_index);
    122	}
    123	wq->to_use = buf;
    124
    125	wq->ring.desc_avail--;
    126}
    127
    128static inline void svnic_wq_service(struct vnic_wq *wq,
    129	struct cq_desc *cq_desc, u16 completed_index,
    130	void (*buf_service)(struct vnic_wq *wq,
    131	struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque),
    132	void *opaque)
    133{
    134	struct vnic_wq_buf *buf;
    135
    136	buf = wq->to_clean;
    137	while (1) {
    138
    139		(*buf_service)(wq, cq_desc, buf, opaque);
    140
    141		wq->ring.desc_avail++;
    142
    143		wq->to_clean = buf->next;
    144
    145		if (buf->index == completed_index)
    146			break;
    147
    148		buf = wq->to_clean;
    149	}
    150}
    151
    152void svnic_wq_free(struct vnic_wq *wq);
    153int svnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq,
    154	unsigned int index, unsigned int desc_count, unsigned int desc_size);
    155int vnic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq,
    156		unsigned int desc_count, unsigned int desc_size);
    157void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
    158		unsigned int fetch_index, unsigned int post_index,
    159		unsigned int error_interrupt_enable,
    160		unsigned int error_interrupt_offset);
    161
    162void svnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
    163	unsigned int error_interrupt_enable,
    164	unsigned int error_interrupt_offset);
    165unsigned int svnic_wq_error_status(struct vnic_wq *wq);
    166void svnic_wq_enable(struct vnic_wq *wq);
    167int svnic_wq_disable(struct vnic_wq *wq);
    168void svnic_wq_clean(struct vnic_wq *wq,
    169	void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf));
    170#endif /* _VNIC_WQ_H_ */