18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci/*
48c2ecf20Sopenharmony_ci * Copyright 2016-2019 HabanaLabs, Ltd.
58c2ecf20Sopenharmony_ci * All Rights Reserved.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "habanalabs.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/slab.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ciint hl_asid_init(struct hl_device *hdev)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	hdev->asid_bitmap = kcalloc(BITS_TO_LONGS(hdev->asic_prop.max_asid),
158c2ecf20Sopenharmony_ci					sizeof(*hdev->asid_bitmap), GFP_KERNEL);
168c2ecf20Sopenharmony_ci	if (!hdev->asid_bitmap)
178c2ecf20Sopenharmony_ci		return -ENOMEM;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	mutex_init(&hdev->asid_mutex);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	/* ASID 0 is reserved for the kernel driver and device CPU */
228c2ecf20Sopenharmony_ci	set_bit(0, hdev->asid_bitmap);
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	return 0;
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_civoid hl_asid_fini(struct hl_device *hdev)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	mutex_destroy(&hdev->asid_mutex);
308c2ecf20Sopenharmony_ci	kfree(hdev->asid_bitmap);
318c2ecf20Sopenharmony_ci}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ciunsigned long hl_asid_alloc(struct hl_device *hdev)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	unsigned long found;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	mutex_lock(&hdev->asid_mutex);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	found = find_first_zero_bit(hdev->asid_bitmap,
408c2ecf20Sopenharmony_ci					hdev->asic_prop.max_asid);
418c2ecf20Sopenharmony_ci	if (found == hdev->asic_prop.max_asid)
428c2ecf20Sopenharmony_ci		found = 0;
438c2ecf20Sopenharmony_ci	else
448c2ecf20Sopenharmony_ci		set_bit(found, hdev->asid_bitmap);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	mutex_unlock(&hdev->asid_mutex);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	return found;
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_civoid hl_asid_free(struct hl_device *hdev, unsigned long asid)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	if (WARN((asid == 0 || asid >= hdev->asic_prop.max_asid),
548c2ecf20Sopenharmony_ci						"Invalid ASID %lu", asid))
558c2ecf20Sopenharmony_ci		return;
568c2ecf20Sopenharmony_ci	clear_bit(asid, hdev->asid_bitmap);
578c2ecf20Sopenharmony_ci}
58