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

hns3 udma: support modify tp and destroy tp

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


CVE: NA

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

URMA uses the modify_tp function to modify the attributes of tp.
UDMA driver will update qp context to hardware based on the value
of mask.

Signed-off-by: default avatarYu Zhang <zhangyu709@huawei.com>
parent 460bb8ae
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -20,11 +20,13 @@
#include "hnae3.h"
#include "hns3_udma_device.h"
#include "hns3_udma_hem.h"
#include "hns3_udma_tp.h"
#include "hns3_udma_jfr.h"
#include "hns3_udma_jfc.h"
#include "hns3_udma_jfs.h"
#include "hns3_udma_segment.h"
#include "hns3_udma_cmd.h"

static int udma_set_eid(struct ubcore_device *dev, union ubcore_eid eid)
{
	struct udma_dev *udma_dev = to_udma_dev(dev);
@@ -328,6 +330,9 @@ static struct ubcore_ops g_udma_dev_ops = {
	.destroy_jfr = udma_destroy_jfr,
	.import_jfr = udma_import_jfr,
	.unimport_jfr = udma_unimport_jfr,
	.create_tp = udma_create_tp,
	.modify_tp = udma_modify_tp,
	.destroy_tp = udma_destroy_tp,
};

static void udma_cleanup_uar_table(struct udma_dev *dev)
+172 −3
Original line number Diff line number Diff line
@@ -16,8 +16,168 @@
#include <linux/acpi.h>
#include <linux/iommu.h>
#include "hns3_udma_jfr.h"
#include "hns3_udma_jfs.h"
#include "hns3_udma_tp.h"

static enum udma_qp_state to_udma_qp_state(enum ubcore_tp_state state)
{
	switch (state) {
	case UBCORE_TP_STATE_RESET:
		return QPS_RESET;
	case UBCORE_TP_STATE_RTR:
		return QPS_RTR;
	case UBCORE_TP_STATE_RTS:
		return QPS_RTS;
	case UBCORE_TP_STATE_ERROR:
		return QPS_ERR;
	default:
		return QPS_ERR;
	}
}

struct udma_modify_tp_attr *udma_get_m_attr(struct ubcore_tp *tp, struct udma_qp *qp,
					    const struct ubcore_tp_attr *attr,
					    union ubcore_tp_attr_mask mask)
{
	struct udma_modify_tp_attr *m_attr;

	m_attr = kzalloc(sizeof(*m_attr), GFP_KERNEL);
	if (m_attr == NULL)
		return NULL;

	memcpy(m_attr->dmac, tp->peer_net_addr.mac, sizeof(m_attr->dmac));

	m_attr->max_dest_rd_atomic = 0;
	m_attr->max_rd_atomic = 0;
	m_attr->rq_psn = tp->rx_psn;
	m_attr->hop_limit = MAX_HOP_LIMIT;
	m_attr->sgid_index = 0;
	*(uint32_t *)(&m_attr->dipv4) = *(uint32_t *)(tp->peer_eid.raw +
						      SGID_H_SHIFT);
	memcpy(m_attr->dgid, tp->peer_eid.raw, sizeof(tp->peer_eid.raw));

	if (!qp->qp_attr.is_tgt) {
		m_attr->retry_cnt = qp->retry_cnt;
		m_attr->ack_timeout = qp->ack_timeout;
		m_attr->rnr_retry = qp->rnr_retry;
		m_attr->priority = qp->priority;
	} else {
		m_attr->min_rnr_timer = qp->min_rnr_timer;
	}

	if (mask.bs.peer_tpn)
		m_attr->dest_qp_num = attr->peer_tpn;

	if (mask.bs.tx_psn)
		m_attr->sq_psn = attr->tx_psn;
	else
		m_attr->sq_psn = tp->tx_psn;

	if (mask.bs.mtu)
		m_attr->path_mtu = attr->mtu;

	return m_attr;
}

int udma_modify_tp(struct ubcore_tp *tp, const struct ubcore_tp_attr *attr,
		   union ubcore_tp_attr_mask mask)
{
	struct udma_modify_tp_attr *m_attr;
	enum udma_qp_state target_state;
	enum udma_qp_state curr_state;
	struct udma_dev *udma_device;
	struct udma_tp *utp;
	struct udma_qp *qp;
	int ret = -EINVAL;

	udma_device = to_udma_dev(tp->ub_dev);
	utp = to_udma_tp(tp);

	qp = &utp->qp;
	if (!qp)
		goto error;

	curr_state = to_udma_qp_state(tp->state);

	if (mask.bs.state)
		target_state = to_udma_qp_state(attr->state);
	else
		target_state = QPS_ERR;

	m_attr = udma_get_m_attr(tp, qp, attr, mask);
	if (!m_attr)
		goto error;

	qp->udma_device = udma_device;
	qp->send_jfc = qp->qp_attr.send_jfc;
	qp->recv_jfc = qp->qp_attr.recv_jfc;
	if (attr)
		qp->ubcore_path_mtu = attr->mtu;
	ret = udma_modify_qp_common(qp, m_attr, curr_state, target_state);
	kfree(m_attr);
error:
	return ret;
}

void *udma_erase_tp(struct udma_tp *udma_tp)
{
	struct udma_qp_attr *qp_attr;
	struct udma_jfr *jfr;
	struct udma_jfs *jfs;

	qp_attr = &udma_tp->qp.qp_attr;
	jfr = qp_attr->jfr;
	jfs = qp_attr->jfs;

	if (jfr)
		return xa_erase(&jfr->tp_table_xa,
				udma_tp->ubcore_tp.tpn);

	if (jfs)
		return xa_erase(&jfs->node_table,
				udma_tp->ubcore_tp.tpn);

	return udma_tp;
}

int udma_destroy_tp(struct ubcore_tp *tp)
{
	struct udma_dev *udma_device = to_udma_dev(tp->ub_dev);
	enum udma_qp_state curr_state;
	struct udma_tp *udma_tp;
	struct udma_qp *qp;
	int ret = 0;

	udma_tp = to_udma_tp(tp);
	if (!udma_erase_tp(udma_tp)) {
		dev_err(udma_device->dev,
			"failed to find tp, tpn = 0x%x\n", tp->tpn);
		return 0;
	}

	qp = &udma_tp->qp;
	curr_state = to_udma_qp_state(tp->state);

	if (qp->state != QPS_RESET) {
		ret = udma_modify_qp_common(qp, NULL, curr_state, QPS_RESET);
		if (ret) {
			dev_err(udma_device->dev,
				"Modify QP 0x%06llx to Reset failed(%d).\n",
				qp->qpn, ret);
			goto error;
		}
	}

	udma_destroy_qp_common(udma_device, qp);

	kfree(udma_tp);

	return ret;

error:
	return -EINVAL;
}

static void udma_set_tp(struct ubcore_device *dev, const struct ubcore_tp_cfg *cfg,
			struct udma_tp *tp)
{
@@ -48,19 +208,28 @@ static int udma_store_tp(struct udma_dev *udma_device, struct udma_tp *tp,
{
	struct udma_qp_attr *qp_attr;
	struct udma_jfr *jfr;
	struct udma_jfs *jfs;
	int ret = 0;

	qp_attr = &tp->qp.qp_attr;
	jfr = qp_attr->jfr;
	jfs = qp_attr->jfs;
	if (jfr) {
		ret = xa_err(xa_store(&jfr->tp_table_xa,
					tp->ubcore_tp.tpn, tp,
		ret = xa_err(xa_store(&jfr->tp_table_xa, tp->ubcore_tp.tpn, tp,
				      GFP_KERNEL));
		if (ret) {
			dev_err(udma_device->dev,
				"failed store jfr tp, ret = %d\n", ret);
			return ret;
		}
	} else if (jfs) {
		ret = xa_err(xa_store(&jfs->node_table, tp->ubcore_tp.tpn, tp,
				      GFP_KERNEL));
		if (ret) {
			dev_err(udma_device->dev,
				"failed store jfs tp, ret = %d\n", ret);
			return ret;
		}
	}

	return ret;
+8 −0
Original line number Diff line number Diff line
@@ -26,9 +26,17 @@ struct udma_tp {
	struct udma_qp		qp;
	struct ubcore_jetty_id	tjetty_id;
};

static inline struct udma_tp *to_udma_tp(struct ubcore_tp *ubcore_tp)
{
	return container_of(ubcore_tp, struct udma_tp, ubcore_tp);
}

struct ubcore_tp *udma_create_tp(struct ubcore_device *dev,
			    const struct ubcore_tp_cfg *cfg,
			    struct ubcore_udata *udata);
int udma_destroy_tp(struct ubcore_tp *tp);
int udma_modify_tp(struct ubcore_tp *tp, const struct ubcore_tp_attr *attr,
		   union ubcore_tp_attr_mask mask);

#endif /* _UDMA_TP_H */