162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * SolidRun DPU driver for control plane
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2022-2023 SolidRun
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci#ifndef _SNET_VDPA_H_
1162306a36Sopenharmony_ci#define _SNET_VDPA_H_
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/vdpa.h>
1462306a36Sopenharmony_ci#include <linux/pci.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define SNET_NAME_SIZE 256
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define SNET_ERR(pdev, fmt, ...) dev_err(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
1962306a36Sopenharmony_ci#define SNET_WARN(pdev, fmt, ...) dev_warn(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
2062306a36Sopenharmony_ci#define SNET_INFO(pdev, fmt, ...) dev_info(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
2162306a36Sopenharmony_ci#define SNET_DBG(pdev, fmt, ...) dev_dbg(&(pdev)->dev, "%s"fmt, "snet_vdpa: ", ##__VA_ARGS__)
2262306a36Sopenharmony_ci#define SNET_HAS_FEATURE(s, f) ((s)->negotiated_features & BIT_ULL(f))
2362306a36Sopenharmony_ci/* Check if negotiated config version is at least @ver */
2462306a36Sopenharmony_ci#define SNET_CFG_VER(snet, ver) ((snet)->psnet->negotiated_cfg_ver >= (ver))
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* VQ struct */
2762306a36Sopenharmony_cistruct snet_vq {
2862306a36Sopenharmony_ci	/* VQ callback */
2962306a36Sopenharmony_ci	struct vdpa_callback cb;
3062306a36Sopenharmony_ci	/* VQ state received from bus */
3162306a36Sopenharmony_ci	struct vdpa_vq_state vq_state;
3262306a36Sopenharmony_ci	/* desc base address */
3362306a36Sopenharmony_ci	u64 desc_area;
3462306a36Sopenharmony_ci	/* device base address */
3562306a36Sopenharmony_ci	u64 device_area;
3662306a36Sopenharmony_ci	/* driver base address */
3762306a36Sopenharmony_ci	u64 driver_area;
3862306a36Sopenharmony_ci	/* Queue size */
3962306a36Sopenharmony_ci	u32 num;
4062306a36Sopenharmony_ci	/* Serial ID for VQ */
4162306a36Sopenharmony_ci	u32 sid;
4262306a36Sopenharmony_ci	/* is ready flag */
4362306a36Sopenharmony_ci	bool ready;
4462306a36Sopenharmony_ci	/* IRQ number */
4562306a36Sopenharmony_ci	u32 irq;
4662306a36Sopenharmony_ci	/* IRQ index, DPU uses this to parse data from MSI-X table */
4762306a36Sopenharmony_ci	u32 irq_idx;
4862306a36Sopenharmony_ci	/* IRQ name */
4962306a36Sopenharmony_ci	char irq_name[SNET_NAME_SIZE];
5062306a36Sopenharmony_ci	/* pointer to mapped PCI BAR register used by this VQ to kick */
5162306a36Sopenharmony_ci	void __iomem *kick_ptr;
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistruct snet {
5562306a36Sopenharmony_ci	/* vdpa device */
5662306a36Sopenharmony_ci	struct vdpa_device vdpa;
5762306a36Sopenharmony_ci	/* Config callback */
5862306a36Sopenharmony_ci	struct vdpa_callback cb;
5962306a36Sopenharmony_ci	/* To lock the control mechanism */
6062306a36Sopenharmony_ci	struct mutex ctrl_lock;
6162306a36Sopenharmony_ci	/* Spinlock to protect critical parts in the control mechanism */
6262306a36Sopenharmony_ci	spinlock_t ctrl_spinlock;
6362306a36Sopenharmony_ci	/* array of virqueues */
6462306a36Sopenharmony_ci	struct snet_vq **vqs;
6562306a36Sopenharmony_ci	/* Used features */
6662306a36Sopenharmony_ci	u64 negotiated_features;
6762306a36Sopenharmony_ci	/* Device serial ID */
6862306a36Sopenharmony_ci	u32 sid;
6962306a36Sopenharmony_ci	/* device status */
7062306a36Sopenharmony_ci	u8 status;
7162306a36Sopenharmony_ci	/* boolean indicating if snet config was passed to the device */
7262306a36Sopenharmony_ci	bool dpu_ready;
7362306a36Sopenharmony_ci	/* IRQ number */
7462306a36Sopenharmony_ci	u32 cfg_irq;
7562306a36Sopenharmony_ci	/* IRQ index, DPU uses this to parse data from MSI-X table */
7662306a36Sopenharmony_ci	u32 cfg_irq_idx;
7762306a36Sopenharmony_ci	/* IRQ name */
7862306a36Sopenharmony_ci	char cfg_irq_name[SNET_NAME_SIZE];
7962306a36Sopenharmony_ci	/* BAR to access the VF */
8062306a36Sopenharmony_ci	void __iomem *bar;
8162306a36Sopenharmony_ci	/* PCI device */
8262306a36Sopenharmony_ci	struct pci_dev *pdev;
8362306a36Sopenharmony_ci	/* Pointer to snet pdev parent device */
8462306a36Sopenharmony_ci	struct psnet *psnet;
8562306a36Sopenharmony_ci	/* Pointer to snet config device */
8662306a36Sopenharmony_ci	struct snet_dev_cfg *cfg;
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistruct snet_dev_cfg {
9062306a36Sopenharmony_ci	/* Device ID following VirtIO spec. */
9162306a36Sopenharmony_ci	u32 virtio_id;
9262306a36Sopenharmony_ci	/* Number of VQs for this device */
9362306a36Sopenharmony_ci	u32 vq_num;
9462306a36Sopenharmony_ci	/* Size of every VQ */
9562306a36Sopenharmony_ci	u32 vq_size;
9662306a36Sopenharmony_ci	/* Virtual Function id */
9762306a36Sopenharmony_ci	u32 vfid;
9862306a36Sopenharmony_ci	/* Device features, following VirtIO spec */
9962306a36Sopenharmony_ci	u64 features;
10062306a36Sopenharmony_ci	/* Reserved for future usage */
10162306a36Sopenharmony_ci	u32 rsvd[6];
10262306a36Sopenharmony_ci	/* VirtIO device specific config size */
10362306a36Sopenharmony_ci	u32 cfg_size;
10462306a36Sopenharmony_ci	/* VirtIO device specific config address */
10562306a36Sopenharmony_ci	void __iomem *virtio_cfg;
10662306a36Sopenharmony_ci} __packed;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistruct snet_cfg {
10962306a36Sopenharmony_ci	/* Magic key */
11062306a36Sopenharmony_ci	u32 key;
11162306a36Sopenharmony_ci	/* Size of total config in bytes */
11262306a36Sopenharmony_ci	u32 cfg_size;
11362306a36Sopenharmony_ci	/* Config version */
11462306a36Sopenharmony_ci	u32 cfg_ver;
11562306a36Sopenharmony_ci	/* Number of Virtual Functions to create */
11662306a36Sopenharmony_ci	u32 vf_num;
11762306a36Sopenharmony_ci	/* BAR to use for the VFs */
11862306a36Sopenharmony_ci	u32 vf_bar;
11962306a36Sopenharmony_ci	/* Where should we write the SNET's config */
12062306a36Sopenharmony_ci	u32 host_cfg_off;
12162306a36Sopenharmony_ci	/* Max. allowed size for a SNET's config */
12262306a36Sopenharmony_ci	u32 max_size_host_cfg;
12362306a36Sopenharmony_ci	/* VirtIO config offset in BAR */
12462306a36Sopenharmony_ci	u32 virtio_cfg_off;
12562306a36Sopenharmony_ci	/* Offset in PCI BAR for VQ kicks */
12662306a36Sopenharmony_ci	u32 kick_off;
12762306a36Sopenharmony_ci	/* Offset in PCI BAR for HW monitoring */
12862306a36Sopenharmony_ci	u32 hwmon_off;
12962306a36Sopenharmony_ci	/* Offset in PCI BAR for Control mechanism */
13062306a36Sopenharmony_ci	u32 ctrl_off;
13162306a36Sopenharmony_ci	/* Config general flags - enum snet_cfg_flags */
13262306a36Sopenharmony_ci	u32 flags;
13362306a36Sopenharmony_ci	/* Reserved for future usage */
13462306a36Sopenharmony_ci	u32 rsvd[6];
13562306a36Sopenharmony_ci	/* Number of snet devices */
13662306a36Sopenharmony_ci	u32 devices_num;
13762306a36Sopenharmony_ci	/* The actual devices */
13862306a36Sopenharmony_ci	struct snet_dev_cfg **devs;
13962306a36Sopenharmony_ci} __packed;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci/* SolidNET PCIe device, one device per PCIe physical function */
14262306a36Sopenharmony_cistruct psnet {
14362306a36Sopenharmony_ci	/* PCI BARs */
14462306a36Sopenharmony_ci	void __iomem *bars[PCI_STD_NUM_BARS];
14562306a36Sopenharmony_ci	/* Negotiated config version */
14662306a36Sopenharmony_ci	u32 negotiated_cfg_ver;
14762306a36Sopenharmony_ci	/* Next IRQ index to use in case when the IRQs are allocated from this device */
14862306a36Sopenharmony_ci	u32 next_irq;
14962306a36Sopenharmony_ci	/* BAR number used to communicate with the device */
15062306a36Sopenharmony_ci	u8 barno;
15162306a36Sopenharmony_ci	/* spinlock to protect data that can be changed by SNET devices */
15262306a36Sopenharmony_ci	spinlock_t lock;
15362306a36Sopenharmony_ci	/* Pointer to the device's config read from BAR */
15462306a36Sopenharmony_ci	struct snet_cfg cfg;
15562306a36Sopenharmony_ci	/* Name of monitor device */
15662306a36Sopenharmony_ci	char hwmon_name[SNET_NAME_SIZE];
15762306a36Sopenharmony_ci};
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cienum snet_cfg_flags {
16062306a36Sopenharmony_ci	/* Create a HWMON device */
16162306a36Sopenharmony_ci	SNET_CFG_FLAG_HWMON = BIT(0),
16262306a36Sopenharmony_ci	/* USE IRQs from the physical function */
16362306a36Sopenharmony_ci	SNET_CFG_FLAG_IRQ_PF = BIT(1),
16462306a36Sopenharmony_ci};
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci#define PSNET_FLAG_ON(p, f)	((p)->cfg.flags & (f))
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic inline u32 psnet_read32(struct psnet *psnet, u32 off)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	return ioread32(psnet->bars[psnet->barno] + off);
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic inline u32 snet_read32(struct snet *snet, u32 off)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	return ioread32(snet->bar + off);
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic inline void snet_write32(struct snet *snet, u32 off, u32 val)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	iowrite32(val, snet->bar + off);
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic inline u64 psnet_read64(struct psnet *psnet, u32 off)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	u64 val;
18662306a36Sopenharmony_ci	/* 64bits are written in 2 halves, low part first */
18762306a36Sopenharmony_ci	val = (u64)psnet_read32(psnet, off);
18862306a36Sopenharmony_ci	val |= ((u64)psnet_read32(psnet, off + 4) << 32);
18962306a36Sopenharmony_ci	return val;
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic inline void snet_write64(struct snet *snet, u32 off, u64 val)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	/* The DPU expects a 64bit integer in 2 halves, the low part first */
19562306a36Sopenharmony_ci	snet_write32(snet, off, (u32)val);
19662306a36Sopenharmony_ci	snet_write32(snet, off + 4, (u32)(val >> 32));
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_HWMON)
20062306a36Sopenharmony_civoid psnet_create_hwmon(struct pci_dev *pdev);
20162306a36Sopenharmony_ci#endif
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_civoid snet_ctrl_clear(struct snet *snet);
20462306a36Sopenharmony_ciint snet_destroy_dev(struct snet *snet);
20562306a36Sopenharmony_ciint snet_read_vq_state(struct snet *snet, u16 idx, struct vdpa_vq_state *state);
20662306a36Sopenharmony_ciint snet_suspend_dev(struct snet *snet);
20762306a36Sopenharmony_ciint snet_resume_dev(struct snet *snet);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci#endif //_SNET_VDPA_H_
210