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

hns3 udma: support of notify address in create jfc

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


CVE: NA

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

Notify address is an address used by write_with_notify.
Write_with_notify can write a data to notify_address
after write operation.

Signed-off-by: default avatarWeibo Zhao <zhaoweibo3@huawei.com>
parent 59589d96
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -25,9 +25,32 @@ enum {
	UDMA_MMAP_UAR_PAGE,
};

enum udma_jfc_init_attr_mask {
	UDMA_JFC_NOTIFY_CREATE_FLAGS = 1 << 0,
};

enum udma_jfc_create_flags {
	UDMA_JFC_CREATE_ENABLE_NOTIFY = 1 << 1,
};

enum udma_jfc_notify_mode {
	UDMA_JFC_NOTIFY_MODE_64B_ALIGN,
	UDMA_JFC_NOTIFY_MODE_4B_ALIGN,
	UDMA_JFC_NOTIFY_MODE_DDR_64B_ALIGN,
	UDMA_JFC_NOTIFY_MODE_DDR_4B_ALIGN,
};

struct udma_jfc_attr_ex {
	uint64_t	jfc_ex_mask; /* Use enum udma_jfc_init_attr_mask */
	uint64_t	create_flags; /* Use enum udma_jfc_create_flags */
	uint64_t	notify_addr;
	uint8_t		notify_mode; /* Use enum udma_jfc_notify_mode */
};

struct udma_create_jfc_ucmd {
	uint64_t		buf_addr;
	uint64_t		db_addr;
	struct udma_jfc_attr_ex	jfc_attr_ex;
};

enum udma_jfc_cap_flags {
+6 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@
#define CQC_NOTIFY_MODE CQC_FIELD_LOC(4, 4)
#define CQC_ARM_ST CQC_FIELD_LOC(7, 6)
#define CQC_SHIFT CQC_FIELD_LOC(12, 8)
#define CQC_NOTIFY_ADDR_0 CQC_FIELD_LOC(31, 24)
#define CQC_CQN CQC_FIELD_LOC(55, 32)
#define CQC_POE_EN CQC_FIELD_LOC(56, 56)
#define CQC_POE_NUM CQC_FIELD_LOC(58, 57)
@@ -86,16 +87,21 @@
#define CQC_CQE_HOP_NUM CQC_FIELD_LOC(127, 126)
#define CQC_CQE_NEX_BLK_ADDR_L CQC_FIELD_LOC(159, 128)
#define CQC_CQE_NEX_BLK_ADDR_H CQC_FIELD_LOC(179, 160)
#define CQC_NOTIFY_ADDR_2 CQC_FIELD_LOC(183, 180)
#define CQC_CQE_BAR_PG_SZ CQC_FIELD_LOC(187, 184)
#define CQC_CQE_BUF_PG_SZ CQC_FIELD_LOC(191, 188)
#define CQC_NOTIFY_ADDR_3 CQC_FIELD_LOC(223, 216)
#define CQC_NOTIFY_ADDR_4 CQC_FIELD_LOC(255, 248)
#define CQC_CQE_BA_L CQC_FIELD_LOC(287, 256)
#define CQC_CQE_BA_H CQC_FIELD_LOC(316, 288)
#define CQC_DB_RECORD_EN CQC_FIELD_LOC(320, 320)
#define CQC_CQE_DB_RECORD_ADDR_L CQC_FIELD_LOC(351, 321)
#define CQC_CQE_DB_RECORD_ADDR_H CQC_FIELD_LOC(383, 352)
#define CQC_CQE_CNT CQC_FIELD_LOC(407, 384)
#define CQC_NOTIFY_ADDR_5 CQC_FIELD_LOC(415, 408)
#define CQC_CQ_MAX_CNT CQC_FIELD_LOC(431, 416)
#define CQC_CQ_PERIOD CQC_FIELD_LOC(447, 432)
#define CQC_NOTIFY_ADDR_6 CQC_FIELD_LOC(509, 504)
#define CQC_NOTIFY_EN CQC_FIELD_LOC(510, 510)

#define UDMA_CQ_DEFAULT_BURST_NUM	0x0
+103 −0
Original line number Diff line number Diff line
@@ -56,6 +56,56 @@ static int check_jfc_cfg(struct udma_dev *udma_dev, const struct ubcore_jfc_cfg
	return 0;
}

static int check_notify_attr(struct udma_dev *udma_dev,
			     struct udma_jfc_attr_ex *jfc_attr_ex)
{
	if (!(udma_dev->caps.flags & UDMA_CAP_FLAG_WRITE_NOTIFY)) {
		dev_err(udma_dev->dev, "Unsupport NOTIFY JFC.\n");
		return -EINVAL;
	}

	switch (jfc_attr_ex->notify_mode) {
	case UDMA_JFC_NOTIFY_MODE_4B_ALIGN:
	case UDMA_JFC_NOTIFY_MODE_DDR_4B_ALIGN:
		break;
	case UDMA_JFC_NOTIFY_MODE_64B_ALIGN:
	case UDMA_JFC_NOTIFY_MODE_DDR_64B_ALIGN:
		dev_err(udma_dev->dev, "Doesn't support notify mode %u\n",
			jfc_attr_ex->notify_mode);
		return -EINVAL;
	default:
		dev_err(udma_dev->dev, "Invalid notify mode %u\n",
			jfc_attr_ex->notify_mode);
		return -EINVAL;
	}

	if (jfc_attr_ex->notify_addr & UDMA_ADDR_4K_MASK) {
		dev_err(udma_dev->dev,
			"Notify addr should be aligned to 4k.\n");
		return -EINVAL;
	}

	return 0;
}

static int check_jfc_attr_ex(struct udma_dev *udma_dev,
			     struct udma_jfc_attr_ex *jfc_attr_ex)
{
	int ret;

	switch (jfc_attr_ex->create_flags) {
	case UDMA_JFC_CREATE_ENABLE_NOTIFY:
		ret = check_notify_attr(udma_dev, jfc_attr_ex);
		break;
	default:
		dev_err(udma_dev->dev, "Invalid create flags %llu\n",
			jfc_attr_ex->create_flags);
		return -EINVAL;
	}

	return ret;
}

static int check_create_jfc(struct udma_dev *udma_dev,
			    const struct ubcore_jfc_cfg *cfg,
			    struct udma_create_jfc_ucmd *ucmd,
@@ -81,6 +131,16 @@ static int check_create_jfc(struct udma_dev *udma_dev,
		return ret;
	}

	if (ucmd->jfc_attr_ex.jfc_ex_mask &
	    UDMA_JFC_NOTIFY_CREATE_FLAGS) {
		ret = check_jfc_attr_ex(udma_dev, &ucmd->jfc_attr_ex);
		if (ret) {
			dev_err(udma_dev->dev,
				"failed to check JFC attr ex.\n");
			return ret;
		}
	}

	return 0;
}

@@ -95,6 +155,8 @@ static void init_jfc(struct udma_jfc *udma_jfc, struct udma_create_jfc_ucmd *ucm
	spin_lock_init(&udma_jfc->lock);
	INIT_LIST_HEAD(&udma_jfc->sq_list);
	INIT_LIST_HEAD(&udma_jfc->rq_list);
	if (ucmd->jfc_attr_ex.jfc_ex_mask & UDMA_JFC_NOTIFY_CREATE_FLAGS)
		udma_jfc->jfc_attr_ex = ucmd->jfc_attr_ex;
}

static int alloc_jfc_cqe_buf(struct udma_dev *dev, struct udma_jfc *jfc,
@@ -169,6 +231,44 @@ static int alloc_jfc_buf(struct udma_dev *udma_dev, struct udma_jfc *udma_jfc,
	return ret;
}

static void set_write_notify_param(struct udma_dev *udma_dev,
				   struct udma_jfc *udma_jfc,
				   struct udma_jfc_context *jfc_context)
{
	uint8_t device_mode;

	if (udma_jfc->jfc_attr_ex.notify_mode == UDMA_JFC_NOTIFY_MODE_4B_ALIGN)
		device_mode = UDMA_NOTIFY_DEV;
	else
		device_mode = UDMA_NOTIFY_DDR;

	udma_reg_enable(jfc_context, CQC_NOTIFY_EN);
	udma_reg_write(jfc_context, CQC_NOTIFY_DEVICE_EN, device_mode);
	/* Supports only 4B alignment. */
	udma_reg_write(jfc_context, CQC_NOTIFY_MODE, UDMA_NOTIFY_MODE_4B);
	udma_reg_write(jfc_context, CQC_NOTIFY_ADDR_0,
		       (uint32_t)udma_get_field64(udma_jfc->jfc_attr_ex.notify_addr,
		       CQC_NOTIFY_ADDR_0_M, CQC_NOTIFY_ADDR_0_S));
	udma_reg_write(jfc_context, CQC_POE_QID,
		       (uint32_t)udma_get_field64(udma_jfc->jfc_attr_ex.notify_addr,
		       CQC_NOTIFY_ADDR_1_M, CQC_NOTIFY_ADDR_1_S));
	udma_reg_write(jfc_context, CQC_NOTIFY_ADDR_2,
		       (uint32_t)udma_get_field64(udma_jfc->jfc_attr_ex.notify_addr,
		       CQC_NOTIFY_ADDR_2_M, CQC_NOTIFY_ADDR_2_S));
	udma_reg_write(jfc_context, CQC_NOTIFY_ADDR_3,
		       (uint32_t)udma_get_field64(udma_jfc->jfc_attr_ex.notify_addr,
		       CQC_NOTIFY_ADDR_3_M, CQC_NOTIFY_ADDR_3_S));
	udma_reg_write(jfc_context, CQC_NOTIFY_ADDR_4,
		       (uint32_t)udma_get_field64(udma_jfc->jfc_attr_ex.notify_addr,
		       CQC_NOTIFY_ADDR_4_M, CQC_NOTIFY_ADDR_4_S));
	udma_reg_write(jfc_context, CQC_NOTIFY_ADDR_5,
		       (uint32_t)udma_get_field64(udma_jfc->jfc_attr_ex.notify_addr,
		       CQC_NOTIFY_ADDR_5_M, CQC_NOTIFY_ADDR_5_S));
	udma_reg_write(jfc_context, CQC_NOTIFY_ADDR_6,
		       (uint32_t)udma_get_field64(udma_jfc->jfc_attr_ex.notify_addr,
		       CQC_NOTIFY_ADDR_6_M, CQC_NOTIFY_ADDR_6_S));
}

static void udma_write_jfc_cqc(struct udma_dev *udma_dev, struct udma_jfc *udma_jfc,
			void *mb_buf, uint64_t *mtts, uint64_t dma_handle)
{
@@ -214,6 +314,9 @@ static void udma_write_jfc_cqc(struct udma_dev *udma_dev, struct udma_jfc *udma_
		udma_reg_write(jfc_context, CQC_CQE_DB_RECORD_ADDR_H,
			       upper_32_bits(udma_jfc->db.dma));
	}

	if (udma_jfc->jfc_attr_ex.create_flags == UDMA_JFC_CREATE_ENABLE_NOTIFY)
		set_write_notify_param(udma_dev, udma_jfc, jfc_context);
}

static int udma_create_jfc_cqc(struct udma_dev *udma_dev,
+23 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ struct udma_jfc {
	struct completion	free;
	struct list_head	sq_list;
	struct list_head	rq_list;
	struct udma_jfc_attr_ex	jfc_attr_ex;
};

#define UDMA_JFC_CONTEXT_SIZE 16
@@ -39,6 +40,28 @@ struct udma_jfc_context {
	uint32_t jfc_data[UDMA_JFC_CONTEXT_SIZE];
};

#define UDMA_NOTIFY_MODE_4B 1UL

enum udma_notify_device_en {
	UDMA_NOTIFY_DEV,
	UDMA_NOTIFY_DDR,
};

#define CQC_NOTIFY_ADDR_0_S 12
#define CQC_NOTIFY_ADDR_0_M GENMASK(19, 12)
#define CQC_NOTIFY_ADDR_1_S 20
#define CQC_NOTIFY_ADDR_1_M GENMASK(29, 20)
#define CQC_NOTIFY_ADDR_2_S 30
#define CQC_NOTIFY_ADDR_2_M GENMASK(33, 30)
#define CQC_NOTIFY_ADDR_3_S 34
#define CQC_NOTIFY_ADDR_3_M GENMASK(41, 34)
#define CQC_NOTIFY_ADDR_4_S 42
#define CQC_NOTIFY_ADDR_4_M GENMASK(49, 42)
#define CQC_NOTIFY_ADDR_5_S 50
#define CQC_NOTIFY_ADDR_5_M GENMASK(57, 50)
#define CQC_NOTIFY_ADDR_6_S 58
#define CQC_NOTIFY_ADDR_6_M GENMASK(63, 58)

static inline struct udma_jfc *to_udma_jfc(struct ubcore_jfc *jfc)
{
	return container_of(jfc, struct udma_jfc, ubcore_jfc);