162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci/*
462306a36Sopenharmony_ci * Copyright 2016-2019 HabanaLabs, Ltd.
562306a36Sopenharmony_ci * All Rights Reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "habanalabs.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/slab.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciint hl_asid_init(struct hl_device *hdev)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	hdev->asid_bitmap = bitmap_zalloc(hdev->asic_prop.max_asid, GFP_KERNEL);
1562306a36Sopenharmony_ci	if (!hdev->asid_bitmap)
1662306a36Sopenharmony_ci		return -ENOMEM;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	mutex_init(&hdev->asid_mutex);
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	/* ASID 0 is reserved for the kernel driver and device CPU */
2162306a36Sopenharmony_ci	set_bit(0, hdev->asid_bitmap);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	return 0;
2462306a36Sopenharmony_ci}
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_civoid hl_asid_fini(struct hl_device *hdev)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	mutex_destroy(&hdev->asid_mutex);
2962306a36Sopenharmony_ci	bitmap_free(hdev->asid_bitmap);
3062306a36Sopenharmony_ci}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ciunsigned long hl_asid_alloc(struct hl_device *hdev)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	unsigned long found;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	mutex_lock(&hdev->asid_mutex);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	found = find_first_zero_bit(hdev->asid_bitmap,
3962306a36Sopenharmony_ci					hdev->asic_prop.max_asid);
4062306a36Sopenharmony_ci	if (found == hdev->asic_prop.max_asid)
4162306a36Sopenharmony_ci		found = 0;
4262306a36Sopenharmony_ci	else
4362306a36Sopenharmony_ci		set_bit(found, hdev->asid_bitmap);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	mutex_unlock(&hdev->asid_mutex);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	return found;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_civoid hl_asid_free(struct hl_device *hdev, unsigned long asid)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	if (asid == HL_KERNEL_ASID_ID || asid >= hdev->asic_prop.max_asid) {
5362306a36Sopenharmony_ci		dev_crit(hdev->dev, "Invalid ASID %lu", asid);
5462306a36Sopenharmony_ci		return;
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	clear_bit(asid, hdev->asid_bitmap);
5862306a36Sopenharmony_ci}
59