210 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * SolidRun DPU driver for control plane4 *5 * Copyright (C) 2022-2023 SolidRun6 *7 * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>8 *9 */10#ifndef _SNET_VDPA_H_11#define _SNET_VDPA_H_12 13#include <linux/vdpa.h>14#include <linux/pci.h>15 16#define SNET_NAME_SIZE 25617 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))25 26/* VQ struct */27struct snet_vq {28 /* VQ callback */29 struct vdpa_callback cb;30 /* VQ state received from bus */31 struct vdpa_vq_state vq_state;32 /* desc base address */33 u64 desc_area;34 /* device base address */35 u64 device_area;36 /* driver base address */37 u64 driver_area;38 /* Queue size */39 u32 num;40 /* Serial ID for VQ */41 u32 sid;42 /* is ready flag */43 bool ready;44 /* IRQ number */45 u32 irq;46 /* IRQ index, DPU uses this to parse data from MSI-X table */47 u32 irq_idx;48 /* IRQ name */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;52};53 54struct snet {55 /* vdpa device */56 struct vdpa_device vdpa;57 /* Config callback */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 */64 struct snet_vq **vqs;65 /* Used features */66 u64 negotiated_features;67 /* Device serial ID */68 u32 sid;69 /* device status */70 u8 status;71 /* boolean indicating if snet config was passed to the device */72 bool dpu_ready;73 /* IRQ number */74 u32 cfg_irq;75 /* IRQ index, DPU uses this to parse data from MSI-X table */76 u32 cfg_irq_idx;77 /* IRQ name */78 char cfg_irq_name[SNET_NAME_SIZE];79 /* BAR to access the VF */80 void __iomem *bar;81 /* PCI device */82 struct pci_dev *pdev;83 /* Pointer to snet pdev parent device */84 struct psnet *psnet;85 /* Pointer to snet config device */86 struct snet_dev_cfg *cfg;87};88 89struct snet_dev_cfg {90 /* Device ID following VirtIO spec. */91 u32 virtio_id;92 /* Number of VQs for this device */93 u32 vq_num;94 /* Size of every VQ */95 u32 vq_size;96 /* Virtual Function id */97 u32 vfid;98 /* Device features, following VirtIO spec */99 u64 features;100 /* Reserved for future usage */101 u32 rsvd[6];102 /* VirtIO device specific config size */103 u32 cfg_size;104 /* VirtIO device specific config address */105 void __iomem *virtio_cfg;106} __packed;107 108struct snet_cfg {109 /* Magic key */110 u32 key;111 /* Size of total config in bytes */112 u32 cfg_size;113 /* Config version */114 u32 cfg_ver;115 /* Number of Virtual Functions to create */116 u32 vf_num;117 /* BAR to use for the VFs */118 u32 vf_bar;119 /* Where should we write the SNET's config */120 u32 host_cfg_off;121 /* Max. allowed size for a SNET's config */122 u32 max_size_host_cfg;123 /* VirtIO config offset in BAR */124 u32 virtio_cfg_off;125 /* Offset in PCI BAR for VQ kicks */126 u32 kick_off;127 /* Offset in PCI BAR for HW monitoring */128 u32 hwmon_off;129 /* Offset in PCI BAR for Control mechanism */130 u32 ctrl_off;131 /* Config general flags - enum snet_cfg_flags */132 u32 flags;133 /* Reserved for future usage */134 u32 rsvd[6];135 /* Number of snet devices */136 u32 devices_num;137 /* The actual devices */138 struct snet_dev_cfg **devs;139} __packed;140 141/* SolidNET PCIe device, one device per PCIe physical function */142struct psnet {143 /* PCI BARs */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 */148 u32 next_irq;149 /* BAR number used to communicate with the device */150 u8 barno;151 /* spinlock to protect data that can be changed by SNET devices */152 spinlock_t lock;153 /* Pointer to the device's config read from BAR */154 struct snet_cfg cfg;155 /* Name of monitor device */156 char hwmon_name[SNET_NAME_SIZE];157};158 159enum 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),164};165 166#define PSNET_FLAG_ON(p, f) ((p)->cfg.flags & (f))167 168static inline u32 psnet_read32(struct psnet *psnet, u32 off)169{170 return ioread32(psnet->bars[psnet->barno] + off);171}172 173static inline u32 snet_read32(struct snet *snet, u32 off)174{175 return ioread32(snet->bar + off);176}177 178static inline void snet_write32(struct snet *snet, u32 off, u32 val)179{180 iowrite32(val, snet->bar + off);181}182 183static inline u64 psnet_read64(struct psnet *psnet, u32 off)184{185 u64 val;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);189 return val;190}191 192static inline void snet_write64(struct snet *snet, u32 off, u64 val)193{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));197}198 199#if IS_ENABLED(CONFIG_HWMON)200void psnet_create_hwmon(struct pci_dev *pdev);201#endif202 203void snet_ctrl_clear(struct snet *snet);204int snet_destroy_dev(struct snet *snet);205int snet_read_vq_state(struct snet *snet, u16 idx, struct vdpa_vq_state *state);206int snet_suspend_dev(struct snet *snet);207int snet_resume_dev(struct snet *snet);208 209#endif //_SNET_VDPA_H_210