Commit 8d47f8c2 authored by Yu Zhang's avatar Yu Zhang Committed by JiangShui
Browse files

hns3 udma: support report events to AE or CE handler.

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


CVE: NA

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

When an AE(asynchronous event) or CE(completion event) interrupt is
triggered, the UDMA Linux driver finally reports them to corresponding
URMA handler.

Signed-off-by: default avatarYu Zhang <zhangyu709@huawei.com>
parent fc19a9b6
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@
#include <linux/acpi.h>
#include "hnae3.h"
#include "hns3_udma_hem.h"
#include "hns3_udma_eq.h"
#include "hns3_udma_jfc.h"
#include "hns3_udma_jfr.h"
#include "hns3_udma_qp.h"
#include "hns3_udma_eq.h"

static int alloc_eq_buf(struct udma_dev *udma_dev, struct udma_eq *eq)
{
@@ -209,6 +211,13 @@ static void aeq_event_report(struct udma_dev *udma_dev,
	case UDMA_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR:
		udma_qp_event(udma_dev, queue_num, event_type);
		break;
	case UDMA_EVENT_TYPE_JFR_LIMIT_REACH:
		udma_jfr_event(udma_dev, queue_num, event_type);
		break;
	case UDMA_EVENT_TYPE_JFC_ACCESS_ERROR:
	case UDMA_EVENT_TYPE_JFC_OVERFLOW:
		udma_jfc_event(udma_dev, queue_num, event_type);
		break;
	case UDMA_EVENT_TYPE_MB:
		udma_cmd_event(udma_dev,
			       le16_to_cpu(aeqe->event.cmd.token),
@@ -369,6 +378,8 @@ static int udma_ceq_int(struct udma_dev *udma_dev,
		cqn = udma_get_field(ceqe->comp, UDMA_CEQE_COMP_CQN_M,
				     UDMA_CEQE_COMP_CQN_S);

		udma_jfc_completion(udma_dev, cqn);

		++eq->cons_index;
		ceqe_found = 1;

+51 −0
Original line number Diff line number Diff line
@@ -592,3 +592,54 @@ int udma_modify_jfc(struct ubcore_jfc *ubcore_jfc, const struct ubcore_jfc_attr

	return ret;
}

void udma_jfc_completion(struct udma_dev *udma_dev, uint32_t cqn)
{
	struct ubcore_jfc *ubcore_jfc;
	struct udma_jfc *udma_jfc;

	udma_jfc = (struct udma_jfc *)xa_load(&udma_dev->jfc_table.xa, cqn);
	if (!udma_jfc) {
		dev_warn(udma_dev->dev,
			 "Completion event for bogus CQ 0x%06x\n", cqn);
		return;
	}

	ubcore_jfc = &udma_jfc->ubcore_jfc;
	if (ubcore_jfc->jfce_handler)
		ubcore_jfc->jfce_handler(ubcore_jfc);
}

void udma_jfc_event(struct udma_dev *udma_dev, uint32_t cqn, int event_type)
{
	struct device *dev = udma_dev->dev;
	struct udma_jfc *udma_jfc;
	struct ubcore_jfc *ubcore_jfc;
	struct ubcore_event event;

	udma_jfc = (struct udma_jfc *)xa_load(&udma_dev->jfc_table.xa, cqn);
	if (!udma_jfc) {
		dev_warn(dev, "Async event for bogus CQ 0x%06x\n", cqn);
		return;
	}

	if (event_type != UDMA_EVENT_TYPE_JFC_ACCESS_ERROR &&
	    event_type != UDMA_EVENT_TYPE_JFC_OVERFLOW) {
		dev_err(dev, "Unexpected event type 0x%x on CQ 0x%06x\n",
			event_type, cqn);
		return;
	}

	refcount_inc(&udma_jfc->refcount);

	ubcore_jfc = &udma_jfc->ubcore_jfc;
	if (ubcore_jfc->jfae_handler) {
		event.ub_dev = ubcore_jfc->ub_dev;
		event.element.jfc = ubcore_jfc;
		event.event_type = UBCORE_EVENT_JFC_ERR;
		ubcore_jfc->jfae_handler(&event, ubcore_jfc->uctx);
	}

	if (refcount_dec_and_test(&udma_jfc->refcount))
		complete(&udma_jfc->free);
}
+2 −0
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ struct ubcore_jfc *udma_create_jfc(struct ubcore_device *dev, const struct ubcor
int udma_destroy_jfc(struct ubcore_jfc *jfc);
int udma_modify_jfc(struct ubcore_jfc *ubcore_jfc, const struct ubcore_jfc_attr *attr,
		    struct ubcore_udata *udata);
void udma_jfc_completion(struct udma_dev *udma_dev, uint32_t cqn);
void udma_jfc_event(struct udma_dev *udma_dev, uint32_t cqn, int event_type);
static inline uint8_t get_jfc_bankid(uint64_t cqn)
{
	/* The lower 2 bits of CQN are used to hash to different banks */
+32 −0
Original line number Diff line number Diff line
@@ -441,3 +441,35 @@ int udma_destroy_jfr(struct ubcore_jfr *jfr)

	return 0;
}

void udma_jfr_event(struct udma_dev *udma_dev, uint32_t jfrn, int event_type)
{
	struct udma_jfr_table *jfr_table = &udma_dev->jfr_table;
	struct ubcore_jfr *ubcore_jfr;
	struct udma_jfr *jfr;
	struct ubcore_event event;

	xa_lock(&jfr_table->xa);
	jfr = (struct udma_jfr *)xa_load(&jfr_table->xa, jfrn);
	xa_unlock(&jfr_table->xa);

	if (!jfr) {
		dev_warn(udma_dev->dev, "Async event for bogus SRQ 0x%08x\n",
			 jfrn);
		return;
	}

	event.event_type = UBCORE_EVENT_JFR_ACCESS_ERR;

	refcount_inc(&jfr->refcount);
	ubcore_jfr = &jfr->ubcore_jfr;
	if (ubcore_jfr->jfae_handler) {
		event.ub_dev = ubcore_jfr->ub_dev;
		event.element.jfr = ubcore_jfr;
		ubcore_jfr->jfae_handler(&event, ubcore_jfr->uctx);
		dev_info(udma_dev->dev, "Async event for JFR 0x%08x\n", jfrn);
	}

	if (refcount_dec_and_test(&jfr->refcount))
		complete(&jfr->free);
}
+1 −0
Original line number Diff line number Diff line
@@ -87,5 +87,6 @@ static inline struct udma_jfr *to_udma_jfr(struct ubcore_jfr *ubcore_jfr)
struct ubcore_jfr *udma_create_jfr(struct ubcore_device *dev, const struct ubcore_jfr_cfg *cfg,
			      struct ubcore_udata *udata);
int udma_destroy_jfr(struct ubcore_jfr *jfr);
void udma_jfr_event(struct udma_dev *udma_dev, uint32_t jfrn, int event_type);

#endif /* _UDMA_JFR_H */