xref: /linux/drivers/dma/idxd/idxd.h (revision ff18de55a62f0e8f0dcf11bfa7f69b23e6e951b0)
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>
11bfe1d560SDave Jiang #include "registers.h"
12bfe1d560SDave Jiang 
13bfe1d560SDave Jiang #define IDXD_DRIVER_VERSION	"1.00"
14bfe1d560SDave Jiang 
15bfe1d560SDave Jiang extern struct kmem_cache *idxd_desc_pool;
16bfe1d560SDave Jiang 
17bfe1d560SDave Jiang #define IDXD_REG_TIMEOUT	50
18bfe1d560SDave Jiang #define IDXD_DRAIN_TIMEOUT	5000
19bfe1d560SDave Jiang 
20bfe1d560SDave Jiang enum idxd_type {
21bfe1d560SDave Jiang 	IDXD_TYPE_UNKNOWN = -1,
22bfe1d560SDave Jiang 	IDXD_TYPE_DSA = 0,
23bfe1d560SDave Jiang 	IDXD_TYPE_MAX
24bfe1d560SDave Jiang };
25bfe1d560SDave Jiang 
26bfe1d560SDave Jiang #define IDXD_NAME_SIZE		128
27bfe1d560SDave Jiang 
28bfe1d560SDave Jiang struct idxd_device_driver {
29bfe1d560SDave Jiang 	struct device_driver drv;
30bfe1d560SDave Jiang };
31bfe1d560SDave Jiang 
32bfe1d560SDave Jiang struct idxd_irq_entry {
33bfe1d560SDave Jiang 	struct idxd_device *idxd;
34bfe1d560SDave Jiang 	int id;
35bfe1d560SDave Jiang 	struct llist_head pending_llist;
36bfe1d560SDave Jiang 	struct list_head work_list;
37bfe1d560SDave Jiang };
38bfe1d560SDave Jiang 
39bfe1d560SDave Jiang struct idxd_group {
40bfe1d560SDave Jiang 	struct device conf_dev;
41bfe1d560SDave Jiang 	struct idxd_device *idxd;
42bfe1d560SDave Jiang 	struct grpcfg grpcfg;
43bfe1d560SDave Jiang 	int id;
44bfe1d560SDave Jiang 	int num_engines;
45bfe1d560SDave Jiang 	int num_wqs;
46bfe1d560SDave Jiang 	bool use_token_limit;
47bfe1d560SDave Jiang 	u8 tokens_allowed;
48bfe1d560SDave Jiang 	u8 tokens_reserved;
49bfe1d560SDave Jiang 	int tc_a;
50bfe1d560SDave Jiang 	int tc_b;
51bfe1d560SDave Jiang };
52bfe1d560SDave Jiang 
53bfe1d560SDave Jiang #define IDXD_MAX_PRIORITY	0xf
54bfe1d560SDave Jiang 
55bfe1d560SDave Jiang enum idxd_wq_state {
56bfe1d560SDave Jiang 	IDXD_WQ_DISABLED = 0,
57bfe1d560SDave Jiang 	IDXD_WQ_ENABLED,
58bfe1d560SDave Jiang };
59bfe1d560SDave Jiang 
60bfe1d560SDave Jiang enum idxd_wq_flag {
61bfe1d560SDave Jiang 	WQ_FLAG_DEDICATED = 0,
62bfe1d560SDave Jiang };
63bfe1d560SDave Jiang 
64bfe1d560SDave Jiang enum idxd_wq_type {
65bfe1d560SDave Jiang 	IDXD_WQT_NONE = 0,
66bfe1d560SDave Jiang 	IDXD_WQT_KERNEL,
6742d279f9SDave Jiang 	IDXD_WQT_USER,
6842d279f9SDave Jiang };
6942d279f9SDave Jiang 
7042d279f9SDave Jiang struct idxd_cdev {
7142d279f9SDave Jiang 	struct cdev cdev;
7242d279f9SDave Jiang 	struct device *dev;
7342d279f9SDave Jiang 	int minor;
7442d279f9SDave Jiang 	struct wait_queue_head err_queue;
75bfe1d560SDave Jiang };
76bfe1d560SDave Jiang 
77bfe1d560SDave Jiang #define IDXD_ALLOCATED_BATCH_SIZE	128U
78bfe1d560SDave Jiang #define WQ_NAME_SIZE   1024
79bfe1d560SDave Jiang #define WQ_TYPE_SIZE   10
80bfe1d560SDave Jiang 
81d1dfe5b8SDave Jiang enum idxd_op_type {
82d1dfe5b8SDave Jiang 	IDXD_OP_BLOCK = 0,
83d1dfe5b8SDave Jiang 	IDXD_OP_NONBLOCK = 1,
84d1dfe5b8SDave Jiang };
85d1dfe5b8SDave Jiang 
868f47d1a5SDave Jiang enum idxd_complete_type {
878f47d1a5SDave Jiang 	IDXD_COMPLETE_NORMAL = 0,
888f47d1a5SDave Jiang 	IDXD_COMPLETE_ABORT,
898f47d1a5SDave Jiang };
908f47d1a5SDave Jiang 
91bfe1d560SDave Jiang struct idxd_wq {
92bfe1d560SDave Jiang 	void __iomem *dportal;
93bfe1d560SDave Jiang 	struct device conf_dev;
9442d279f9SDave Jiang 	struct idxd_cdev idxd_cdev;
95bfe1d560SDave Jiang 	struct idxd_device *idxd;
96bfe1d560SDave Jiang 	int id;
97bfe1d560SDave Jiang 	enum idxd_wq_type type;
98bfe1d560SDave Jiang 	struct idxd_group *group;
99bfe1d560SDave Jiang 	int client_count;
100bfe1d560SDave Jiang 	struct mutex wq_lock;	/* mutex for workqueue */
101bfe1d560SDave Jiang 	u32 size;
102bfe1d560SDave Jiang 	u32 threshold;
103bfe1d560SDave Jiang 	u32 priority;
104bfe1d560SDave Jiang 	enum idxd_wq_state state;
105bfe1d560SDave Jiang 	unsigned long flags;
106bfe1d560SDave Jiang 	union wqcfg wqcfg;
107bfe1d560SDave Jiang 	u32 vec_ptr;		/* interrupt steering */
108bfe1d560SDave Jiang 	struct dsa_hw_desc **hw_descs;
109bfe1d560SDave Jiang 	int num_descs;
110bfe1d560SDave Jiang 	struct dsa_completion_record *compls;
111bfe1d560SDave Jiang 	dma_addr_t compls_addr;
112bfe1d560SDave Jiang 	int compls_size;
113bfe1d560SDave Jiang 	struct idxd_desc **descs;
1140705107fSDave Jiang 	struct sbitmap_queue sbq;
1158f47d1a5SDave Jiang 	struct dma_chan dma_chan;
116bfe1d560SDave Jiang 	char name[WQ_NAME_SIZE + 1];
117d7aad555SDave Jiang 	u64 max_xfer_bytes;
118e7184b15SDave Jiang 	u32 max_batch_size;
119bfe1d560SDave Jiang };
120bfe1d560SDave Jiang 
121bfe1d560SDave Jiang struct idxd_engine {
122bfe1d560SDave Jiang 	struct device conf_dev;
123bfe1d560SDave Jiang 	int id;
124bfe1d560SDave Jiang 	struct idxd_group *group;
125bfe1d560SDave Jiang 	struct idxd_device *idxd;
126bfe1d560SDave Jiang };
127bfe1d560SDave Jiang 
128bfe1d560SDave Jiang /* shadow registers */
129bfe1d560SDave Jiang struct idxd_hw {
130bfe1d560SDave Jiang 	u32 version;
131bfe1d560SDave Jiang 	union gen_cap_reg gen_cap;
132bfe1d560SDave Jiang 	union wq_cap_reg wq_cap;
133bfe1d560SDave Jiang 	union group_cap_reg group_cap;
134bfe1d560SDave Jiang 	union engine_cap_reg engine_cap;
135bfe1d560SDave Jiang 	struct opcap opcap;
136bfe1d560SDave Jiang };
137bfe1d560SDave Jiang 
138bfe1d560SDave Jiang enum idxd_device_state {
139bfe1d560SDave Jiang 	IDXD_DEV_HALTED = -1,
140bfe1d560SDave Jiang 	IDXD_DEV_DISABLED = 0,
141bfe1d560SDave Jiang 	IDXD_DEV_CONF_READY,
142bfe1d560SDave Jiang 	IDXD_DEV_ENABLED,
143bfe1d560SDave Jiang };
144bfe1d560SDave Jiang 
145bfe1d560SDave Jiang enum idxd_device_flag {
146bfe1d560SDave Jiang 	IDXD_FLAG_CONFIGURABLE = 0,
1470d5c10b4SDave Jiang 	IDXD_FLAG_CMD_RUNNING,
148bfe1d560SDave Jiang };
149bfe1d560SDave Jiang 
150bfe1d560SDave Jiang struct idxd_device {
151bfe1d560SDave Jiang 	enum idxd_type type;
152bfe1d560SDave Jiang 	struct device conf_dev;
153bfe1d560SDave Jiang 	struct list_head list;
154bfe1d560SDave Jiang 	struct idxd_hw hw;
155bfe1d560SDave Jiang 	enum idxd_device_state state;
156bfe1d560SDave Jiang 	unsigned long flags;
157bfe1d560SDave Jiang 	int id;
15842d279f9SDave Jiang 	int major;
159*ff18de55SDave Jiang 	u8 cmd_status;
160bfe1d560SDave Jiang 
161bfe1d560SDave Jiang 	struct pci_dev *pdev;
162bfe1d560SDave Jiang 	void __iomem *reg_base;
163bfe1d560SDave Jiang 
164bfe1d560SDave Jiang 	spinlock_t dev_lock;	/* spinlock for device */
1650d5c10b4SDave Jiang 	struct completion *cmd_done;
166bfe1d560SDave Jiang 	struct idxd_group *groups;
167bfe1d560SDave Jiang 	struct idxd_wq *wqs;
168bfe1d560SDave Jiang 	struct idxd_engine *engines;
169bfe1d560SDave Jiang 
170bfe1d560SDave Jiang 	int num_groups;
171bfe1d560SDave Jiang 
172bfe1d560SDave Jiang 	u32 msix_perm_offset;
173bfe1d560SDave Jiang 	u32 wqcfg_offset;
174bfe1d560SDave Jiang 	u32 grpcfg_offset;
175bfe1d560SDave Jiang 	u32 perfmon_offset;
176bfe1d560SDave Jiang 
177bfe1d560SDave Jiang 	u64 max_xfer_bytes;
178bfe1d560SDave Jiang 	u32 max_batch_size;
179bfe1d560SDave Jiang 	int max_groups;
180bfe1d560SDave Jiang 	int max_engines;
181bfe1d560SDave Jiang 	int max_tokens;
182bfe1d560SDave Jiang 	int max_wqs;
183bfe1d560SDave Jiang 	int max_wq_size;
184bfe1d560SDave Jiang 	int token_limit;
185c52ca478SDave Jiang 	int nr_tokens;		/* non-reserved tokens */
186bfe1d560SDave Jiang 
187bfe1d560SDave Jiang 	union sw_err_reg sw_err;
1880d5c10b4SDave Jiang 	wait_queue_head_t cmd_waitq;
189bfe1d560SDave Jiang 	struct msix_entry *msix_entries;
190bfe1d560SDave Jiang 	int num_wq_irqs;
191bfe1d560SDave Jiang 	struct idxd_irq_entry *irq_entries;
1928f47d1a5SDave Jiang 
1938f47d1a5SDave Jiang 	struct dma_device dma_dev;
1940d5c10b4SDave Jiang 	struct workqueue_struct *wq;
1950d5c10b4SDave Jiang 	struct work_struct work;
196bfe1d560SDave Jiang };
197bfe1d560SDave Jiang 
198bfe1d560SDave Jiang /* IDXD software descriptor */
199bfe1d560SDave Jiang struct idxd_desc {
200bfe1d560SDave Jiang 	struct dsa_hw_desc *hw;
201bfe1d560SDave Jiang 	dma_addr_t desc_dma;
202bfe1d560SDave Jiang 	struct dsa_completion_record *completion;
203bfe1d560SDave Jiang 	dma_addr_t compl_dma;
2048f47d1a5SDave Jiang 	struct dma_async_tx_descriptor txd;
205bfe1d560SDave Jiang 	struct llist_node llnode;
206bfe1d560SDave Jiang 	struct list_head list;
207bfe1d560SDave Jiang 	int id;
2080705107fSDave Jiang 	int cpu;
209bfe1d560SDave Jiang 	struct idxd_wq *wq;
210bfe1d560SDave Jiang };
211bfe1d560SDave Jiang 
212bfe1d560SDave Jiang #define confdev_to_idxd(dev) container_of(dev, struct idxd_device, conf_dev)
213bfe1d560SDave Jiang #define confdev_to_wq(dev) container_of(dev, struct idxd_wq, conf_dev)
214bfe1d560SDave Jiang 
21542d279f9SDave Jiang extern struct bus_type dsa_bus_type;
21642d279f9SDave Jiang 
217bfe1d560SDave Jiang static inline bool wq_dedicated(struct idxd_wq *wq)
218bfe1d560SDave Jiang {
219bfe1d560SDave Jiang 	return test_bit(WQ_FLAG_DEDICATED, &wq->flags);
220bfe1d560SDave Jiang }
221bfe1d560SDave Jiang 
22242d279f9SDave Jiang enum idxd_portal_prot {
22342d279f9SDave Jiang 	IDXD_PORTAL_UNLIMITED = 0,
22442d279f9SDave Jiang 	IDXD_PORTAL_LIMITED,
22542d279f9SDave Jiang };
22642d279f9SDave Jiang 
22742d279f9SDave Jiang static inline int idxd_get_wq_portal_offset(enum idxd_portal_prot prot)
22842d279f9SDave Jiang {
22942d279f9SDave Jiang 	return prot * 0x1000;
23042d279f9SDave Jiang }
23142d279f9SDave Jiang 
23242d279f9SDave Jiang static inline int idxd_get_wq_portal_full_offset(int wq_id,
23342d279f9SDave Jiang 						 enum idxd_portal_prot prot)
23442d279f9SDave Jiang {
23542d279f9SDave Jiang 	return ((wq_id * 4) << PAGE_SHIFT) + idxd_get_wq_portal_offset(prot);
23642d279f9SDave Jiang }
23742d279f9SDave Jiang 
238bfe1d560SDave Jiang static inline void idxd_set_type(struct idxd_device *idxd)
239bfe1d560SDave Jiang {
240bfe1d560SDave Jiang 	struct pci_dev *pdev = idxd->pdev;
241bfe1d560SDave Jiang 
242bfe1d560SDave Jiang 	if (pdev->device == PCI_DEVICE_ID_INTEL_DSA_SPR0)
243bfe1d560SDave Jiang 		idxd->type = IDXD_TYPE_DSA;
244bfe1d560SDave Jiang 	else
245bfe1d560SDave Jiang 		idxd->type = IDXD_TYPE_UNKNOWN;
246bfe1d560SDave Jiang }
247bfe1d560SDave Jiang 
248c52ca478SDave Jiang static inline void idxd_wq_get(struct idxd_wq *wq)
249c52ca478SDave Jiang {
250c52ca478SDave Jiang 	wq->client_count++;
251c52ca478SDave Jiang }
252c52ca478SDave Jiang 
253c52ca478SDave Jiang static inline void idxd_wq_put(struct idxd_wq *wq)
254c52ca478SDave Jiang {
255c52ca478SDave Jiang 	wq->client_count--;
256c52ca478SDave Jiang }
257c52ca478SDave Jiang 
258c52ca478SDave Jiang static inline int idxd_wq_refcount(struct idxd_wq *wq)
259c52ca478SDave Jiang {
260c52ca478SDave Jiang 	return wq->client_count;
261c52ca478SDave Jiang };
262c52ca478SDave Jiang 
263bfe1d560SDave Jiang const char *idxd_get_dev_name(struct idxd_device *idxd);
264c52ca478SDave Jiang int idxd_register_bus_type(void);
265c52ca478SDave Jiang void idxd_unregister_bus_type(void);
266c52ca478SDave Jiang int idxd_setup_sysfs(struct idxd_device *idxd);
267c52ca478SDave Jiang void idxd_cleanup_sysfs(struct idxd_device *idxd);
268c52ca478SDave Jiang int idxd_register_driver(void);
269c52ca478SDave Jiang void idxd_unregister_driver(void);
27042d279f9SDave Jiang struct bus_type *idxd_get_bus_type(struct idxd_device *idxd);
271bfe1d560SDave Jiang 
272bfe1d560SDave Jiang /* device interrupt control */
273bfe1d560SDave Jiang irqreturn_t idxd_irq_handler(int vec, void *data);
274bfe1d560SDave Jiang irqreturn_t idxd_misc_thread(int vec, void *data);
275bfe1d560SDave Jiang irqreturn_t idxd_wq_thread(int irq, void *data);
276bfe1d560SDave Jiang void idxd_mask_error_interrupts(struct idxd_device *idxd);
277bfe1d560SDave Jiang void idxd_unmask_error_interrupts(struct idxd_device *idxd);
278bfe1d560SDave Jiang void idxd_mask_msix_vectors(struct idxd_device *idxd);
2794548a6adSDave Jiang void idxd_mask_msix_vector(struct idxd_device *idxd, int vec_id);
2804548a6adSDave Jiang void idxd_unmask_msix_vector(struct idxd_device *idxd, int vec_id);
281bfe1d560SDave Jiang 
282bfe1d560SDave Jiang /* device control */
2830d5c10b4SDave Jiang void idxd_device_init_reset(struct idxd_device *idxd);
284bfe1d560SDave Jiang int idxd_device_enable(struct idxd_device *idxd);
285bfe1d560SDave Jiang int idxd_device_disable(struct idxd_device *idxd);
2860d5c10b4SDave Jiang void idxd_device_reset(struct idxd_device *idxd);
287bfe1d560SDave Jiang void idxd_device_cleanup(struct idxd_device *idxd);
288bfe1d560SDave Jiang int idxd_device_config(struct idxd_device *idxd);
289bfe1d560SDave Jiang void idxd_device_wqs_clear_state(struct idxd_device *idxd);
290bfe1d560SDave Jiang 
291bfe1d560SDave Jiang /* work queue control */
292bfe1d560SDave Jiang int idxd_wq_alloc_resources(struct idxd_wq *wq);
293bfe1d560SDave Jiang void idxd_wq_free_resources(struct idxd_wq *wq);
294bfe1d560SDave Jiang int idxd_wq_enable(struct idxd_wq *wq);
295bfe1d560SDave Jiang int idxd_wq_disable(struct idxd_wq *wq);
2960d5c10b4SDave Jiang void idxd_wq_drain(struct idxd_wq *wq);
297c52ca478SDave Jiang int idxd_wq_map_portal(struct idxd_wq *wq);
298c52ca478SDave Jiang void idxd_wq_unmap_portal(struct idxd_wq *wq);
299da32b28cSDave Jiang void idxd_wq_disable_cleanup(struct idxd_wq *wq);
300bfe1d560SDave Jiang 
301d1dfe5b8SDave Jiang /* submission */
302d1dfe5b8SDave Jiang int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc);
303d1dfe5b8SDave Jiang struct idxd_desc *idxd_alloc_desc(struct idxd_wq *wq, enum idxd_op_type optype);
304d1dfe5b8SDave Jiang void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc);
305d1dfe5b8SDave Jiang 
3068f47d1a5SDave Jiang /* dmaengine */
3078f47d1a5SDave Jiang int idxd_register_dma_device(struct idxd_device *idxd);
3088f47d1a5SDave Jiang void idxd_unregister_dma_device(struct idxd_device *idxd);
3098f47d1a5SDave Jiang int idxd_register_dma_channel(struct idxd_wq *wq);
3108f47d1a5SDave Jiang void idxd_unregister_dma_channel(struct idxd_wq *wq);
3118f47d1a5SDave Jiang void idxd_parse_completion_status(u8 status, enum dmaengine_tx_result *res);
3128f47d1a5SDave Jiang void idxd_dma_complete_txd(struct idxd_desc *desc,
3138f47d1a5SDave Jiang 			   enum idxd_complete_type comp_type);
3148f47d1a5SDave Jiang dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx);
3158f47d1a5SDave Jiang 
31642d279f9SDave Jiang /* cdev */
31742d279f9SDave Jiang int idxd_cdev_register(void);
31842d279f9SDave Jiang void idxd_cdev_remove(void);
31942d279f9SDave Jiang int idxd_cdev_get_major(struct idxd_device *idxd);
32042d279f9SDave Jiang int idxd_wq_add_cdev(struct idxd_wq *wq);
32142d279f9SDave Jiang void idxd_wq_del_cdev(struct idxd_wq *wq);
32242d279f9SDave Jiang 
323bfe1d560SDave Jiang #endif
324