aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/uacce.h
blob: 0e215e6d0534aa06b335889f0c136c383b3b3933 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef _LINUX_UACCE_H
#define _LINUX_UACCE_H

#include <linux/cdev.h>
#include <uapi/misc/uacce/uacce.h>

#define UACCE_NAME		"uacce"
#define UACCE_MAX_REGION	2
#define UACCE_MAX_NAME_SIZE	64

struct uacce_queue;
struct uacce_device;

/**
 * struct uacce_qfile_region - structure of queue file region
 * @type: type of the region
 */
struct uacce_qfile_region {
	enum uacce_qfrt type;
};

/**
 * struct uacce_ops - uacce device operations
 * @get_available_instances:  get available instances left of the device
 * @get_queue: get a queue from the device
 * @put_queue: free a queue to the device
 * @start_queue: make the queue start work after get_queue
 * @stop_queue: make the queue stop work before put_queue
 * @is_q_updated: check whether the task is finished
 * @mmap: mmap addresses of queue to user space
 * @ioctl: ioctl for user space users of the queue
 */
struct uacce_ops {
	int (*get_available_instances)(struct uacce_device *uacce);
	int (*get_queue)(struct uacce_device *uacce, unsigned long arg,
			 struct uacce_queue *q);
	void (*put_queue)(struct uacce_queue *q);
	int (*start_queue)(struct uacce_queue *q);
	void (*stop_queue)(struct uacce_queue *q);
	int (*is_q_updated)(struct uacce_queue *q);
	int (*mmap)(struct uacce_queue *q, struct vm_area_struct *vma,
		    struct uacce_qfile_region *qfr);
	long (*ioctl)(struct uacce_queue *q, unsigned int cmd,
		      unsigned long arg);
};

/**
 * struct uacce_interface - interface required for uacce_register()
 * @name: the uacce device name.  Will show up in sysfs
 * @flags: uacce device attributes
 * @ops: pointer to the struct uacce_ops
 */
struct uacce_interface {
	char name[UACCE_MAX_NAME_SIZE];
	unsigned int flags;
	const struct uacce_ops *ops;
};

enum uacce_q_state {
	UACCE_Q_ZOMBIE = 0,
	UACCE_Q_INIT,
	UACCE_Q_STARTED,
};

/**
 * struct uacce_queue
 * @uacce: pointer to uacce
 * @priv: private pointer
 * @wait: wait queue head
 * @list: index into uacce_mm
 * @uacce_mm: the corresponding mm
 * @qfrs: pointer of qfr regions
 * @state: queue state machine
 */
struct uacce_queue {
	struct uacce_device *uacce;
	void *priv;
	wait_queue_head_t wait;
	struct list_head list;
	struct uacce_mm *uacce_mm;
	struct uacce_qfile_region *qfrs[UACCE_MAX_REGION];
	enum uacce_q_state state;
};

/**
 * struct uacce_device
 * @algs: supported algorithms
 * @api_ver: api version
 * @ops: pointer to the struct uacce_ops
 * @qf_pg_num: page numbers of the queue file regions
 * @parent: pointer to the parent device
 * @is_vf: whether virtual function
 * @flags: uacce attributes
 * @dev_id: id of the uacce device
 * @cdev: cdev of the uacce
 * @dev: dev of the uacce
 * @priv: private pointer of the uacce
 * @mm_list: list head of uacce_mm->list
 * @mm_lock: lock for mm_list
 * @inode: core vfs
 */
struct uacce_device {
	const char *algs;
	const char *api_ver;
	const struct uacce_ops *ops;
	unsigned long qf_pg_num[UACCE_MAX_REGION];
	struct device *parent;
	bool is_vf;
	u32 flags;
	u32 dev_id;
	struct cdev *cdev;
	struct device dev;
	void *priv;
	struct list_head mm_list;
	struct mutex mm_lock;
	struct inode *inode;
};

/**
 * struct uacce_mm - keep track of queues bound to a process
 * @list: index into uacce_device
 * @queues: list of queues
 * @mm: the mm struct
 * @lock: protects the list of queues
 * @pasid: pasid of the uacce_mm
 * @handle: iommu_sva handle return from iommu_sva_bind_device
 */
struct uacce_mm {
	struct list_head list;
	struct list_head queues;
	struct mm_struct *mm;
	struct mutex lock;
	int pasid;
	struct iommu_sva *handle;
};

#if IS_ENABLED(CONFIG_UACCE)

struct uacce_device *uacce_alloc(struct device *parent,
				 struct uacce_interface *interface);
int uacce_register(struct uacce_device *uacce);
void uacce_remove(struct uacce_device *uacce);

#else /* CONFIG_UACCE */

static inline
struct uacce_device *uacce_alloc(struct device *parent,
				 struct uacce_interface *interface)
{
	return ERR_PTR(-ENODEV);
}

static inline int uacce_register(struct uacce_device *uacce)
{
	return -EINVAL;
}

static inline void uacce_remove(struct uacce_device *uacce) {}

#endif /* CONFIG_UACCE */

#endif /* _LINUX_UACCE_H */