Commit 16a9377d authored by Weili Qian's avatar Weili Qian Committed by JiangShui
Browse files

crypto: hisilicon/qm - add stop function by hardware

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8LFYK


CVE: NA

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

Hardware V3 could be able to drain function by sending mailbox
to hardware which will trigger tasks in device to be flushed out.

Signed-off-by: default avatarWeili Qian <qianweili@huawei.com>
Signed-off-by: default avatarJiangShui Yang <yangjiangshui@h-partners.com>
parent e619190e
Loading
Loading
Loading
Loading
+33 −8
Original line number Diff line number Diff line
@@ -313,6 +313,7 @@ static const struct hisi_qm_cap_info qm_cap_info_comm[] = {
	{QM_SUPPORT_DB_ISOLATION, 0x30,   0, BIT(0),  0x0, 0x0, 0x0},
	{QM_SUPPORT_FUNC_QOS,     0x3100, 0, BIT(8),  0x0, 0x0, 0x1},
	{QM_SUPPORT_STOP_QP,      0x3100, 0, BIT(9),  0x0, 0x0, 0x1},
	{QM_SUPPORT_STOP_FUNC,     0x3100, 0, BIT(10), 0x0, 0x0, 0x1},
	{QM_SUPPORT_MB_COMMAND,   0x3100, 0, BIT(11), 0x0, 0x0, 0x1},
	{QM_SUPPORT_SVA_PREFETCH, 0x3100, 0, BIT(14), 0x0, 0x0, 0x1},
};
@@ -1756,6 +1757,11 @@ static int qm_ping_pf(struct hisi_qm *qm, u64 cmd)
	return ret;
}

static int qm_drain_qm(struct hisi_qm *qm)
{
	return hisi_qm_mb_write(qm, QM_MB_CMD_FLUSH_QM, 0, 0, 0);
}

static int qm_stop_qp(struct hisi_qp *qp)
{
	return hisi_qm_mb_write(qp->qm, QM_MB_CMD_STOP_QP, 0, qp->qp_id, 0);
@@ -2194,7 +2200,8 @@ static int qm_drain_qp(struct hisi_qp *qp)
}
static int qm_stop_qp_nolock(struct hisi_qp *qp)
{
	struct device *dev = &qp->qm->pdev->dev;
	struct hisi_qm *qm = qp->qm;
	struct device *dev = &qm->pdev->dev;
	int ret;

	/*
@@ -2210,11 +2217,15 @@ static int qm_stop_qp_nolock(struct hisi_qp *qp)

	atomic_set(&qp->qp_status.flags, QP_STOP);

	/* V3 supports direct stop function when FLR prepare */
	if (qm->ver < QM_HW_V3 || qm->status.stop_reason == QM_NORMAL) {
		ret = qm_drain_qp(qp);
		if (ret)
		dev_err(dev, "Failed to drain out data for stopping!\n");
			dev_err(dev, "Failed to drain out data for stopping qp(%u)!\n",
					qp->qp_id);
	}

	flush_workqueue(qp->qm->wq);
	flush_workqueue(qm->wq);
	if (unlikely(qp->is_resetting && atomic_read(&qp->qp_status.used)))
		qp_stop_fail_cb(qp);

@@ -3282,16 +3293,29 @@ int hisi_qm_stop(struct hisi_qm *qm, enum qm_stop_reason r)

	down_write(&qm->qps_lock);

	qm->status.stop_reason = r;
	if (atomic_read(&qm->status.flags) == QM_STOP)
		goto err_unlock;

	/* Stop all the request sending at first. */
	atomic_set(&qm->status.flags, QM_STOP);
	qm->status.stop_reason = r;

	if (qm->status.stop_reason == QM_SOFT_RESET ||
	    qm->status.stop_reason == QM_DOWN) {
	if (qm->status.stop_reason != QM_NORMAL) {
		hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET);
		/*
		 * When performing soft reset, the hardware will no longer
		 * do tasks, and the tasks in the device will be flushed
		 * out directly since the master ooo is closed.
		 */
		if (test_bit(QM_SUPPORT_STOP_FUNC, &qm->caps) &&
		    r != QM_SOFT_RESET) {
			ret = qm_drain_qm(qm);
			if (ret) {
				dev_err(dev, "failed to drain qm!\n");
				goto err_unlock;
			}
		}

		ret = qm_stop_started_qp(qm);
		if (ret < 0) {
			dev_err(dev, "Failed to stop started qp!\n");
@@ -3311,6 +3335,7 @@ int hisi_qm_stop(struct hisi_qm *qm, enum qm_stop_reason r)
	}

	qm_clear_queues(qm);
	qm->status.stop_reason = QM_NORMAL;

err_unlock:
	up_write(&qm->qps_lock);
+2 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@
#define QM_MB_CMD_CQC_BT                0x5
#define QM_MB_CMD_SQC_VFT_V2            0x6
#define QM_MB_CMD_STOP_QP               0x8
#define QM_MB_CMD_FLUSH_QM				0x9
#define QM_MB_CMD_SRC                   0xc
#define QM_MB_CMD_DST                   0xd

@@ -152,6 +153,7 @@ enum qm_cap_bits {
	QM_SUPPORT_DB_ISOLATION = 0x0,
	QM_SUPPORT_FUNC_QOS,
	QM_SUPPORT_STOP_QP,
	QM_SUPPORT_STOP_FUNC,
	QM_SUPPORT_MB_COMMAND,
	QM_SUPPORT_SVA_PREFETCH,
	QM_SUPPORT_RPM,