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

hns3 udma: create and destroy u-context

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


CVE: NA

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

This patch is code for create and destroy u-context.
Context is isolated by process. Uar in u-context
contains doorbell address and direct wqe address.

Signed-off-by: default avatarWeibo Zhao <zhaoweibo3@huawei.com>
parent a214398c
Loading
Loading
Loading
Loading
+34 −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_ABI_H
#define _UDMA_ABI_H

#include <linux/types.h>
struct udma_create_ctx_resp {
	uint32_t num_comp_vectors;
	uint32_t num_qps_shift;
	uint32_t num_jfs_shift;
	uint32_t num_jfr_shift;
	uint32_t num_jetty_shift;
	uint32_t max_jfc_cqe;
	uint32_t cqe_size;
	uint32_t max_jfr_wr;
	uint32_t max_jfr_sge;
	uint32_t max_jfs_wr;
	uint32_t max_jfs_sge;
};

#endif /* _UDMA_ABI_H */
+28 −0
Original line number Diff line number Diff line
@@ -78,6 +78,10 @@
#define EQ_REG_OFFSET			0x4
#define UDMA_DEFAULT_MAX_JETTY_X_SHIFT	8

#define UDMA_DB_ADDR_OFFSET 0x230
#define UDMA_DEV_START_OFFSET 2
#define UDMA_DEV_EX_START_OFFSET 4

enum {
	NO_ARMED = 0x0
};
@@ -138,6 +142,12 @@ enum {
	UDMA_BUF_NOFAIL = BIT(2),
};

struct udma_uar {
	uint64_t	pfn;
	uint64_t	index;
	uint64_t	logic_idx;
};

struct udma_ida {
	struct ida	ida;
	uint32_t	min; /* Lowest ID to allocate.  */
@@ -241,6 +251,12 @@ struct udma_work {
};

struct udma_dev;
struct udma_ucontext {
	struct ubcore_ucontext		uctx;
	struct udma_uar			uar;
	uint64_t			pdn;
};

struct udma_cmd_context {
	struct completion	done;
	int			result;
@@ -621,6 +637,7 @@ struct udma_dev {
	struct udma_hem_table		qpc_timer_table;
	struct udma_hem_table		cqc_timer_table;
	struct udma_hem_table		gmv_table;
	uint64_t			dwqe_page;
	struct list_head		qp_list;
	spinlock_t			qp_list_lock;
	struct list_head		dip_list;
@@ -652,6 +669,17 @@ static inline uint32_t to_udma_hem_hopnum(uint32_t hopnum, uint32_t count)
	return 0;
}

static inline struct udma_ucontext
			*to_udma_ucontext(struct ubcore_ucontext *uctx)
{
	return container_of(uctx, struct udma_ucontext, uctx);
}

static inline struct udma_dev *to_udma_dev(const struct ubcore_device *ubcore_dev)
{
	return container_of(ubcore_dev, struct udma_dev, ub_dev);
}

static inline uint32_t to_udma_hw_page_shift(uint32_t page_shift)
{
	return page_shift - UDMA_HW_PAGE_SHIFT;
+111 −1
Original line number Diff line number Diff line
@@ -13,14 +13,124 @@
 *
 */

#include <linux/pci.h>
#include "urma/ubcore_api.h"
#include "hns3_udma_abi.h"
#include "hns3_udma_device.h"
#include "hns3_udma_hem.h"
#include "hns3_udma_jfc.h"
#include "hns3_udma_cmd.h"
static int udma_uar_alloc(struct udma_dev *udma_dev, struct udma_uar *uar)
{
	struct udma_ida *uar_ida = &udma_dev->uar_ida;
	int id;

static struct ubcore_ops g_udma_dev_ops = {
	/* Using bitmap to manager UAR index */
	id = ida_alloc_range(&uar_ida->ida, uar_ida->min, uar_ida->max,
			     GFP_KERNEL);
	if (id < 0) {
		dev_err(udma_dev->dev, "failed to alloc uar id(%d).\n", id);
		return id;
	}
	uar->logic_idx = (uint64_t)id;

	if (uar->logic_idx > 0 && udma_dev->caps.phy_num_uars > 1)
		uar->index = (uar->logic_idx - 1) %
			     (udma_dev->caps.phy_num_uars - 1) + 1;
	else
		uar->index = 0;

	uar->pfn = ((pci_resource_start(udma_dev->pci_dev,
					UDMA_DEV_START_OFFSET)) >> PAGE_SHIFT);
	if (udma_dev->caps.flags & UDMA_CAP_FLAG_DIRECT_WQE)
		udma_dev->dwqe_page =
			pci_resource_start(udma_dev->pci_dev,
					   UDMA_DEV_EX_START_OFFSET);

	return 0;
}

static int udma_init_ctx_resp(struct udma_dev *dev, struct ubcore_udrv_priv *udrv_data)
{
	struct udma_create_ctx_resp resp = {};
	int ret;

	resp.num_comp_vectors = dev->caps.num_comp_vectors;
	resp.num_qps_shift = dev->caps.num_qps_shift;
	resp.num_jfs_shift = dev->caps.num_jfs_shift;
	resp.num_jfr_shift = dev->caps.num_jfr_shift;
	resp.num_jetty_shift = dev->caps.num_jetty_shift;
	resp.max_jfc_cqe = dev->caps.max_cqes;
	resp.cqe_size = dev->caps.cqe_sz;
	resp.max_jfr_wr = dev->caps.max_srq_wrs;
	resp.max_jfr_sge = dev->caps.max_srq_sges;
	resp.max_jfs_wr = dev->caps.max_wqes;
	resp.max_jfs_sge = dev->caps.max_sq_sg;

	ret = copy_to_user((void *)udrv_data->out_addr, &resp,
			   min(udrv_data->out_len, (uint32_t)sizeof(resp)));
	if (ret)
		dev_err(dev->dev,
			"copy ctx resp to user failed, ret = %d.\n", ret);

	return ret;
}

static void udma_uar_free(struct udma_dev *udma_dev,
			  struct udma_ucontext *context)
{
	ida_free(&udma_dev->uar_ida.ida, (int)context->uar.logic_idx);
}

static struct ubcore_ucontext *udma_alloc_ucontext(struct ubcore_device *dev,
						   uint32_t uasid,
						   struct ubcore_udrv_priv *udrv_data)
{
	struct udma_dev *udma_dev = to_udma_dev(dev);
	struct udma_ucontext *context;
	int ret;

	context = kzalloc(sizeof(struct udma_ucontext), GFP_KERNEL);
	if (!context)
		return NULL;

	ret = udma_uar_alloc(udma_dev, &context->uar);
	if (ret) {
		dev_err(udma_dev->dev, "Alloc udma_uar Failed.\n");
		goto err_alloc_ucontext;
	}

	context->pdn = uasid; /* Use the UASID as pd number */
	ret = udma_init_ctx_resp(udma_dev, udrv_data);
	if (ret) {
		dev_err(udma_dev->dev, "Init ctx resp failed.\n");
		goto err_alloc_uar;
	}

	return &context->uctx;

err_alloc_uar:
	udma_uar_free(udma_dev, context);
err_alloc_ucontext:
	kfree(context);
	return NULL;
}

static int udma_free_ucontext(struct ubcore_ucontext *uctx)
{
	struct udma_ucontext *context = to_udma_ucontext(uctx);
	struct udma_dev *udma_dev = to_udma_dev(uctx->ub_dev);

	ida_free(&udma_dev->uar_ida.ida, (int)context->uar.logic_idx);
	kfree(context);
	return 0;
}

static struct ubcore_ops g_udma_dev_ops = {
	.owner = THIS_MODULE,
	.abi_version = 1,
	.alloc_ucontext = udma_alloc_ucontext,
	.free_ucontext = udma_free_ucontext,
};

static void udma_cleanup_uar_table(struct udma_dev *dev)