From 8949ebb146ba2c4a4dd4c96381141035a4f372d2 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 01:55:49 +0000 Subject: [PATCH 01/11] update kae_driver/hisilicon/hpre/hpre_main.c. Signed-off-by: HUI --- kae_driver/hisilicon/hpre/hpre_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kae_driver/hisilicon/hpre/hpre_main.c b/kae_driver/hisilicon/hpre/hpre_main.c index 732b4c3..47ebf81 100755 --- a/kae_driver/hisilicon/hpre/hpre_main.c +++ b/kae_driver/hisilicon/hpre/hpre_main.c @@ -109,6 +109,7 @@ #define HPRE_VIA_MSI_DSM 1 #define HPRE_SQE_MASK_OFFSET 8 #define HPRE_SQE_MASK_LEN 24 +#define HPRE_CTX_Q_NUM_DEF 1 #define HPRE_DFX_BASE 0x301000 #define HPRE_DFX_COMMON1 0x301400 -- Gitee From 013553f14b30e691aed03c1e5e83a99e2443f173 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 02:11:34 +0000 Subject: [PATCH 02/11] update kae_driver/hisilicon/hpre/hpre_main.c. Signed-off-by: HUI --- kae_driver/hisilicon/hpre/hpre_main.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/kae_driver/hisilicon/hpre/hpre_main.c b/kae_driver/hisilicon/hpre/hpre_main.c index 47ebf81..a3350ac 100755 --- a/kae_driver/hisilicon/hpre/hpre_main.c +++ b/kae_driver/hisilicon/hpre/hpre_main.c @@ -1395,18 +1395,17 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) dev_warn(&pdev->dev, "init debugfs fail!\n"); - ret = hisi_qm_alg_register(qm, &hpre_devices); - if (ret < 0) { - pci_err(pdev, "fail to register algs to crypto!\n"); + ret = qm_register_uacce(qm); + if (ret) { + pci_err(pdev, "Failed to register uacce (%d)!\n", ret); goto err_with_qm_start; } - if (qm->uacce) { - ret = uacce_register(qm->uacce); - if (ret) { - pci_err(pdev, "failed to register uacce (%d)!\n", ret); - goto err_with_alg_register; - } + hisi_qm_add_list(qm, &hpre_devices); + ret = hisi_qm_alg_register(qm, &hpre_devices, HPRE_CTX_Q_NUM_DEF); + if (ret < 0) { + pci_err(pdev, "fail to register algs to crypto!\n"); + goto err_qm_del_list; } if (qm->fun_type == QM_HW_PF && vfs_num) { @@ -1420,7 +1419,10 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; err_with_alg_register: - hisi_qm_alg_unregister(qm, &hpre_devices); + hisi_qm_alg_unregister(qm, &hpre_devices, HPRE_CTX_Q_NUM_DEF); + +err_qm_del_list: + hisi_qm_del_list(qm, &hpre_devices); err_with_qm_start: hpre_debugfs_exit(qm); @@ -1442,7 +1444,8 @@ static void hpre_remove(struct pci_dev *pdev) hisi_qm_pm_uninit(qm); hisi_qm_wait_task_finish(qm, &hpre_devices); - hisi_qm_alg_unregister(qm, &hpre_devices); + hisi_qm_alg_unregister(qm, &hpre_devices, HPRE_CTX_Q_NUM_DEF); + hisi_qm_del_list(qm, &hpre_devices); if (qm->fun_type == QM_HW_PF && qm->vfs_num) hisi_qm_sriov_disable(pdev, true); -- Gitee From afc28ab26f6e2b2b11aabb407c7ef3d61ae390ed Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 08:09:15 +0000 Subject: [PATCH 03/11] update kae_driver/hisilicon/qm.c. Signed-off-by: HUI --- kae_driver/hisilicon/qm.c | 331 +++++++++++++++++++++++++++----------- 1 file changed, 241 insertions(+), 90 deletions(-) diff --git a/kae_driver/hisilicon/qm.c b/kae_driver/hisilicon/qm.c index bac7bc9..5cd9099 100755 --- a/kae_driver/hisilicon/qm.c +++ b/kae_driver/hisilicon/qm.c @@ -3252,7 +3252,24 @@ static void hisi_qm_cache_wb(struct hisi_qm *qm) static void qm_qp_event_notifier(struct hisi_qp *qp) { - wake_up_interruptible(&qp->uacce_q->wait); + uacce_wake_up(qp->uacce_q); +} + +/** + * hisi_qm_get_free_qp_num() - Get free number of qp in qm. + * @qm: The qm which want to get free qp. + * + * This function return free number of qp in qm. + */ +static int hisi_qm_get_free_qp_num(struct hisi_qm *qm) +{ + int ret; + + down_read(&qm->qps_lock); + ret = qm->qp_num - qm->qp_in_used; + up_read(&qm->qps_lock); + + return ret; } /* This function returns free number of qp in qm. */ @@ -3416,7 +3433,7 @@ static long hisi_qm_uacce_ioctl(struct uacce_queue *q, unsigned int cmd, qm_set_sqctype(q, qp_ctx.qc_type); qp_ctx.id = qp->qp_id; - if (copy_to_user((void __user *)arg, &qp_ctx, + if (copy_to_user((void __user *)(uintptr_t)arg, &qp_ctx, sizeof(struct hisi_qp_ctx))) return -EFAULT; @@ -3439,7 +3456,104 @@ static long hisi_qm_uacce_ioctl(struct uacce_queue *q, unsigned int cmd, return -EINVAL; } ++ +static enum uacce_dev_state hisi_qm_get_state(struct uacce_device *uacce) +{ + struct hisi_qm *qm = uacce->priv; + enum qm_state curr; + + curr = atomic_read(&qm->status.flags); + if (curr == QM_STOP) + return UACCE_DEV_ERR; + + return UACCE_DEV_NORMAL; +} + +static int qm_uacce_isolate_init(struct hisi_qm *qm) +{ + struct pci_dev *pdev = qm->pdev; + struct uacce_device *pf_uacce, *uacce; + struct device *pf_dev = &(pci_physfn(pdev)->dev); + + uacce = qm->uacce; + if (uacce->is_vf) { + /* VF uses PF's isoalte data */ + pf_uacce = dev_to_uacce(pf_dev); + if (!pf_uacce) { + pci_err(pdev, "fail to PF device!\n"); + return -ENODEV; + } + + uacce->isolate = &pf_uacce->isolate_data; + } else { + uacce->isolate = &uacce->isolate_data; + } + + return 0; + } + +static void qm_uacce_api_ver_init(struct hisi_qm *qm) +{ + struct uacce_device *uacce = qm->uacce; + + if (uacce->flags & UACCE_DEV_IOMMU) { + qm->use_sva = uacce->flags & UACCE_DEV_SVA ? true : false; + + if (qm->ver == QM_HW_V1) + uacce->api_ver = HISI_QM_API_VER_BASE; + else if (qm->ver == QM_HW_V2) + uacce->api_ver = HISI_QM_API_VER2_BASE; + else + uacce->api_ver = HISI_QM_API_VER3_BASE; + } else { + qm->use_sva = false; + + if (qm->ver == QM_HW_V1) + uacce->api_ver = HISI_QM_API_VER_BASE + UACCE_API_VER_NOIOMMU_SUBFIX; + else if (qm->ver == QM_HW_V2) + uacce->api_ver = HISI_QM_API_VER2_BASE + UACCE_API_VER_NOIOMMU_SUBFIX; + else + uacce->api_ver = HISI_QM_API_VER3_BASE + UACCE_API_VER_NOIOMMU_SUBFIX; + } +} + +static void qm_uacce_base_init(struct hisi_qm *qm) +{ + unsigned long dus_page_nr, mmio_page_nr; + struct uacce_device *uacce = qm->uacce; + struct pci_dev *pdev = qm->pdev; + + qm_uacce_api_ver_init(qm); + + if (qm->ver == QM_HW_V1) + mmio_page_nr = QM_DOORBELL_PAGE_NR; + else if (qm->ver == QM_HW_V2 || !qm->use_db_isolation) + mmio_page_nr = QM_DOORBELL_PAGE_NR + + QM_DOORBELL_SQ_CQ_BASE_V2 / PAGE_SIZE; + else + mmio_page_nr = QM_QP_DB_INTERVAL / PAGE_SIZE; + + uacce->is_vf = pdev->is_virtfn; + uacce->priv = qm; + uacce->algs = qm->algs; + uacce->parent = &pdev->dev; + + /* Add one more page for device or qp status */ + dus_page_nr = (PAGE_SIZE - 1 + qm->sqe_size * QM_Q_DEPTH + + sizeof(struct cqe) * QM_Q_DEPTH + PAGE_SIZE) >> + PAGE_SHIFT; + + uacce->qf_pg_num[UACCE_QFRT_MMIO] = mmio_page_nr; + uacce->qf_pg_num[UACCE_QFRT_DUS] = dus_page_nr; +} +/* + * the device is set the UACCE_DEV_SVA, but it will be cut if SVA patch is not + * available + */ static const struct uacce_ops uacce_qm_ops = { .get_available_instances = hisi_qm_get_available_instances, .get_queue = hisi_qm_uacce_get_queue, @@ -3448,73 +3562,81 @@ static const struct uacce_ops uacce_qm_ops = { .stop_queue = hisi_qm_uacce_stop_queue, .mmap = hisi_qm_uacce_mmap, .ioctl = hisi_qm_uacce_ioctl, + .get_dev_state = hisi_qm_get_state, .is_q_updated = hisi_qm_is_q_updated, }; +static void qm_remove_uacce(struct hisi_qm *qm) +{ + struct uacce_device *uacce = qm->uacce; + + if (qm->use_uacce) { + qm->uacce = NULL; + uacce_remove(uacce); + } +} + static int qm_alloc_uacce(struct hisi_qm *qm) { + struct uacce_interface interface; struct pci_dev *pdev = qm->pdev; struct uacce_device *uacce; - unsigned long mmio_page_nr; - unsigned long dus_page_nr; - u16 sq_depth, cq_depth; - struct uacce_interface interface = { - .flags = UACCE_DEV_SVA, - .ops = &uacce_qm_ops, - }; - int ret; + int name_len, ret; - ret = strscpy(interface.name, dev_driver_string(&pdev->dev), - sizeof(interface.name)); - if (ret < 0) - return -ENAMETOOLONG; - - uacce = uacce_alloc(&pdev->dev, &interface); - if (IS_ERR(uacce)) - return PTR_ERR(uacce); + if (!qm->use_uacce) + return 0; - if (uacce->flags & UACCE_DEV_SVA) { - qm->use_sva = true; - } else { - /* only consider sva case */ - uacce_remove(uacce); - qm->uacce = NULL; + name_len = strlen(pdev->driver->name); + if (name_len >= UACCE_MAX_NAME_SIZE) { + pci_err(pdev, "The driver name(%d) is longer than %d!\n", + name_len, UACCE_MAX_NAME_SIZE); return -EINVAL; } - uacce->is_vf = pdev->is_virtfn; - uacce->priv = qm; + strncpy(interface.name, pdev->driver->name, name_len); + interface.name[name_len] = '\0'; - if (qm->ver == QM_HW_V1) - uacce->api_ver = HISI_QM_API_VER_BASE; - else if (qm->ver == QM_HW_V2) - uacce->api_ver = HISI_QM_API_VER2_BASE; - else - uacce->api_ver = HISI_QM_API_VER3_BASE; - - if (qm->ver == QM_HW_V1) - mmio_page_nr = QM_DOORBELL_PAGE_NR; - else if (!test_bit(QM_SUPPORT_DB_ISOLATION, &qm->caps)) - mmio_page_nr = QM_DOORBELL_PAGE_NR + - QM_DOORBELL_SQ_CQ_BASE_V2 / PAGE_SIZE; - else - mmio_page_nr = qm->db_interval / PAGE_SIZE; - - qm_get_xqc_depth(qm, &sq_depth, &cq_depth, QM_QP_DEPTH_CAP); + interface.flags = qm->use_iommu ? UACCE_DEV_IOMMU : UACCE_DEV_NOIOMMU; + if (qm->mode == UACCE_MODE_SVA) { + if (!qm->use_iommu) { + pci_err(pdev, "SMMU not opened, not support uacce mode 1!\n"); + return -EINVAL; + } - /* Add one more page for device or qp status */ - dus_page_nr = (PAGE_SIZE - 1 + qm->sqe_size * sq_depth + - sizeof(struct qm_cqe) * cq_depth + PAGE_SIZE) >> - PAGE_SHIFT; + interface.flags |= UACCE_DEV_SVA; + } - uacce->qf_pg_num[UACCE_QFRT_MMIO] = mmio_page_nr; - uacce->qf_pg_num[UACCE_QFRT_DUS] = dus_page_nr; + interface.ops = &uacce_qm_ops; + + uacce = uacce_alloc(&pdev->dev, &interface); + if (IS_ERR(uacce)) { + pci_err(pdev, "fail to alloc uacce device\n!"); + return PTR_ERR(uacce); + } qm->uacce = uacce; - return 0; + qm_uacce_base_init(qm); + ret = qm_uacce_isolate_init(qm); + if (ret) + goto err_rm_uacce; + + return ret; +err_rm_uacce: + qm_remove_uacce(qm); + return ret; } +int qm_register_uacce(struct hisi_qm *qm) +{ + if (!qm->use_uacce) + return 0; + + dev_info(&qm->pdev->dev, "qm register to uacce\n"); + return uacce_register(qm->uacce); + } +EXPORT_SYMBOL_GPL(qm_register_uacce); + /** * qm_frozen() - Try to froze QM to cut continuous queue request. If * there is user on the QM, return failure without doing anything. @@ -3645,7 +3767,21 @@ err_free_qp_finish_id: return ret; } -static void hisi_qm_pre_init(struct hisi_qm *qm) +static inline bool is_iommu_used(struct device *dev) +{ + struct iommu_domain *domain; + + domain = iommu_get_domain_for_dev(dev); + if (domain) { + dev_info(dev, "SMMU Opened, iommu type = %u\n", domain->type); + return domain->type & __IOMMU_DOMAIN_PAGING; + } + + return false; +} + + +static int hisi_qm_pre_init(struct hisi_qm *qm) { struct pci_dev *pdev = qm->pdev; @@ -3656,15 +3792,29 @@ static void hisi_qm_pre_init(struct hisi_qm *qm) else qm->ops = &qm_hw_ops_v3; + switch (qm->mode) { + case UACCE_MODE_NOUACCE: + qm->use_uacce = false; + break; + case UACCE_MODE_SVA: + case UACCE_MODE_NOIOMMU: + qm->use_uacce = true; + break; + default: + pci_err(pdev, "uacce mode error!\n"); + return -EINVAL; + } pci_set_drvdata(pdev, qm); mutex_init(&qm->mailbox_lock); init_rwsem(&qm->qps_lock); qm->qp_in_used = 0; qm->misc_ctl = false; + qm->use_iommu = is_iommu_used(&pdev->dev); if (test_bit(QM_SUPPORT_RPM, &qm->caps)) { if (!acpi_device_power_manageable(ACPI_COMPANION(&pdev->dev))) dev_info(&pdev->dev, "_PS0 and _PR0 are not defined"); } + return 0; } static void qm_cmd_uninit(struct hisi_qm *qm) @@ -3778,12 +3928,10 @@ void hisi_qm_uninit(struct hisi_qm *qm) hisi_qm_set_state(qm, VF_NOT_READY); up_write(&qm->qps_lock); + qm_remove_uacce(qm); qm_irqs_unregister(qm); hisi_qm_pci_uninit(qm); - if (qm->use_sva) { - uacce_remove(qm->uacce); - qm->uacce = NULL; - } + } EXPORT_SYMBOL_GPL(hisi_qm_uninit); @@ -5137,6 +5285,12 @@ static int qm_controller_reset_prepare(struct hisi_qm *qm) return ret; } + if (qm->use_uacce) { + ret = uacce_hw_err_isolate(qm->uacce); + if (ret) + pci_err(pdev, "failed to isolate hw err!\n"); + } + ret = qm_wait_vf_prepare_finish(qm); if (ret) pci_err(pdev, "failed to stop by vfs in soft reset!\n"); @@ -5845,62 +5999,60 @@ static void qm_cmd_process(struct work_struct *cmd_process) } /** - * hisi_qm_alg_register() - Register alg to crypto and add qm to qm_list. + * hisi_qm_alg_register() - Register alg to crypto. * @qm: The qm needs add. * @qm_list: The qm list. + * @guard: Guard of qp_num. * - * This function adds qm to qm list, and will register algorithm to - * crypto when the qm list is empty. + * Register algorithm to crypto when the first function is satisfy guard. */ -int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list) +int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list, int guard) { struct device *dev = &qm->pdev->dev; - int flag = 0; int ret = 0; - mutex_lock(&qm_list->lock); - if (list_empty(&qm_list->list)) - flag = 1; - list_add_tail(&qm->list, &qm_list->list); - mutex_unlock(&qm_list->lock); if (qm->ver <= QM_HW_V2 && qm->use_sva) { dev_info(dev, "HW V2 not both use uacce sva mode and hardware crypto algs.\n"); return 0; } - if (flag) { + if (qm->qp_num < guard) { + dev_info(dev, "qp_num is less than task need.\n"); + return 0; + } + + if (!atomic_read(&qm_list->alg_refcnt)) { ret = qm_list->register_to_crypto(qm); - if (ret) { - mutex_lock(&qm_list->lock); - list_del(&qm->list); - mutex_unlock(&qm_list->lock); - } + if (ret) + return ret; } - return ret; + atomic_inc(&qm_list->alg_refcnt); + + return 0; } EXPORT_SYMBOL_GPL(hisi_qm_alg_register); /** - * hisi_qm_alg_unregister() - Unregister alg from crypto and delete qm from - * qm list. + * hisi_qm_alg_unregister() - Unregister alg from crypto. * @qm: The qm needs delete. * @qm_list: The qm list. + * @guard: Guard of qp_num. * - * This function deletes qm from qm list, and will unregister algorithm - * from crypto when the qm list is empty. + * Unregister algorithm from crypto when the last function is satisfy guard. */ -void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list) +void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list, int guard) { - mutex_lock(&qm_list->lock); - list_del(&qm->list); - mutex_unlock(&qm_list->lock); - if (qm->ver <= QM_HW_V2 && qm->use_sva) return; - if (list_empty(&qm_list->list)) + if (qm->qp_num < guard) + return; + + atomic_dec(&qm_list->alg_refcnt); + + if (!atomic_read(&qm_list->alg_refcnt)) qm_list->unregister_from_crypto(qm); } EXPORT_SYMBOL_GPL(hisi_qm_alg_unregister); @@ -6378,7 +6530,9 @@ int hisi_qm_init(struct hisi_qm *qm) struct device *dev = &pdev->dev; int ret; - hisi_qm_pre_init(qm); + ret = hisi_qm_pre_init(qm); + if (ret) + return ret; ret = hisi_qm_pci_init(qm); if (ret) @@ -6397,10 +6551,10 @@ int hisi_qm_init(struct hisi_qm *qm) } } - if (qm->mode == UACCE_MODE_SVA) { - ret = qm_alloc_uacce(qm); - if (ret < 0) - dev_warn(dev, "fail to alloc uacce (%d)\n", ret); + ret = qm_alloc_uacce(qm); + if (ret < 0) { + dev_err(dev, "failed to alloc uacce (%d)\n", ret); + goto err_irq_register; } ret = hisi_qm_memory_init(qm); @@ -6421,10 +6575,7 @@ int hisi_qm_init(struct hisi_qm *qm) err_free_qm_memory: hisi_qm_memory_uninit(qm); err_alloc_uacce: - if (qm->use_sva) { - uacce_remove(qm->uacce); - qm->uacce = NULL; - } + qm_remove_uacce(qm); err_irq_register: qm_irqs_unregister(qm); err_pci_init: -- Gitee From 5225dddcfc3560da74f30c68b8895e6d284ec645 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 08:29:23 +0000 Subject: [PATCH 04/11] update kae_driver/hisilicon/hisi_acc_qm.h. Signed-off-by: HUI --- kae_driver/hisilicon/hisi_acc_qm.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/kae_driver/hisilicon/hisi_acc_qm.h b/kae_driver/hisilicon/hisi_acc_qm.h index 4ea4c23..d85a08d 100755 --- a/kae_driver/hisilicon/hisi_acc_qm.h +++ b/kae_driver/hisilicon/hisi_acc_qm.h @@ -99,7 +99,8 @@ /* uacce mode of the driver */ #define UACCE_MODE_NOUACCE 0 /* don't use uacce */ #define UACCE_MODE_SVA 1 /* use uacce sva mode */ -#define UACCE_MODE_DESC "0(default) means only register to crypto, 1 means both register to crypto and uacce" +#define UACCE_MODE_NOIOMMU 2 /* use uacce noiommu mode */ +#define UACCE_MODE_DESC "Mode of UACCE can be 0(default), 1, 2" enum qm_stop_reason { QM_NORMAL, @@ -265,6 +266,7 @@ struct hisi_qm_list { struct list_head list; int (*register_to_crypto)(struct hisi_qm *qm); void (*unregister_from_crypto)(struct hisi_qm *qm); + atomic_t alg_refcnt; }; struct hisi_qm_poll_data { @@ -332,7 +334,9 @@ struct hisi_qm { struct work_struct cmd_process; const char *algs; + bool use_uacce; bool use_sva; + bool use_iommu; bool is_frozen; resource_size_t phys_base; @@ -438,7 +442,7 @@ static inline int mode_set(const char *val, const struct kernel_param *kp) return -EINVAL; ret = kstrtou32(val, 10, &n); - if (ret != 0 || (n != UACCE_MODE_SVA && + if (ret != 0 || (n != UACCE_MODE_NOIOMMU && n != UACCE_MODE_SVA && n != UACCE_MODE_NOUACCE)) return -EINVAL; @@ -456,6 +460,22 @@ static inline void hisi_qm_init_list(struct hisi_qm_list *qm_list) mutex_init(&qm_list->lock); } +static inline void hisi_qm_add_list(struct hisi_qm *qm, struct hisi_qm_list *qm_list) +{ + mutex_lock(&qm_list->lock); + list_add_tail(&qm->list, &qm_list->list); + mutex_unlock(&qm_list->lock); +} + +static inline void hisi_qm_del_list(struct hisi_qm *qm, struct hisi_qm_list *qm_list) +{ + mutex_lock(&qm_list->lock); + list_del(&qm->list); + mutex_unlock(&qm_list->lock); +} + +int qm_register_uacce(struct hisi_qm *qm); + int hisi_qm_init(struct hisi_qm *qm); void hisi_qm_uninit(struct hisi_qm *qm); int hisi_qm_start(struct hisi_qm *qm); @@ -501,8 +521,8 @@ int hisi_qm_alloc_qps_node(struct hisi_qm_list *qm_list, int qp_num, void hisi_qm_free_qps(struct hisi_qp **qps, int qp_num); void hisi_qm_dev_shutdown(struct pci_dev *pdev); void hisi_qm_wait_task_finish(struct hisi_qm *qm, struct hisi_qm_list *qm_list); -int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list); -void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list); +int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list, int guard); +void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list, int guard); int hisi_qm_resume(struct device *dev); int hisi_qm_suspend(struct device *dev); void hisi_qm_pm_uninit(struct hisi_qm *qm); -- Gitee From 2ca3f358c256d6a09423392e1c051b8024426900 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 08:37:50 +0000 Subject: [PATCH 05/11] update kae_driver/hisilicon/sec2/sec_main.c. Signed-off-by: HUI --- kae_driver/hisilicon/sec2/sec_main.c | 40 +++++++++++----------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/kae_driver/hisilicon/sec2/sec_main.c b/kae_driver/hisilicon/sec2/sec_main.c index e28b501..d451a85 100755 --- a/kae_driver/hisilicon/sec2/sec_main.c +++ b/kae_driver/hisilicon/sec2/sec_main.c @@ -404,13 +404,10 @@ static const struct kernel_param_ops sec_uacce_mode_ops = { .get = param_get_int, }; -/* - * uacce_mode = 0 means sec only register to crypto, - * uacce_mode = 1 means sec both register to crypto and uacce. - */ + static u32 uacce_mode = UACCE_MODE_NOUACCE; module_param_cb(uacce_mode, &sec_uacce_mode_ops, &uacce_mode, 0444); -MODULE_PARM_DESC(uacce_mode, UACCE_MODE_DESC); +MODULE_PARM_DESC(uacce_mode, "Mode of UACCE can be 0(default), 1, 2"); static const struct pci_device_id sec_dev_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HUAWEI_SEC_PF) }, @@ -1233,23 +1230,17 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) pci_warn(pdev, "Failed to init debugfs!\n"); - if (qm->qp_num >= ctx_q_num) { - ret = hisi_qm_alg_register(qm, &sec_devices); - if (ret < 0) { - pr_err("Failed to register driver to crypto.\n"); - goto err_qm_stop; - } - } else { - pci_warn(qm->pdev, - "Failed to use kernel mode, qp not enough!\n"); + ret = qm_register_uacce(qm); + if (ret) { + pci_err(pdev, "Failed to register uacce (%d)!\n", ret); + goto err_qm_stop; } - if (qm->uacce) { - ret = uacce_register(qm->uacce); - if (ret) { - pci_err(pdev, "failed to register uacce (%d)!\n", ret); - goto err_alg_unregister; - } + hisi_qm_add_list(qm, &sec_devices); + ret = hisi_qm_alg_register(qm, &sec_devices, ctx_q_num); + if (ret < 0) { + pr_err("Failed to register driver to crypto.\n"); + goto err_qm_del_list; } if (qm->fun_type == QM_HW_PF && vfs_num) { @@ -1263,8 +1254,9 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; err_alg_unregister: - if (qm->qp_num >= ctx_q_num) - hisi_qm_alg_unregister(qm, &sec_devices); + hisi_qm_alg_unregister(qm, &sec_devices, ctx_q_num); +err_qm_del_list: + hisi_qm_del_list(qm, &sec_devices); err_qm_stop: sec_debugfs_exit(qm); hisi_qm_stop(qm, QM_NORMAL); @@ -1282,8 +1274,8 @@ static void sec_remove(struct pci_dev *pdev) hisi_qm_pm_uninit(qm); hisi_qm_wait_task_finish(qm, &sec_devices); - if (qm->qp_num >= ctx_q_num) - hisi_qm_alg_unregister(qm, &sec_devices); + hisi_qm_alg_unregister(qm, &sec_devices, ctx_q_num); + hisi_qm_del_list(qm, &sec_devices); if (qm->fun_type == QM_HW_PF && qm->vfs_num) hisi_qm_sriov_disable(pdev, true); -- Gitee From d1b9763c8a6c02260c0fcf7987a0b3d41ef581e6 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 08:49:35 +0000 Subject: [PATCH 06/11] update kae_driver/hisilicon/zip/zip_main.c. Signed-off-by: HUI --- kae_driver/hisilicon/zip/zip_main.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/kae_driver/hisilicon/zip/zip_main.c b/kae_driver/hisilicon/zip/zip_main.c index a61a176..8ef3cb2 100755 --- a/kae_driver/hisilicon/zip/zip_main.c +++ b/kae_driver/hisilicon/zip/zip_main.c @@ -68,6 +68,7 @@ #define HZIP_SQE_SIZE 128 #define HZIP_PF_DEF_Q_NUM 64 #define HZIP_PF_DEF_Q_BASE 0 +#define HZIP_CTX_Q_NUM_DEF 2 #define HZIP_SOFT_CTRL_CNT_CLR_CE 0x301000 #define HZIP_SOFT_CTRL_CNT_CLR_CE_BIT BIT(0) @@ -1229,18 +1230,17 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) pci_err(pdev, "failed to init debugfs (%d)!\n", ret); - ret = hisi_qm_alg_register(qm, &zip_devices); + hisi_qm_add_list(qm, &zip_devices); + ret = hisi_qm_alg_register(qm, &zip_devices, HZIP_CTX_Q_NUM_DEF); if (ret < 0) { pci_err(pdev, "failed to register driver to crypto!\n"); goto err_qm_stop; } - if (qm->uacce) { - ret = uacce_register(qm->uacce); - if (ret) { - pci_err(pdev, "failed to register uacce (%d)!\n", ret); - goto err_qm_alg_unregister; - } + ret = qm_register_uacce(qm); + if (ret) { + pci_err(pdev, "Failed to register uacce (%d)!\n", ret); + goto err_qm_alg_unregister; } if (qm->fun_type == QM_HW_PF && vfs_num > 0) { @@ -1254,9 +1254,10 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; err_qm_alg_unregister: - hisi_qm_alg_unregister(qm, &zip_devices); + hisi_qm_alg_unregister(qm, &zip_devices, HZIP_CTX_Q_NUM_DEF); err_qm_stop: + hisi_qm_del_list(qm, &zip_devices); hisi_zip_debugfs_exit(qm); hisi_qm_stop(qm, QM_NORMAL); @@ -1276,7 +1277,8 @@ static void hisi_zip_remove(struct pci_dev *pdev) hisi_qm_pm_uninit(qm); hisi_qm_wait_task_finish(qm, &zip_devices); - hisi_qm_alg_unregister(qm, &zip_devices); + hisi_qm_alg_unregister(qm, &zip_devices, HZIP_CTX_Q_NUM_DEF); + hisi_qm_del_list(qm, &zip_devices); if (qm->fun_type == QM_HW_PF && qm->vfs_num) hisi_qm_sriov_disable(pdev, true); -- Gitee From 8daccbc085f0eba2986a93ae2ca8f51824eb5f94 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 08:51:23 +0000 Subject: [PATCH 07/11] update kae_driver/uacce/Kconfig. Signed-off-by: HUI --- kae_driver/uacce/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/kae_driver/uacce/Kconfig b/kae_driver/uacce/Kconfig index 5e39b60..6cff4d4 100755 --- a/kae_driver/uacce/Kconfig +++ b/kae_driver/uacce/Kconfig @@ -1,6 +1,7 @@ config UACCE tristate "Accelerator Framework for User Land" depends on IOMMU_API + select ANON_INODES help UACCE provides interface for the user process to access the hardware without interaction with the kernel space in data path. -- Gitee From 6df8c69e31894236ff293fac4eaeab6790addfff Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 11:08:14 +0000 Subject: [PATCH 08/11] update kae_driver/uacce/uacce.c. Signed-off-by: HUI --- kae_driver/uacce/uacce.c | 625 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 604 insertions(+), 21 deletions(-) diff --git a/kae_driver/uacce/uacce.c b/kae_driver/uacce/uacce.c index faad393..6526c53 100755 --- a/kae_driver/uacce/uacce.c +++ b/kae_driver/uacce/uacce.c @@ -1,16 +1,111 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include #include +#include #include #include #include #include #include "../include_linux/uacce.h" +#include static struct class *uacce_class; static dev_t uacce_devt; static DEFINE_XARRAY_ALLOC(uacce_xa); +static const struct file_operations uacce_fops; +static struct uacce_qfile_region noiommu_ss_default_qfr = { + .type = UACCE_QFRT_SS, +}; + +static int cdev_get(struct device *dev, void *data) +{ + struct uacce_device *uacce; + struct device **t_dev = data; + + uacce = container_of(dev, struct uacce_device, dev); + if (uacce->parent == *t_dev) { + *t_dev = dev; + return 1; + } + + return 0; +} + +/** + * dev_to_uacce - Get structure uacce device from its parent device + * @dev the device + */ +struct uacce_device *dev_to_uacce(struct device *dev) +{ + struct device **tdev = &dev; + int ret; + + ret = class_for_each_device(uacce_class, NULL, tdev, cdev_get); + if (ret) { + dev = *tdev; + return container_of(dev, struct uacce_device, dev); + } + return NULL; +} +EXPORT_SYMBOL_GPL(dev_to_uacce); + +/** + * uacce_hw_err_isolate - Try to isolate the uacce device with its VFs + * according to user's configuration of isolation strategy. Warning: this + * API should be called while there is no user on the device, or the users + * on this device are suspended by slot resetting preparation of PCI AER. + * @uacce the uacce device + */ +int uacce_hw_err_isolate(struct uacce_device *uacce) +{ + struct uacce_hw_err *err, *tmp, *hw_err; + struct uacce_err_isolate *isolate; + u32 count = 0; + + if (!uacce) + return -EINVAL; + isolate = uacce->isolate; + +#define SECONDS_PER_HOUR 3600 + + /* all the hw errs are processed by PF driver */ + if (uacce->is_vf || atomic_read(&isolate->is_isolate) || + !isolate->hw_err_isolate_hz) + return 0; + + hw_err = kzalloc(sizeof(*hw_err), GFP_ATOMIC); + if (!hw_err) + return -ENOMEM; + hw_err->tick_stamp = jiffies; + list_for_each_entry_safe(err, tmp, &isolate->hw_errs, list) { + if ((hw_err->tick_stamp - err->tick_stamp) / HZ > + SECONDS_PER_HOUR) { + list_del(&err->list); + kfree(err); + } else { + count++; + } + } + list_add(&hw_err->list, &isolate->hw_errs); + + if (count >= isolate->hw_err_isolate_hz) + atomic_set(&isolate->is_isolate, 1); + + return 0; +} +EXPORT_SYMBOL_GPL(uacce_hw_err_isolate); + +static void uacce_hw_err_destroy(struct uacce_device *uacce) +{ + struct uacce_hw_err *err, *tmp; + + list_for_each_entry_safe(err, tmp, &uacce->isolate_data.hw_errs, list) { + list_del(&err->list); + kfree(err); + } +} + /* * If the parent driver or the device disappears, the queue state is invalid and * ops are not usable anymore. @@ -52,6 +147,146 @@ static int uacce_put_queue(struct uacce_queue *q) return 0; } +static long uacce_cmd_share_qfr(struct uacce_queue *src, int fd) +{ + struct device *dev = &src->uacce->dev; + struct file *filep = fget(fd); + struct uacce_queue *tgt; + int ret = -EINVAL; + + if (!filep) { + dev_err(dev, "filep is NULL!\n"); + return ret; + } + + if (filep->f_op != &uacce_fops) { + dev_err(dev, "file ops mismatch!\n"); + goto out_with_fd; + } + + tgt = filep->private_data; + if (!tgt) { + dev_err(dev, "target queue is not exist!\n"); + goto out_with_fd; + } + + mutex_lock(&uacce_mutex); + if (tgt->state == UACCE_Q_ZOMBIE || src->state == UACCE_Q_ZOMBIE) { + dev_err(dev, "target or source queue is zombie!\n"); + goto out_with_fd; + } + + if (!src->qfrs[UACCE_QFRT_SS] || tgt->qfrs[UACCE_QFRT_SS]) { + dev_err(dev, "src q's SS not exists or target q's SS exists!\n"); + goto out_with_fd; + } + + /* In No-IOMMU mode, taget queue uses default SS qfr */ + tgt->qfrs[UACCE_QFRT_SS] = &noiommu_ss_default_qfr; + + ret = 0; + +out_with_fd: + mutex_unlock(&uacce_mutex); + fput(filep); + + return ret; +} + +static long uacce_get_ss_dma(struct uacce_queue *q, void __user *arg) +{ + struct uacce_device *uacce = q->uacce; + struct uacce_dma_slice *slice; + unsigned long slice_idx = 0; + unsigned long dma, size; + unsigned int max_idx; + long ret = -EFAULT; + + if (q->state == UACCE_Q_ZOMBIE) { + dev_err(&uacce->dev, "queue is zombie!\n"); + ret = -EINVAL; + goto param_check; + } + + if (!q->qfrs[UACCE_QFRT_SS]) { + dev_err(&uacce->dev, "no ss dma region!\n"); + ret = -EINVAL; + goto param_check; + } + + slice = q->qfrs[UACCE_QFRT_SS]->dma_list; + if (copy_from_user(&slice_idx, arg, sizeof(unsigned long))) { + dev_err(&uacce->dev, "copy_from_user fail!\n"); + goto param_check; + } + + if (slice[0].total_num - 1 < slice_idx) { + dev_err(&uacce->dev, "no ss slice idx %lu err, total %u!\n", + slice_idx, slice[0].total_num); + ret = -EINVAL; + goto param_check; + } + + dma = slice[slice_idx].dma; + size = slice[slice_idx].size; + if (!size) { + max_idx = slice[0].total_num - 1; + dev_err(&uacce->dev, "%luth ss region[0x%lx, %lu] no exist, range[[0](0x%llx, %llu) -> [%u](0x%llx, %llu)]\n", + slice_idx, dma, size, + slice[0].dma, slice[0].size, max_idx, + slice[max_idx].dma, slice[max_idx].size); + ret = -ENODEV; + goto param_check; + } + dma = dma | ((size >> UACCE_GRAN_SHIFT) & UACCE_GRAN_NUM_MASK); + if (copy_to_user(arg, &dma, sizeof(unsigned long))) { + dev_err(&uacce->dev, "copy_to_user fail!\n"); + goto param_check; + } + + ret = (long)(slice[0].total_num - 1 - slice_idx); + +param_check: + return ret; +} + +static void uacce_free_dma_buffers(struct uacce_queue *q) +{ + struct uacce_qfile_region *qfr = q->qfrs[UACCE_QFRT_SS]; + struct device *pdev = q->uacce->parent; + int i = 0; + + if (module_refcount(pdev->driver->owner) > 0) + module_put(pdev->driver->owner); + + if (!qfr->dma_list) + return; + while (i < qfr->dma_list[0].total_num) { + WARN_ON(!qfr->dma_list[i].size || !qfr->dma_list[i].dma); + dev_dbg(pdev, "free dma qfr (kaddr=%lx, dma=%llx)\n", + (unsigned long)qfr->dma_list[i].kaddr, + qfr->dma_list[i].dma); + dma_free_coherent(pdev, qfr->dma_list[i].size, + qfr->dma_list[i].kaddr, + qfr->dma_list[i].dma); + i++; + } + kfree(qfr->dma_list); + qfr->dma_list = NULL; +} + +/** + * uacce_wake_up - Wake up the process who is waiting this queue + * @q the accelerator queue to wake up + */ +void uacce_wake_up(struct uacce_queue *q) +{ + if (unlikely(!q)) + return; + + wake_up_interruptible(&q->wait); +} +EXPORT_SYMBOL_GPL(uacce_wake_up); static long uacce_fops_unl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) @@ -79,6 +314,11 @@ static long uacce_fops_unl_ioctl(struct file *filep, case UACCE_CMD_PUT_Q: ret = uacce_put_queue(q); break; + case UACCE_CMD_SHARE_SVAS: + return uacce_cmd_share_qfr(q, (int)arg); + + case UACCE_CMD_GET_SS_DMA: + return uacce_get_ss_dma(q, (void __user *)(uintptr_t)arg); default: if (uacce->ops->ioctl) ret = uacce->ops->ioctl(q, cmd, arg); @@ -94,7 +334,7 @@ out_unlock: static long uacce_fops_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { - arg = (unsigned long)compat_ptr(arg); + arg = (unsigned long)(uintptr_t)compat_ptr(arg); return uacce_fops_unl_ioctl(filep, cmd, arg); } @@ -157,6 +397,7 @@ static int uacce_fops_open(struct inode *inode, struct file *filep) goto out_with_mem; q->uacce = uacce; + q->filep = filep; if (uacce->ops->get_queue) { ret = uacce->ops->get_queue(uacce, q->pasid, q); @@ -164,6 +405,7 @@ static int uacce_fops_open(struct inode *inode, struct file *filep) goto out_with_bond; } + atomic_inc(&uacce->ref); init_waitqueue_head(&q->wait); filep->private_data = q; uacce->inode = inode; @@ -185,6 +427,7 @@ out_with_mem: static int uacce_fops_release(struct inode *inode, struct file *filep) { struct uacce_queue *q = filep->private_data; + struct uacce_qfile_region *ss = q->qfrs[UACCE_QFRT_SS]; struct uacce_device *uacce = q->uacce; mutex_lock(&uacce->mutex); @@ -192,38 +435,278 @@ static int uacce_fops_release(struct inode *inode, struct file *filep) uacce_unbind_queue(q); list_del(&q->list); mutex_unlock(&uacce->mutex); + + if (ss && ss != &noiommu_ss_default_qfr) { + uacce_free_dma_buffers(q); + kfree(ss); + } + kfree(q); return 0; } +static vm_fault_t uacce_vma_fault(struct vm_fault *vmf) +{ + if (vmf->flags & (FAULT_FLAG_MKWRITE | FAULT_FLAG_WRITE)) + return VM_FAULT_SIGBUS; + + return 0; +} + static void uacce_vma_close(struct vm_area_struct *vma) { struct uacce_queue *q = vma->vm_private_data; struct uacce_qfile_region *qfr = NULL; + struct uacce_device *uacce = q->uacce; + struct device *dev = &q->uacce->dev; - if (vma->vm_pgoff < UACCE_MAX_REGION) - qfr = q->qfrs[vma->vm_pgoff]; + if (vma->vm_pgoff >= UACCE_MAX_REGION) + return; - kfree(qfr); + qfr = q->qfrs[vma->vm_pgoff]; + if (!qfr) { + dev_err(dev, "qfr NULL, type %lu!\n", vma->vm_pgoff); + return; + } + + if (qfr->type == UACCE_QFRT_SS && + atomic_read(¤t->active_mm->mm_users) > 0) { + if ((q->state == UACCE_Q_STARTED) && uacce->ops->stop_queue) + uacce->ops->stop_queue(q); + uacce_free_dma_buffers(q); + kfree(qfr); + q->qfrs[vma->vm_pgoff] = NULL; + } else if (qfr->type != UACCE_QFRT_SS) { + kfree(qfr); + q->qfrs[vma->vm_pgoff] = NULL; + } } static const struct vm_operations_struct uacce_vm_ops = { - .close = uacce_vma_close, + .fault = uacce_vma_fault, + .close = uacce_vma_close, }; +static int get_sort_base(struct uacce_dma_slice *list, int low, int high, + struct uacce_dma_slice *tmp) +{ + tmp->kaddr = list[low].kaddr; + tmp->size = list[low].size; + tmp->dma = list[low].dma; + + if (low > high) + return -EINVAL; + else if (low == high) + return 0; + + while (low < high) { + while (low < high && list[high].dma > tmp->dma) + high--; + list[low].kaddr = list[high].kaddr; + list[low].dma = list[high].dma; + list[low].size = list[high].size; + while (low < high && list[low].dma < tmp->dma) + low++; + list[high].kaddr = list[low].kaddr; + list[high].dma = list[low].dma; + list[high].size = list[low].size; + } + list[low].kaddr = tmp->kaddr; + list[low].dma = tmp->dma; + list[low].size = tmp->size; + + return low; +} + +static int uacce_sort_dma_buffers(struct uacce_dma_slice *list, int low, + int high, struct uacce_dma_slice *tmp) +{ + int *idx_list; + int top = 0; + int pilot; + + idx_list = kcalloc(list[0].total_num, sizeof(int), + GFP_KERNEL | __GFP_ZERO); + if (!idx_list) + return -ENOMEM; + + pilot = get_sort_base(list, low, high, tmp); + if (pilot <= 0) { + if (pilot) + pr_err("fail to sort base!\n"); + kfree(idx_list); + return pilot; + } + + if (pilot > low + 1) { + idx_list[top++] = low; + idx_list[top++] = pilot - 1; + } + if (pilot < high - 1) { + idx_list[top++] = pilot + 1; + idx_list[top++] = high; + } + while (top > 0) { + high = idx_list[--top]; + low = idx_list[--top]; + pilot = get_sort_base(list, low, high, tmp); + if (pilot > low + 1) { + idx_list[top++] = low; + idx_list[top++] = pilot - 1; + } + if (pilot < high - 1) { + idx_list[top++] = pilot + 1; + idx_list[top++] = high; + } + } + + kfree(idx_list); + return 0; +} + +static int uacce_alloc_dma_buffers(struct uacce_queue *q, + struct vm_area_struct *vma) +{ + struct uacce_qfile_region *qfr = q->qfrs[UACCE_QFRT_SS]; + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long max_size = PAGE_SIZE << (MAX_ORDER - 1); + struct device *pdev = q->uacce->parent; + struct uacce_device *uacce = q->uacce; + unsigned long start = vma->vm_start; + struct uacce_dma_slice *slice; + unsigned long ss_num; + int ret, i; + + /* + * When IOMMU closed, set maximum slice size is 128M, default is 4M + * when IOMMU opened, set maxinum slice size base on actual size + */ + if (uacce->flags & UACCE_DEV_IOMMU) + max_size = size; + else if (max_size > UACCE_GRAN_NUM_MASK << UACCE_GRAN_SHIFT) + max_size = (UACCE_GRAN_NUM_MASK + 1) << (UACCE_GRAN_SHIFT - 1); + + ss_num = size / max_size + (size % max_size ? 1 : 0); + slice = kcalloc(ss_num + 1, sizeof(*slice), GFP_KERNEL | __GFP_ZERO); + if (!slice) + return -ENOMEM; + + (void)try_module_get(pdev->driver->owner); + qfr->dma_list = slice; + for (i = 0; i < ss_num; i++) { + if (start + max_size > vma->vm_end) + size = vma->vm_end - start; + else + size = max_size; + dev_dbg(pdev, "allocate dma %ld pages\n", + (size + PAGE_SIZE - 1) >> PAGE_SHIFT); + slice[i].kaddr = dma_alloc_coherent(pdev, (size + + PAGE_SIZE - 1) & PAGE_MASK, + &slice[i].dma, GFP_KERNEL); + if (!slice[i].kaddr) { + dev_err(pdev, "Get dma slice(sz=%lu,dma=0x%llx) fail!\n", + size, slice[i].dma); + slice[0].total_num = i; + uacce_free_dma_buffers(q); + return -ENOMEM; + } + slice[i].size = (size + PAGE_SIZE - 1) & PAGE_MASK; + slice[i].total_num = ss_num; + start += size; + } + + ret = uacce_sort_dma_buffers(slice, 0, slice[0].total_num - 1, + &slice[ss_num]); + if (ret) { + dev_err(pdev, "failed to sort dma buffers.\n"); + uacce_free_dma_buffers(q); + return ret; + } + + return 0; +} + +static int uacce_mmap_dma_buffers(struct uacce_queue *q, + struct vm_area_struct *vma) +{ + struct uacce_qfile_region *qfr = q->qfrs[UACCE_QFRT_SS]; + struct uacce_dma_slice *slice = qfr->dma_list; + struct device *pdev = q->uacce->parent; + unsigned long vm_pgoff; + int ret = 0; + int i = 0; + + /* + * dma_mmap_coherent() requires vm_pgoff as 0 + * restore vm_pfoff to initial value for mmap() + */ + vm_pgoff = vma->vm_pgoff; + vma->vm_pgoff = 0; + while (i < slice[0].total_num && slice[i].size) { + vma->vm_end = vma->vm_start + slice[i].size; + ret = dma_mmap_coherent(pdev, vma, slice[i].kaddr, + slice[i].dma, + slice[i].size); + if (ret) { + dev_err(pdev, "dma mmap fail(dma=0x%llx,size=0x%llx)!\n", + slice[i].dma, slice[i].size); + goto DMA_MMAP_FAIL; + } + + i++; + vma->vm_start = vma->vm_end; + } + + /* System unmap_region will clean the results, we need do nothing */ +DMA_MMAP_FAIL: + vma->vm_pgoff = vm_pgoff; + vma->vm_start = qfr->iova; + vma->vm_end = vma->vm_start + (qfr->nr_pages << PAGE_SHIFT); + + return ret; +} + +static int uacce_create_region(struct uacce_queue *q, + struct vm_area_struct *vma, + struct uacce_qfile_region *qfr) +{ + int ret; + + qfr->iova = vma->vm_start; + qfr->nr_pages = vma_pages(vma); + + /* allocate memory */ + ret = uacce_alloc_dma_buffers(q, vma); + if (ret) + return ret; + + ret = uacce_mmap_dma_buffers(q, vma); + if (ret) + goto err_with_pages; + + return ret; + +err_with_pages: + uacce_free_dma_buffers(q); + return ret; +} + static int uacce_fops_mmap(struct file *filep, struct vm_area_struct *vma) { struct uacce_queue *q = filep->private_data; struct uacce_device *uacce = q->uacce; - struct uacce_qfile_region *qfr; enum uacce_qfrt type = UACCE_MAX_REGION; - int ret = 0; + struct uacce_qfile_region *qfr; + int ret = -EINVAL; if (vma->vm_pgoff < UACCE_MAX_REGION) type = vma->vm_pgoff; else - return -EINVAL; + return ret; + + if (q->qfrs[type]) + return -EEXIST; qfr = kzalloc(sizeof(*qfr), GFP_KERNEL); if (!qfr) @@ -240,10 +723,7 @@ static int uacce_fops_mmap(struct file *filep, struct vm_area_struct *vma) goto out_with_lock; } - if (q->qfrs[type]) { - ret = -EEXIST; - goto out_with_lock; - } + q->qfrs[type] = qfr; switch (type) { case UACCE_QFRT_MMIO: @@ -258,12 +738,17 @@ static int uacce_fops_mmap(struct file *filep, struct vm_area_struct *vma) goto out_with_lock; break; + case UACCE_QFRT_SS: + ret = uacce_create_region(q, vma, qfr); + if (ret) + goto out_with_lock; + break; + default: ret = -EINVAL; goto out_with_lock; } - q->qfrs[type] = qfr; mutex_unlock(&q->mutex); return ret; @@ -271,6 +756,7 @@ static int uacce_fops_mmap(struct file *filep, struct vm_area_struct *vma) out_with_lock: mutex_unlock(&q->mutex); kfree(qfr); + q->qfrs[type] = NULL; return ret; } @@ -313,7 +799,7 @@ static ssize_t api_show(struct device *dev, { struct uacce_device *uacce = to_uacce_device(dev); - return sprintf(buf, "%s\n", uacce->api_ver); + return sysfs_emit(buf, "%s\n", uacce->api_ver); } static ssize_t flags_show(struct device *dev, @@ -321,7 +807,7 @@ static ssize_t flags_show(struct device *dev, { struct uacce_device *uacce = to_uacce_device(dev); - return sprintf(buf, "%u\n", uacce->flags); + return sysfs_emit(buf, "%u\n", uacce->flags); } static ssize_t available_instances_show(struct device *dev, @@ -333,7 +819,7 @@ static ssize_t available_instances_show(struct device *dev, if (!uacce->ops->get_available_instances) return -ENODEV; - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", uacce->ops->get_available_instances(uacce)); } @@ -342,7 +828,7 @@ static ssize_t algorithms_show(struct device *dev, { struct uacce_device *uacce = to_uacce_device(dev); - return sprintf(buf, "%s\n", uacce->algs); + return sysfs_emit(buf, "%s\n", uacce->algs); } static ssize_t region_mmio_size_show(struct device *dev, @@ -350,7 +836,7 @@ static ssize_t region_mmio_size_show(struct device *dev, { struct uacce_device *uacce = to_uacce_device(dev); - return sprintf(buf, "%lu\n", + return sysfs_emit(buf, "%lu\n", uacce->qf_pg_num[UACCE_QFRT_MMIO] << PAGE_SHIFT); } @@ -359,24 +845,112 @@ static ssize_t region_dus_size_show(struct device *dev, { struct uacce_device *uacce = to_uacce_device(dev); - return sprintf(buf, "%lu\n", + return sysfs_emit(buf, "%lu\n", uacce->qf_pg_num[UACCE_QFRT_DUS] << PAGE_SHIFT); } +static ssize_t isolate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct uacce_device *uacce = to_uacce_device(dev); + + return sysfs_emit(buf, "%d\n", atomic_read(&uacce->isolate->is_isolate)); +} + ++static ssize_t isolate_strategy_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct uacce_device *uacce = to_uacce_device(dev); + + return sysfs_emit(buf, "%u\n", uacce->isolate->hw_err_isolate_hz); +} + +static ssize_t isolate_strategy_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct uacce_device *uacce = to_uacce_device(dev); + unsigned long val = 0; + +#define MAX_ISOLATE_STRATEGY 65535 + + /* must be set by PF */ + if (uacce->is_vf) + return -EINVAL; + + if (kstrtoul(buf, 0, &val) < 0) + return -EINVAL; + + if (val > MAX_ISOLATE_STRATEGY) + return -EINVAL; + + if (atomic_read(&uacce->ref)) + return -EBUSY; + + uacce->isolate->hw_err_isolate_hz = val; + dev_info(uacce->parent, + "the value of isolate_strategy is set to %lu.\n", val); + + return count; +} + +static ssize_t dev_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct uacce_device *uacce = to_uacce_device(dev); + + return sysfs_emit(buf, "%d\n", uacce->ops->get_dev_state(uacce)); +} + +static ssize_t node_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct uacce_device *uacce = to_uacce_device(dev); + int node_id = -1; + +#ifdef CONFIG_NUMA + node_id = uacce->parent->numa_node; +#endif + return sysfs_emit(buf, "%d\n", node_id); +} + +static ssize_t numa_distance_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct uacce_device *uacce = to_uacce_device(dev); + int distance = 0; + +#ifdef CONFIG_NUMA + distance = node_distance(uacce->parent->numa_node, + cpu_to_node(smp_processor_id())); +#endif + return sysfs_emit(buf, "%d\n", distance); +} + static DEVICE_ATTR_RO(api); static DEVICE_ATTR_RO(flags); +static DEVICE_ATTR_RO(node_id); static DEVICE_ATTR_RO(available_instances); static DEVICE_ATTR_RO(algorithms); static DEVICE_ATTR_RO(region_mmio_size); static DEVICE_ATTR_RO(region_dus_size); +static DEVICE_ATTR_RO(isolate); +static DEVICE_ATTR_RW(isolate_strategy); +static DEVICE_ATTR_RO(dev_state); +static DEVICE_ATTR_RO(numa_distance); static struct attribute *uacce_dev_attrs[] = { &dev_attr_api.attr, &dev_attr_flags.attr, + &dev_attr_node_id.attr, &dev_attr_available_instances.attr, &dev_attr_algorithms.attr, &dev_attr_region_mmio_size.attr, &dev_attr_region_dus_size.attr, + &dev_attr_isolate.attr, + &dev_attr_isolate_strategy.attr, + &dev_attr_dev_state.attr, + &dev_attr_numa_distance.attr, NULL, }; @@ -474,6 +1048,8 @@ struct uacce_device *uacce_alloc(struct device *parent, goto err_with_uacce; INIT_LIST_HEAD(&uacce->queues); + INIT_LIST_HEAD(&uacce->isolate_data.hw_errs); + mutex_init(&uacce->mutex); device_initialize(&uacce->dev); uacce->dev.devt = MKDEV(MAJOR(uacce_devt), uacce->dev_id); @@ -481,7 +1057,10 @@ struct uacce_device *uacce_alloc(struct device *parent, uacce->dev.groups = uacce_dev_groups; uacce->dev.parent = uacce->parent; uacce->dev.release = uacce_release; - dev_set_name(&uacce->dev, "%s-%d", interface->name, uacce->dev_id); + dev_set_name(&uacce->dev, "%s-%u", interface->name, uacce->dev_id); + + if (flags & UACCE_DEV_NOIOMMU) + dev_warn(&uacce->dev, "register to noiommu mode, it's not safe for kernel\n"); return uacce; @@ -576,8 +1155,12 @@ static int __init uacce_init(void) ret = alloc_chrdev_region(&uacce_devt, 0, MINORMASK, UACCE_NAME); if (ret) - class_destroy(uacce_class); + goto destroy_class; + + return 0; +destroy_class: + class_destroy(uacce_class); return ret; } -- Gitee From c7836d10b0df54f99bfbc983f095d1bf328fb8fd Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 11:29:22 +0000 Subject: [PATCH 09/11] update kae_driver/include_linux/uacce.h. Signed-off-by: HUI --- kae_driver/include_linux/uacce.h | 63 +++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/kae_driver/include_linux/uacce.h b/kae_driver/include_linux/uacce.h index 9ce88c2..f410ec3 100755 --- a/kae_driver/include_linux/uacce.h +++ b/kae_driver/include_linux/uacce.h @@ -3,21 +3,50 @@ #define _LINUX_UACCE_H #include +#include +#include +#include +#include #include #define UACCE_NAME "uacce" -#define UACCE_MAX_REGION 2 +#define UACCE_MAX_REGION 3 #define UACCE_MAX_NAME_SIZE 64 struct uacce_queue; struct uacce_device; +struct uacce_hw_err { + struct list_head list; + unsigned long long tick_stamp; +}; + +struct uacce_err_isolate { + struct list_head hw_errs; + u32 hw_err_isolate_hz; /* user cfg freq which triggers isolation */ + atomic_t is_isolate; +}; + +struct uacce_dma_slice { + void *kaddr; /* kernel address for ss */ + dma_addr_t dma; /* dma address, if created by dma api */ + u64 size; /* Size of this dma slice */ + u32 total_num; /* Total slices in this dma list */ +}; + /** * struct uacce_qfile_region - structure of queue file region * @type: type of the region */ struct uacce_qfile_region { enum uacce_qfrt type; + unsigned long iova; /* iova share between user and device space */ + unsigned long nr_pages; + int prot; + unsigned int flags; + struct list_head qs; /* qs sharing the same region, for ss */ + void *kaddr; /* kernel address for dko */ + struct uacce_dma_slice *dma_list; }; /** @@ -28,8 +57,11 @@ struct uacce_qfile_region { * @start_queue: make the queue start work after get_queue * @stop_queue: make the queue stop work before put_queue * @is_q_updated: check whether the task is finished + * @mask_notify: mask the task irq of queue * @mmap: mmap addresses of queue to user space * @ioctl: ioctl for user space users of the queue + * @reset: reset the WD device + * @reset_queue: reset the queue */ struct uacce_ops { int (*get_available_instances)(struct uacce_device *uacce); @@ -38,11 +70,13 @@ struct uacce_ops { void (*put_queue)(struct uacce_queue *q); int (*start_queue)(struct uacce_queue *q); void (*stop_queue)(struct uacce_queue *q); + void (*dump_queue)(const struct uacce_queue *q); int (*is_q_updated)(struct uacce_queue *q); int (*mmap)(struct uacce_queue *q, struct vm_area_struct *vma, struct uacce_qfile_region *qfr); long (*ioctl)(struct uacce_queue *q, unsigned int cmd, unsigned long arg); + enum uacce_dev_state (*get_dev_state)(struct uacce_device *uacce); }; /** @@ -57,6 +91,11 @@ struct uacce_interface { const struct uacce_ops *ops; }; +enum uacce_dev_state { + UACCE_DEV_ERR = -1, + UACCE_DEV_NORMAL, +}; + enum uacce_q_state { UACCE_Q_ZOMBIE = 0, UACCE_Q_INIT, @@ -69,6 +108,7 @@ enum uacce_q_state { * @priv: private pointer * @wait: wait queue head * @list: index into uacce queues list + * @uacce_mm: the corresponding mm * @qfrs: pointer of qfr regions * @mutex: protects queue state * @state: queue state machine @@ -77,10 +117,13 @@ enum uacce_q_state { */ struct uacce_queue { struct uacce_device *uacce; + u32 flags; + atomic_t status; void *priv; wait_queue_head_t wait; struct list_head list; struct uacce_qfile_region *qfrs[UACCE_MAX_REGION]; + struct file *filep; struct mutex mutex; enum uacce_q_state state; u32 pasid; @@ -102,11 +145,13 @@ struct uacce_queue { * @mutex: protects uacce operation * @priv: private pointer of the uacce * @queues: list of queues + * @ref: reference of the uacce * @inode: core vfs */ struct uacce_device { const char *algs; const char *api_ver; + int status; const struct uacce_ops *ops; unsigned long qf_pg_num[UACCE_MAX_REGION]; struct device *parent; @@ -117,6 +162,9 @@ struct uacce_device { struct device dev; struct mutex mutex; void *priv; + atomic_t ref; + struct uacce_err_isolate isolate_data; + struct uacce_err_isolate *isolate; struct list_head queues; struct inode *inode; }; @@ -127,6 +175,9 @@ struct uacce_device *uacce_alloc(struct device *parent, struct uacce_interface *interface); int uacce_register(struct uacce_device *uacce); void uacce_remove(struct uacce_device *uacce); +struct uacce_device *dev_to_uacce(struct device *dev); +void uacce_wake_up(struct uacce_queue *q); +int uacce_hw_err_isolate(struct uacce_device *uacce); #else /* CONFIG_UACCE */ @@ -144,6 +195,16 @@ static inline int uacce_register(struct uacce_device *uacce) static inline void uacce_remove(struct uacce_device *uacce) {} ++static inline struct uacce_device *dev_to_uacce(struct device *dev) +{ + return NULL; +} +static inline void uacce_wake_up(struct uacce_queue *q) {} +int uacce_hw_err_isolate(struct uacce_device *uacce) +{ + return -EINVAL; +} + #endif /* CONFIG_UACCE */ #endif /* _LINUX_UACCE_H */ -- Gitee From fb16fbdc79cfe71b0b3e1753a08bf69ae55d170d Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 11:38:45 +0000 Subject: [PATCH 10/11] update kae_driver/hisilicon/hisi_qm.h. Signed-off-by: HUI --- kae_driver/hisilicon/hisi_qm.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/kae_driver/hisilicon/hisi_qm.h b/kae_driver/hisilicon/hisi_qm.h index 3e66dbc..f3a363a 100755 --- a/kae_driver/hisilicon/hisi_qm.h +++ b/kae_driver/hisilicon/hisi_qm.h @@ -2,7 +2,33 @@ #ifndef _UAPI_HISI_QM_H #define _UAPI_HISI_QM_H -#include +#define QM_CQE_SIZE 16 + +/* default queue depth for sq/cq/eq */ +#define QM_Q_DEPTH 1024 + +/* page number for queue file region */ +#define QM_DOORBELL_PAGE_NR 1 +#define QM_DKO_PAGE_NR 4 +#define QM_DUS_PAGE_NR 36 + +#define QM_DOORBELL_PG_START 0 +#define QM_DKO_PAGE_START (QM_DOORBELL_PG_START + QM_DOORBELL_PAGE_NR) +#define QM_DUS_PAGE_START (QM_DKO_PAGE_START + QM_DKO_PAGE_NR) +#define QM_SS_PAGE_START (QM_DUS_PAGE_START + QM_DUS_PAGE_NR) + +#define QM_DOORBELL_OFFSET 0x340 +#define QM_V2_DOORBELL_OFFSET 0x1000 + +struct cqe { + __le32 rsvd0; + __le16 cmd_id; + __le16 rsvd1; + __le16 sq_head; + __le16 sq_num; + __le16 rsvd2; + __le16 w7; +}; /** * struct hisi_qp_ctx - User data for hisi qp. -- Gitee From f627b19856fbf8ef3ed9e9106995c7c145c72b19 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 3 Jan 2023 11:43:00 +0000 Subject: [PATCH 11/11] update kae_driver/include_uapi_linux/uacce.h. Signed-off-by: HUI --- kae_driver/include_uapi_linux/uacce.h | 50 +++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/kae_driver/include_uapi_linux/uacce.h b/kae_driver/include_uapi_linux/uacce.h index cc71856..265dfb0 100755 --- a/kae_driver/include_uapi_linux/uacce.h +++ b/kae_driver/include_uapi_linux/uacce.h @@ -5,6 +5,7 @@ #include #include +#define UACCE_CLASS_NAME "uacce" /* * UACCE_CMD_START_Q: Start queue */ @@ -17,22 +18,57 @@ */ #define UACCE_CMD_PUT_Q _IO('W', 1) -/* - * UACCE Device flags: - * UACCE_DEV_SVA: Shared Virtual Addresses - * Support PASID - * Support device page faults (PCI PRI or SMMU Stall) +#define UACCE_CMD_SHARE_SVAS _IO('W', 2) + +#define UACCE_CMD_GET_SS_DMA _IOR('W', 3, unsigned long) + + +/** + * UACCE Device Attributes: + * + * NOIOMMU: the device has no IOMMU support + * can do ssva, but no map to the dev + * IOMMU: the device has IOMMU support and enable __IOMMU_DOMAIN_PAGING + * PASID: the device has IOMMU which support PASID setting + * can do ssva, mapped to dev per process + * FAULT_FROM_DEV: the device has IOMMU which can do page fault request + * no need for ssva, should be used with PASID + * KMAP_DUS: map the Device user-shared space to kernel + * DRVMAP_DUS: Driver self-maintain its DUS + * SVA: full function device + * SHARE_DOMAIN: no PASID, can do ssva only for one process and the kernel */ #define UACCE_DEV_SVA BIT(0) +#define UACCE_DEV_NOIOMMU BIT(1) +#define UACCE_DEV_IOMMU BIT(7) + + +/* uacce mode of the driver */ +#define UACCE_MODE_NOUACCE 0 /* don't use uacce */ +#define UACCE_MODE_SVA 1 /* use uacce sva mode */ +#define UACCE_MODE_NOIOMMU 2 /* use uacce noiommu mode */ + +#define UACCE_API_VER_NOIOMMU_SUBFIX "_noiommu" + +#define UACCE_QFR_NA ((unsigned long)-1) /** * enum uacce_qfrt: queue file region type * @UACCE_QFRT_MMIO: device mmio region * @UACCE_QFRT_DUS: device user share region + * @UACCE_QFRT_SS: static share memory(no-sva) */ enum uacce_qfrt { - UACCE_QFRT_MMIO = 0, - UACCE_QFRT_DUS = 1, + UACCE_QFRT_MMIO = 0, /* device mmio region */ + UACCE_QFRT_DUS, /* device user share */ + UACCE_QFRT_SS, /* static share memory */ + UACCE_QFRT_MAX, }; +#define UACCE_QFRT_INVALID UACCE_QFRT_MAX + +/* Pass DMA SS region slice size by granularity 64KB */ +#define UACCE_GRAN_SIZE 0x10000ull +#define UACCE_GRAN_SHIFT 16 +#define UACCE_GRAN_NUM_MASK 0xfffull #endif -- Gitee