1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * SolidRun DPU driver for control plane
5 * Copyright (C) 2022-2023 SolidRun
7 * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
13 #include <linux/vdpa.h>
14 #include <linux/pci.h>
16 #define SNET_NAME_SIZE 256
18 #define SNET_ERR(pdev, fmt, ...) dev_err(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
19 #define SNET_WARN(pdev, fmt, ...) dev_warn(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
20 #define SNET_INFO(pdev, fmt, ...) dev_info(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
21 #define SNET_DBG(pdev, fmt, ...) dev_dbg(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
22 #define SNET_HAS_FEATURE(s, f) ((s)->negotiated_features & BIT_ULL(f))
23 /* Check if negotiated config version is at least @ver */
24 #define SNET_CFG_VER(snet, ver) ((snet)->psnet->negotiated_cfg_ver >= (ver))
29 struct vdpa_callback cb;
30 /* VQ state received from bus */
31 struct vdpa_vq_state vq_state;
32 /* desc base address */
34 /* device base address */
36 /* driver base address */
40 /* Serial ID for VQ */
46 /* IRQ index, DPU uses this to parse data from MSI-X table */
49 char irq_name[SNET_NAME_SIZE];
50 /* pointer to mapped PCI BAR register used by this VQ to kick */
51 void __iomem *kick_ptr;
56 struct vdpa_device vdpa;
58 struct vdpa_callback cb;
59 /* To lock the control mechanism */
60 struct mutex ctrl_lock;
61 /* Spinlock to protect critical parts in the control mechanism */
62 spinlock_t ctrl_spinlock;
63 /* array of virqueues */
66 u64 negotiated_features;
67 /* Device serial ID */
71 /* boolean indicating if snet config was passed to the device */
75 /* IRQ index, DPU uses this to parse data from MSI-X table */
78 char cfg_irq_name[SNET_NAME_SIZE];
79 /* BAR to access the VF */
83 /* Pointer to snet pdev parent device */
85 /* Pointer to snet config device */
86 struct snet_dev_cfg *cfg;
90 /* Device ID following VirtIO spec. */
92 /* Number of VQs for this device */
94 /* Size of every VQ */
96 /* Virtual Function id */
98 /* Device features, following VirtIO spec */
100 /* Reserved for future usage */
102 /* VirtIO device specific config size */
104 /* VirtIO device specific config address */
105 void __iomem *virtio_cfg;
111 /* Size of total config in bytes */
115 /* Number of Virtual Functions to create */
117 /* BAR to use for the VFs */
119 /* Where should we write the SNET's config */
121 /* Max. allowed size for a SNET's config */
122 u32 max_size_host_cfg;
123 /* VirtIO config offset in BAR */
125 /* Offset in PCI BAR for VQ kicks */
127 /* Offset in PCI BAR for HW monitoring */
129 /* Offset in PCI BAR for Control mechanism */
131 /* Config general flags - enum snet_cfg_flags */
133 /* Reserved for future usage */
135 /* Number of snet devices */
137 /* The actual devices */
138 struct snet_dev_cfg **devs;
141 /* SolidNET PCIe device, one device per PCIe physical function */
144 void __iomem *bars[PCI_STD_NUM_BARS];
145 /* Negotiated config version */
146 u32 negotiated_cfg_ver;
147 /* Next IRQ index to use in case when the IRQs are allocated from this device */
149 /* BAR number used to communicate with the device */
151 /* spinlock to protect data that can be changed by SNET devices */
153 /* Pointer to the device's config read from BAR */
155 /* Name of monitor device */
156 char hwmon_name[SNET_NAME_SIZE];
159 enum snet_cfg_flags {
160 /* Create a HWMON device */
161 SNET_CFG_FLAG_HWMON = BIT(0),
162 /* USE IRQs from the physical function */
163 SNET_CFG_FLAG_IRQ_PF = BIT(1),
166 #define PSNET_FLAG_ON(p, f) ((p)->cfg.flags & (f))
168 static inline u32 psnet_read32(struct psnet *psnet, u32 off)
170 return ioread32(psnet->bars[psnet->barno] + off);
173 static inline u32 snet_read32(struct snet *snet, u32 off)
175 return ioread32(snet->bar + off);
178 static inline void snet_write32(struct snet *snet, u32 off, u32 val)
180 iowrite32(val, snet->bar + off);
183 static inline u64 psnet_read64(struct psnet *psnet, u32 off)
186 /* 64bits are written in 2 halves, low part first */
187 val = (u64)psnet_read32(psnet, off);
188 val |= ((u64)psnet_read32(psnet, off + 4) << 32);
192 static inline void snet_write64(struct snet *snet, u32 off, u64 val)
194 /* The DPU expects a 64bit integer in 2 halves, the low part first */
195 snet_write32(snet, off, (u32)val);
196 snet_write32(snet, off + 4, (u32)(val >> 32));
199 #if IS_ENABLED(CONFIG_HWMON)
200 void psnet_create_hwmon(struct pci_dev *pdev);
203 void snet_ctrl_clear(struct snet *snet);
204 int snet_destroy_dev(struct snet *snet);
205 int snet_read_vq_state(struct snet *snet, u16 idx, struct vdpa_vq_state *state);
206 int snet_suspend_dev(struct snet *snet);
207 int snet_resume_dev(struct snet *snet);
209 #endif //_SNET_VDPA_H_