Commit 5918be3e authored by Weibo Zhao's avatar Weibo Zhao Committed by JiangShui
Browse files

hns3 udma: feature of record doorbell

driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I85R2F


CVE: NA

--------------------------------------------------------------

This patch is the code for record doorbell. Record doorbell is
a 8B memory which saves value of jfr pi and jfc ci. It works
as doorbell but not real-time. When hardware need to update
jfr-pi for example, hardware would read jfr record doorbell to
update latest jfr pi value.

Signed-off-by: default avatarWeibo Zhao <zhaoweibo3@huawei.com>
parent 6060aa7b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ ccflags-y += -I$(srctree)/drivers/net/ethernet/hisilicon/hns3/ \
		-I$(srctree)/drivers/ub/urma/

$(MODULE_NAME)-objs := hns3_udma_hw.o hns3_udma_main.o hns3_udma_cmd.o \
			hns3_udma_hem.o hns3_udma_qp.o hns3_udma_eq.o
			hns3_udma_hem.o hns3_udma_qp.o hns3_udma_eq.o \
			hns3_udma_db.o

obj-$(CONFIG_UB_UDMA_HNS3) := hns3_udma.o
+83 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Huawei UDMA Linux driver
 * Copyright (c) 2023-2023 Hisilicon Limited.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 */

#include <linux/scatterlist.h>
#include <linux/slab.h>
#include "urma/ubcore_api.h"
#include "hns3_udma_device.h"
#include "hns3_udma_db.h"

int udma_db_map_user(struct udma_dev *udma_dev, uint64_t virt,
		     struct udma_db *db)
{
	uint64_t page_addr = virt & PAGE_MASK;
	union ubcore_umem_flag access = {};
	struct udma_user_db_page *db_page;
	uint32_t offset;
	int ret = 0;

	mutex_lock(&udma_dev->pgdir_mutex);

	list_for_each_entry(db_page, &udma_dev->pgdir_list, list) {
		if (db_page->user_virt == page_addr)
			goto found;
	}

	db_page = kmalloc(sizeof(*db_page), GFP_KERNEL);
	if (!db_page) {
		ret = -ENOMEM;
		goto out;
	}

	refcount_set(&db_page->refcount, 1);
	db_page->user_virt = page_addr;
	access.bs.non_pin = 0;
	access.bs.writable = 1;
	db_page->umem = ubcore_umem_get(&udma_dev->ub_dev, page_addr,
					PAGE_SIZE, access);
	if (IS_ERR(db_page->umem)) {
		ret = PTR_ERR(db_page->umem);
		kfree(db_page);
		goto out;
	}

	list_add(&db_page->list, &udma_dev->pgdir_list);

found:
	offset = virt - page_addr;
	db->dma = sg_dma_address(db_page->umem->sg_head.sgl) + offset;
	db->virt_addr = (char *)sg_virt(db_page->umem->sg_head.sgl) + offset;
	db->user_page = db_page;
	refcount_inc(&db_page->refcount);

out:
	mutex_unlock(&udma_dev->pgdir_mutex);

	return ret;
}

void udma_db_unmap_user(struct udma_dev *udma_dev, struct udma_db *db)
{
	mutex_lock(&udma_dev->pgdir_mutex);

	refcount_dec(&db->user_page->refcount);
	if (refcount_dec_if_one(&db->user_page->refcount)) {
		list_del(&db->user_page->list);
		ubcore_umem_release(db->user_page->umem);
		kfree(db->user_page);
	}

	mutex_unlock(&udma_dev->pgdir_mutex);
}
+26 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei UDMA Linux driver
 * Copyright (c) 2023-2023 Hisilicon Limited.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 */

#ifndef _UDMA_DB_H
#define _UDMA_DB_H

#include "hns3_udma_device.h"

int udma_db_map_user(struct udma_dev *udma_dev, uint64_t virt,
		     struct udma_db *db);

void udma_db_unmap_user(struct udma_dev *udma_dev, struct udma_db *db);

#endif /* _UDMA_DB_H */
+15 −0
Original line number Diff line number Diff line
@@ -215,6 +215,13 @@ struct udma_mtr {
	struct udma_hem_cfg	hem_cfg; /* config for hardware addressing */
};

struct udma_user_db_page {
	struct list_head	list;
	struct ubcore_umem	*umem;
	uint64_t		user_virt;
	refcount_t		refcount;
};

struct udma_ceqe {
	uint32_t	comp;
	uint32_t	rsv[15];
@@ -251,6 +258,14 @@ struct udma_work {
};

struct udma_dev;

struct udma_db {
	uint32_t	*db_record;
	struct udma_user_db_page *user_page;
	dma_addr_t	dma;
	void		*virt_addr;
};

struct udma_ucontext {
	struct ubcore_ucontext		uctx;
	struct udma_uar			uar;