xref: /openbmc/linux/drivers/vdpa/solidrun/snet_vdpa.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
151a8f9d7SAlvaro Karsz /* SPDX-License-Identifier: GPL-2.0-only */
251a8f9d7SAlvaro Karsz /*
351a8f9d7SAlvaro Karsz  * SolidRun DPU driver for control plane
451a8f9d7SAlvaro Karsz  *
53f3a1675SAlvaro Karsz  * Copyright (C) 2022-2023 SolidRun
651a8f9d7SAlvaro Karsz  *
751a8f9d7SAlvaro Karsz  * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
851a8f9d7SAlvaro Karsz  *
951a8f9d7SAlvaro Karsz  */
1051a8f9d7SAlvaro Karsz #ifndef _SNET_VDPA_H_
1151a8f9d7SAlvaro Karsz #define _SNET_VDPA_H_
1251a8f9d7SAlvaro Karsz 
1351a8f9d7SAlvaro Karsz #include <linux/vdpa.h>
1451a8f9d7SAlvaro Karsz #include <linux/pci.h>
1551a8f9d7SAlvaro Karsz 
1651a8f9d7SAlvaro Karsz #define SNET_NAME_SIZE 256
1751a8f9d7SAlvaro Karsz 
1851a8f9d7SAlvaro Karsz #define SNET_ERR(pdev, fmt, ...) dev_err(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
1951a8f9d7SAlvaro Karsz #define SNET_WARN(pdev, fmt, ...) dev_warn(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
2051a8f9d7SAlvaro Karsz #define SNET_INFO(pdev, fmt, ...) dev_info(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
2151a8f9d7SAlvaro Karsz #define SNET_DBG(pdev, fmt, ...) dev_dbg(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
2251a8f9d7SAlvaro Karsz #define SNET_HAS_FEATURE(s, f) ((s)->negotiated_features & BIT_ULL(f))
233f3a1675SAlvaro Karsz /* Check if negotiated config version is at least @ver */
243f3a1675SAlvaro Karsz #define SNET_CFG_VER(snet, ver) ((snet)->psnet->negotiated_cfg_ver >= (ver))
253f3a1675SAlvaro Karsz 
2651a8f9d7SAlvaro Karsz /* VQ struct */
2751a8f9d7SAlvaro Karsz struct snet_vq {
2851a8f9d7SAlvaro Karsz 	/* VQ callback */
2951a8f9d7SAlvaro Karsz 	struct vdpa_callback cb;
303f3a1675SAlvaro Karsz 	/* VQ state received from bus */
313f3a1675SAlvaro Karsz 	struct vdpa_vq_state vq_state;
3251a8f9d7SAlvaro Karsz 	/* desc base address */
3351a8f9d7SAlvaro Karsz 	u64 desc_area;
3451a8f9d7SAlvaro Karsz 	/* device base address */
3551a8f9d7SAlvaro Karsz 	u64 device_area;
3651a8f9d7SAlvaro Karsz 	/* driver base address */
3751a8f9d7SAlvaro Karsz 	u64 driver_area;
3851a8f9d7SAlvaro Karsz 	/* Queue size */
3951a8f9d7SAlvaro Karsz 	u32 num;
4051a8f9d7SAlvaro Karsz 	/* Serial ID for VQ */
4151a8f9d7SAlvaro Karsz 	u32 sid;
4251a8f9d7SAlvaro Karsz 	/* is ready flag */
4351a8f9d7SAlvaro Karsz 	bool ready;
4451a8f9d7SAlvaro Karsz 	/* IRQ number */
4551a8f9d7SAlvaro Karsz 	u32 irq;
4651a8f9d7SAlvaro Karsz 	/* IRQ index, DPU uses this to parse data from MSI-X table */
4751a8f9d7SAlvaro Karsz 	u32 irq_idx;
4851a8f9d7SAlvaro Karsz 	/* IRQ name */
4951a8f9d7SAlvaro Karsz 	char irq_name[SNET_NAME_SIZE];
5051a8f9d7SAlvaro Karsz 	/* pointer to mapped PCI BAR register used by this VQ to kick */
5151a8f9d7SAlvaro Karsz 	void __iomem *kick_ptr;
5251a8f9d7SAlvaro Karsz };
5351a8f9d7SAlvaro Karsz 
5451a8f9d7SAlvaro Karsz struct snet {
5551a8f9d7SAlvaro Karsz 	/* vdpa device */
5651a8f9d7SAlvaro Karsz 	struct vdpa_device vdpa;
5751a8f9d7SAlvaro Karsz 	/* Config callback */
5851a8f9d7SAlvaro Karsz 	struct vdpa_callback cb;
593f3a1675SAlvaro Karsz 	/* To lock the control mechanism */
603f3a1675SAlvaro Karsz 	struct mutex ctrl_lock;
613f3a1675SAlvaro Karsz 	/* Spinlock to protect critical parts in the control mechanism */
623f3a1675SAlvaro Karsz 	spinlock_t ctrl_spinlock;
6351a8f9d7SAlvaro Karsz 	/* array of virqueues */
6451a8f9d7SAlvaro Karsz 	struct snet_vq **vqs;
6551a8f9d7SAlvaro Karsz 	/* Used features */
6651a8f9d7SAlvaro Karsz 	u64 negotiated_features;
6751a8f9d7SAlvaro Karsz 	/* Device serial ID */
6851a8f9d7SAlvaro Karsz 	u32 sid;
6951a8f9d7SAlvaro Karsz 	/* device status */
7051a8f9d7SAlvaro Karsz 	u8 status;
7151a8f9d7SAlvaro Karsz 	/* boolean indicating if snet config was passed to the device */
7251a8f9d7SAlvaro Karsz 	bool dpu_ready;
7351a8f9d7SAlvaro Karsz 	/* IRQ number */
7451a8f9d7SAlvaro Karsz 	u32 cfg_irq;
7551a8f9d7SAlvaro Karsz 	/* IRQ index, DPU uses this to parse data from MSI-X table */
7651a8f9d7SAlvaro Karsz 	u32 cfg_irq_idx;
7751a8f9d7SAlvaro Karsz 	/* IRQ name */
7851a8f9d7SAlvaro Karsz 	char cfg_irq_name[SNET_NAME_SIZE];
7951a8f9d7SAlvaro Karsz 	/* BAR to access the VF */
8051a8f9d7SAlvaro Karsz 	void __iomem *bar;
8151a8f9d7SAlvaro Karsz 	/* PCI device */
8251a8f9d7SAlvaro Karsz 	struct pci_dev *pdev;
8351a8f9d7SAlvaro Karsz 	/* Pointer to snet pdev parent device */
8451a8f9d7SAlvaro Karsz 	struct psnet *psnet;
8551a8f9d7SAlvaro Karsz 	/* Pointer to snet config device */
8651a8f9d7SAlvaro Karsz 	struct snet_dev_cfg *cfg;
8751a8f9d7SAlvaro Karsz };
8851a8f9d7SAlvaro Karsz 
8951a8f9d7SAlvaro Karsz struct snet_dev_cfg {
9051a8f9d7SAlvaro Karsz 	/* Device ID following VirtIO spec. */
9151a8f9d7SAlvaro Karsz 	u32 virtio_id;
9251a8f9d7SAlvaro Karsz 	/* Number of VQs for this device */
9351a8f9d7SAlvaro Karsz 	u32 vq_num;
9451a8f9d7SAlvaro Karsz 	/* Size of every VQ */
9551a8f9d7SAlvaro Karsz 	u32 vq_size;
9651a8f9d7SAlvaro Karsz 	/* Virtual Function id */
9751a8f9d7SAlvaro Karsz 	u32 vfid;
9851a8f9d7SAlvaro Karsz 	/* Device features, following VirtIO spec */
9951a8f9d7SAlvaro Karsz 	u64 features;
10051a8f9d7SAlvaro Karsz 	/* Reserved for future usage */
10151a8f9d7SAlvaro Karsz 	u32 rsvd[6];
10251a8f9d7SAlvaro Karsz 	/* VirtIO device specific config size */
10351a8f9d7SAlvaro Karsz 	u32 cfg_size;
10451a8f9d7SAlvaro Karsz 	/* VirtIO device specific config address */
10551a8f9d7SAlvaro Karsz 	void __iomem *virtio_cfg;
10651a8f9d7SAlvaro Karsz } __packed;
10751a8f9d7SAlvaro Karsz 
10851a8f9d7SAlvaro Karsz struct snet_cfg {
10951a8f9d7SAlvaro Karsz 	/* Magic key */
11051a8f9d7SAlvaro Karsz 	u32 key;
11151a8f9d7SAlvaro Karsz 	/* Size of total config in bytes */
11251a8f9d7SAlvaro Karsz 	u32 cfg_size;
11351a8f9d7SAlvaro Karsz 	/* Config version */
11451a8f9d7SAlvaro Karsz 	u32 cfg_ver;
11551a8f9d7SAlvaro Karsz 	/* Number of Virtual Functions to create */
11651a8f9d7SAlvaro Karsz 	u32 vf_num;
11751a8f9d7SAlvaro Karsz 	/* BAR to use for the VFs */
11851a8f9d7SAlvaro Karsz 	u32 vf_bar;
11951a8f9d7SAlvaro Karsz 	/* Where should we write the SNET's config */
12051a8f9d7SAlvaro Karsz 	u32 host_cfg_off;
12151a8f9d7SAlvaro Karsz 	/* Max. allowed size for a SNET's config */
12251a8f9d7SAlvaro Karsz 	u32 max_size_host_cfg;
12351a8f9d7SAlvaro Karsz 	/* VirtIO config offset in BAR */
12451a8f9d7SAlvaro Karsz 	u32 virtio_cfg_off;
12551a8f9d7SAlvaro Karsz 	/* Offset in PCI BAR for VQ kicks */
12651a8f9d7SAlvaro Karsz 	u32 kick_off;
12751a8f9d7SAlvaro Karsz 	/* Offset in PCI BAR for HW monitoring */
12851a8f9d7SAlvaro Karsz 	u32 hwmon_off;
1293f3a1675SAlvaro Karsz 	/* Offset in PCI BAR for Control mechanism */
1303f3a1675SAlvaro Karsz 	u32 ctrl_off;
13151a8f9d7SAlvaro Karsz 	/* Config general flags - enum snet_cfg_flags */
13251a8f9d7SAlvaro Karsz 	u32 flags;
13351a8f9d7SAlvaro Karsz 	/* Reserved for future usage */
13451a8f9d7SAlvaro Karsz 	u32 rsvd[6];
13551a8f9d7SAlvaro Karsz 	/* Number of snet devices */
13651a8f9d7SAlvaro Karsz 	u32 devices_num;
13751a8f9d7SAlvaro Karsz 	/* The actual devices */
13851a8f9d7SAlvaro Karsz 	struct snet_dev_cfg **devs;
13951a8f9d7SAlvaro Karsz } __packed;
14051a8f9d7SAlvaro Karsz 
14151a8f9d7SAlvaro Karsz /* SolidNET PCIe device, one device per PCIe physical function */
14251a8f9d7SAlvaro Karsz struct psnet {
14351a8f9d7SAlvaro Karsz 	/* PCI BARs */
14451a8f9d7SAlvaro Karsz 	void __iomem *bars[PCI_STD_NUM_BARS];
14551a8f9d7SAlvaro Karsz 	/* Negotiated config version */
14651a8f9d7SAlvaro Karsz 	u32 negotiated_cfg_ver;
14751a8f9d7SAlvaro Karsz 	/* Next IRQ index to use in case when the IRQs are allocated from this device */
14851a8f9d7SAlvaro Karsz 	u32 next_irq;
14951a8f9d7SAlvaro Karsz 	/* BAR number used to communicate with the device */
15051a8f9d7SAlvaro Karsz 	u8 barno;
15151a8f9d7SAlvaro Karsz 	/* spinlock to protect data that can be changed by SNET devices */
15251a8f9d7SAlvaro Karsz 	spinlock_t lock;
15351a8f9d7SAlvaro Karsz 	/* Pointer to the device's config read from BAR */
15451a8f9d7SAlvaro Karsz 	struct snet_cfg cfg;
15551a8f9d7SAlvaro Karsz 	/* Name of monitor device */
15651a8f9d7SAlvaro Karsz 	char hwmon_name[SNET_NAME_SIZE];
15751a8f9d7SAlvaro Karsz };
15851a8f9d7SAlvaro Karsz 
15951a8f9d7SAlvaro Karsz enum snet_cfg_flags {
16051a8f9d7SAlvaro Karsz 	/* Create a HWMON device */
16151a8f9d7SAlvaro Karsz 	SNET_CFG_FLAG_HWMON = BIT(0),
16251a8f9d7SAlvaro Karsz 	/* USE IRQs from the physical function */
16351a8f9d7SAlvaro Karsz 	SNET_CFG_FLAG_IRQ_PF = BIT(1),
16451a8f9d7SAlvaro Karsz };
16551a8f9d7SAlvaro Karsz 
16651a8f9d7SAlvaro Karsz #define PSNET_FLAG_ON(p, f)	((p)->cfg.flags & (f))
16751a8f9d7SAlvaro Karsz 
psnet_read32(struct psnet * psnet,u32 off)16851a8f9d7SAlvaro Karsz static inline u32 psnet_read32(struct psnet *psnet, u32 off)
16951a8f9d7SAlvaro Karsz {
17051a8f9d7SAlvaro Karsz 	return ioread32(psnet->bars[psnet->barno] + off);
17151a8f9d7SAlvaro Karsz }
17251a8f9d7SAlvaro Karsz 
snet_read32(struct snet * snet,u32 off)17351a8f9d7SAlvaro Karsz static inline u32 snet_read32(struct snet *snet, u32 off)
17451a8f9d7SAlvaro Karsz {
17551a8f9d7SAlvaro Karsz 	return ioread32(snet->bar + off);
17651a8f9d7SAlvaro Karsz }
17751a8f9d7SAlvaro Karsz 
snet_write32(struct snet * snet,u32 off,u32 val)17851a8f9d7SAlvaro Karsz static inline void snet_write32(struct snet *snet, u32 off, u32 val)
17951a8f9d7SAlvaro Karsz {
18051a8f9d7SAlvaro Karsz 	iowrite32(val, snet->bar + off);
18151a8f9d7SAlvaro Karsz }
18251a8f9d7SAlvaro Karsz 
psnet_read64(struct psnet * psnet,u32 off)18351a8f9d7SAlvaro Karsz static inline u64 psnet_read64(struct psnet *psnet, u32 off)
18451a8f9d7SAlvaro Karsz {
18551a8f9d7SAlvaro Karsz 	u64 val;
18651a8f9d7SAlvaro Karsz 	/* 64bits are written in 2 halves, low part first */
18751a8f9d7SAlvaro Karsz 	val = (u64)psnet_read32(psnet, off);
18851a8f9d7SAlvaro Karsz 	val |= ((u64)psnet_read32(psnet, off + 4) << 32);
18951a8f9d7SAlvaro Karsz 	return val;
19051a8f9d7SAlvaro Karsz }
19151a8f9d7SAlvaro Karsz 
snet_write64(struct snet * snet,u32 off,u64 val)19251a8f9d7SAlvaro Karsz static inline void snet_write64(struct snet *snet, u32 off, u64 val)
19351a8f9d7SAlvaro Karsz {
19451a8f9d7SAlvaro Karsz 	/* The DPU expects a 64bit integer in 2 halves, the low part first */
19551a8f9d7SAlvaro Karsz 	snet_write32(snet, off, (u32)val);
19651a8f9d7SAlvaro Karsz 	snet_write32(snet, off + 4, (u32)(val >> 32));
19751a8f9d7SAlvaro Karsz }
19851a8f9d7SAlvaro Karsz 
19951a8f9d7SAlvaro Karsz #if IS_ENABLED(CONFIG_HWMON)
20051a8f9d7SAlvaro Karsz void psnet_create_hwmon(struct pci_dev *pdev);
20151a8f9d7SAlvaro Karsz #endif
20251a8f9d7SAlvaro Karsz 
2033f3a1675SAlvaro Karsz void snet_ctrl_clear(struct snet *snet);
2043f3a1675SAlvaro Karsz int snet_destroy_dev(struct snet *snet);
2053f3a1675SAlvaro Karsz int snet_read_vq_state(struct snet *snet, u16 idx, struct vdpa_vq_state *state);
206*3616bf37SAlvaro Karsz int snet_suspend_dev(struct snet *snet);
2073f3a1675SAlvaro Karsz int snet_resume_dev(struct snet *snet);
20851a8f9d7SAlvaro Karsz 
209 #endif //_SNET_VDPA_H_
210