This patchset includes some misc updates.
patch 1-3: modify the accelerator probe process.
patch 4: refactor module parameter pf_q_num.
patch 5-6: add state machine and FLR support.
patch 7: remove use_dma_api related useless codes.
patch 8-9: QM initialization process and memory management optimization.
patch 10-11: add device error report through abnormal irq.
patch 12: tiny change of zip driver.
Longfang Liu (3):
crypto: hisilicon/sec2 - modify the SEC probe process
crypto: hisilicon/hpre - modify the HPRE probe process
crypto: hisilicon/zip - modify the ZIP probe process
Shukun Tan (5):
crypto: hisilicon - refactor module parameter pf_q_num related code
crypto: hisilicon - add FLR support
crypto: hisilicon - remove use_dma_api related codes
crypto: hisilicon - remove codes of directly report device errors
through MSI
crypto: hisilicon - add device error report through abnormal irq
Weili Qian (2):
crypto: hisilicon - unify initial value assignment into QM
crypto: hisilicon - QM memory management optimization
Zhou Wang (2):
crypto: hisilicon/qm - add state machine for QM
crypto: hisilicon/zip - Use temporary sqe when doing work
drivers/crypto/hisilicon/hpre/hpre_main.c | 107 ++-
drivers/crypto/hisilicon/qm.c | 1101 +++++++++++++++++++----------
drivers/crypto/hisilicon/qm.h | 75 +-
drivers/crypto/hisilicon/sec2/sec_main.c | 134 ++--
drivers/crypto/hisilicon/zip/zip_crypto.c | 11 +-
drivers/crypto/hisilicon/zip/zip_main.c | 128 ++--
6 files changed, 950 insertions(+), 606 deletions(-)
--
2.7.4
From: Zhou Wang <[email protected]>
Add specific states for qm and qp, every state change under critical region
to prevent from race condition. Meanwhile, qp state change will also depend
on qm state.
Due to the introduction of these states, it is necessary to pay attention
to the calls of public logic, such as concurrent scenarios resetting and
releasing queue will call hisi_qm_stop, which needs to add additional
status to distinguish and process.
Signed-off-by: Zhou Wang <[email protected]>
Signed-off-by: Shukun Tan <[email protected]>
---
drivers/crypto/hisilicon/qm.c | 366 +++++++++++++++++++++++++++++++++---------
drivers/crypto/hisilicon/qm.h | 24 ++-
2 files changed, 307 insertions(+), 83 deletions(-)
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index 69d02cb..e42097e 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -352,6 +352,93 @@ static const char * const qm_fifo_overflow[] = {
"cq", "eq", "aeq",
};
+static const char * const qm_s[] = {
+ "init", "start", "close", "stop",
+};
+
+static const char * const qp_s[] = {
+ "none", "init", "start", "stop", "close",
+};
+
+static bool qm_avail_state(struct hisi_qm *qm, enum qm_state new)
+{
+ enum qm_state curr = atomic_read(&qm->status.flags);
+ bool avail = false;
+
+ switch (curr) {
+ case QM_INIT:
+ if (new == QM_START || new == QM_CLOSE)
+ avail = true;
+ break;
+ case QM_START:
+ if (new == QM_STOP)
+ avail = true;
+ break;
+ case QM_STOP:
+ if (new == QM_CLOSE || new == QM_START)
+ avail = true;
+ break;
+ default:
+ break;
+ }
+
+ dev_dbg(&qm->pdev->dev, "change qm state from %s to %s\n",
+ qm_s[curr], qm_s[new]);
+
+ if (!avail)
+ dev_warn(&qm->pdev->dev, "Can not change qm state from %s to %s\n",
+ qm_s[curr], qm_s[new]);
+
+ return avail;
+}
+
+static bool qm_qp_avail_state(struct hisi_qm *qm, struct hisi_qp *qp,
+ enum qp_state new)
+{
+ enum qm_state qm_curr = atomic_read(&qm->status.flags);
+ enum qp_state qp_curr = 0;
+ bool avail = false;
+
+ if (qp)
+ qp_curr = atomic_read(&qp->qp_status.flags);
+
+ switch (new) {
+ case QP_INIT:
+ if (qm_curr == QM_START || qm_curr == QM_INIT)
+ avail = true;
+ break;
+ case QP_START:
+ if ((qm_curr == QM_START && qp_curr == QP_INIT) ||
+ (qm_curr == QM_START && qp_curr == QP_STOP))
+ avail = true;
+ break;
+ case QP_STOP:
+ if ((qm_curr == QM_START && qp_curr == QP_START) ||
+ (qp_curr == QP_INIT))
+ avail = true;
+ break;
+ case QP_CLOSE:
+ if ((qm_curr == QM_START && qp_curr == QP_INIT) ||
+ (qm_curr == QM_START && qp_curr == QP_STOP) ||
+ (qm_curr == QM_STOP && qp_curr == QP_STOP) ||
+ (qm_curr == QM_STOP && qp_curr == QP_INIT))
+ avail = true;
+ break;
+ default:
+ break;
+ }
+
+ dev_dbg(&qm->pdev->dev, "change qp state from %s to %s in QM %s\n",
+ qp_s[qp_curr], qp_s[new], qm_s[qm_curr]);
+
+ if (!avail)
+ dev_warn(&qm->pdev->dev,
+ "Can not change qp state from %s to %s in QM %s\n",
+ qp_s[qp_curr], qp_s[new], qm_s[qm_curr]);
+
+ return avail;
+}
+
/* return 0 mailbox ready, -ETIMEDOUT hardware timeout */
static int qm_wait_mb_ready(struct hisi_qm *qm)
{
@@ -699,7 +786,7 @@ static void qm_init_qp_status(struct hisi_qp *qp)
qp_status->sq_tail = 0;
qp_status->cq_head = 0;
qp_status->cqc_phase = true;
- qp_status->flags = 0;
+ atomic_set(&qp_status->flags, 0);
}
static void qm_vft_data_cfg(struct hisi_qm *qm, enum vft_type type, u32 base,
@@ -1155,29 +1242,21 @@ static void *qm_get_avail_sqe(struct hisi_qp *qp)
return qp->sqe + sq_tail * qp->qm->sqe_size;
}
-/**
- * hisi_qm_create_qp() - Create a queue pair from qm.
- * @qm: The qm we create a qp from.
- * @alg_type: Accelerator specific algorithm type in sqc.
- *
- * return created qp, -EBUSY if all qps in qm allocated, -ENOMEM if allocating
- * qp memory fails.
- */
-struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type)
+static struct hisi_qp *qm_create_qp_nolock(struct hisi_qm *qm, u8 alg_type)
{
struct device *dev = &qm->pdev->dev;
struct hisi_qp *qp;
int qp_id, ret;
+ if (!qm_qp_avail_state(qm, NULL, QP_INIT))
+ return ERR_PTR(-EPERM);
+
qp = kzalloc(sizeof(*qp), GFP_KERNEL);
if (!qp)
return ERR_PTR(-ENOMEM);
- write_lock(&qm->qps_lock);
-
qp_id = find_first_zero_bit(qm->qp_bitmap, qm->qp_num);
if (qp_id >= qm->qp_num) {
- write_unlock(&qm->qps_lock);
dev_info(&qm->pdev->dev, "QM all queues are busy!\n");
ret = -EBUSY;
goto err_free_qp;
@@ -1185,9 +1264,6 @@ struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type)
set_bit(qp_id, qm->qp_bitmap);
qm->qp_array[qp_id] = qp;
qm->qp_in_used++;
-
- write_unlock(&qm->qps_lock);
-
qp->qm = qm;
if (qm->use_dma_api) {
@@ -1206,18 +1282,36 @@ struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type)
qp->qp_id = qp_id;
qp->alg_type = alg_type;
+ atomic_set(&qp->qp_status.flags, QP_INIT);
return qp;
err_clear_bit:
- write_lock(&qm->qps_lock);
qm->qp_array[qp_id] = NULL;
clear_bit(qp_id, qm->qp_bitmap);
- write_unlock(&qm->qps_lock);
err_free_qp:
kfree(qp);
return ERR_PTR(ret);
}
+
+/**
+ * hisi_qm_create_qp() - Create a queue pair from qm.
+ * @qm: The qm we create a qp from.
+ * @alg_type: Accelerator specific algorithm type in sqc.
+ *
+ * return created qp, -EBUSY if all qps in qm allocated, -ENOMEM if allocating
+ * qp memory fails.
+ */
+struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type)
+{
+ struct hisi_qp *qp;
+
+ down_write(&qm->qps_lock);
+ qp = qm_create_qp_nolock(qm, alg_type);
+ up_write(&qm->qps_lock);
+
+ return qp;
+}
EXPORT_SYMBOL_GPL(hisi_qm_create_qp);
/**
@@ -1232,16 +1326,23 @@ void hisi_qm_release_qp(struct hisi_qp *qp)
struct qm_dma *qdma = &qp->qdma;
struct device *dev = &qm->pdev->dev;
+ down_write(&qm->qps_lock);
+
+ if (!qm_qp_avail_state(qm, qp, QP_CLOSE)) {
+ up_write(&qm->qps_lock);
+ return;
+ }
+
if (qm->use_dma_api && qdma->va)
dma_free_coherent(dev, qdma->size, qdma->va, qdma->dma);
- write_lock(&qm->qps_lock);
qm->qp_array[qp->qp_id] = NULL;
clear_bit(qp->qp_id, qm->qp_bitmap);
qm->qp_in_used--;
- write_unlock(&qm->qps_lock);
kfree(qp);
+
+ up_write(&qm->qps_lock);
}
EXPORT_SYMBOL_GPL(hisi_qm_release_qp);
@@ -1312,15 +1413,7 @@ static int qm_qp_ctx_cfg(struct hisi_qp *qp, int qp_id, int pasid)
return ret;
}
-/**
- * hisi_qm_start_qp() - Start a qp into running.
- * @qp: The qp we want to start to run.
- * @arg: Accelerator specific argument.
- *
- * After this function, qp can receive request from user. Return 0 if
- * successful, Return -EBUSY if failed.
- */
-int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg)
+static int qm_start_qp_nolock(struct hisi_qp *qp, unsigned long arg)
{
struct hisi_qm *qm = qp->qm;
struct device *dev = &qm->pdev->dev;
@@ -1330,6 +1423,9 @@ int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg)
size_t off = 0;
int ret;
+ if (!qm_qp_avail_state(qm, qp, QP_START))
+ return -EPERM;
+
#define QP_INIT_BUF(qp, type, size) do { \
(qp)->type = ((qp)->qdma.va + (off)); \
(qp)->type##_dma = (qp)->qdma.dma + (off); \
@@ -1360,10 +1456,31 @@ int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg)
if (ret)
return ret;
+ atomic_set(&qp->qp_status.flags, QP_START);
dev_dbg(dev, "queue %d started\n", qp_id);
return 0;
}
+
+/**
+ * hisi_qm_start_qp() - Start a qp into running.
+ * @qp: The qp we want to start to run.
+ * @arg: Accelerator specific argument.
+ *
+ * After this function, qp can receive request from user. Return 0 if
+ * successful, Return -EBUSY if failed.
+ */
+int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg)
+{
+ struct hisi_qm *qm = qp->qm;
+ int ret;
+
+ down_write(&qm->qps_lock);
+ ret = qm_start_qp_nolock(qp, arg);
+ up_write(&qm->qps_lock);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(hisi_qm_start_qp);
static void *qm_ctx_alloc(struct hisi_qm *qm, size_t ctx_size,
@@ -1467,20 +1584,26 @@ static int qm_drain_qp(struct hisi_qp *qp)
return ret;
}
-/**
- * hisi_qm_stop_qp() - Stop a qp in qm.
- * @qp: The qp we want to stop.
- *
- * This function is reverse of hisi_qm_start_qp. Return 0 if successful.
- */
-int hisi_qm_stop_qp(struct hisi_qp *qp)
+static int qm_stop_qp_nolock(struct hisi_qp *qp)
{
struct device *dev = &qp->qm->pdev->dev;
int ret;
- /* it is stopped */
- if (test_bit(QP_STOP, &qp->qp_status.flags))
+ /*
+ * It is allowed to stop and release qp when reset, If the qp is
+ * stopped when reset but still want to be released then, the
+ * is_resetting flag should be set negative so that this qp will not
+ * be restarted after reset.
+ */
+ if (atomic_read(&qp->qp_status.flags) == QP_STOP) {
+ qp->is_resetting = false;
return 0;
+ }
+
+ if (!qm_qp_avail_state(qp->qm, qp, QP_STOP))
+ return -EPERM;
+
+ atomic_set(&qp->qp_status.flags, QP_STOP);
ret = qm_drain_qp(qp);
if (ret)
@@ -1491,12 +1614,27 @@ int hisi_qm_stop_qp(struct hisi_qp *qp)
else
flush_work(&qp->qm->work);
- set_bit(QP_STOP, &qp->qp_status.flags);
-
dev_dbg(dev, "stop queue %u!", qp->qp_id);
return 0;
}
+
+/**
+ * hisi_qm_stop_qp() - Stop a qp in qm.
+ * @qp: The qp we want to stop.
+ *
+ * This function is reverse of hisi_qm_start_qp. Return 0 if successful.
+ */
+int hisi_qm_stop_qp(struct hisi_qp *qp)
+{
+ int ret;
+
+ down_write(&qp->qm->qps_lock);
+ ret = qm_stop_qp_nolock(qp);
+ up_write(&qp->qm->qps_lock);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(hisi_qm_stop_qp);
/**
@@ -1506,6 +1644,13 @@ EXPORT_SYMBOL_GPL(hisi_qm_stop_qp);
*
* This function will return -EBUSY if qp is currently full, and -EAGAIN
* if qp related qm is resetting.
+ *
+ * Note: This function may run with qm_irq_thread and ACC reset at same time.
+ * It has no race with qm_irq_thread. However, during hisi_qp_send, ACC
+ * reset may happen, we have no lock here considering performance. This
+ * causes current qm_db sending fail or can not receive sended sqe. QM
+ * sync/async receive function should handle the error sqe. ACC reset
+ * done function should clear used sqe to 0.
*/
int hisi_qp_send(struct hisi_qp *qp, const void *msg)
{
@@ -1514,7 +1659,9 @@ int hisi_qp_send(struct hisi_qp *qp, const void *msg)
u16 sq_tail_next = (sq_tail + 1) % QM_Q_DEPTH;
void *sqe = qm_get_avail_sqe(qp);
- if (unlikely(test_bit(QP_STOP, &qp->qp_status.flags))) {
+ if (unlikely(atomic_read(&qp->qp_status.flags) == QP_STOP ||
+ atomic_read(&qp->qm->status.flags) == QM_STOP ||
+ qp->is_resetting)) {
dev_info(&qp->qm->pdev->dev, "QP is stopped or resetting\n");
return -EAGAIN;
}
@@ -1554,11 +1701,11 @@ static int hisi_qm_get_available_instances(struct uacce_device *uacce)
int i, ret;
struct hisi_qm *qm = uacce->priv;
- read_lock(&qm->qps_lock);
+ down_read(&qm->qps_lock);
for (i = 0, ret = 0; i < qm->qp_num; i++)
if (!qm->qp_array[i])
ret++;
- read_unlock(&qm->qps_lock);
+ up_read(&qm->qps_lock);
return ret;
}
@@ -1658,9 +1805,9 @@ static int qm_set_sqctype(struct uacce_queue *q, u16 type)
struct hisi_qm *qm = q->uacce->priv;
struct hisi_qp *qp = q->priv;
- write_lock(&qm->qps_lock);
+ down_write(&qm->qps_lock);
qp->alg_type = type;
- write_unlock(&qm->qps_lock);
+ up_write(&qm->qps_lock);
return 0;
}
@@ -1762,9 +1909,9 @@ int hisi_qm_get_free_qp_num(struct hisi_qm *qm)
{
int ret;
- read_lock(&qm->qps_lock);
+ down_read(&qm->qps_lock);
ret = qm->qp_num - qm->qp_in_used;
- read_unlock(&qm->qps_lock);
+ up_read(&qm->qps_lock);
return ret;
}
@@ -1840,9 +1987,10 @@ int hisi_qm_init(struct hisi_qm *qm)
qm->qp_in_used = 0;
mutex_init(&qm->mailbox_lock);
- rwlock_init(&qm->qps_lock);
+ init_rwsem(&qm->qps_lock);
INIT_WORK(&qm->work, qm_work_process);
+ atomic_set(&qm->status.flags, QM_INIT);
dev_dbg(dev, "init qm %s with %s\n", pdev->is_physfn ? "pf" : "vf",
qm->use_dma_api ? "dma api" : "iommu api");
@@ -1875,6 +2023,13 @@ void hisi_qm_uninit(struct hisi_qm *qm)
struct pci_dev *pdev = qm->pdev;
struct device *dev = &pdev->dev;
+ down_write(&qm->qps_lock);
+
+ if (!qm_avail_state(qm, QM_CLOSE)) {
+ up_write(&qm->qps_lock);
+ return;
+ }
+
uacce_remove(qm->uacce);
qm->uacce = NULL;
@@ -1890,6 +2045,8 @@ void hisi_qm_uninit(struct hisi_qm *qm)
iounmap(qm->io_base);
pci_release_mem_regions(pdev);
pci_disable_device(pdev);
+
+ up_write(&qm->qps_lock);
}
EXPORT_SYMBOL_GPL(hisi_qm_uninit);
@@ -2072,12 +2229,21 @@ static int __hisi_qm_start(struct hisi_qm *qm)
int hisi_qm_start(struct hisi_qm *qm)
{
struct device *dev = &qm->pdev->dev;
+ int ret = 0;
+
+ down_write(&qm->qps_lock);
+
+ if (!qm_avail_state(qm, QM_START)) {
+ up_write(&qm->qps_lock);
+ return -EPERM;
+ }
dev_dbg(dev, "qm start with %d queue pairs\n", qm->qp_num);
if (!qm->qp_num) {
dev_err(dev, "qp_num should not be 0\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_unlock;
}
if (!qm->qp_bitmap) {
@@ -2086,12 +2252,15 @@ int hisi_qm_start(struct hisi_qm *qm)
qm->qp_array = devm_kcalloc(dev, qm->qp_num,
sizeof(struct hisi_qp *),
GFP_KERNEL);
- if (!qm->qp_bitmap || !qm->qp_array)
- return -ENOMEM;
+ if (!qm->qp_bitmap || !qm->qp_array) {
+ ret = -ENOMEM;
+ goto err_unlock;
+ }
}
if (!qm->use_dma_api) {
dev_dbg(&qm->pdev->dev, "qm delay start\n");
+ up_write(&qm->qps_lock);
return 0;
} else if (!qm->qdma.va) {
qm->qdma.size = QMC_ALIGN(sizeof(struct qm_eqe) * QM_Q_DEPTH) +
@@ -2102,11 +2271,19 @@ int hisi_qm_start(struct hisi_qm *qm)
&qm->qdma.dma, GFP_KERNEL);
dev_dbg(dev, "allocate qm dma buf(va=%pK, dma=%pad, size=%zx)\n",
qm->qdma.va, &qm->qdma.dma, qm->qdma.size);
- if (!qm->qdma.va)
- return -ENOMEM;
+ if (!qm->qdma.va) {
+ ret = -ENOMEM;
+ goto err_unlock;
+ }
}
- return __hisi_qm_start(qm);
+ ret = __hisi_qm_start(qm);
+ if (!ret)
+ atomic_set(&qm->status.flags, QM_START);
+
+err_unlock:
+ up_write(&qm->qps_lock);
+ return ret;
}
EXPORT_SYMBOL_GPL(hisi_qm_start);
@@ -2120,20 +2297,44 @@ static int qm_restart(struct hisi_qm *qm)
if (ret < 0)
return ret;
- write_lock(&qm->qps_lock);
+ down_write(&qm->qps_lock);
for (i = 0; i < qm->qp_num; i++) {
qp = qm->qp_array[i];
- if (qp) {
- ret = hisi_qm_start_qp(qp, 0);
+ if (qp && atomic_read(&qp->qp_status.flags) == QP_STOP &&
+ qp->is_resetting == true) {
+ ret = qm_start_qp_nolock(qp, 0);
if (ret < 0) {
dev_err(dev, "Failed to start qp%d!\n", i);
- write_unlock(&qm->qps_lock);
+ up_write(&qm->qps_lock);
+ return ret;
+ }
+ qp->is_resetting = false;
+ }
+ }
+ up_write(&qm->qps_lock);
+
+ return 0;
+}
+
+/* Stop started qps in reset flow */
+static int qm_stop_started_qp(struct hisi_qm *qm)
+{
+ struct device *dev = &qm->pdev->dev;
+ struct hisi_qp *qp;
+ int i, ret;
+
+ for (i = 0; i < qm->qp_num; i++) {
+ qp = qm->qp_array[i];
+ if (qp && atomic_read(&qp->qp_status.flags) == QP_START) {
+ qp->is_resetting = true;
+ ret = qm_stop_qp_nolock(qp);
+ if (ret < 0) {
+ dev_err(dev, "Failed to stop qp%d!\n", i);
return ret;
}
}
}
- write_unlock(&qm->qps_lock);
return 0;
}
@@ -2149,7 +2350,7 @@ static void qm_clear_queues(struct hisi_qm *qm)
for (i = 0; i < qm->qp_num; i++) {
qp = qm->qp_array[i];
- if (qp)
+ if (qp && qp->is_resetting)
memset(qp->qdma.va, 0, qp->qdma.size);
}
@@ -2166,41 +2367,43 @@ static void qm_clear_queues(struct hisi_qm *qm)
*/
int hisi_qm_stop(struct hisi_qm *qm)
{
- struct device *dev;
- struct hisi_qp *qp;
- int ret = 0, i;
+ struct device *dev = &qm->pdev->dev;
+ int ret = 0;
- if (!qm || !qm->pdev) {
- WARN_ON(1);
- return -EINVAL;
+ down_write(&qm->qps_lock);
+
+ if (!qm_avail_state(qm, QM_STOP)) {
+ ret = -EPERM;
+ goto err_unlock;
}
- dev = &qm->pdev->dev;
+ if (qm->status.stop_reason == QM_SOFT_RESET ||
+ qm->status.stop_reason == QM_FLR) {
+ ret = qm_stop_started_qp(qm);
+ if (ret < 0) {
+ dev_err(dev, "Failed to stop started qp!\n");
+ goto err_unlock;
+ }
+ }
/* Mask eq and aeq irq */
writel(0x1, qm->io_base + QM_VF_EQ_INT_MASK);
writel(0x1, qm->io_base + QM_VF_AEQ_INT_MASK);
- /* Stop all qps belong to this qm */
- for (i = 0; i < qm->qp_num; i++) {
- qp = qm->qp_array[i];
- if (qp) {
- ret = hisi_qm_stop_qp(qp);
- if (ret < 0) {
- dev_err(dev, "Failed to stop qp%d!\n", i);
- return -EBUSY;
- }
- }
- }
-
if (qm->fun_type == QM_HW_PF) {
ret = hisi_qm_set_vft(qm, 0, 0, 0);
- if (ret < 0)
+ if (ret < 0) {
dev_err(dev, "Failed to set vft!\n");
+ ret = -EBUSY;
+ goto err_unlock;
+ }
}
qm_clear_queues(qm);
+ atomic_set(&qm->status.flags, QM_STOP);
+err_unlock:
+ up_write(&qm->qps_lock);
return ret;
}
EXPORT_SYMBOL_GPL(hisi_qm_stop);
@@ -2772,6 +2975,7 @@ static int qm_set_msi(struct hisi_qm *qm, bool set)
static int qm_vf_reset_prepare(struct hisi_qm *qm)
{
struct hisi_qm_list *qm_list = qm->qm_list;
+ int stop_reason = qm->status.stop_reason;
struct pci_dev *pdev = qm->pdev;
struct pci_dev *virtfn;
struct hisi_qm *vf_qm;
@@ -2784,6 +2988,7 @@ static int qm_vf_reset_prepare(struct hisi_qm *qm)
continue;
if (pci_physfn(virtfn) == pdev) {
+ vf_qm->status.stop_reason = stop_reason;
ret = hisi_qm_stop(vf_qm);
if (ret)
goto stop_fail;
@@ -2830,6 +3035,7 @@ static int qm_controller_reset_prepare(struct hisi_qm *qm)
}
}
+ qm->status.stop_reason = QM_SOFT_RESET;
ret = hisi_qm_stop(qm);
if (ret) {
pci_err(pdev, "Fails to stop QM!\n");
diff --git a/drivers/crypto/hisilicon/qm.h b/drivers/crypto/hisilicon/qm.h
index d1be8cd..eff156a 100644
--- a/drivers/crypto/hisilicon/qm.h
+++ b/drivers/crypto/hisilicon/qm.h
@@ -84,8 +84,24 @@
/* page number for queue file region */
#define QM_DOORBELL_PAGE_NR 1
+enum qm_stop_reason {
+ QM_NORMAL,
+ QM_SOFT_RESET,
+ QM_FLR,
+};
+
+enum qm_state {
+ QM_INIT = 0,
+ QM_START,
+ QM_CLOSE,
+ QM_STOP,
+};
+
enum qp_state {
+ QP_INIT = 1,
+ QP_START,
QP_STOP,
+ QP_CLOSE,
};
enum qm_hw_ver {
@@ -129,7 +145,8 @@ struct hisi_qm_status {
bool eqc_phase;
u32 aeq_head;
bool aeqc_phase;
- unsigned long flags;
+ atomic_t flags;
+ int stop_reason;
};
struct hisi_qm;
@@ -196,7 +213,7 @@ struct hisi_qm {
struct hisi_qm_err_status err_status;
unsigned long reset_flag;
- rwlock_t qps_lock;
+ struct rw_semaphore qps_lock;
unsigned long *qp_bitmap;
struct hisi_qp **qp_array;
@@ -225,7 +242,7 @@ struct hisi_qp_status {
u16 sq_tail;
u16 cq_head;
bool cqc_phase;
- unsigned long flags;
+ atomic_t flags;
};
struct hisi_qp_ops {
@@ -250,6 +267,7 @@ struct hisi_qp {
void (*event_cb)(struct hisi_qp *qp);
struct hisi_qm *qm;
+ bool is_resetting;
u16 pasid;
struct uacce_queue *uacce_q;
};
--
2.7.4
put q_num_set similar code into qm to reduce the redundancy.
Signed-off-by: Shukun Tan <[email protected]>
Reviewed-by: Zhou Wang <[email protected]>
---
drivers/crypto/hisilicon/hpre/hpre_main.c | 39 ++++++-------------------------
drivers/crypto/hisilicon/qm.h | 39 +++++++++++++++++++++++++++++++
drivers/crypto/hisilicon/sec2/sec_main.c | 35 ++-------------------------
drivers/crypto/hisilicon/zip/zip_main.c | 33 +-------------------------
4 files changed, 49 insertions(+), 97 deletions(-)
diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
index f3859de..f1bb626 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_main.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
@@ -159,44 +159,19 @@ static struct debugfs_reg32 hpre_com_dfx_regs[] = {
{"INT_STATUS ", HPRE_INT_STATUS},
};
-static int hpre_pf_q_num_set(const char *val, const struct kernel_param *kp)
+static int pf_q_num_set(const char *val, const struct kernel_param *kp)
{
- struct pci_dev *pdev;
- u32 n, q_num;
- u8 rev_id;
- int ret;
-
- if (!val)
- return -EINVAL;
-
- pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI, HPRE_PCI_DEVICE_ID, NULL);
- if (!pdev) {
- q_num = HPRE_QUEUE_NUM_V2;
- pr_info("No device found currently, suppose queue number is %d\n",
- q_num);
- } else {
- rev_id = pdev->revision;
- if (rev_id != QM_HW_V2)
- return -EINVAL;
-
- q_num = HPRE_QUEUE_NUM_V2;
- }
-
- ret = kstrtou32(val, 10, &n);
- if (ret != 0 || n == 0 || n > q_num)
- return -EINVAL;
-
- return param_set_int(val, kp);
+ return q_num_set(val, kp, HPRE_PCI_DEVICE_ID);
}
static const struct kernel_param_ops hpre_pf_q_num_ops = {
- .set = hpre_pf_q_num_set,
+ .set = pf_q_num_set,
.get = param_get_int,
};
-static u32 hpre_pf_q_num = HPRE_PF_DEF_Q_NUM;
-module_param_cb(hpre_pf_q_num, &hpre_pf_q_num_ops, &hpre_pf_q_num, 0444);
-MODULE_PARM_DESC(hpre_pf_q_num, "Number of queues in PF of CS(1-1024)");
+static u32 pf_q_num = HPRE_PF_DEF_Q_NUM;
+module_param_cb(pf_q_num, &hpre_pf_q_num_ops, &pf_q_num, 0444);
+MODULE_PARM_DESC(pf_q_num, "Number of queues in PF of CS(1-1024)");
static const struct kernel_param_ops vfs_num_ops = {
.set = vfs_num_set,
@@ -688,7 +663,7 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
if (pdev->is_physfn) {
qm->qp_base = HPRE_PF_DEF_Q_BASE;
- qm->qp_num = hpre_pf_q_num;
+ qm->qp_num = pf_q_num;
}
qm->use_dma_api = true;
diff --git a/drivers/crypto/hisilicon/qm.h b/drivers/crypto/hisilicon/qm.h
index 9d17167..d1be8cd 100644
--- a/drivers/crypto/hisilicon/qm.h
+++ b/drivers/crypto/hisilicon/qm.h
@@ -8,6 +8,8 @@
#include <linux/module.h>
#include <linux/pci.h>
+#define QM_QNUM_V1 4096
+#define QM_QNUM_V2 1024
#define QM_MAX_VFS_NUM_V2 63
/* qm user domain */
@@ -252,6 +254,43 @@ struct hisi_qp {
struct uacce_queue *uacce_q;
};
+static inline int q_num_set(const char *val, const struct kernel_param *kp,
+ unsigned int device)
+{
+ struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI,
+ device, NULL);
+ u32 n, q_num;
+ u8 rev_id;
+ int ret;
+
+ if (!val)
+ return -EINVAL;
+
+ if (!pdev) {
+ q_num = min_t(u32, QM_QNUM_V1, QM_QNUM_V2);
+ pr_info("No device found currently, suppose queue number is %d\n",
+ q_num);
+ } else {
+ rev_id = pdev->revision;
+ switch (rev_id) {
+ case QM_HW_V1:
+ q_num = QM_QNUM_V1;
+ break;
+ case QM_HW_V2:
+ q_num = QM_QNUM_V2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ ret = kstrtou32(val, 10, &n);
+ if (ret || !n || n > q_num)
+ return -EINVAL;
+
+ return param_set_int(val, kp);
+}
+
static inline int vfs_num_set(const char *val, const struct kernel_param *kp)
{
u32 n;
diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c
index ea029e3..5aba775 100644
--- a/drivers/crypto/hisilicon/sec2/sec_main.c
+++ b/drivers/crypto/hisilicon/sec2/sec_main.c
@@ -136,45 +136,14 @@ static struct debugfs_reg32 sec_dfx_regs[] = {
static int sec_pf_q_num_set(const char *val, const struct kernel_param *kp)
{
- struct pci_dev *pdev;
- u32 n, q_num;
- u8 rev_id;
- int ret;
-
- if (!val)
- return -EINVAL;
-
- pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI,
- SEC_PF_PCI_DEVICE_ID, NULL);
- if (!pdev) {
- q_num = min_t(u32, SEC_QUEUE_NUM_V1, SEC_QUEUE_NUM_V2);
- pr_info("No device, suppose queue number is %d!\n", q_num);
- } else {
- rev_id = pdev->revision;
-
- switch (rev_id) {
- case QM_HW_V1:
- q_num = SEC_QUEUE_NUM_V1;
- break;
- case QM_HW_V2:
- q_num = SEC_QUEUE_NUM_V2;
- break;
- default:
- return -EINVAL;
- }
- }
-
- ret = kstrtou32(val, 10, &n);
- if (ret || !n || n > q_num)
- return -EINVAL;
-
- return param_set_int(val, kp);
+ return q_num_set(val, kp, SEC_PF_PCI_DEVICE_ID);
}
static const struct kernel_param_ops sec_pf_q_num_ops = {
.set = sec_pf_q_num_set,
.get = param_get_int,
};
+
static u32 pf_q_num = SEC_PF_DEF_Q_NUM;
module_param_cb(pf_q_num, &sec_pf_q_num_ops, &pf_q_num, 0444);
MODULE_PARM_DESC(pf_q_num, "Number of queues in PF(v1 0-4096, v2 0-1024)");
diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c
index 4672eaa..3c838e2 100644
--- a/drivers/crypto/hisilicon/zip/zip_main.c
+++ b/drivers/crypto/hisilicon/zip/zip_main.c
@@ -192,38 +192,7 @@ static struct debugfs_reg32 hzip_dfx_regs[] = {
static int pf_q_num_set(const char *val, const struct kernel_param *kp)
{
- struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI,
- PCI_DEVICE_ID_ZIP_PF, NULL);
- u32 n, q_num;
- u8 rev_id;
- int ret;
-
- if (!val)
- return -EINVAL;
-
- if (!pdev) {
- q_num = min_t(u32, HZIP_QUEUE_NUM_V1, HZIP_QUEUE_NUM_V2);
- pr_info("No device found currently, suppose queue number is %d\n",
- q_num);
- } else {
- rev_id = pdev->revision;
- switch (rev_id) {
- case QM_HW_V1:
- q_num = HZIP_QUEUE_NUM_V1;
- break;
- case QM_HW_V2:
- q_num = HZIP_QUEUE_NUM_V2;
- break;
- default:
- return -EINVAL;
- }
- }
-
- ret = kstrtou32(val, 10, &n);
- if (ret != 0 || n > q_num || n == 0)
- return -EINVAL;
-
- return param_set_int(val, kp);
+ return q_num_set(val, kp, PCI_DEVICE_ID_ZIP_PF);
}
static const struct kernel_param_ops pf_q_num_ops = {
--
2.7.4
By configuring the device error in firmware to report through abnormal
interruption, process all NFE errors in irq handler.
Signed-off-by: Shukun Tan <[email protected]>
Reviewed-by: Zhou Wang <[email protected]>
---
drivers/crypto/hisilicon/qm.c | 339 +++++++++++++++++++++++-------------------
drivers/crypto/hisilicon/qm.h | 1 +
2 files changed, 187 insertions(+), 153 deletions(-)
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index 80935d6..6365f93 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -219,6 +219,12 @@ enum vft_type {
CQC_VFT,
};
+enum acc_err_result {
+ ACC_ERR_NONE,
+ ACC_ERR_NEED_RESET,
+ ACC_ERR_RECOVERED,
+};
+
struct qm_cqe {
__le32 rsvd0;
__le16 cmd_id;
@@ -315,7 +321,7 @@ struct hisi_qm_hw_ops {
int (*debug_init)(struct hisi_qm *qm);
void (*hw_error_init)(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe);
void (*hw_error_uninit)(struct hisi_qm *qm);
- pci_ers_result_t (*hw_error_handle)(struct hisi_qm *qm);
+ enum acc_err_result (*hw_error_handle)(struct hisi_qm *qm);
};
static const char * const qm_debug_file_name[] = {
@@ -704,46 +710,6 @@ static irqreturn_t qm_aeq_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t qm_abnormal_irq(int irq, void *data)
-{
- return IRQ_HANDLED;
-}
-
-static int qm_irq_register(struct hisi_qm *qm)
-{
- struct pci_dev *pdev = qm->pdev;
- int ret;
-
- ret = request_irq(pci_irq_vector(pdev, QM_EQ_EVENT_IRQ_VECTOR),
- qm_irq, IRQF_SHARED, qm->dev_name, qm);
- if (ret)
- return ret;
-
- if (qm->ver == QM_HW_V2) {
- ret = request_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR),
- qm_aeq_irq, IRQF_SHARED, qm->dev_name, qm);
- if (ret)
- goto err_aeq_irq;
-
- if (qm->fun_type == QM_HW_PF) {
- ret = request_irq(pci_irq_vector(pdev,
- QM_ABNORMAL_EVENT_IRQ_VECTOR),
- qm_abnormal_irq, IRQF_SHARED,
- qm->dev_name, qm);
- if (ret)
- goto err_abonormal_irq;
- }
- }
-
- return 0;
-
-err_abonormal_irq:
- free_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), qm);
-err_aeq_irq:
- free_irq(pci_irq_vector(pdev, QM_EQ_EVENT_IRQ_VECTOR), qm);
- return ret;
-}
-
static void qm_irq_unregister(struct hisi_qm *qm)
{
struct pci_dev *pdev = qm->pdev;
@@ -1163,7 +1129,7 @@ static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status)
}
}
-static pci_ers_result_t qm_hw_error_handle_v2(struct hisi_qm *qm)
+static enum acc_err_result qm_hw_error_handle_v2(struct hisi_qm *qm)
{
u32 error_status, tmp;
@@ -1179,13 +1145,13 @@ static pci_ers_result_t qm_hw_error_handle_v2(struct hisi_qm *qm)
if (error_status == QM_DB_RANDOM_INVALID) {
writel(error_status, qm->io_base +
QM_ABNORMAL_INT_SOURCE);
- return PCI_ERS_RESULT_RECOVERED;
+ return ACC_ERR_RECOVERED;
}
- return PCI_ERS_RESULT_NEED_RESET;
+ return ACC_ERR_NEED_RESET;
}
- return PCI_ERS_RESULT_RECOVERED;
+ return ACC_ERR_RECOVERED;
}
static const struct hisi_qm_hw_ops qm_hw_ops_v1 = {
@@ -1943,100 +1909,6 @@ static void hisi_qm_pre_init(struct hisi_qm *qm)
}
/**
- * hisi_qm_init() - Initialize configures about qm.
- * @qm: The qm needing init.
- *
- * This function init qm, then we can call hisi_qm_start to put qm into work.
- */
-int hisi_qm_init(struct hisi_qm *qm)
-{
- struct pci_dev *pdev = qm->pdev;
- struct device *dev = &pdev->dev;
- unsigned int num_vec;
- int ret;
-
- hisi_qm_pre_init(qm);
-
- ret = qm_alloc_uacce(qm);
- if (ret < 0)
- dev_warn(&pdev->dev, "fail to alloc uacce (%d)\n", ret);
-
- ret = pci_enable_device_mem(pdev);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to enable device mem!\n");
- goto err_remove_uacce;
- }
-
- ret = pci_request_mem_regions(pdev, qm->dev_name);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to request mem regions!\n");
- goto err_disable_pcidev;
- }
-
- qm->phys_base = pci_resource_start(pdev, PCI_BAR_2);
- qm->phys_size = pci_resource_len(qm->pdev, PCI_BAR_2);
- qm->io_base = ioremap(qm->phys_base, qm->phys_size);
- if (!qm->io_base) {
- ret = -EIO;
- goto err_release_mem_regions;
- }
-
- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
- if (ret < 0)
- goto err_iounmap;
- pci_set_master(pdev);
-
- if (!qm->ops->get_irq_num) {
- ret = -EOPNOTSUPP;
- goto err_iounmap;
- }
- num_vec = qm->ops->get_irq_num(qm);
- ret = pci_alloc_irq_vectors(pdev, num_vec, num_vec, PCI_IRQ_MSI);
- if (ret < 0) {
- dev_err(dev, "Failed to enable MSI vectors!\n");
- goto err_iounmap;
- }
-
- ret = qm_irq_register(qm);
- if (ret)
- goto err_free_irq_vectors;
-
- if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V2) {
- /* v2 starts to support get vft by mailbox */
- ret = hisi_qm_get_vft(qm, &qm->qp_base, &qm->qp_num);
- if (ret)
- goto err_irq_unregister;
- }
-
- ret = hisi_qm_memory_init(qm);
- if (ret)
- goto err_irq_unregister;
-
- INIT_WORK(&qm->work, qm_work_process);
-
- atomic_set(&qm->status.flags, QM_INIT);
-
- return 0;
-
-err_irq_unregister:
- qm_irq_unregister(qm);
-err_free_irq_vectors:
- pci_free_irq_vectors(pdev);
-err_iounmap:
- iounmap(qm->io_base);
-err_release_mem_regions:
- pci_release_mem_regions(pdev);
-err_disable_pcidev:
- pci_disable_device(pdev);
-err_remove_uacce:
- uacce_remove(qm->uacce);
- qm->uacce = NULL;
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(hisi_qm_init);
-
-/**
* hisi_qm_uninit() - Uninitialize qm.
* @qm: The qm needed uninit.
*
@@ -2460,11 +2332,11 @@ static void qm_hw_error_uninit(struct hisi_qm *qm)
qm->ops->hw_error_uninit(qm);
}
-static pci_ers_result_t qm_hw_error_handle(struct hisi_qm *qm)
+static enum acc_err_result qm_hw_error_handle(struct hisi_qm *qm)
{
if (!qm->ops->hw_error_handle) {
dev_err(&qm->pdev->dev, "QM doesn't support hw error report!\n");
- return PCI_ERS_RESULT_NONE;
+ return ACC_ERR_NONE;
}
return qm->ops->hw_error_handle(qm);
@@ -2777,13 +2649,13 @@ int hisi_qm_sriov_configure(struct pci_dev *pdev, int num_vfs)
}
EXPORT_SYMBOL_GPL(hisi_qm_sriov_configure);
-static pci_ers_result_t qm_dev_err_handle(struct hisi_qm *qm)
+static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm)
{
u32 err_sts;
if (!qm->err_ini->get_dev_hw_err_status) {
dev_err(&qm->pdev->dev, "Device doesn't support get hw error status!\n");
- return PCI_ERS_RESULT_NONE;
+ return ACC_ERR_NONE;
}
/* get device hardware error status */
@@ -2794,20 +2666,19 @@ static pci_ers_result_t qm_dev_err_handle(struct hisi_qm *qm)
if (!qm->err_ini->log_dev_hw_err) {
dev_err(&qm->pdev->dev, "Device doesn't support log hw error!\n");
- return PCI_ERS_RESULT_NEED_RESET;
+ return ACC_ERR_NEED_RESET;
}
qm->err_ini->log_dev_hw_err(qm, err_sts);
- return PCI_ERS_RESULT_NEED_RESET;
+ return ACC_ERR_NEED_RESET;
}
- return PCI_ERS_RESULT_RECOVERED;
+ return ACC_ERR_RECOVERED;
}
-static pci_ers_result_t qm_process_dev_error(struct pci_dev *pdev)
+static enum acc_err_result qm_process_dev_error(struct hisi_qm *qm)
{
- struct hisi_qm *qm = pci_get_drvdata(pdev);
- pci_ers_result_t qm_ret, dev_ret;
+ enum acc_err_result qm_ret, dev_ret;
/* log qm error */
qm_ret = qm_hw_error_handle(qm);
@@ -2815,9 +2686,9 @@ static pci_ers_result_t qm_process_dev_error(struct pci_dev *pdev)
/* log device error */
dev_ret = qm_dev_err_handle(qm);
- return (qm_ret == PCI_ERS_RESULT_NEED_RESET ||
- dev_ret == PCI_ERS_RESULT_NEED_RESET) ?
- PCI_ERS_RESULT_NEED_RESET : PCI_ERS_RESULT_RECOVERED;
+ return (qm_ret == ACC_ERR_NEED_RESET ||
+ dev_ret == ACC_ERR_NEED_RESET) ?
+ ACC_ERR_NEED_RESET : ACC_ERR_RECOVERED;
}
/**
@@ -2831,6 +2702,9 @@ static pci_ers_result_t qm_process_dev_error(struct pci_dev *pdev)
pci_ers_result_t hisi_qm_dev_err_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
+ struct hisi_qm *qm = pci_get_drvdata(pdev);
+ enum acc_err_result ret;
+
if (pdev->is_virtfn)
return PCI_ERS_RESULT_NONE;
@@ -2838,7 +2712,11 @@ pci_ers_result_t hisi_qm_dev_err_detected(struct pci_dev *pdev,
if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT;
- return qm_process_dev_error(pdev);
+ ret = qm_process_dev_error(qm);
+ if (ret == ACC_ERR_NEED_RESET)
+ return PCI_ERS_RESULT_NEED_RESET;
+
+ return PCI_ERS_RESULT_RECOVERED;
}
EXPORT_SYMBOL_GPL(hisi_qm_dev_err_detected);
@@ -3428,6 +3306,161 @@ void hisi_qm_reset_done(struct pci_dev *pdev)
}
EXPORT_SYMBOL_GPL(hisi_qm_reset_done);
+static irqreturn_t qm_abnormal_irq(int irq, void *data)
+{
+ struct hisi_qm *qm = data;
+ enum acc_err_result ret;
+
+ ret = qm_process_dev_error(qm);
+ if (ret == ACC_ERR_NEED_RESET)
+ schedule_work(&qm->rst_work);
+
+ return IRQ_HANDLED;
+}
+
+static int qm_irq_register(struct hisi_qm *qm)
+{
+ struct pci_dev *pdev = qm->pdev;
+ int ret;
+
+ ret = request_irq(pci_irq_vector(pdev, QM_EQ_EVENT_IRQ_VECTOR),
+ qm_irq, IRQF_SHARED, qm->dev_name, qm);
+ if (ret)
+ return ret;
+
+ if (qm->ver == QM_HW_V2) {
+ ret = request_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR),
+ qm_aeq_irq, IRQF_SHARED, qm->dev_name, qm);
+ if (ret)
+ goto err_aeq_irq;
+
+ if (qm->fun_type == QM_HW_PF) {
+ ret = request_irq(pci_irq_vector(pdev,
+ QM_ABNORMAL_EVENT_IRQ_VECTOR),
+ qm_abnormal_irq, IRQF_SHARED,
+ qm->dev_name, qm);
+ if (ret)
+ goto err_abonormal_irq;
+ }
+ }
+
+ return 0;
+
+err_abonormal_irq:
+ free_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), qm);
+err_aeq_irq:
+ free_irq(pci_irq_vector(pdev, QM_EQ_EVENT_IRQ_VECTOR), qm);
+ return ret;
+}
+
+static void hisi_qm_controller_reset(struct work_struct *rst_work)
+{
+ struct hisi_qm *qm = container_of(rst_work, struct hisi_qm, rst_work);
+ int ret;
+
+ /* reset pcie device controller */
+ ret = qm_controller_reset(qm);
+ if (ret)
+ dev_err(&qm->pdev->dev, "controller reset failed (%d)\n", ret);
+
+}
+
+/**
+ * hisi_qm_init() - Initialize configures about qm.
+ * @qm: The qm needing init.
+ *
+ * This function init qm, then we can call hisi_qm_start to put qm into work.
+ */
+int hisi_qm_init(struct hisi_qm *qm)
+{
+ struct pci_dev *pdev = qm->pdev;
+ struct device *dev = &pdev->dev;
+ unsigned int num_vec;
+ int ret;
+
+ hisi_qm_pre_init(qm);
+
+ ret = qm_alloc_uacce(qm);
+ if (ret < 0)
+ dev_warn(&pdev->dev, "fail to alloc uacce (%d)\n", ret);
+
+ ret = pci_enable_device_mem(pdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to enable device mem!\n");
+ goto err_remove_uacce;
+ }
+
+ ret = pci_request_mem_regions(pdev, qm->dev_name);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to request mem regions!\n");
+ goto err_disable_pcidev;
+ }
+
+ qm->phys_base = pci_resource_start(pdev, PCI_BAR_2);
+ qm->phys_size = pci_resource_len(qm->pdev, PCI_BAR_2);
+ qm->io_base = ioremap(qm->phys_base, qm->phys_size);
+ if (!qm->io_base) {
+ ret = -EIO;
+ goto err_release_mem_regions;
+ }
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (ret < 0)
+ goto err_iounmap;
+ pci_set_master(pdev);
+
+ if (!qm->ops->get_irq_num) {
+ ret = -EOPNOTSUPP;
+ goto err_iounmap;
+ }
+ num_vec = qm->ops->get_irq_num(qm);
+ ret = pci_alloc_irq_vectors(pdev, num_vec, num_vec, PCI_IRQ_MSI);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable MSI vectors!\n");
+ goto err_iounmap;
+ }
+
+ ret = qm_irq_register(qm);
+ if (ret)
+ goto err_free_irq_vectors;
+
+ if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V2) {
+ /* v2 starts to support get vft by mailbox */
+ ret = hisi_qm_get_vft(qm, &qm->qp_base, &qm->qp_num);
+ if (ret)
+ goto err_irq_unregister;
+ }
+
+ ret = hisi_qm_memory_init(qm);
+ if (ret)
+ goto err_irq_unregister;
+
+ INIT_WORK(&qm->work, qm_work_process);
+ if (qm->fun_type == QM_HW_PF)
+ INIT_WORK(&qm->rst_work, hisi_qm_controller_reset);
+
+ atomic_set(&qm->status.flags, QM_INIT);
+
+ return 0;
+
+err_irq_unregister:
+ qm_irq_unregister(qm);
+err_free_irq_vectors:
+ pci_free_irq_vectors(pdev);
+err_iounmap:
+ iounmap(qm->io_base);
+err_release_mem_regions:
+ pci_release_mem_regions(pdev);
+err_disable_pcidev:
+ pci_disable_device(pdev);
+err_remove_uacce:
+ uacce_remove(qm->uacce);
+ qm->uacce = NULL;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_qm_init);
+
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Zhou Wang <[email protected]>");
MODULE_DESCRIPTION("HiSilicon Accelerator queue manager driver");
diff --git a/drivers/crypto/hisilicon/qm.h b/drivers/crypto/hisilicon/qm.h
index fc5e96a..a431ff2 100644
--- a/drivers/crypto/hisilicon/qm.h
+++ b/drivers/crypto/hisilicon/qm.h
@@ -226,6 +226,7 @@ struct hisi_qm {
struct workqueue_struct *wq;
struct work_struct work;
+ struct work_struct rst_work;
const char *algs;
bool use_sva;
--
2.7.4
On Sat, May 09, 2020 at 05:43:53PM +0800, Shukun Tan wrote:
> This patchset includes some misc updates.
> patch 1-3: modify the accelerator probe process.
> patch 4: refactor module parameter pf_q_num.
> patch 5-6: add state machine and FLR support.
> patch 7: remove use_dma_api related useless codes.
> patch 8-9: QM initialization process and memory management optimization.
> patch 10-11: add device error report through abnormal irq.
> patch 12: tiny change of zip driver.
>
> Longfang Liu (3):
> crypto: hisilicon/sec2 - modify the SEC probe process
> crypto: hisilicon/hpre - modify the HPRE probe process
> crypto: hisilicon/zip - modify the ZIP probe process
>
> Shukun Tan (5):
> crypto: hisilicon - refactor module parameter pf_q_num related code
> crypto: hisilicon - add FLR support
> crypto: hisilicon - remove use_dma_api related codes
> crypto: hisilicon - remove codes of directly report device errors
> through MSI
> crypto: hisilicon - add device error report through abnormal irq
>
> Weili Qian (2):
> crypto: hisilicon - unify initial value assignment into QM
> crypto: hisilicon - QM memory management optimization
>
> Zhou Wang (2):
> crypto: hisilicon/qm - add state machine for QM
> crypto: hisilicon/zip - Use temporary sqe when doing work
>
> drivers/crypto/hisilicon/hpre/hpre_main.c | 107 ++-
> drivers/crypto/hisilicon/qm.c | 1101 +++++++++++++++++++----------
> drivers/crypto/hisilicon/qm.h | 75 +-
> drivers/crypto/hisilicon/sec2/sec_main.c | 134 ++--
> drivers/crypto/hisilicon/zip/zip_crypto.c | 11 +-
> drivers/crypto/hisilicon/zip/zip_main.c | 128 ++--
> 6 files changed, 950 insertions(+), 606 deletions(-)
All applied. Thanks.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt