summaryrefslogtreecommitdiff
path: root/drivers/vdpa/solidrun/snet_vdpa.h
blob: 36ac285835ea85790735d867dcec1b774b6a01d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * SolidRun DPU driver for control plane
 *
 * Copyright (C) 2022-2023 SolidRun
 *
 * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
 *
 */
#ifndef _SNET_VDPA_H_
#define _SNET_VDPA_H_

#include <linux/vdpa.h>
#include <linux/pci.h>

#define SNET_NAME_SIZE 256

#define SNET_ERR(pdev, fmt, ...) dev_err(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
#define SNET_WARN(pdev, fmt, ...) dev_warn(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
#define SNET_INFO(pdev, fmt, ...) dev_info(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
#define SNET_DBG(pdev, fmt, ...) dev_dbg(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
#define SNET_HAS_FEATURE(s, f) ((s)->negotiated_features & BIT_ULL(f))
/* Check if negotiated config version is at least @ver */
#define SNET_CFG_VER(snet, ver) ((snet)->psnet->negotiated_cfg_ver >= (ver))

/* VQ struct */
struct snet_vq {
	/* VQ callback */
	struct vdpa_callback cb;
	/* VQ state received from bus */
	struct vdpa_vq_state vq_state;
	/* desc base address */
	u64 desc_area;
	/* device base address */
	u64 device_area;
	/* driver base address */
	u64 driver_area;
	/* Queue size */
	u32 num;
	/* Serial ID for VQ */
	u32 sid;
	/* is ready flag */
	bool ready;
	/* IRQ number */
	u32 irq;
	/* IRQ index, DPU uses this to parse data from MSI-X table */
	u32 irq_idx;
	/* IRQ name */
	char irq_name[SNET_NAME_SIZE];
	/* pointer to mapped PCI BAR register used by this VQ to kick */
	void __iomem *kick_ptr;
};

struct snet {
	/* vdpa device */
	struct vdpa_device vdpa;
	/* Config callback */
	struct vdpa_callback cb;
	/* To lock the control mechanism */
	struct mutex ctrl_lock;
	/* Spinlock to protect critical parts in the control mechanism */
	spinlock_t ctrl_spinlock;
	/* array of virqueues */
	struct snet_vq **vqs;
	/* Used features */
	u64 negotiated_features;
	/* Device serial ID */
	u32 sid;
	/* device status */
	u8 status;
	/* boolean indicating if snet config was passed to the device */
	bool dpu_ready;
	/* IRQ number */
	u32 cfg_irq;
	/* IRQ index, DPU uses this to parse data from MSI-X table */
	u32 cfg_irq_idx;
	/* IRQ name */
	char cfg_irq_name[SNET_NAME_SIZE];
	/* BAR to access the VF */
	void __iomem *bar;
	/* PCI device */
	struct pci_dev *pdev;
	/* Pointer to snet pdev parent device */
	struct psnet *psnet;
	/* Pointer to snet config device */
	struct snet_dev_cfg *cfg;
};

struct snet_dev_cfg {
	/* Device ID following VirtIO spec. */
	u32 virtio_id;
	/* Number of VQs for this device */
	u32 vq_num;
	/* Size of every VQ */
	u32 vq_size;
	/* Virtual Function id */
	u32 vfid;
	/* Device features, following VirtIO spec */
	u64 features;
	/* Reserved for future usage */
	u32 rsvd[6];
	/* VirtIO device specific config size */
	u32 cfg_size;
	/* VirtIO device specific config address */
	void __iomem *virtio_cfg;
} __packed;

struct snet_cfg {
	/* Magic key */
	u32 key;
	/* Size of total config in bytes */
	u32 cfg_size;
	/* Config version */
	u32 cfg_ver;
	/* Number of Virtual Functions to create */
	u32 vf_num;
	/* BAR to use for the VFs */
	u32 vf_bar;
	/* Where should we write the SNET's config */
	u32 host_cfg_off;
	/* Max. allowed size for a SNET's config */
	u32 max_size_host_cfg;
	/* VirtIO config offset in BAR */
	u32 virtio_cfg_off;
	/* Offset in PCI BAR for VQ kicks */
	u32 kick_off;
	/* Offset in PCI BAR for HW monitoring */
	u32 hwmon_off;
	/* Offset in PCI BAR for Control mechanism */
	u32 ctrl_off;
	/* Config general flags - enum snet_cfg_flags */
	u32 flags;
	/* Reserved for future usage */
	u32 rsvd[6];
	/* Number of snet devices */
	u32 devices_num;
	/* The actual devices */
	struct snet_dev_cfg **devs;
} __packed;

/* SolidNET PCIe device, one device per PCIe physical function */
struct psnet {
	/* PCI BARs */
	void __iomem *bars[PCI_STD_NUM_BARS];
	/* Negotiated config version */
	u32 negotiated_cfg_ver;
	/* Next IRQ index to use in case when the IRQs are allocated from this device */
	u32 next_irq;
	/* BAR number used to communicate with the device */
	u8 barno;
	/* spinlock to protect data that can be changed by SNET devices */
	spinlock_t lock;
	/* Pointer to the device's config read from BAR */
	struct snet_cfg cfg;
	/* Name of monitor device */
	char hwmon_name[SNET_NAME_SIZE];
};

enum snet_cfg_flags {
	/* Create a HWMON device */
	SNET_CFG_FLAG_HWMON = BIT(0),
	/* USE IRQs from the physical function */
	SNET_CFG_FLAG_IRQ_PF = BIT(1),
};

#define PSNET_FLAG_ON(p, f)	((p)->cfg.flags & (f))

static inline u32 psnet_read32(struct psnet *psnet, u32 off)
{
	return ioread32(psnet->bars[psnet->barno] + off);
}

static inline u32 snet_read32(struct snet *snet, u32 off)
{
	return ioread32(snet->bar + off);
}

static inline void snet_write32(struct snet *snet, u32 off, u32 val)
{
	iowrite32(val, snet->bar + off);
}

static inline u64 psnet_read64(struct psnet *psnet, u32 off)
{
	u64 val;
	/* 64bits are written in 2 halves, low part first */
	val = (u64)psnet_read32(psnet, off);
	val |= ((u64)psnet_read32(psnet, off + 4) << 32);
	return val;
}

static inline void snet_write64(struct snet *snet, u32 off, u64 val)
{
	/* The DPU expects a 64bit integer in 2 halves, the low part first */
	snet_write32(snet, off, (u32)val);
	snet_write32(snet, off + 4, (u32)(val >> 32));
}

#if IS_ENABLED(CONFIG_HWMON)
void psnet_create_hwmon(struct pci_dev *pdev);
#endif

void snet_ctrl_clear(struct snet *snet);
int snet_destroy_dev(struct snet *snet);
int snet_read_vq_state(struct snet *snet, u16 idx, struct vdpa_vq_state *state);
int snet_suspend_dev(struct snet *snet);
int snet_resume_dev(struct snet *snet);

#endif //_SNET_VDPA_H_