xref: /linux/drivers/dma/idxd/idxd.h (revision f6d442f7088cbf5e2ac4561aca6888380239d5b9)
1bfe1d560SDave Jiang /* SPDX-License-Identifier: GPL-2.0 */
2bfe1d560SDave Jiang /* Copyright(c) 2019 Intel Corporation. All rights rsvd. */
3bfe1d560SDave Jiang #ifndef _IDXD_H_
4bfe1d560SDave Jiang #define _IDXD_H_
5bfe1d560SDave Jiang 
6bfe1d560SDave Jiang #include <linux/sbitmap.h>
78f47d1a5SDave Jiang #include <linux/dmaengine.h>
8bfe1d560SDave Jiang #include <linux/percpu-rwsem.h>
9bfe1d560SDave Jiang #include <linux/wait.h>
1042d279f9SDave Jiang #include <linux/cdev.h>
1147c16ac2SDave Jiang #include <linux/idr.h>
1281dd4d4dSTom Zanussi #include <linux/pci.h>
138b67426eSDave Jiang #include <linux/ioasid.h>
1481dd4d4dSTom Zanussi #include <linux/perf_event.h>
15a9c17152SDave Jiang #include <uapi/linux/idxd.h>
16bfe1d560SDave Jiang #include "registers.h"
17bfe1d560SDave Jiang 
18bfe1d560SDave Jiang #define IDXD_DRIVER_VERSION	"1.00"
19bfe1d560SDave Jiang 
20bfe1d560SDave Jiang extern struct kmem_cache *idxd_desc_pool;
21ade8a86bSDave Jiang extern bool tc_override;
22bfe1d560SDave Jiang 
2339786285SDave Jiang struct idxd_wq;
24700af3a0SDave Jiang struct idxd_dev;
25700af3a0SDave Jiang 
26700af3a0SDave Jiang enum idxd_dev_type {
27700af3a0SDave Jiang 	IDXD_DEV_NONE = -1,
28700af3a0SDave Jiang 	IDXD_DEV_DSA = 0,
29700af3a0SDave Jiang 	IDXD_DEV_IAX,
30700af3a0SDave Jiang 	IDXD_DEV_WQ,
31700af3a0SDave Jiang 	IDXD_DEV_GROUP,
32700af3a0SDave Jiang 	IDXD_DEV_ENGINE,
33700af3a0SDave Jiang 	IDXD_DEV_CDEV,
34700af3a0SDave Jiang 	IDXD_DEV_MAX_TYPE,
35700af3a0SDave Jiang };
36700af3a0SDave Jiang 
37700af3a0SDave Jiang struct idxd_dev {
38700af3a0SDave Jiang 	struct device conf_dev;
39700af3a0SDave Jiang 	enum idxd_dev_type type;
40700af3a0SDave Jiang };
4139786285SDave Jiang 
42bfe1d560SDave Jiang #define IDXD_REG_TIMEOUT	50
43bfe1d560SDave Jiang #define IDXD_DRAIN_TIMEOUT	5000
44bfe1d560SDave Jiang 
45bfe1d560SDave Jiang enum idxd_type {
46bfe1d560SDave Jiang 	IDXD_TYPE_UNKNOWN = -1,
47bfe1d560SDave Jiang 	IDXD_TYPE_DSA = 0,
48f25b4638SDave Jiang 	IDXD_TYPE_IAX,
49f25b4638SDave Jiang 	IDXD_TYPE_MAX,
50bfe1d560SDave Jiang };
51bfe1d560SDave Jiang 
52bfe1d560SDave Jiang #define IDXD_NAME_SIZE		128
5381dd4d4dSTom Zanussi #define IDXD_PMU_EVENT_MAX	64
54bfe1d560SDave Jiang 
55bfe1d560SDave Jiang struct idxd_device_driver {
56da5a11d7SDave Jiang 	const char *name;
575fee6567SDave Jiang 	enum idxd_dev_type *type;
58fcc2281bSDave Jiang 	int (*probe)(struct idxd_dev *idxd_dev);
59fcc2281bSDave Jiang 	void (*remove)(struct idxd_dev *idxd_dev);
60bfe1d560SDave Jiang 	struct device_driver drv;
61bfe1d560SDave Jiang };
62bfe1d560SDave Jiang 
63c05257b5SDave Jiang extern struct idxd_device_driver dsa_drv;
64034b3290SDave Jiang extern struct idxd_device_driver idxd_drv;
650cda4f69SDave Jiang extern struct idxd_device_driver idxd_dmaengine_drv;
66448c3de8SDave Jiang extern struct idxd_device_driver idxd_user_drv;
67c05257b5SDave Jiang 
688b67426eSDave Jiang #define INVALID_INT_HANDLE	-1
69bfe1d560SDave Jiang struct idxd_irq_entry {
70bfe1d560SDave Jiang 	struct idxd_device *idxd;
71bfe1d560SDave Jiang 	int id;
725fc8e85fSDave Jiang 	int vector;
73bfe1d560SDave Jiang 	struct llist_head pending_llist;
74bfe1d560SDave Jiang 	struct list_head work_list;
75e4f4d8cdSDave Jiang 	/*
76e4f4d8cdSDave Jiang 	 * Lock to protect access between irq thread process descriptor
77e4f4d8cdSDave Jiang 	 * and irq thread processing error descriptor.
78e4f4d8cdSDave Jiang 	 */
79e4f4d8cdSDave Jiang 	spinlock_t list_lock;
808b67426eSDave Jiang 	int int_handle;
818b67426eSDave Jiang 	struct idxd_wq *wq;
828b67426eSDave Jiang 	ioasid_t pasid;
83bfe1d560SDave Jiang };
84bfe1d560SDave Jiang 
85bfe1d560SDave Jiang struct idxd_group {
86700af3a0SDave Jiang 	struct idxd_dev idxd_dev;
87bfe1d560SDave Jiang 	struct idxd_device *idxd;
88bfe1d560SDave Jiang 	struct grpcfg grpcfg;
89bfe1d560SDave Jiang 	int id;
90bfe1d560SDave Jiang 	int num_engines;
91bfe1d560SDave Jiang 	int num_wqs;
92bfe1d560SDave Jiang 	bool use_token_limit;
93bfe1d560SDave Jiang 	u8 tokens_allowed;
94bfe1d560SDave Jiang 	u8 tokens_reserved;
95bfe1d560SDave Jiang 	int tc_a;
96bfe1d560SDave Jiang 	int tc_b;
97bfe1d560SDave Jiang };
98bfe1d560SDave Jiang 
9981dd4d4dSTom Zanussi struct idxd_pmu {
10081dd4d4dSTom Zanussi 	struct idxd_device *idxd;
10181dd4d4dSTom Zanussi 
10281dd4d4dSTom Zanussi 	struct perf_event *event_list[IDXD_PMU_EVENT_MAX];
10381dd4d4dSTom Zanussi 	int n_events;
10481dd4d4dSTom Zanussi 
10581dd4d4dSTom Zanussi 	DECLARE_BITMAP(used_mask, IDXD_PMU_EVENT_MAX);
10681dd4d4dSTom Zanussi 
10781dd4d4dSTom Zanussi 	struct pmu pmu;
10881dd4d4dSTom Zanussi 	char name[IDXD_NAME_SIZE];
10981dd4d4dSTom Zanussi 	int cpu;
11081dd4d4dSTom Zanussi 
11181dd4d4dSTom Zanussi 	int n_counters;
11281dd4d4dSTom Zanussi 	int counter_width;
11381dd4d4dSTom Zanussi 	int n_event_categories;
11481dd4d4dSTom Zanussi 
11581dd4d4dSTom Zanussi 	bool per_counter_caps_supported;
11681dd4d4dSTom Zanussi 	unsigned long supported_event_categories;
11781dd4d4dSTom Zanussi 
11881dd4d4dSTom Zanussi 	unsigned long supported_filters;
11981dd4d4dSTom Zanussi 	int n_filters;
12081dd4d4dSTom Zanussi 
12181dd4d4dSTom Zanussi 	struct hlist_node cpuhp_node;
12281dd4d4dSTom Zanussi };
12381dd4d4dSTom Zanussi 
124bfe1d560SDave Jiang #define IDXD_MAX_PRIORITY	0xf
125bfe1d560SDave Jiang 
126bfe1d560SDave Jiang enum idxd_wq_state {
127bfe1d560SDave Jiang 	IDXD_WQ_DISABLED = 0,
128bfe1d560SDave Jiang 	IDXD_WQ_ENABLED,
129bfe1d560SDave Jiang };
130bfe1d560SDave Jiang 
131bfe1d560SDave Jiang enum idxd_wq_flag {
132bfe1d560SDave Jiang 	WQ_FLAG_DEDICATED = 0,
1338e50d392SDave Jiang 	WQ_FLAG_BLOCK_ON_FAULT,
134bfe1d560SDave Jiang };
135bfe1d560SDave Jiang 
136bfe1d560SDave Jiang enum idxd_wq_type {
137bfe1d560SDave Jiang 	IDXD_WQT_NONE = 0,
138bfe1d560SDave Jiang 	IDXD_WQT_KERNEL,
13942d279f9SDave Jiang 	IDXD_WQT_USER,
14042d279f9SDave Jiang };
14142d279f9SDave Jiang 
14242d279f9SDave Jiang struct idxd_cdev {
14304922b74SDave Jiang 	struct idxd_wq *wq;
14442d279f9SDave Jiang 	struct cdev cdev;
145700af3a0SDave Jiang 	struct idxd_dev idxd_dev;
14642d279f9SDave Jiang 	int minor;
147bfe1d560SDave Jiang };
148bfe1d560SDave Jiang 
149bfe1d560SDave Jiang #define IDXD_ALLOCATED_BATCH_SIZE	128U
150bfe1d560SDave Jiang #define WQ_NAME_SIZE   1024
151bfe1d560SDave Jiang #define WQ_TYPE_SIZE   10
152bfe1d560SDave Jiang 
153d1dfe5b8SDave Jiang enum idxd_op_type {
154d1dfe5b8SDave Jiang 	IDXD_OP_BLOCK = 0,
155d1dfe5b8SDave Jiang 	IDXD_OP_NONBLOCK = 1,
156d1dfe5b8SDave Jiang };
157d1dfe5b8SDave Jiang 
1588f47d1a5SDave Jiang enum idxd_complete_type {
1598f47d1a5SDave Jiang 	IDXD_COMPLETE_NORMAL = 0,
1608f47d1a5SDave Jiang 	IDXD_COMPLETE_ABORT,
1618e50d392SDave Jiang 	IDXD_COMPLETE_DEV_FAIL,
1628f47d1a5SDave Jiang };
1638f47d1a5SDave Jiang 
16439786285SDave Jiang struct idxd_dma_chan {
16539786285SDave Jiang 	struct dma_chan chan;
16639786285SDave Jiang 	struct idxd_wq *wq;
16739786285SDave Jiang };
16839786285SDave Jiang 
169bfe1d560SDave Jiang struct idxd_wq {
1708e50d392SDave Jiang 	void __iomem *portal;
171a9c17152SDave Jiang 	u32 portal_offset;
17293a40a6dSDave Jiang 	struct percpu_ref wq_active;
17393a40a6dSDave Jiang 	struct completion wq_dead;
174700af3a0SDave Jiang 	struct idxd_dev idxd_dev;
17504922b74SDave Jiang 	struct idxd_cdev *idxd_cdev;
17604922b74SDave Jiang 	struct wait_queue_head err_queue;
177bfe1d560SDave Jiang 	struct idxd_device *idxd;
178bfe1d560SDave Jiang 	int id;
1798b67426eSDave Jiang 	struct idxd_irq_entry *ie;
180bfe1d560SDave Jiang 	enum idxd_wq_type type;
181bfe1d560SDave Jiang 	struct idxd_group *group;
182bfe1d560SDave Jiang 	int client_count;
183bfe1d560SDave Jiang 	struct mutex wq_lock;	/* mutex for workqueue */
184bfe1d560SDave Jiang 	u32 size;
185bfe1d560SDave Jiang 	u32 threshold;
186bfe1d560SDave Jiang 	u32 priority;
187bfe1d560SDave Jiang 	enum idxd_wq_state state;
188bfe1d560SDave Jiang 	unsigned long flags;
189d98793b5SDave Jiang 	union wqcfg *wqcfg;
190bfe1d560SDave Jiang 	struct dsa_hw_desc **hw_descs;
191bfe1d560SDave Jiang 	int num_descs;
192f25b4638SDave Jiang 	union {
193bfe1d560SDave Jiang 		struct dsa_completion_record *compls;
194f25b4638SDave Jiang 		struct iax_completion_record *iax_compls;
195f25b4638SDave Jiang 	};
196bfe1d560SDave Jiang 	dma_addr_t compls_addr;
197bfe1d560SDave Jiang 	int compls_size;
198bfe1d560SDave Jiang 	struct idxd_desc **descs;
1990705107fSDave Jiang 	struct sbitmap_queue sbq;
20039786285SDave Jiang 	struct idxd_dma_chan *idxd_chan;
201bfe1d560SDave Jiang 	char name[WQ_NAME_SIZE + 1];
202d7aad555SDave Jiang 	u64 max_xfer_bytes;
203e7184b15SDave Jiang 	u32 max_batch_size;
20492de5fa2SDave Jiang 	bool ats_dis;
205bfe1d560SDave Jiang };
206bfe1d560SDave Jiang 
207bfe1d560SDave Jiang struct idxd_engine {
208700af3a0SDave Jiang 	struct idxd_dev idxd_dev;
209bfe1d560SDave Jiang 	int id;
210bfe1d560SDave Jiang 	struct idxd_group *group;
211bfe1d560SDave Jiang 	struct idxd_device *idxd;
212bfe1d560SDave Jiang };
213bfe1d560SDave Jiang 
214bfe1d560SDave Jiang /* shadow registers */
215bfe1d560SDave Jiang struct idxd_hw {
216bfe1d560SDave Jiang 	u32 version;
217bfe1d560SDave Jiang 	union gen_cap_reg gen_cap;
218bfe1d560SDave Jiang 	union wq_cap_reg wq_cap;
219bfe1d560SDave Jiang 	union group_cap_reg group_cap;
220bfe1d560SDave Jiang 	union engine_cap_reg engine_cap;
221bfe1d560SDave Jiang 	struct opcap opcap;
222eb15e715SDave Jiang 	u32 cmd_cap;
223bfe1d560SDave Jiang };
224bfe1d560SDave Jiang 
225bfe1d560SDave Jiang enum idxd_device_state {
226bfe1d560SDave Jiang 	IDXD_DEV_HALTED = -1,
227bfe1d560SDave Jiang 	IDXD_DEV_DISABLED = 0,
228bfe1d560SDave Jiang 	IDXD_DEV_ENABLED,
229bfe1d560SDave Jiang };
230bfe1d560SDave Jiang 
231bfe1d560SDave Jiang enum idxd_device_flag {
232bfe1d560SDave Jiang 	IDXD_FLAG_CONFIGURABLE = 0,
2330d5c10b4SDave Jiang 	IDXD_FLAG_CMD_RUNNING,
2348e50d392SDave Jiang 	IDXD_FLAG_PASID_ENABLED,
235bfe1d560SDave Jiang };
236bfe1d560SDave Jiang 
23739786285SDave Jiang struct idxd_dma_dev {
23839786285SDave Jiang 	struct idxd_device *idxd;
23939786285SDave Jiang 	struct dma_device dma;
24039786285SDave Jiang };
24139786285SDave Jiang 
242435b512dSDave Jiang struct idxd_driver_data {
243435b512dSDave Jiang 	const char *name_prefix;
244bfe1d560SDave Jiang 	enum idxd_type type;
245435b512dSDave Jiang 	struct device_type *dev_type;
246435b512dSDave Jiang 	int compl_size;
247435b512dSDave Jiang 	int align;
248435b512dSDave Jiang };
249435b512dSDave Jiang 
250435b512dSDave Jiang struct idxd_device {
251700af3a0SDave Jiang 	struct idxd_dev idxd_dev;
252435b512dSDave Jiang 	struct idxd_driver_data *data;
253bfe1d560SDave Jiang 	struct list_head list;
254bfe1d560SDave Jiang 	struct idxd_hw hw;
255bfe1d560SDave Jiang 	enum idxd_device_state state;
256bfe1d560SDave Jiang 	unsigned long flags;
257bfe1d560SDave Jiang 	int id;
25842d279f9SDave Jiang 	int major;
259125d1037SDave Jiang 	u32 cmd_status;
260bfe1d560SDave Jiang 
261bfe1d560SDave Jiang 	struct pci_dev *pdev;
262bfe1d560SDave Jiang 	void __iomem *reg_base;
263bfe1d560SDave Jiang 
264bfe1d560SDave Jiang 	spinlock_t dev_lock;	/* spinlock for device */
26553b2ee7fSDave Jiang 	spinlock_t cmd_lock;	/* spinlock for device commands */
2660d5c10b4SDave Jiang 	struct completion *cmd_done;
267defe49f9SDave Jiang 	struct idxd_group **groups;
2687c5dd23eSDave Jiang 	struct idxd_wq **wqs;
26975b91130SDave Jiang 	struct idxd_engine **engines;
270bfe1d560SDave Jiang 
2718e50d392SDave Jiang 	struct iommu_sva *sva;
2728e50d392SDave Jiang 	unsigned int pasid;
2738e50d392SDave Jiang 
274bfe1d560SDave Jiang 	int num_groups;
2758b67426eSDave Jiang 	int irq_cnt;
2768b67426eSDave Jiang 	bool request_int_handles;
277bfe1d560SDave Jiang 
278bfe1d560SDave Jiang 	u32 msix_perm_offset;
279bfe1d560SDave Jiang 	u32 wqcfg_offset;
280bfe1d560SDave Jiang 	u32 grpcfg_offset;
281bfe1d560SDave Jiang 	u32 perfmon_offset;
282bfe1d560SDave Jiang 
283bfe1d560SDave Jiang 	u64 max_xfer_bytes;
284bfe1d560SDave Jiang 	u32 max_batch_size;
285bfe1d560SDave Jiang 	int max_groups;
286bfe1d560SDave Jiang 	int max_engines;
287bfe1d560SDave Jiang 	int max_tokens;
288bfe1d560SDave Jiang 	int max_wqs;
289bfe1d560SDave Jiang 	int max_wq_size;
290bfe1d560SDave Jiang 	int token_limit;
291c52ca478SDave Jiang 	int nr_tokens;		/* non-reserved tokens */
292d98793b5SDave Jiang 	unsigned int wqcfg_size;
293bfe1d560SDave Jiang 
294bfe1d560SDave Jiang 	union sw_err_reg sw_err;
2950d5c10b4SDave Jiang 	wait_queue_head_t cmd_waitq;
296bfe1d560SDave Jiang 	int num_wq_irqs;
297bfe1d560SDave Jiang 	struct idxd_irq_entry *irq_entries;
2988f47d1a5SDave Jiang 
29939786285SDave Jiang 	struct idxd_dma_dev *idxd_dma;
3000d5c10b4SDave Jiang 	struct workqueue_struct *wq;
3010d5c10b4SDave Jiang 	struct work_struct work;
302eb15e715SDave Jiang 
30381dd4d4dSTom Zanussi 	struct idxd_pmu *idxd_pmu;
304bfe1d560SDave Jiang };
305bfe1d560SDave Jiang 
306bfe1d560SDave Jiang /* IDXD software descriptor */
307bfe1d560SDave Jiang struct idxd_desc {
308f25b4638SDave Jiang 	union {
309bfe1d560SDave Jiang 		struct dsa_hw_desc *hw;
310f25b4638SDave Jiang 		struct iax_hw_desc *iax_hw;
311f25b4638SDave Jiang 	};
312bfe1d560SDave Jiang 	dma_addr_t desc_dma;
313f25b4638SDave Jiang 	union {
314bfe1d560SDave Jiang 		struct dsa_completion_record *completion;
315f25b4638SDave Jiang 		struct iax_completion_record *iax_completion;
316f25b4638SDave Jiang 	};
317bfe1d560SDave Jiang 	dma_addr_t compl_dma;
3188f47d1a5SDave Jiang 	struct dma_async_tx_descriptor txd;
319bfe1d560SDave Jiang 	struct llist_node llnode;
320bfe1d560SDave Jiang 	struct list_head list;
321bfe1d560SDave Jiang 	int id;
3220705107fSDave Jiang 	int cpu;
323bfe1d560SDave Jiang 	struct idxd_wq *wq;
324bfe1d560SDave Jiang };
325bfe1d560SDave Jiang 
3266b4b87f2SDave Jiang /*
3276b4b87f2SDave Jiang  * This is software defined error for the completion status. We overload the error code
3286b4b87f2SDave Jiang  * that will never appear in completion status and only SWERR register.
3296b4b87f2SDave Jiang  */
3306b4b87f2SDave Jiang enum idxd_completion_status {
3316b4b87f2SDave Jiang 	IDXD_COMP_DESC_ABORT = 0xff,
3326b4b87f2SDave Jiang };
3336b4b87f2SDave Jiang 
334700af3a0SDave Jiang #define idxd_confdev(idxd) &idxd->idxd_dev.conf_dev
335700af3a0SDave Jiang #define wq_confdev(wq) &wq->idxd_dev.conf_dev
336700af3a0SDave Jiang #define engine_confdev(engine) &engine->idxd_dev.conf_dev
337700af3a0SDave Jiang #define group_confdev(group) &group->idxd_dev.conf_dev
338700af3a0SDave Jiang #define cdev_dev(cdev) &cdev->idxd_dev.conf_dev
339700af3a0SDave Jiang 
340700af3a0SDave Jiang #define confdev_to_idxd_dev(dev) container_of(dev, struct idxd_dev, conf_dev)
341fcc2281bSDave Jiang #define idxd_dev_to_idxd(idxd_dev) container_of(idxd_dev, struct idxd_device, idxd_dev)
342fcc2281bSDave Jiang #define idxd_dev_to_wq(idxd_dev) container_of(idxd_dev, struct idxd_wq, idxd_dev)
343700af3a0SDave Jiang 
344700af3a0SDave Jiang static inline struct idxd_device *confdev_to_idxd(struct device *dev)
345700af3a0SDave Jiang {
346700af3a0SDave Jiang 	struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev);
347700af3a0SDave Jiang 
348fcc2281bSDave Jiang 	return idxd_dev_to_idxd(idxd_dev);
349700af3a0SDave Jiang }
350700af3a0SDave Jiang 
351700af3a0SDave Jiang static inline struct idxd_wq *confdev_to_wq(struct device *dev)
352700af3a0SDave Jiang {
353700af3a0SDave Jiang 	struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev);
354700af3a0SDave Jiang 
355fcc2281bSDave Jiang 	return idxd_dev_to_wq(idxd_dev);
356700af3a0SDave Jiang }
357700af3a0SDave Jiang 
358700af3a0SDave Jiang static inline struct idxd_engine *confdev_to_engine(struct device *dev)
359700af3a0SDave Jiang {
360700af3a0SDave Jiang 	struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev);
361700af3a0SDave Jiang 
362700af3a0SDave Jiang 	return container_of(idxd_dev, struct idxd_engine, idxd_dev);
363700af3a0SDave Jiang }
364700af3a0SDave Jiang 
365700af3a0SDave Jiang static inline struct idxd_group *confdev_to_group(struct device *dev)
366700af3a0SDave Jiang {
367700af3a0SDave Jiang 	struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev);
368700af3a0SDave Jiang 
369700af3a0SDave Jiang 	return container_of(idxd_dev, struct idxd_group, idxd_dev);
370700af3a0SDave Jiang }
371700af3a0SDave Jiang 
372700af3a0SDave Jiang static inline struct idxd_cdev *dev_to_cdev(struct device *dev)
373700af3a0SDave Jiang {
374700af3a0SDave Jiang 	struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev);
375700af3a0SDave Jiang 
376700af3a0SDave Jiang 	return container_of(idxd_dev, struct idxd_cdev, idxd_dev);
377700af3a0SDave Jiang }
378700af3a0SDave Jiang 
379700af3a0SDave Jiang static inline void idxd_dev_set_type(struct idxd_dev *idev, int type)
380700af3a0SDave Jiang {
381700af3a0SDave Jiang 	if (type >= IDXD_DEV_MAX_TYPE) {
382700af3a0SDave Jiang 		idev->type = IDXD_DEV_NONE;
383700af3a0SDave Jiang 		return;
384700af3a0SDave Jiang 	}
385700af3a0SDave Jiang 
386700af3a0SDave Jiang 	idev->type = type;
387700af3a0SDave Jiang }
388bfe1d560SDave Jiang 
38942d279f9SDave Jiang extern struct bus_type dsa_bus_type;
39042d279f9SDave Jiang 
3918e50d392SDave Jiang extern bool support_enqcmd;
3924b73e4ebSDave Jiang extern struct ida idxd_ida;
39347c16ac2SDave Jiang extern struct device_type dsa_device_type;
39447c16ac2SDave Jiang extern struct device_type iax_device_type;
3957c5dd23eSDave Jiang extern struct device_type idxd_wq_device_type;
39675b91130SDave Jiang extern struct device_type idxd_engine_device_type;
397defe49f9SDave Jiang extern struct device_type idxd_group_device_type;
39847c16ac2SDave Jiang 
399fcc2281bSDave Jiang static inline bool is_dsa_dev(struct idxd_dev *idxd_dev)
40047c16ac2SDave Jiang {
401fcc2281bSDave Jiang 	return idxd_dev->type == IDXD_DEV_DSA;
40247c16ac2SDave Jiang }
40347c16ac2SDave Jiang 
404fcc2281bSDave Jiang static inline bool is_iax_dev(struct idxd_dev *idxd_dev)
40547c16ac2SDave Jiang {
406fcc2281bSDave Jiang 	return idxd_dev->type == IDXD_DEV_IAX;
40747c16ac2SDave Jiang }
40847c16ac2SDave Jiang 
409fcc2281bSDave Jiang static inline bool is_idxd_dev(struct idxd_dev *idxd_dev)
41047c16ac2SDave Jiang {
411fcc2281bSDave Jiang 	return is_dsa_dev(idxd_dev) || is_iax_dev(idxd_dev);
41247c16ac2SDave Jiang }
4138e50d392SDave Jiang 
414fcc2281bSDave Jiang static inline bool is_idxd_wq_dev(struct idxd_dev *idxd_dev)
4157c5dd23eSDave Jiang {
416fcc2281bSDave Jiang 	return idxd_dev->type == IDXD_DEV_WQ;
4177c5dd23eSDave Jiang }
4187c5dd23eSDave Jiang 
4197c5dd23eSDave Jiang static inline bool is_idxd_wq_dmaengine(struct idxd_wq *wq)
4207c5dd23eSDave Jiang {
4217c5dd23eSDave Jiang 	if (wq->type == IDXD_WQT_KERNEL && strcmp(wq->name, "dmaengine") == 0)
4227c5dd23eSDave Jiang 		return true;
4237c5dd23eSDave Jiang 	return false;
4247c5dd23eSDave Jiang }
4257c5dd23eSDave Jiang 
4266e7f3ee9SDave Jiang static inline bool is_idxd_wq_user(struct idxd_wq *wq)
4277c5dd23eSDave Jiang {
4287c5dd23eSDave Jiang 	return wq->type == IDXD_WQT_USER;
4297c5dd23eSDave Jiang }
4307c5dd23eSDave Jiang 
4316e7f3ee9SDave Jiang static inline bool is_idxd_wq_kernel(struct idxd_wq *wq)
4326e7f3ee9SDave Jiang {
4336e7f3ee9SDave Jiang 	return wq->type == IDXD_WQT_KERNEL;
4346e7f3ee9SDave Jiang }
4356e7f3ee9SDave Jiang 
436bfe1d560SDave Jiang static inline bool wq_dedicated(struct idxd_wq *wq)
437bfe1d560SDave Jiang {
438bfe1d560SDave Jiang 	return test_bit(WQ_FLAG_DEDICATED, &wq->flags);
439bfe1d560SDave Jiang }
440bfe1d560SDave Jiang 
4418e50d392SDave Jiang static inline bool wq_shared(struct idxd_wq *wq)
4428e50d392SDave Jiang {
4438e50d392SDave Jiang 	return !test_bit(WQ_FLAG_DEDICATED, &wq->flags);
4448e50d392SDave Jiang }
4458e50d392SDave Jiang 
4468e50d392SDave Jiang static inline bool device_pasid_enabled(struct idxd_device *idxd)
4478e50d392SDave Jiang {
4488e50d392SDave Jiang 	return test_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags);
4498e50d392SDave Jiang }
4508e50d392SDave Jiang 
4518e50d392SDave Jiang static inline bool device_swq_supported(struct idxd_device *idxd)
4528e50d392SDave Jiang {
4538e50d392SDave Jiang 	return (support_enqcmd && device_pasid_enabled(idxd));
4548e50d392SDave Jiang }
4558e50d392SDave Jiang 
45642d279f9SDave Jiang enum idxd_portal_prot {
45742d279f9SDave Jiang 	IDXD_PORTAL_UNLIMITED = 0,
45842d279f9SDave Jiang 	IDXD_PORTAL_LIMITED,
45942d279f9SDave Jiang };
46042d279f9SDave Jiang 
461eb15e715SDave Jiang enum idxd_interrupt_type {
462eb15e715SDave Jiang 	IDXD_IRQ_MSIX = 0,
463eb15e715SDave Jiang 	IDXD_IRQ_IMS,
464eb15e715SDave Jiang };
465eb15e715SDave Jiang 
46642d279f9SDave Jiang static inline int idxd_get_wq_portal_offset(enum idxd_portal_prot prot)
46742d279f9SDave Jiang {
46842d279f9SDave Jiang 	return prot * 0x1000;
46942d279f9SDave Jiang }
47042d279f9SDave Jiang 
47142d279f9SDave Jiang static inline int idxd_get_wq_portal_full_offset(int wq_id,
47242d279f9SDave Jiang 						 enum idxd_portal_prot prot)
47342d279f9SDave Jiang {
47442d279f9SDave Jiang 	return ((wq_id * 4) << PAGE_SHIFT) + idxd_get_wq_portal_offset(prot);
47542d279f9SDave Jiang }
47642d279f9SDave Jiang 
477a9c17152SDave Jiang #define IDXD_PORTAL_MASK	(PAGE_SIZE - 1)
478a9c17152SDave Jiang 
479a9c17152SDave Jiang /*
480a9c17152SDave Jiang  * Even though this function can be accessed by multiple threads, it is safe to use.
481a9c17152SDave Jiang  * At worst the address gets used more than once before it gets incremented. We don't
482a9c17152SDave Jiang  * hit a threshold until iops becomes many million times a second. So the occasional
483a9c17152SDave Jiang  * reuse of the same address is tolerable compare to using an atomic variable. This is
484a9c17152SDave Jiang  * safe on a system that has atomic load/store for 32bit integers. Given that this is an
485a9c17152SDave Jiang  * Intel iEP device, that should not be a problem.
486a9c17152SDave Jiang  */
487a9c17152SDave Jiang static inline void __iomem *idxd_wq_portal_addr(struct idxd_wq *wq)
488a9c17152SDave Jiang {
489a9c17152SDave Jiang 	int ofs = wq->portal_offset;
490a9c17152SDave Jiang 
491a9c17152SDave Jiang 	wq->portal_offset = (ofs + sizeof(struct dsa_raw_desc)) & IDXD_PORTAL_MASK;
492a9c17152SDave Jiang 	return wq->portal + ofs;
493a9c17152SDave Jiang }
494a9c17152SDave Jiang 
495c52ca478SDave Jiang static inline void idxd_wq_get(struct idxd_wq *wq)
496c52ca478SDave Jiang {
497c52ca478SDave Jiang 	wq->client_count++;
498c52ca478SDave Jiang }
499c52ca478SDave Jiang 
500c52ca478SDave Jiang static inline void idxd_wq_put(struct idxd_wq *wq)
501c52ca478SDave Jiang {
502c52ca478SDave Jiang 	wq->client_count--;
503c52ca478SDave Jiang }
504c52ca478SDave Jiang 
505c52ca478SDave Jiang static inline int idxd_wq_refcount(struct idxd_wq *wq)
506c52ca478SDave Jiang {
507c52ca478SDave Jiang 	return wq->client_count;
508c52ca478SDave Jiang };
509c52ca478SDave Jiang 
5103ecfc913SDave Jiang int __must_check __idxd_driver_register(struct idxd_device_driver *idxd_drv,
5113ecfc913SDave Jiang 					struct module *module, const char *mod_name);
5123ecfc913SDave Jiang #define idxd_driver_register(driver) \
5133ecfc913SDave Jiang 	__idxd_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
5143ecfc913SDave Jiang 
5153ecfc913SDave Jiang void idxd_driver_unregister(struct idxd_device_driver *idxd_drv);
5163ecfc913SDave Jiang 
5176e7f3ee9SDave Jiang #define module_idxd_driver(__idxd_driver) \
5186e7f3ee9SDave Jiang 	module_driver(__idxd_driver, idxd_driver_register, idxd_driver_unregister)
5196e7f3ee9SDave Jiang 
520c52ca478SDave Jiang int idxd_register_bus_type(void);
521c52ca478SDave Jiang void idxd_unregister_bus_type(void);
52247c16ac2SDave Jiang int idxd_register_devices(struct idxd_device *idxd);
52347c16ac2SDave Jiang void idxd_unregister_devices(struct idxd_device *idxd);
524c52ca478SDave Jiang int idxd_register_driver(void);
525c52ca478SDave Jiang void idxd_unregister_driver(void);
5265b0c68c4SDave Jiang void idxd_wqs_quiesce(struct idxd_device *idxd);
527*f6d442f7SDave Jiang bool idxd_queue_int_handle_resubmit(struct idxd_desc *desc);
528bfe1d560SDave Jiang 
529bfe1d560SDave Jiang /* device interrupt control */
5306df0e6c5SDave Jiang void idxd_msix_perm_setup(struct idxd_device *idxd);
5316df0e6c5SDave Jiang void idxd_msix_perm_clear(struct idxd_device *idxd);
532bfe1d560SDave Jiang irqreturn_t idxd_misc_thread(int vec, void *data);
533bfe1d560SDave Jiang irqreturn_t idxd_wq_thread(int irq, void *data);
534bfe1d560SDave Jiang void idxd_mask_error_interrupts(struct idxd_device *idxd);
535bfe1d560SDave Jiang void idxd_unmask_error_interrupts(struct idxd_device *idxd);
536bfe1d560SDave Jiang void idxd_mask_msix_vectors(struct idxd_device *idxd);
5374548a6adSDave Jiang void idxd_mask_msix_vector(struct idxd_device *idxd, int vec_id);
5384548a6adSDave Jiang void idxd_unmask_msix_vector(struct idxd_device *idxd, int vec_id);
539bfe1d560SDave Jiang 
540bfe1d560SDave Jiang /* device control */
541034b3290SDave Jiang int idxd_register_idxd_drv(void);
542034b3290SDave Jiang void idxd_unregister_idxd_drv(void);
543bd42805bSDave Jiang int idxd_device_drv_probe(struct idxd_dev *idxd_dev);
544745e92a6SDave Jiang void idxd_device_drv_remove(struct idxd_dev *idxd_dev);
5451f2bb403SDave Jiang int drv_enable_wq(struct idxd_wq *wq);
5460cda4f69SDave Jiang int __drv_enable_wq(struct idxd_wq *wq);
54769e4f8beSDave Jiang void drv_disable_wq(struct idxd_wq *wq);
5480cda4f69SDave Jiang void __drv_disable_wq(struct idxd_wq *wq);
54989e3becdSDave Jiang int idxd_device_init_reset(struct idxd_device *idxd);
550bfe1d560SDave Jiang int idxd_device_enable(struct idxd_device *idxd);
551bfe1d560SDave Jiang int idxd_device_disable(struct idxd_device *idxd);
5520d5c10b4SDave Jiang void idxd_device_reset(struct idxd_device *idxd);
5530dcfe41eSDave Jiang void idxd_device_clear_state(struct idxd_device *idxd);
554bfe1d560SDave Jiang int idxd_device_config(struct idxd_device *idxd);
5558e50d392SDave Jiang void idxd_device_drain_pasid(struct idxd_device *idxd, int pasid);
5568c66bbdcSDave Jiang int idxd_device_load_config(struct idxd_device *idxd);
557eb15e715SDave Jiang int idxd_device_request_int_handle(struct idxd_device *idxd, int idx, int *handle,
558eb15e715SDave Jiang 				   enum idxd_interrupt_type irq_type);
559eb15e715SDave Jiang int idxd_device_release_int_handle(struct idxd_device *idxd, int handle,
560eb15e715SDave Jiang 				   enum idxd_interrupt_type irq_type);
561bfe1d560SDave Jiang 
562bfe1d560SDave Jiang /* work queue control */
5635b0c68c4SDave Jiang void idxd_wqs_unmap_portal(struct idxd_device *idxd);
564bfe1d560SDave Jiang int idxd_wq_alloc_resources(struct idxd_wq *wq);
565bfe1d560SDave Jiang void idxd_wq_free_resources(struct idxd_wq *wq);
566bfe1d560SDave Jiang int idxd_wq_enable(struct idxd_wq *wq);
5670dcfe41eSDave Jiang int idxd_wq_disable(struct idxd_wq *wq, bool reset_config);
5680d5c10b4SDave Jiang void idxd_wq_drain(struct idxd_wq *wq);
569ea9aadc0SDave Jiang void idxd_wq_reset(struct idxd_wq *wq);
570c52ca478SDave Jiang int idxd_wq_map_portal(struct idxd_wq *wq);
571c52ca478SDave Jiang void idxd_wq_unmap_portal(struct idxd_wq *wq);
5728e50d392SDave Jiang int idxd_wq_set_pasid(struct idxd_wq *wq, int pasid);
5738e50d392SDave Jiang int idxd_wq_disable_pasid(struct idxd_wq *wq);
574bd5970a0SDave Jiang void __idxd_wq_quiesce(struct idxd_wq *wq);
57593a40a6dSDave Jiang void idxd_wq_quiesce(struct idxd_wq *wq);
57693a40a6dSDave Jiang int idxd_wq_init_percpu_ref(struct idxd_wq *wq);
577bfe1d560SDave Jiang 
578d1dfe5b8SDave Jiang /* submission */
579d1dfe5b8SDave Jiang int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc);
580d1dfe5b8SDave Jiang struct idxd_desc *idxd_alloc_desc(struct idxd_wq *wq, enum idxd_op_type optype);
581d1dfe5b8SDave Jiang void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc);
582d1dfe5b8SDave Jiang 
5838f47d1a5SDave Jiang /* dmaengine */
5848f47d1a5SDave Jiang int idxd_register_dma_device(struct idxd_device *idxd);
5858f47d1a5SDave Jiang void idxd_unregister_dma_device(struct idxd_device *idxd);
5868f47d1a5SDave Jiang int idxd_register_dma_channel(struct idxd_wq *wq);
5878f47d1a5SDave Jiang void idxd_unregister_dma_channel(struct idxd_wq *wq);
5888f47d1a5SDave Jiang void idxd_parse_completion_status(u8 status, enum dmaengine_tx_result *res);
5898f47d1a5SDave Jiang void idxd_dma_complete_txd(struct idxd_desc *desc,
5905d78abb6SDave Jiang 			   enum idxd_complete_type comp_type, bool free_desc);
5918f47d1a5SDave Jiang 
59242d279f9SDave Jiang /* cdev */
59342d279f9SDave Jiang int idxd_cdev_register(void);
59442d279f9SDave Jiang void idxd_cdev_remove(void);
59542d279f9SDave Jiang int idxd_cdev_get_major(struct idxd_device *idxd);
59642d279f9SDave Jiang int idxd_wq_add_cdev(struct idxd_wq *wq);
59742d279f9SDave Jiang void idxd_wq_del_cdev(struct idxd_wq *wq);
59842d279f9SDave Jiang 
59981dd4d4dSTom Zanussi /* perfmon */
60081dd4d4dSTom Zanussi #if IS_ENABLED(CONFIG_INTEL_IDXD_PERFMON)
60181dd4d4dSTom Zanussi int perfmon_pmu_init(struct idxd_device *idxd);
60281dd4d4dSTom Zanussi void perfmon_pmu_remove(struct idxd_device *idxd);
60381dd4d4dSTom Zanussi void perfmon_counter_overflow(struct idxd_device *idxd);
60481dd4d4dSTom Zanussi void perfmon_init(void);
60581dd4d4dSTom Zanussi void perfmon_exit(void);
60681dd4d4dSTom Zanussi #else
60781dd4d4dSTom Zanussi static inline int perfmon_pmu_init(struct idxd_device *idxd) { return 0; }
60881dd4d4dSTom Zanussi static inline void perfmon_pmu_remove(struct idxd_device *idxd) {}
60981dd4d4dSTom Zanussi static inline void perfmon_counter_overflow(struct idxd_device *idxd) {}
61081dd4d4dSTom Zanussi static inline void perfmon_init(void) {}
61181dd4d4dSTom Zanussi static inline void perfmon_exit(void) {}
61281dd4d4dSTom Zanussi #endif
61381dd4d4dSTom Zanussi 
614bfe1d560SDave Jiang #endif
615