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