Loading...
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_ |