diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 21e7340360e796ab9c959353ce0ca3d1e43314f9..24ceccf0b7a1033e211ed11c280553abe0b46a9a 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -251,9 +251,6 @@ #define QM_QOS_MAX_CIR_U 6 #define QM_AUTOSUSPEND_DELAY 3000 -#define QM_MIG_REGION_SEL 0x100198 -#define QM_MIG_REGION_EN 0x1 - /* abnormal status value for stopping queue */ #define QM_STOP_QUEUE_FAIL 1 #define QM_DUMP_SQC_FAIL 3 @@ -3169,7 +3166,7 @@ static void hisi_mig_region_clear(struct hisi_qm *qm) /* Clear migration region set of PF */ if (qm->fun_type == QM_HW_PF && qm->ver > QM_HW_V3) { val = readl(qm->io_base + QM_MIG_REGION_SEL); - val &= ~BIT(0); + val &= ~QM_MIG_REGION_EN; writel(val, qm->io_base + QM_MIG_REGION_SEL); } } @@ -6109,6 +6106,7 @@ static int qm_rebuild_for_resume(struct hisi_qm *qm) } qm_cmd_init(qm); + hisi_mig_region_enable(qm); qm_dev_err_init(qm); /* Set the doorbell timeout to QM_DB_TIMEOUT_CFG ns. */ writel(QM_DB_TIMEOUT_SET, qm->io_base + QM_DB_TIMEOUT_CFG); diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c index 1f548d963360cdeae65eb5bab10eadcb26e817ae..a5af415cdb9761d550e6cb146a08151a4622050d 100644 --- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c +++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c @@ -92,75 +92,25 @@ static int qm_get_vft(struct hisi_qm *qm, u32 *base) return qp_num; } -static int qm_get_xqc_regs(struct hisi_acc_vf_core_device *hisi_acc_vdev, - struct acc_vf_data *vf_data) +static void qm_xqc_reg_offsets(struct hisi_qm *qm, + u32 *eqc_addr, u32 *aeqc_addr) { - struct hisi_qm *qm = &hisi_acc_vdev->vf_qm; - struct device *dev = &qm->pdev->dev; - u32 eqc_addr, aeqc_addr; - int ret; - - if (qm->ver == QM_HW_V3) { - eqc_addr = QM_EQC_DW0; - aeqc_addr = QM_AEQC_DW0; - } else { - eqc_addr = QM_EQC_PF_DW0; - aeqc_addr = QM_AEQC_PF_DW0; - } - - /* QM_EQC_DW has 7 regs */ - ret = qm_read_regs(qm, eqc_addr, vf_data->qm_eqc_dw, 7); - if (ret) { - dev_err(dev, "failed to read QM_EQC_DW\n"); - return ret; - } - - /* QM_AEQC_DW has 7 regs */ - ret = qm_read_regs(qm, aeqc_addr, vf_data->qm_aeqc_dw, 7); - if (ret) { - dev_err(dev, "failed to read QM_AEQC_DW\n"); - return ret; - } - - return 0; -} - -static int qm_set_xqc_regs(struct hisi_acc_vf_core_device *hisi_acc_vdev, - struct acc_vf_data *vf_data) -{ - struct hisi_qm *qm = &hisi_acc_vdev->vf_qm; - struct device *dev = &qm->pdev->dev; - u32 eqc_addr, aeqc_addr; - int ret; + struct hisi_acc_vf_core_device *hisi_acc_vdev = + container_of(qm, struct hisi_acc_vf_core_device, vf_qm); - if (qm->ver == QM_HW_V3) { - eqc_addr = QM_EQC_DW0; - aeqc_addr = QM_AEQC_DW0; + if (hisi_acc_vdev->drv_mode == HW_ACC_MIG_VF_CTRL) { + *eqc_addr = QM_EQC_VF_DW0; + *aeqc_addr = QM_AEQC_VF_DW0; } else { - eqc_addr = QM_EQC_PF_DW0; - aeqc_addr = QM_AEQC_PF_DW0; + *eqc_addr = QM_EQC_PF_DW0; + *aeqc_addr = QM_AEQC_PF_DW0; } - - /* QM_EQC_DW has 7 regs */ - ret = qm_write_regs(qm, eqc_addr, vf_data->qm_eqc_dw, 7); - if (ret) { - dev_err(dev, "failed to write QM_EQC_DW\n"); - return ret; - } - - /* QM_AEQC_DW has 7 regs */ - ret = qm_write_regs(qm, aeqc_addr, vf_data->qm_aeqc_dw, 7); - if (ret) { - dev_err(dev, "failed to write QM_AEQC_DW\n"); - return ret; - } - - return 0; } static int qm_get_regs(struct hisi_qm *qm, struct acc_vf_data *vf_data) { struct device *dev = &qm->pdev->dev; + u32 eqc_addr, aeqc_addr; int ret; ret = qm_read_regs(qm, QM_VF_AEQ_INT_MASK, &vf_data->aeq_int_mask, 1); @@ -200,12 +150,28 @@ static int qm_get_regs(struct hisi_qm *qm, struct acc_vf_data *vf_data) return ret; } + qm_xqc_reg_offsets(qm, &eqc_addr, &aeqc_addr); + /* QM_EQC_DW has 7 regs */ + ret = qm_read_regs(qm, eqc_addr, vf_data->qm_eqc_dw, 7); + if (ret) { + dev_err(dev, "failed to read QM_EQC_DW\n"); + return ret; + } + + /* QM_AEQC_DW has 7 regs */ + ret = qm_read_regs(qm, aeqc_addr, vf_data->qm_aeqc_dw, 7); + if (ret) { + dev_err(dev, "failed to read QM_AEQC_DW\n"); + return ret; + } + return 0; } static int qm_set_regs(struct hisi_qm *qm, struct acc_vf_data *vf_data) { struct device *dev = &qm->pdev->dev; + u32 eqc_addr, aeqc_addr; int ret; /* Check VF state */ @@ -257,6 +223,21 @@ static int qm_set_regs(struct hisi_qm *qm, struct acc_vf_data *vf_data) return ret; } + qm_xqc_reg_offsets(qm, &eqc_addr, &aeqc_addr); + /* QM_EQC_DW has 7 regs */ + ret = qm_write_regs(qm, eqc_addr, vf_data->qm_eqc_dw, 7); + if (ret) { + dev_err(dev, "failed to write QM_EQC_DW\n"); + return ret; + } + + /* QM_AEQC_DW has 7 regs */ + ret = qm_write_regs(qm, aeqc_addr, vf_data->qm_aeqc_dw, 7); + if (ret) { + dev_err(dev, "failed to write QM_AEQC_DW\n"); + return ret; + } + return 0; } @@ -532,10 +513,6 @@ static int vf_qm_load_data(struct hisi_acc_vf_core_device *hisi_acc_vdev, return ret; } - ret = qm_set_xqc_regs(hisi_acc_vdev, vf_data); - if (ret) - return ret; - ret = hisi_qm_mb_write(qm, QM_MB_CMD_SQC_BT, qm->sqc_dma, 0, 0); if (ret) { dev_err(dev, "set sqc failed\n"); @@ -603,10 +580,6 @@ static int vf_qm_state_save(struct hisi_acc_vf_core_device *hisi_acc_vdev, vf_data->vf_qm_state = QM_READY; hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state; - ret = qm_get_xqc_regs(hisi_acc_vdev, vf_data); - if (ret) - return -EINVAL; - ret = vf_qm_read_data(vf_qm, vf_data); if (ret) return ret; @@ -1231,8 +1204,23 @@ static int hisi_acc_vf_qm_init(struct hisi_acc_vf_core_device *hisi_acc_vdev) struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm; struct hisi_qm *pf_qm = hisi_acc_vdev->pf_qm; struct pci_dev *vf_dev = vdev->pdev; + u32 val; - if (pf_qm->ver == QM_HW_V3) { + val = readl(pf_qm->io_base + QM_MIG_REGION_SEL); + if (pf_qm->ver > QM_HW_V3 && (val & QM_MIG_REGION_EN)) + hisi_acc_vdev->drv_mode = HW_ACC_MIG_PF_CTRL; + else + hisi_acc_vdev->drv_mode = HW_ACC_MIG_VF_CTRL; + + if (hisi_acc_vdev->drv_mode == HW_ACC_MIG_PF_CTRL) { + /* + * On hardware platforms greater than QM_HW_V3, the migration function + * register is placed in the BAR2 configuration region of the PF, + * and each VF device occupies 8KB of configuration space. + */ + vf_qm->io_base = pf_qm->io_base + QM_MIG_REGION_OFFSET + + hisi_acc_vdev->vf_id * QM_MIG_REGION_SIZE; + } else { /* * ACC VF dev BAR2 region consists of both functional register space * and migration control register space. For migration to work, we @@ -1257,18 +1245,9 @@ static int hisi_acc_vf_qm_init(struct hisi_acc_vf_core_device *hisi_acc_vdev) pci_resource_len(vf_dev, VFIO_PCI_BAR2_REGION_INDEX)); if (!vf_qm->io_base) return -EIO; - - vf_qm->fun_type = QM_HW_VF; - vf_qm->ver = pf_qm->ver; - } else { - /* - * In the new HW platform, the migration function register space is in BAR2 of PF, - * and each VF occupies 8KB address space. - */ - vf_qm->io_base = pf_qm->io_base + QM_MIG_REGION_OFFSET + - hisi_acc_vdev->vf_id * QM_MIG_REGION_SIZE; - vf_qm->fun_type = QM_HW_PF; } + vf_qm->fun_type = QM_HW_VF; + vf_qm->ver = pf_qm->ver; vf_qm->pdev = vf_dev; mutex_init(&vf_qm->mailbox_lock); @@ -1312,23 +1291,18 @@ static size_t hisi_acc_get_resource_len(struct vfio_pci_core_device *vdev, hisi_acc_drvdata(vdev->pdev); /* - * ACC VF dev 64KB BAR2 region consists of both functional - * register space and migration control register space, each - * uses 32KB BAR2 region, on the system with more than 64KB - * page size, even if the migration control register space - * is written by VM, it will only affects the VF. - * - * In order to support the live migration function in the - * system with a page size above 64KB, the driver needs - * to ensure that the VF region size is aligned with the - * system page size. - * - * On the new hardware platform, the live migration control register - * has been moved from VF to PF. + * On the old HW_ACC_MIG_VF_CTRL mode device, the ACC VF device + * BAR2 region encompasses both functional register space + * and migration control register space. + * only the functional region should be report to Guest. */ - if (hisi_acc_vdev->pf_qm->ver == QM_HW_V3) + if (hisi_acc_vdev->drv_mode == HW_ACC_MIG_VF_CTRL) return (pci_resource_len(vdev->pdev, index) >> 1); - + /* + * On the new HW device, the migration control register + * has been moved to the PF device BAR2 region. + * The VF device BAR2 is entirely functional register space. + */ return pci_resource_len(vdev->pdev, index); } @@ -1367,7 +1341,7 @@ static int hisi_acc_vfio_pci_mmap(struct vfio_device *core_vdev, u64 req_len, pgoff, req_start; resource_size_t end; - end = PAGE_ALIGN(hisi_acc_get_resource_len(vdev, index)); + end = hisi_acc_get_resource_len(vdev, index); req_len = vma->vm_end - vma->vm_start; pgoff = vma->vm_pgoff & ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1); @@ -1600,7 +1574,7 @@ static void hisi_acc_vfio_pci_close_device(struct vfio_device *core_vdev) hisi_acc_vf_disable_fds(hisi_acc_vdev); mutex_lock(&hisi_acc_vdev->open_mutex); hisi_acc_vdev->dev_opened = false; - if (vf_qm->ver == QM_HW_V3) + if (hisi_acc_vdev->drv_mode == HW_ACC_MIG_VF_CTRL) iounmap(vf_qm->io_base); mutex_unlock(&hisi_acc_vdev->open_mutex); vfio_pci_core_close_device(core_vdev); @@ -1691,8 +1665,10 @@ static void hisi_acc_vfio_debug_init(struct hisi_acc_vf_core_device *hisi_acc_vd } migf = kzalloc(sizeof(*migf), GFP_KERNEL); - if (!migf) + if (!migf) { + dput(vfio_dev_migration); return; + } hisi_acc_vdev->debug_migf = migf; vfio_hisi_acc = debugfs_create_dir("hisi_acc", vfio_dev_migration); @@ -1702,6 +1678,8 @@ static void hisi_acc_vfio_debug_init(struct hisi_acc_vf_core_device *hisi_acc_vd hisi_acc_vf_migf_read); debugfs_create_devm_seqfile(dev, "cmd_state", vfio_hisi_acc, hisi_acc_vf_debug_cmd); + + dput(vfio_dev_migration); } static void hisi_acc_vf_debugfs_exit(struct hisi_acc_vf_core_device *hisi_acc_vdev) diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h index 65c2a454665a4fa6eece2ba1bc8939e9e09e6f85..bd661093a5df9d8aaeb17e11c5558a04cd253864 100644 --- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h +++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h @@ -50,8 +50,10 @@ #define QM_QUE_ISO_CFG_V 0x0030 #define QM_PAGE_SIZE 0x0034 -#define QM_EQC_DW0 0X8000 -#define QM_AEQC_DW0 0X8020 +#define QM_EQC_VF_DW0 0X8000 +#define QM_AEQC_VF_DW0 0X8020 +#define QM_EQC_PF_DW0 0x1c00 +#define QM_AEQC_PF_DW0 0x1c20 #define ACC_DRV_MAJOR_VER 1 #define ACC_DRV_MINOR_VER 0 @@ -59,14 +61,24 @@ #define ACC_DEV_MAGIC_V1 0XCDCDCDCDFEEDAACC #define ACC_DEV_MAGIC_V2 0xAACCFEEDDECADEDE -#define QM_MIG_REGION_OFFSET 0x180000 -#define QM_MIG_REGION_SIZE 0x2000 +#define QM_RESET_WAIT_TIMEOUT 400 -#define QM_SUB_VERSION_ID 0x100210 -#define QM_EQC_PF_DW0 0x1c00 -#define QM_AEQC_PF_DW0 0x1c20 +#define QM_MIG_REGION_OFFSET 0x180000 +#define QM_MIG_REGION_SIZE 0x2000 + +/** + * On HW_ACC_MIG_VF_CTRL mode, the configuration domain supporting live + * migration functionality is located in the latter 32KB of the VF's BAR2. + * The Guest is only provided with the first 32KB of the VF's BAR2. + * On HW_ACC_MIG_PF_CTRL mode, the configuration domain supporting live + * migration functionality is located in the PF's BAR2, and the entire 64KB + * of the VF's BAR2 is allocated to the Guest. + */ +enum hw_drv_mode { + HW_ACC_MIG_VF_CTRL = 0, + HW_ACC_MIG_PF_CTRL, +}; -#define QM_RESET_WAIT_TIMEOUT 400 struct acc_vf_data { #define QM_MATCH_SIZE offsetofend(struct acc_vf_data, qm_rsv_state) /* QM match information */ @@ -134,6 +146,7 @@ struct hisi_acc_vf_core_device { struct pci_dev *vf_dev; struct hisi_qm *pf_qm; struct hisi_qm vf_qm; + enum hw_drv_mode drv_mode; /* * vf_qm_state represents the QM_VF_STATE register value. * It is set by Guest driver for the ACC VF dev indicating diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index efda10558b6c2a16f917cbe4d7ef5b1950d12b3a..a2c2743af50698092dd779a6fe499e7dad4696b8 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -97,6 +97,9 @@ #define QM_DEV_ALG_MAX_LEN 256 +#define QM_MIG_REGION_SEL 0x100198 +#define QM_MIG_REGION_EN BIT(0) + /* uacce mode of the driver */ #define UACCE_MODE_NOUACCE 0 /* don't use uacce */ #define UACCE_MODE_SVA 1 /* use uacce sva mode */