xref: /freebsd/sys/dev/qat/qat_common/adf_dev_mgr.c (revision 058ac3e8063366dafa634d9107642e12b038bf09)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include "qat_freebsd.h"
5 #include "adf_cfg.h"
6 #include "adf_common_drv.h"
7 #include "adf_accel_devices.h"
8 #include "icp_qat_uclo.h"
9 #include "icp_qat_fw.h"
10 #include "icp_qat_fw_init_admin.h"
11 #include "adf_cfg_strings.h"
12 #include "adf_transport_access_macros.h"
13 #include "adf_transport_internal.h"
14 #include <sys/mutex.h>
15 #include "adf_cfg.h"
16 #include "adf_common_drv.h"
17 
18 #define ADF_AE_PAIR 2
19 #define PKE_SLICES_PER_AE_PAIR 5
20 
21 static LIST_HEAD(accel_table);
22 static LIST_HEAD(vfs_table);
23 static DEFINE_MUTEX(table_lock);
24 static uint32_t num_devices;
25 static u8 id_map[ADF_MAX_DEVICES];
26 
27 struct vf_id_map {
28 	u32 bdf;
29 	u32 id;
30 	u32 fake_id;
31 	bool attached;
32 	struct list_head list;
33 };
34 
35 /**
36  * adf_get_vf_real_id() - Translate fake to real device id
37  *
38  * The "real" id is assigned to a device when it is initially
39  * bound to the driver.
40  * The "fake" id is usually the same as the real id, but
41  * can change when devices are unbound from the qat driver,
42  * perhaps to assign the device to a guest.
43  */
44 static int
45 adf_get_vf_real_id(u32 fake)
46 {
47 	struct list_head *itr;
48 
49 	list_for_each(itr, &vfs_table)
50 	{
51 		struct vf_id_map *ptr = list_entry(itr, struct vf_id_map, list);
52 		if (ptr->fake_id == fake)
53 			return ptr->id;
54 	}
55 	return -1;
56 }
57 
58 /**
59  * adf_clean_vf_map() - Cleans VF id mapings
60  *
61  * Function cleans internal ids for virtual functions.
62  * @vf: flag indicating whether mappings is cleaned
63  *	for vfs only or for vfs and pfs
64  */
65 void
66 adf_clean_vf_map(bool vf)
67 {
68 	struct vf_id_map *map;
69 	struct list_head *ptr, *tmp;
70 
71 	mutex_lock(&table_lock);
72 	list_for_each_safe(ptr, tmp, &vfs_table)
73 	{
74 		map = list_entry(ptr, struct vf_id_map, list);
75 		if (map->bdf != -1) {
76 			id_map[map->id] = 0;
77 			num_devices--;
78 		}
79 
80 		if (vf && map->bdf == -1)
81 			continue;
82 
83 		list_del(ptr);
84 		free(map, M_QAT);
85 	}
86 	mutex_unlock(&table_lock);
87 }
88 
89 /**
90  * adf_devmgr_update_class_index() - Update internal index
91  * @hw_data:  Pointer to internal device data.
92  *
93  * Function updates internal dev index for VFs
94  */
95 void
96 adf_devmgr_update_class_index(struct adf_hw_device_data *hw_data)
97 {
98 	struct adf_hw_device_class *class = hw_data->dev_class;
99 	struct list_head *itr;
100 	int i = 0;
101 
102 	list_for_each(itr, &accel_table)
103 	{
104 		struct adf_accel_dev *ptr =
105 		    list_entry(itr, struct adf_accel_dev, list);
106 
107 		if (ptr->hw_device->dev_class == class)
108 			ptr->hw_device->instance_id = i++;
109 
110 		if (i == class->instances)
111 			break;
112 	}
113 }
114 
115 static unsigned int
116 adf_find_free_id(void)
117 {
118 	unsigned int i;
119 
120 	for (i = 0; i < ADF_MAX_DEVICES; i++) {
121 		if (!id_map[i]) {
122 			id_map[i] = 1;
123 			return i;
124 		}
125 	}
126 	return ADF_MAX_DEVICES + 1;
127 }
128 
129 /**
130  * adf_devmgr_add_dev() - Add accel_dev to the acceleration framework
131  * @accel_dev:  Pointer to acceleration device.
132  * @pf:		Corresponding PF if the accel_dev is a VF
133  *
134  * Function adds acceleration device to the acceleration framework.
135  * To be used by QAT device specific drivers.
136  *
137  * Return: 0 on success, error code otherwise.
138  */
139 int
140 adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, struct adf_accel_dev *pf)
141 {
142 	struct list_head *itr;
143 	int ret = 0;
144 
145 	if (num_devices == ADF_MAX_DEVICES) {
146 		device_printf(GET_DEV(accel_dev),
147 			      "Only support up to %d devices\n",
148 			      ADF_MAX_DEVICES);
149 		return EFAULT;
150 	}
151 
152 	mutex_lock(&table_lock);
153 
154 	/* PF on host or VF on guest */
155 	if (!accel_dev->is_vf || (accel_dev->is_vf && !pf)) {
156 		struct vf_id_map *map;
157 
158 		list_for_each(itr, &accel_table)
159 		{
160 			struct adf_accel_dev *ptr =
161 			    list_entry(itr, struct adf_accel_dev, list);
162 
163 			if (ptr == accel_dev) {
164 				ret = EEXIST;
165 				goto unlock;
166 			}
167 		}
168 
169 		list_add_tail(&accel_dev->list, &accel_table);
170 		accel_dev->accel_id = adf_find_free_id();
171 		if (accel_dev->accel_id > ADF_MAX_DEVICES) {
172 			ret = EFAULT;
173 			goto unlock;
174 		}
175 		num_devices++;
176 		map = malloc(sizeof(*map), M_QAT, GFP_KERNEL);
177 		if (!map) {
178 			ret = ENOMEM;
179 			goto unlock;
180 		}
181 		map->bdf = ~0;
182 		map->id = accel_dev->accel_id;
183 		map->fake_id = map->id;
184 		map->attached = true;
185 		list_add_tail(&map->list, &vfs_table);
186 	} else if (accel_dev->is_vf && pf) {
187 		ret = ENOTSUP;
188 		goto unlock;
189 	}
190 unlock:
191 	mutex_unlock(&table_lock);
192 	return ret;
193 }
194 
195 struct list_head *
196 adf_devmgr_get_head(void)
197 {
198 	return &accel_table;
199 }
200 
201 /**
202  * adf_devmgr_rm_dev() - Remove accel_dev from the acceleration framework.
203  * @accel_dev:  Pointer to acceleration device.
204  * @pf:		Corresponding PF if the accel_dev is a VF
205  *
206  * Function removes acceleration device from the acceleration framework.
207  * To be used by QAT device specific drivers.
208  *
209  * Return: void
210  */
211 void
212 adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev, struct adf_accel_dev *pf)
213 {
214 	mutex_lock(&table_lock);
215 	if (!accel_dev->is_vf || (accel_dev->is_vf && !pf)) {
216 		id_map[accel_dev->accel_id] = 0;
217 		num_devices--;
218 	}
219 	list_del(&accel_dev->list);
220 	mutex_unlock(&table_lock);
221 }
222 
223 struct adf_accel_dev *
224 adf_devmgr_get_first(void)
225 {
226 	struct adf_accel_dev *dev = NULL;
227 
228 	if (!list_empty(&accel_table))
229 		dev =
230 		    list_first_entry(&accel_table, struct adf_accel_dev, list);
231 	return dev;
232 }
233 
234 /**
235  * adf_devmgr_pci_to_accel_dev() - Get accel_dev associated with the pci_dev.
236  * @accel_dev:  Pointer to pci device.
237  *
238  * Function returns acceleration device associated with the given pci device.
239  * To be used by QAT device specific drivers.
240  *
241  * Return: pointer to accel_dev or NULL if not found.
242  */
243 struct adf_accel_dev *
244 adf_devmgr_pci_to_accel_dev(device_t pci_dev)
245 {
246 	struct list_head *itr;
247 
248 	mutex_lock(&table_lock);
249 	list_for_each(itr, &accel_table)
250 	{
251 		struct adf_accel_dev *ptr =
252 		    list_entry(itr, struct adf_accel_dev, list);
253 
254 		if (ptr->accel_pci_dev.pci_dev == pci_dev) {
255 			mutex_unlock(&table_lock);
256 			return ptr;
257 		}
258 	}
259 	mutex_unlock(&table_lock);
260 	return NULL;
261 }
262 
263 struct adf_accel_dev *
264 adf_devmgr_get_dev_by_id(uint32_t id)
265 {
266 	struct list_head *itr;
267 	int real_id;
268 
269 	mutex_lock(&table_lock);
270 	real_id = adf_get_vf_real_id(id);
271 	if (real_id < 0)
272 		goto unlock;
273 
274 	id = real_id;
275 
276 	list_for_each(itr, &accel_table)
277 	{
278 		struct adf_accel_dev *ptr =
279 		    list_entry(itr, struct adf_accel_dev, list);
280 		if (ptr->accel_id == id) {
281 			mutex_unlock(&table_lock);
282 			return ptr;
283 		}
284 	}
285 unlock:
286 	mutex_unlock(&table_lock);
287 	return NULL;
288 }
289 
290 int
291 adf_devmgr_verify_id(uint32_t *id)
292 {
293 	struct adf_accel_dev *accel_dev;
294 
295 	if (*id == ADF_CFG_ALL_DEVICES)
296 		return 0;
297 
298 	accel_dev = adf_devmgr_get_dev_by_id(*id);
299 	if (!accel_dev)
300 		return ENODEV;
301 
302 	/* Correct the id if real and fake differ */
303 	*id = accel_dev->accel_id;
304 	return 0;
305 }
306 
307 static int
308 adf_get_num_dettached_vfs(void)
309 {
310 	struct list_head *itr;
311 	int vfs = 0;
312 
313 	mutex_lock(&table_lock);
314 	list_for_each(itr, &vfs_table)
315 	{
316 		struct vf_id_map *ptr = list_entry(itr, struct vf_id_map, list);
317 		if (ptr->bdf != ~0 && !ptr->attached)
318 			vfs++;
319 	}
320 	mutex_unlock(&table_lock);
321 	return vfs;
322 }
323 
324 void
325 adf_devmgr_get_num_dev(uint32_t *num)
326 {
327 	*num = num_devices - adf_get_num_dettached_vfs();
328 }
329 
330 /**
331  * adf_dev_in_use() - Check whether accel_dev is currently in use
332  * @accel_dev: Pointer to acceleration device.
333  *
334  * To be used by QAT device specific drivers.
335  *
336  * Return: 1 when device is in use, 0 otherwise.
337  */
338 int
339 adf_dev_in_use(struct adf_accel_dev *accel_dev)
340 {
341 	return atomic_read(&accel_dev->ref_count) != 0;
342 }
343 
344 /**
345  * adf_dev_get() - Increment accel_dev reference count
346  * @accel_dev: Pointer to acceleration device.
347  *
348  * Increment the accel_dev refcount and if this is the first time
349  * incrementing it during this period the accel_dev is in use,
350  * increment the module refcount too.
351  * To be used by QAT device specific drivers.
352  *
353  * Return: void
354  */
355 void
356 adf_dev_get(struct adf_accel_dev *accel_dev)
357 {
358 	if (atomic_add_return(1, &accel_dev->ref_count) == 1)
359 		device_busy(GET_DEV(accel_dev));
360 }
361 
362 /**
363  * adf_dev_put() - Decrement accel_dev reference count
364  * @accel_dev: Pointer to acceleration device.
365  *
366  * Decrement the accel_dev refcount and if this is the last time
367  * decrementing it during this period the accel_dev is in use,
368  * decrement the module refcount too.
369  * To be used by QAT device specific drivers.
370  *
371  * Return: void
372  */
373 void
374 adf_dev_put(struct adf_accel_dev *accel_dev)
375 {
376 	if (atomic_sub_return(1, &accel_dev->ref_count) == 0)
377 		device_unbusy(GET_DEV(accel_dev));
378 }
379 
380 /**
381  * adf_devmgr_in_reset() - Check whether device is in reset
382  * @accel_dev: Pointer to acceleration device.
383  *
384  * To be used by QAT device specific drivers.
385  *
386  * Return: 1 when the device is being reset, 0 otherwise.
387  */
388 int
389 adf_devmgr_in_reset(struct adf_accel_dev *accel_dev)
390 {
391 	return test_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
392 }
393 
394 /**
395  * adf_dev_started() - Check whether device has started
396  * @accel_dev: Pointer to acceleration device.
397  *
398  * To be used by QAT device specific drivers.
399  *
400  * Return: 1 when the device has started, 0 otherwise
401  */
402 int
403 adf_dev_started(struct adf_accel_dev *accel_dev)
404 {
405 	return test_bit(ADF_STATUS_STARTED, &accel_dev->status);
406 }
407