Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: hisilicon/qm - obtain stop queue status

The debugfs files 'dev_state' and 'dev_timeout' are added.
Users can query the current queue stop status through these two
files. And set the waiting timeout when the queue is released.

dev_state: if dev_timeout is set, dev_state indicates the status
of stopping the queue. 0 indicates that the queue is stopped
successfully. Other values indicate that the queue stops fail.
If dev_timeout is not set, the value of dev_state is 0;

dev_timeout: if the queue fails to stop, the queue is released
after waiting dev_timeout * 20ms.

Signed-off-by: Weili Qian <qianweili@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Weili Qian and committed by
Herbert Xu
ce133a22 12b8ae68

+138 -26
+15
Documentation/ABI/testing/debugfs-hisi-hpre
··· 118 118 0: busy, 1: idle. 119 119 Only available for PF, and take no other effect on HPRE. 120 120 121 + What: /sys/kernel/debug/hisi_hpre/<bdf>/qm/dev_timeout 122 + Date: Feb 2024 123 + Contact: linux-crypto@vger.kernel.org 124 + Description: Set the wait time when stop queue fails. Available for both PF 125 + and VF, and take no other effect on HPRE. 126 + 0: not wait(default), others value: wait dev_timeout * 20 microsecond. 127 + 128 + What: /sys/kernel/debug/hisi_hpre/<bdf>/qm/dev_state 129 + Date: Feb 2024 130 + Contact: linux-crypto@vger.kernel.org 131 + Description: Dump the stop queue status of the QM. The default value is 0, 132 + if dev_timeout is set, when stop queue fails, the dev_state 133 + will return non-zero value. Available for both PF and VF, 134 + and take no other effect on HPRE. 135 + 121 136 What: /sys/kernel/debug/hisi_hpre/<bdf>/hpre_dfx/diff_regs 122 137 Date: Mar 2022 123 138 Contact: linux-crypto@vger.kernel.org
+15
Documentation/ABI/testing/debugfs-hisi-sec
··· 98 98 0: busy, 1: idle. 99 99 Only available for PF, and take no other effect on SEC. 100 100 101 + What: /sys/kernel/debug/hisi_sec2/<bdf>/qm/dev_timeout 102 + Date: Feb 2024 103 + Contact: linux-crypto@vger.kernel.org 104 + Description: Set the wait time when stop queue fails. Available for both PF 105 + and VF, and take no other effect on SEC. 106 + 0: not wait(default), others value: wait dev_timeout * 20 microsecond. 107 + 108 + What: /sys/kernel/debug/hisi_sec2/<bdf>/qm/dev_state 109 + Date: Feb 2024 110 + Contact: linux-crypto@vger.kernel.org 111 + Description: Dump the stop queue status of the QM. The default value is 0, 112 + if dev_timeout is set, when stop queue fails, the dev_state 113 + will return non-zero value. Available for both PF and VF, 114 + and take no other effect on SEC. 115 + 101 116 What: /sys/kernel/debug/hisi_sec2/<bdf>/sec_dfx/diff_regs 102 117 Date: Mar 2022 103 118 Contact: linux-crypto@vger.kernel.org
+15
Documentation/ABI/testing/debugfs-hisi-zip
··· 111 111 0: busy, 1: idle. 112 112 Only available for PF, and take no other effect on ZIP. 113 113 114 + What: /sys/kernel/debug/hisi_zip/<bdf>/qm/dev_timeout 115 + Date: Feb 2024 116 + Contact: linux-crypto@vger.kernel.org 117 + Description: Set the wait time when stop queue fails. Available for both PF 118 + and VF, and take no other effect on ZIP. 119 + 0: not wait(default), others value: wait dev_timeout * 20 microsecond. 120 + 121 + What: /sys/kernel/debug/hisi_zip/<bdf>/qm/dev_state 122 + Date: Feb 2024 123 + Contact: linux-crypto@vger.kernel.org 124 + Description: Dump the stop queue status of the QM. The default value is 0, 125 + if dev_timeout is set, when stop queue fails, the dev_state 126 + will return non-zero value. Available for both PF and VF, 127 + and take no other effect on ZIP. 128 + 114 129 What: /sys/kernel/debug/hisi_zip/<bdf>/zip_dfx/diff_regs 115 130 Date: Mar 2022 116 131 Contact: linux-crypto@vger.kernel.org
+5
drivers/crypto/hisilicon/debugfs.c
··· 1112 1112 void hisi_qm_debug_init(struct hisi_qm *qm) 1113 1113 { 1114 1114 struct dfx_diff_registers *qm_regs = qm->debug.qm_diff_regs; 1115 + struct qm_dev_dfx *dev_dfx = &qm->debug.dev_dfx; 1115 1116 struct qm_dfx *dfx = &qm->debug.dfx; 1116 1117 struct dentry *qm_d; 1117 1118 void *data; ··· 1141 1140 1142 1141 debugfs_create_file("status", 0444, qm->debug.qm_d, qm, 1143 1142 &qm_status_fops); 1143 + 1144 + debugfs_create_u32("dev_state", 0444, qm->debug.qm_d, &dev_dfx->dev_state); 1145 + debugfs_create_u32("dev_timeout", 0644, qm->debug.qm_d, &dev_dfx->dev_timeout); 1146 + 1144 1147 for (i = 0; i < ARRAY_SIZE(qm_dfx_files); i++) { 1145 1148 data = (atomic64_t *)((uintptr_t)dfx + qm_dfx_files[i].offset); 1146 1149 debugfs_create_file(qm_dfx_files[i].name,
+82 -26
drivers/crypto/hisilicon/qm.c
··· 236 236 237 237 #define QM_DEV_ALG_MAX_LEN 256 238 238 239 + /* abnormal status value for stopping queue */ 240 + #define QM_STOP_QUEUE_FAIL 1 241 + #define QM_DUMP_SQC_FAIL 3 242 + #define QM_DUMP_CQC_FAIL 4 243 + #define QM_FINISH_WAIT 5 244 + 239 245 #define QM_MK_CQC_DW3_V1(hop_num, pg_sz, buf_sz, cqe_sz) \ 240 246 (((hop_num) << QM_CQ_HOP_NUM_SHIFT) | \ 241 247 ((pg_sz) << QM_CQ_PAGE_SIZE_SHIFT) | \ ··· 2043 2037 } 2044 2038 } 2045 2039 2046 - /** 2047 - * qm_drain_qp() - Drain a qp. 2048 - * @qp: The qp we want to drain. 2049 - * 2050 - * Determine whether the queue is cleared by judging the tail pointers of 2051 - * sq and cq. 2052 - */ 2053 - static int qm_drain_qp(struct hisi_qp *qp) 2040 + static int qm_wait_qp_empty(struct hisi_qm *qm, u32 *state, u32 qp_id) 2054 2041 { 2055 - struct hisi_qm *qm = qp->qm; 2056 2042 struct device *dev = &qm->pdev->dev; 2057 2043 struct qm_sqc sqc; 2058 2044 struct qm_cqc cqc; 2059 2045 int ret, i = 0; 2060 2046 2061 - /* No need to judge if master OOO is blocked. */ 2062 - if (qm_check_dev_error(qm)) 2063 - return 0; 2064 - 2065 - /* Kunpeng930 supports drain qp by device */ 2066 - if (test_bit(QM_SUPPORT_STOP_QP, &qm->caps)) { 2067 - ret = qm_stop_qp(qp); 2068 - if (ret) 2069 - dev_err(dev, "Failed to stop qp(%u)!\n", qp->qp_id); 2070 - return ret; 2071 - } 2072 - 2073 2047 while (++i) { 2074 - ret = qm_set_and_get_xqc(qm, QM_MB_CMD_SQC, &sqc, qp->qp_id, 1); 2048 + ret = qm_set_and_get_xqc(qm, QM_MB_CMD_SQC, &sqc, qp_id, 1); 2075 2049 if (ret) { 2076 2050 dev_err_ratelimited(dev, "Failed to dump sqc!\n"); 2051 + *state = QM_DUMP_SQC_FAIL; 2077 2052 return ret; 2078 2053 } 2079 2054 2080 - ret = qm_set_and_get_xqc(qm, QM_MB_CMD_CQC, &cqc, qp->qp_id, 1); 2055 + ret = qm_set_and_get_xqc(qm, QM_MB_CMD_CQC, &cqc, qp_id, 1); 2081 2056 if (ret) { 2082 2057 dev_err_ratelimited(dev, "Failed to dump cqc!\n"); 2058 + *state = QM_DUMP_CQC_FAIL; 2083 2059 return ret; 2084 2060 } 2085 2061 ··· 2070 2082 break; 2071 2083 2072 2084 if (i == MAX_WAIT_COUNTS) { 2073 - dev_err(dev, "Fail to empty queue %u!\n", qp->qp_id); 2074 - return -EBUSY; 2085 + dev_err(dev, "Fail to empty queue %u!\n", qp_id); 2086 + *state = QM_STOP_QUEUE_FAIL; 2087 + return -ETIMEDOUT; 2075 2088 } 2076 2089 2077 2090 usleep_range(WAIT_PERIOD_US_MIN, WAIT_PERIOD_US_MAX); 2078 2091 } 2079 2092 2080 2093 return 0; 2094 + } 2095 + 2096 + /** 2097 + * qm_drain_qp() - Drain a qp. 2098 + * @qp: The qp we want to drain. 2099 + * 2100 + * If the device does not support stopping queue by sending mailbox, 2101 + * determine whether the queue is cleared by judging the tail pointers of 2102 + * sq and cq. 2103 + */ 2104 + static int qm_drain_qp(struct hisi_qp *qp) 2105 + { 2106 + struct hisi_qm *qm = qp->qm; 2107 + struct hisi_qm *pf_qm = pci_get_drvdata(pci_physfn(qm->pdev)); 2108 + u32 state = 0; 2109 + int ret; 2110 + 2111 + /* No need to judge if master OOO is blocked. */ 2112 + if (qm_check_dev_error(pf_qm)) 2113 + return 0; 2114 + 2115 + /* HW V3 supports drain qp by device */ 2116 + if (test_bit(QM_SUPPORT_STOP_QP, &qm->caps)) { 2117 + ret = qm_stop_qp(qp); 2118 + if (ret) { 2119 + dev_err(&qm->pdev->dev, "Failed to stop qp!\n"); 2120 + state = QM_STOP_QUEUE_FAIL; 2121 + goto set_dev_state; 2122 + } 2123 + return ret; 2124 + } 2125 + 2126 + ret = qm_wait_qp_empty(qm, &state, qp->qp_id); 2127 + if (ret) 2128 + goto set_dev_state; 2129 + 2130 + return 0; 2131 + 2132 + set_dev_state: 2133 + if (qm->debug.dev_dfx.dev_timeout) 2134 + qm->debug.dev_dfx.dev_state = state; 2135 + 2136 + return ret; 2081 2137 } 2082 2138 2083 2139 static int qm_stop_qp_nolock(struct hisi_qp *qp) ··· 2351 2319 2352 2320 static void hisi_qm_uacce_stop_queue(struct uacce_queue *q) 2353 2321 { 2354 - hisi_qm_stop_qp(q->priv); 2322 + struct hisi_qp *qp = q->priv; 2323 + struct hisi_qm *qm = qp->qm; 2324 + struct qm_dev_dfx *dev_dfx = &qm->debug.dev_dfx; 2325 + u32 i = 0; 2326 + 2327 + hisi_qm_stop_qp(qp); 2328 + 2329 + if (!dev_dfx->dev_timeout || !dev_dfx->dev_state) 2330 + return; 2331 + 2332 + /* 2333 + * After the queue fails to be stopped, 2334 + * wait for a period of time before releasing the queue. 2335 + */ 2336 + while (++i) { 2337 + msleep(WAIT_PERIOD); 2338 + 2339 + /* Since dev_timeout maybe modified, check i >= dev_timeout */ 2340 + if (i >= dev_dfx->dev_timeout) { 2341 + dev_err(&qm->pdev->dev, "Stop q %u timeout, state %u\n", 2342 + qp->qp_id, dev_dfx->dev_state); 2343 + dev_dfx->dev_state = QM_FINISH_WAIT; 2344 + break; 2345 + } 2346 + } 2355 2347 } 2356 2348 2357 2349 static int hisi_qm_is_q_updated(struct uacce_queue *q)
+6
include/linux/hisi_acc_qm.h
··· 163 163 const char *alg; 164 164 }; 165 165 166 + struct qm_dev_dfx { 167 + u32 dev_state; 168 + u32 dev_timeout; 169 + }; 170 + 166 171 struct dfx_diff_registers { 167 172 u32 *regs; 168 173 u32 reg_offset; ··· 196 191 struct dentry *debug_root; 197 192 struct dentry *qm_d; 198 193 struct debugfs_file files[DEBUG_FILE_NUM]; 194 + struct qm_dev_dfx dev_dfx; 199 195 unsigned int *qm_last_words; 200 196 /* ACC engines recoreding last regs */ 201 197 unsigned int *last_words;