1 // SPDX-License-Identifier: GPL-2.0
2 
3 /*
4  * Copyright 2016-2019 HabanaLabs, Ltd.
5  * All Rights Reserved.
6  */
7 
8 #include "habanalabs.h"
9 
10 #include <linux/slab.h>
11 
hl_asid_init(struct hl_device * hdev)12 int hl_asid_init(struct hl_device *hdev)
13 {
14 	hdev->asid_bitmap = kcalloc(BITS_TO_LONGS(hdev->asic_prop.max_asid),
15 					sizeof(*hdev->asid_bitmap), GFP_KERNEL);
16 	if (!hdev->asid_bitmap)
17 		return -ENOMEM;
18 
19 	mutex_init(&hdev->asid_mutex);
20 
21 	/* ASID 0 is reserved for the kernel driver and device CPU */
22 	set_bit(0, hdev->asid_bitmap);
23 
24 	return 0;
25 }
26 
hl_asid_fini(struct hl_device * hdev)27 void hl_asid_fini(struct hl_device *hdev)
28 {
29 	mutex_destroy(&hdev->asid_mutex);
30 	kfree(hdev->asid_bitmap);
31 }
32 
hl_asid_alloc(struct hl_device * hdev)33 unsigned long hl_asid_alloc(struct hl_device *hdev)
34 {
35 	unsigned long found;
36 
37 	mutex_lock(&hdev->asid_mutex);
38 
39 	found = find_first_zero_bit(hdev->asid_bitmap,
40 					hdev->asic_prop.max_asid);
41 	if (found == hdev->asic_prop.max_asid)
42 		found = 0;
43 	else
44 		set_bit(found, hdev->asid_bitmap);
45 
46 	mutex_unlock(&hdev->asid_mutex);
47 
48 	return found;
49 }
50 
hl_asid_free(struct hl_device * hdev,unsigned long asid)51 void hl_asid_free(struct hl_device *hdev, unsigned long asid)
52 {
53 	if (WARN((asid == 0 || asid >= hdev->asic_prop.max_asid),
54 						"Invalid ASID %lu", asid))
55 		return;
56 	clear_bit(asid, hdev->asid_bitmap);
57 }
58