xref: /openbmc/linux/drivers/vdpa/solidrun/snet_vdpa.h (revision 51a8f9d7f587290944d6fc733d1f897091c63159)
1*51a8f9d7SAlvaro Karsz /* SPDX-License-Identifier: GPL-2.0-only */
2*51a8f9d7SAlvaro Karsz /*
3*51a8f9d7SAlvaro Karsz  * SolidRun DPU driver for control plane
4*51a8f9d7SAlvaro Karsz  *
5*51a8f9d7SAlvaro Karsz  * Copyright (C) 2022 SolidRun
6*51a8f9d7SAlvaro Karsz  *
7*51a8f9d7SAlvaro Karsz  * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
8*51a8f9d7SAlvaro Karsz  *
9*51a8f9d7SAlvaro Karsz  */
10*51a8f9d7SAlvaro Karsz #ifndef _SNET_VDPA_H_
11*51a8f9d7SAlvaro Karsz #define _SNET_VDPA_H_
12*51a8f9d7SAlvaro Karsz 
13*51a8f9d7SAlvaro Karsz #include <linux/vdpa.h>
14*51a8f9d7SAlvaro Karsz #include <linux/pci.h>
15*51a8f9d7SAlvaro Karsz 
16*51a8f9d7SAlvaro Karsz #define SNET_NAME_SIZE 256
17*51a8f9d7SAlvaro Karsz 
18*51a8f9d7SAlvaro Karsz #define SNET_ERR(pdev, fmt, ...) dev_err(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
19*51a8f9d7SAlvaro Karsz #define SNET_WARN(pdev, fmt, ...) dev_warn(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
20*51a8f9d7SAlvaro Karsz #define SNET_INFO(pdev, fmt, ...) dev_info(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
21*51a8f9d7SAlvaro Karsz #define SNET_DBG(pdev, fmt, ...) dev_dbg(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
22*51a8f9d7SAlvaro Karsz #define SNET_HAS_FEATURE(s, f) ((s)->negotiated_features & BIT_ULL(f))
23*51a8f9d7SAlvaro Karsz /* VQ struct */
24*51a8f9d7SAlvaro Karsz struct snet_vq {
25*51a8f9d7SAlvaro Karsz 	/* VQ callback */
26*51a8f9d7SAlvaro Karsz 	struct vdpa_callback cb;
27*51a8f9d7SAlvaro Karsz 	/* desc base address */
28*51a8f9d7SAlvaro Karsz 	u64 desc_area;
29*51a8f9d7SAlvaro Karsz 	/* device base address */
30*51a8f9d7SAlvaro Karsz 	u64 device_area;
31*51a8f9d7SAlvaro Karsz 	/* driver base address */
32*51a8f9d7SAlvaro Karsz 	u64 driver_area;
33*51a8f9d7SAlvaro Karsz 	/* Queue size */
34*51a8f9d7SAlvaro Karsz 	u32 num;
35*51a8f9d7SAlvaro Karsz 	/* Serial ID for VQ */
36*51a8f9d7SAlvaro Karsz 	u32 sid;
37*51a8f9d7SAlvaro Karsz 	/* is ready flag */
38*51a8f9d7SAlvaro Karsz 	bool ready;
39*51a8f9d7SAlvaro Karsz 	/* IRQ number */
40*51a8f9d7SAlvaro Karsz 	u32 irq;
41*51a8f9d7SAlvaro Karsz 	/* IRQ index, DPU uses this to parse data from MSI-X table */
42*51a8f9d7SAlvaro Karsz 	u32 irq_idx;
43*51a8f9d7SAlvaro Karsz 	/* IRQ name */
44*51a8f9d7SAlvaro Karsz 	char irq_name[SNET_NAME_SIZE];
45*51a8f9d7SAlvaro Karsz 	/* pointer to mapped PCI BAR register used by this VQ to kick */
46*51a8f9d7SAlvaro Karsz 	void __iomem *kick_ptr;
47*51a8f9d7SAlvaro Karsz };
48*51a8f9d7SAlvaro Karsz 
49*51a8f9d7SAlvaro Karsz struct snet {
50*51a8f9d7SAlvaro Karsz 	/* vdpa device */
51*51a8f9d7SAlvaro Karsz 	struct vdpa_device vdpa;
52*51a8f9d7SAlvaro Karsz 	/* Config callback */
53*51a8f9d7SAlvaro Karsz 	struct vdpa_callback cb;
54*51a8f9d7SAlvaro Karsz 	/* array of virqueues */
55*51a8f9d7SAlvaro Karsz 	struct snet_vq **vqs;
56*51a8f9d7SAlvaro Karsz 	/* Used features */
57*51a8f9d7SAlvaro Karsz 	u64 negotiated_features;
58*51a8f9d7SAlvaro Karsz 	/* Device serial ID */
59*51a8f9d7SAlvaro Karsz 	u32 sid;
60*51a8f9d7SAlvaro Karsz 	/* device status */
61*51a8f9d7SAlvaro Karsz 	u8 status;
62*51a8f9d7SAlvaro Karsz 	/* boolean indicating if snet config was passed to the device */
63*51a8f9d7SAlvaro Karsz 	bool dpu_ready;
64*51a8f9d7SAlvaro Karsz 	/* IRQ number */
65*51a8f9d7SAlvaro Karsz 	u32 cfg_irq;
66*51a8f9d7SAlvaro Karsz 	/* IRQ index, DPU uses this to parse data from MSI-X table */
67*51a8f9d7SAlvaro Karsz 	u32 cfg_irq_idx;
68*51a8f9d7SAlvaro Karsz 	/* IRQ name */
69*51a8f9d7SAlvaro Karsz 	char cfg_irq_name[SNET_NAME_SIZE];
70*51a8f9d7SAlvaro Karsz 	/* BAR to access the VF */
71*51a8f9d7SAlvaro Karsz 	void __iomem *bar;
72*51a8f9d7SAlvaro Karsz 	/* PCI device */
73*51a8f9d7SAlvaro Karsz 	struct pci_dev *pdev;
74*51a8f9d7SAlvaro Karsz 	/* Pointer to snet pdev parent device */
75*51a8f9d7SAlvaro Karsz 	struct psnet *psnet;
76*51a8f9d7SAlvaro Karsz 	/* Pointer to snet config device */
77*51a8f9d7SAlvaro Karsz 	struct snet_dev_cfg *cfg;
78*51a8f9d7SAlvaro Karsz };
79*51a8f9d7SAlvaro Karsz 
80*51a8f9d7SAlvaro Karsz struct snet_dev_cfg {
81*51a8f9d7SAlvaro Karsz 	/* Device ID following VirtIO spec. */
82*51a8f9d7SAlvaro Karsz 	u32 virtio_id;
83*51a8f9d7SAlvaro Karsz 	/* Number of VQs for this device */
84*51a8f9d7SAlvaro Karsz 	u32 vq_num;
85*51a8f9d7SAlvaro Karsz 	/* Size of every VQ */
86*51a8f9d7SAlvaro Karsz 	u32 vq_size;
87*51a8f9d7SAlvaro Karsz 	/* Virtual Function id */
88*51a8f9d7SAlvaro Karsz 	u32 vfid;
89*51a8f9d7SAlvaro Karsz 	/* Device features, following VirtIO spec */
90*51a8f9d7SAlvaro Karsz 	u64 features;
91*51a8f9d7SAlvaro Karsz 	/* Reserved for future usage */
92*51a8f9d7SAlvaro Karsz 	u32 rsvd[6];
93*51a8f9d7SAlvaro Karsz 	/* VirtIO device specific config size */
94*51a8f9d7SAlvaro Karsz 	u32 cfg_size;
95*51a8f9d7SAlvaro Karsz 	/* VirtIO device specific config address */
96*51a8f9d7SAlvaro Karsz 	void __iomem *virtio_cfg;
97*51a8f9d7SAlvaro Karsz } __packed;
98*51a8f9d7SAlvaro Karsz 
99*51a8f9d7SAlvaro Karsz struct snet_cfg {
100*51a8f9d7SAlvaro Karsz 	/* Magic key */
101*51a8f9d7SAlvaro Karsz 	u32 key;
102*51a8f9d7SAlvaro Karsz 	/* Size of total config in bytes */
103*51a8f9d7SAlvaro Karsz 	u32 cfg_size;
104*51a8f9d7SAlvaro Karsz 	/* Config version */
105*51a8f9d7SAlvaro Karsz 	u32 cfg_ver;
106*51a8f9d7SAlvaro Karsz 	/* Number of Virtual Functions to create */
107*51a8f9d7SAlvaro Karsz 	u32 vf_num;
108*51a8f9d7SAlvaro Karsz 	/* BAR to use for the VFs */
109*51a8f9d7SAlvaro Karsz 	u32 vf_bar;
110*51a8f9d7SAlvaro Karsz 	/* Where should we write the SNET's config */
111*51a8f9d7SAlvaro Karsz 	u32 host_cfg_off;
112*51a8f9d7SAlvaro Karsz 	/* Max. allowed size for a SNET's config */
113*51a8f9d7SAlvaro Karsz 	u32 max_size_host_cfg;
114*51a8f9d7SAlvaro Karsz 	/* VirtIO config offset in BAR */
115*51a8f9d7SAlvaro Karsz 	u32 virtio_cfg_off;
116*51a8f9d7SAlvaro Karsz 	/* Offset in PCI BAR for VQ kicks */
117*51a8f9d7SAlvaro Karsz 	u32 kick_off;
118*51a8f9d7SAlvaro Karsz 	/* Offset in PCI BAR for HW monitoring */
119*51a8f9d7SAlvaro Karsz 	u32 hwmon_off;
120*51a8f9d7SAlvaro Karsz 	/* Offset in PCI BAR for SNET messages */
121*51a8f9d7SAlvaro Karsz 	u32 msg_off;
122*51a8f9d7SAlvaro Karsz 	/* Config general flags - enum snet_cfg_flags */
123*51a8f9d7SAlvaro Karsz 	u32 flags;
124*51a8f9d7SAlvaro Karsz 	/* Reserved for future usage */
125*51a8f9d7SAlvaro Karsz 	u32 rsvd[6];
126*51a8f9d7SAlvaro Karsz 	/* Number of snet devices */
127*51a8f9d7SAlvaro Karsz 	u32 devices_num;
128*51a8f9d7SAlvaro Karsz 	/* The actual devices */
129*51a8f9d7SAlvaro Karsz 	struct snet_dev_cfg **devs;
130*51a8f9d7SAlvaro Karsz } __packed;
131*51a8f9d7SAlvaro Karsz 
132*51a8f9d7SAlvaro Karsz /* SolidNET PCIe device, one device per PCIe physical function */
133*51a8f9d7SAlvaro Karsz struct psnet {
134*51a8f9d7SAlvaro Karsz 	/* PCI BARs */
135*51a8f9d7SAlvaro Karsz 	void __iomem *bars[PCI_STD_NUM_BARS];
136*51a8f9d7SAlvaro Karsz 	/* Negotiated config version */
137*51a8f9d7SAlvaro Karsz 	u32 negotiated_cfg_ver;
138*51a8f9d7SAlvaro Karsz 	/* Next IRQ index to use in case when the IRQs are allocated from this device */
139*51a8f9d7SAlvaro Karsz 	u32 next_irq;
140*51a8f9d7SAlvaro Karsz 	/* BAR number used to communicate with the device */
141*51a8f9d7SAlvaro Karsz 	u8 barno;
142*51a8f9d7SAlvaro Karsz 	/* spinlock to protect data that can be changed by SNET devices */
143*51a8f9d7SAlvaro Karsz 	spinlock_t lock;
144*51a8f9d7SAlvaro Karsz 	/* Pointer to the device's config read from BAR */
145*51a8f9d7SAlvaro Karsz 	struct snet_cfg cfg;
146*51a8f9d7SAlvaro Karsz 	/* Name of monitor device */
147*51a8f9d7SAlvaro Karsz 	char hwmon_name[SNET_NAME_SIZE];
148*51a8f9d7SAlvaro Karsz };
149*51a8f9d7SAlvaro Karsz 
150*51a8f9d7SAlvaro Karsz enum snet_cfg_flags {
151*51a8f9d7SAlvaro Karsz 	/* Create a HWMON device */
152*51a8f9d7SAlvaro Karsz 	SNET_CFG_FLAG_HWMON = BIT(0),
153*51a8f9d7SAlvaro Karsz 	/* USE IRQs from the physical function */
154*51a8f9d7SAlvaro Karsz 	SNET_CFG_FLAG_IRQ_PF = BIT(1),
155*51a8f9d7SAlvaro Karsz };
156*51a8f9d7SAlvaro Karsz 
157*51a8f9d7SAlvaro Karsz #define PSNET_FLAG_ON(p, f)	((p)->cfg.flags & (f))
158*51a8f9d7SAlvaro Karsz 
159*51a8f9d7SAlvaro Karsz static inline u32 psnet_read32(struct psnet *psnet, u32 off)
160*51a8f9d7SAlvaro Karsz {
161*51a8f9d7SAlvaro Karsz 	return ioread32(psnet->bars[psnet->barno] + off);
162*51a8f9d7SAlvaro Karsz }
163*51a8f9d7SAlvaro Karsz 
164*51a8f9d7SAlvaro Karsz static inline u32 snet_read32(struct snet *snet, u32 off)
165*51a8f9d7SAlvaro Karsz {
166*51a8f9d7SAlvaro Karsz 	return ioread32(snet->bar + off);
167*51a8f9d7SAlvaro Karsz }
168*51a8f9d7SAlvaro Karsz 
169*51a8f9d7SAlvaro Karsz static inline void snet_write32(struct snet *snet, u32 off, u32 val)
170*51a8f9d7SAlvaro Karsz {
171*51a8f9d7SAlvaro Karsz 	iowrite32(val, snet->bar + off);
172*51a8f9d7SAlvaro Karsz }
173*51a8f9d7SAlvaro Karsz 
174*51a8f9d7SAlvaro Karsz static inline u64 psnet_read64(struct psnet *psnet, u32 off)
175*51a8f9d7SAlvaro Karsz {
176*51a8f9d7SAlvaro Karsz 	u64 val;
177*51a8f9d7SAlvaro Karsz 	/* 64bits are written in 2 halves, low part first */
178*51a8f9d7SAlvaro Karsz 	val = (u64)psnet_read32(psnet, off);
179*51a8f9d7SAlvaro Karsz 	val |= ((u64)psnet_read32(psnet, off + 4) << 32);
180*51a8f9d7SAlvaro Karsz 	return val;
181*51a8f9d7SAlvaro Karsz }
182*51a8f9d7SAlvaro Karsz 
183*51a8f9d7SAlvaro Karsz static inline void snet_write64(struct snet *snet, u32 off, u64 val)
184*51a8f9d7SAlvaro Karsz {
185*51a8f9d7SAlvaro Karsz 	/* The DPU expects a 64bit integer in 2 halves, the low part first */
186*51a8f9d7SAlvaro Karsz 	snet_write32(snet, off, (u32)val);
187*51a8f9d7SAlvaro Karsz 	snet_write32(snet, off + 4, (u32)(val >> 32));
188*51a8f9d7SAlvaro Karsz }
189*51a8f9d7SAlvaro Karsz 
190*51a8f9d7SAlvaro Karsz #if IS_ENABLED(CONFIG_HWMON)
191*51a8f9d7SAlvaro Karsz void psnet_create_hwmon(struct pci_dev *pdev);
192*51a8f9d7SAlvaro Karsz #endif
193*51a8f9d7SAlvaro Karsz 
194*51a8f9d7SAlvaro Karsz #endif //_SNET_VDPA_H_
195