crypto: hisilicon/sec2 - save capability registers in probe process
authorZhiqi Song <songzhiqi1@huawei.com>
Sat, 2 Dec 2023 09:17:21 +0000 (17:17 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 8 Dec 2023 03:59:45 +0000 (11:59 +0800)
Pre-store the valid value of the sec alg support related capability
register in sec_qm_init(), which will be called by probe process.
It can reduce the number of capability register queries and avoid
obtaining incorrect values in abnormal scenarios, such as reset
failed and the memory space disabled.

Fixes: 921715b6b782 ("crypto: hisilicon/sec - get algorithm bitmap from registers")
Signed-off-by: Zhiqi Song <songzhiqi1@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/hisilicon/sec2/sec.h
drivers/crypto/hisilicon/sec2/sec_crypto.c
drivers/crypto/hisilicon/sec2/sec_main.c

index 3e57fc04b377038146bc23fd9612623e37d5a5c3..410c83712e2851d861ce424b5d1b9630abce3944 100644 (file)
@@ -220,6 +220,13 @@ enum sec_cap_type {
        SEC_CORE4_ALG_BITMAP_HIGH,
 };
 
+enum sec_cap_reg_record_idx {
+       SEC_DRV_ALG_BITMAP_LOW_IDX = 0x0,
+       SEC_DRV_ALG_BITMAP_HIGH_IDX,
+       SEC_DEV_ALG_BITMAP_LOW_IDX,
+       SEC_DEV_ALG_BITMAP_HIGH_IDX,
+};
+
 void sec_destroy_qps(struct hisi_qp **qps, int qp_num);
 struct hisi_qp **sec_create_qps(void);
 int sec_register_to_crypto(struct hisi_qm *qm);
index 6fcabbc87860a6419b426d31b8a48e8f94e2d75a..ba7f305d43c107751118405878d984f7eb6fb7a6 100644 (file)
@@ -2547,9 +2547,12 @@ err:
 
 int sec_register_to_crypto(struct hisi_qm *qm)
 {
-       u64 alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH, SEC_DRV_ALG_BITMAP_LOW);
+       u64 alg_mask;
        int ret = 0;
 
+       alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH_IDX,
+                                     SEC_DRV_ALG_BITMAP_LOW_IDX);
+
        mutex_lock(&sec_algs_lock);
        if (sec_available_devs) {
                sec_available_devs++;
@@ -2578,7 +2581,10 @@ unlock:
 
 void sec_unregister_from_crypto(struct hisi_qm *qm)
 {
-       u64 alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH, SEC_DRV_ALG_BITMAP_LOW);
+       u64 alg_mask;
+
+       alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH_IDX,
+                                     SEC_DRV_ALG_BITMAP_LOW_IDX);
 
        mutex_lock(&sec_algs_lock);
        if (--sec_available_devs)
index 2eceab7600ca706d4a8cf9f5f876529f44b543d0..878d94ab5d6d8cd6ee2af59ce2a34eb54745a9a5 100644 (file)
@@ -167,6 +167,13 @@ static const struct hisi_qm_cap_info sec_basic_info[] = {
        {SEC_CORE4_ALG_BITMAP_HIGH, 0x3170, 0, GENMASK(31, 0), 0x3FFF, 0x3FFF, 0x3FFF},
 };
 
+static const u32 sec_pre_store_caps[] = {
+       SEC_DRV_ALG_BITMAP_LOW,
+       SEC_DRV_ALG_BITMAP_HIGH,
+       SEC_DEV_ALG_BITMAP_LOW,
+       SEC_DEV_ALG_BITMAP_HIGH,
+};
+
 static const struct qm_dev_alg sec_dev_algs[] = { {
                .alg_msk = SEC_CIPHER_BITMAP,
                .alg = "cipher\n",
@@ -388,8 +395,8 @@ u64 sec_get_alg_bitmap(struct hisi_qm *qm, u32 high, u32 low)
 {
        u32 cap_val_h, cap_val_l;
 
-       cap_val_h = hisi_qm_get_hw_info(qm, sec_basic_info, high, qm->cap_ver);
-       cap_val_l = hisi_qm_get_hw_info(qm, sec_basic_info, low, qm->cap_ver);
+       cap_val_h = qm->cap_tables.dev_cap_table[high].cap_val;
+       cap_val_l = qm->cap_tables.dev_cap_table[low].cap_val;
 
        return ((u64)cap_val_h << SEC_ALG_BITMAP_SHIFT) | (u64)cap_val_l;
 }
@@ -1071,6 +1078,28 @@ static int sec_pf_probe_init(struct sec_dev *sec)
        return ret;
 }
 
+static int sec_pre_store_cap_reg(struct hisi_qm *qm)
+{
+       struct hisi_qm_cap_record *sec_cap;
+       struct pci_dev *pdev = qm->pdev;
+       size_t i, size;
+
+       size = ARRAY_SIZE(sec_pre_store_caps);
+       sec_cap = devm_kzalloc(&pdev->dev, sizeof(*sec_cap) * size, GFP_KERNEL);
+       if (!sec_cap)
+               return -ENOMEM;
+
+       for (i = 0; i < size; i++) {
+               sec_cap[i].type = sec_pre_store_caps[i];
+               sec_cap[i].cap_val = hisi_qm_get_hw_info(qm, sec_basic_info,
+                                    sec_pre_store_caps[i], qm->cap_ver);
+       }
+
+       qm->cap_tables.dev_cap_table = sec_cap;
+
+       return 0;
+}
+
 static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
 {
        u64 alg_msk;
@@ -1108,7 +1137,15 @@ static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
                return ret;
        }
 
-       alg_msk = sec_get_alg_bitmap(qm, SEC_DEV_ALG_BITMAP_HIGH, SEC_DEV_ALG_BITMAP_LOW);
+       /* Fetch and save the value of capability registers */
+       ret = sec_pre_store_cap_reg(qm);
+       if (ret) {
+               pci_err(qm->pdev, "Failed to pre-store capability registers!\n");
+               hisi_qm_uninit(qm);
+               return ret;
+       }
+
+       alg_msk = sec_get_alg_bitmap(qm, SEC_DEV_ALG_BITMAP_HIGH_IDX, SEC_DEV_ALG_BITMAP_LOW_IDX);
        ret = hisi_qm_set_algs(qm, alg_msk, sec_dev_algs, ARRAY_SIZE(sec_dev_algs));
        if (ret) {
                pci_err(qm->pdev, "Failed to set sec algs!\n");