Register the qaic_pci_sriov_configure callback to allow VFs to be
created through AIC200's sysfs numvfs entry. Additionally, define
a new MHI family for the 5 channels supported by AIC200 VFs: NNC,
Telemetry, IPCR, Loopback, and SSR.

Co-developed-by: Troy Hanson <[email protected]>
Signed-off-by: Troy Hanson <[email protected]>
Signed-off-by: Zack McKevitt <[email protected]>
Signed-off-by: Youssef Samir <[email protected]>
---
 drivers/accel/qaic/mhi_controller.c | 192 +++++++++++++++++++++++++++-
 drivers/accel/qaic/qaic.h           |   1 +
 drivers/accel/qaic/qaic_drv.c       |  36 ++++++
 3 files changed, 227 insertions(+), 2 deletions(-)

diff --git a/drivers/accel/qaic/mhi_controller.c 
b/drivers/accel/qaic/mhi_controller.c
index 40e6d262ef21..c720b70b1e0f 100644
--- a/drivers/accel/qaic/mhi_controller.c
+++ b/drivers/accel/qaic/mhi_controller.c
@@ -23,6 +23,7 @@ MODULE_PARM_DESC(mhi_timeout_ms, "MHI controller timeout 
value");
 static const char *fw_image_paths[FAMILY_MAX] = {
        [FAMILY_AIC100] = "qcom/aic100/sbl.bin",
        [FAMILY_AIC200] = "qcom/aic200/sbl.bin",
+       [FAMILY_AIC200_VF] = NULL,
 };
 
 static const struct mhi_channel_config aic100_channels[] = {
@@ -691,6 +692,159 @@ static const struct mhi_channel_config aic200_channels[] 
= {
        },
 };
 
+static const struct mhi_channel_config aic200vf_channels[] = {
+       {
+               .name = "QAIC_LOOPBACK",
+               .num = 0,
+               .num_elements = 32,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_TO_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "QAIC_LOOPBACK",
+               .num = 1,
+               .num_elements = 32,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_FROM_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "QAIC_SSR",
+               .num = 6,
+               .num_elements = 32,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_TO_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "QAIC_SSR",
+               .num = 7,
+               .num_elements = 32,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_FROM_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "QAIC_CONTROL",
+               .num = 10,
+               .num_elements = 128,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_TO_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "QAIC_CONTROL",
+               .num = 11,
+               .num_elements = 128,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_FROM_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "QAIC_TELEMETRY",
+               .num = 16,
+               .num_elements = 32,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_TO_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "QAIC_TELEMETRY",
+               .num = 17,
+               .num_elements = 32,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_FROM_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "IPCR",
+               .num = 24,
+               .num_elements = 32,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_TO_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+       {
+               .name = "IPCR",
+               .num = 25,
+               .num_elements = 32,
+               .local_elements = 0,
+               .event_ring = 0,
+               .dir = DMA_FROM_DEVICE,
+               .ee_mask = MHI_CH_EE_AMSS,
+               .pollcfg = 0,
+               .doorbell = MHI_DB_BRST_DISABLE,
+               .lpm_notify = false,
+               .offload_channel = false,
+               .doorbell_mode_switch = false,
+               .wake_capable = false,
+       },
+};
+
 static struct mhi_event_config aic100_events[] = {
        {
                .num_elements = 32,
@@ -721,6 +875,21 @@ static struct mhi_event_config aic200_events[] = {
        },
 };
 
+static struct mhi_event_config aic200vf_events[] = {
+       {
+               .num_elements = 32,
+               .irq_moderation_ms = 0,
+               .irq = 0,
+               .channel = U32_MAX,
+               .priority = 1,
+               .mode = MHI_DB_BRST_DISABLE,
+               .data_type = MHI_ER_CTRL,
+               .hardware_event = false,
+               .client_managed = false,
+               .offload_channel = false,
+       },
+};
+
 static struct mhi_controller_config mhi_cntrl_configs[] = {
        [FAMILY_AIC100] = {
                .max_channels = 128,
@@ -744,6 +913,17 @@ static struct mhi_controller_config mhi_cntrl_configs[] = {
                .use_bounce_buf = false,
                .m2_no_db = false,
        },
+       [FAMILY_AIC200_VF] = {
+               .max_channels = 128,
+               .timeout_ms = 0, /* controlled by mhi_timeout */
+               .buf_len = 0,
+               .num_channels = ARRAY_SIZE(aic200vf_channels),
+               .ch_cfg = aic200vf_channels,
+               .num_events = ARRAY_SIZE(aic200vf_events),
+               .event_cfg = aic200vf_events,
+               .use_bounce_buf = false,
+               .m2_no_db = false,
+       },
 };
 
 static int mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, 
u32 *out)
@@ -864,11 +1044,19 @@ struct mhi_controller 
*qaic_mhi_register_controller(struct pci_dev *pci_dev, voi
 
        mhi_cntrl->fw_image = fw_image_paths[family];
 
-       if (family == FAMILY_AIC200) {
+       switch (family) {
+       case FAMILY_AIC200:
                mhi_cntrl->name = "AIC200";
                mhi_cntrl->seg_len = SZ_512K;
-       } else {
+               break;
+       case FAMILY_AIC200_VF:
+               mhi_cntrl->name = "AIC200_VF";
+               break;
+       case FAMILY_AIC100:
                mhi_cntrl->name = "AIC100";
+               break;
+       default:
+               mhi_cntrl->name = NULL;
        }
 
        /* use latest configured timeout */
diff --git a/drivers/accel/qaic/qaic.h b/drivers/accel/qaic/qaic.h
index 02ca99000e2a..889fa51da7da 100644
--- a/drivers/accel/qaic/qaic.h
+++ b/drivers/accel/qaic/qaic.h
@@ -35,6 +35,7 @@
 enum aic_families {
        FAMILY_AIC100,
        FAMILY_AIC200,
+       FAMILY_AIC200_VF,
        FAMILY_MAX,
 };
 
diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c
index 0acf6cdd44f8..cde8eb8c7a71 100644
--- a/drivers/accel/qaic/qaic_drv.c
+++ b/drivers/accel/qaic/qaic_drv.c
@@ -77,6 +77,13 @@ static const struct qaic_device_config aic200_config = {
        .dbc_bar_idx = 2,
 };
 
+static const struct qaic_device_config aic200vf_config = {
+       .family = FAMILY_AIC200_VF,
+       .bar_mask = BIT(0) | BIT(1) | BIT(2) | BIT(4),
+       .mhi_bar_idx = 1,
+       .dbc_bar_idx = 2,
+};
+
 bool datapath_polling;
 module_param(datapath_polling, bool, 0400);
 MODULE_PARM_DESC(datapath_polling, "Operate the datapath in polling mode");
@@ -761,6 +768,34 @@ static const struct dev_pm_ops qaic_pm_ops = {
        SYSTEM_SLEEP_PM_OPS(qaic_pm_suspend, qaic_pm_resume)
 };
 
+static int qaic_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+       struct qaic_device *qdev = pci_get_drvdata(pdev);
+       int ret;
+
+       /* Qaic device must be online to process VF bringup */
+       if (qdev->dev_state == QAIC_OFFLINE)
+               return -ENODEV;
+
+       if (qdev->dev_state == QAIC_BOOT)
+               return -EBUSY;
+
+       if (num_vfs == 0) {
+               pci_disable_sriov(pdev);
+               return 0;
+       }
+
+       ret = pci_enable_sriov(pdev, num_vfs);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to enable SR-IOV: %d (requested %d 
VFs, max %d)\n",
+                       ret, num_vfs, pci_sriov_get_totalvfs(pdev));
+               return ret;
+       }
+
+       dev_dbg(&pdev->dev, "Successfully enabled %d VFs\n", num_vfs);
+       return num_vfs;
+}
+
 static struct pci_driver qaic_pci_driver = {
        .name = QAIC_NAME,
        .id_table = qaic_ids,
@@ -768,6 +803,7 @@ static struct pci_driver qaic_pci_driver = {
        .remove = qaic_pci_remove,
        .shutdown = qaic_pci_shutdown,
        .err_handler = &qaic_pci_err_handler,
+       .sriov_configure = qaic_pci_sriov_configure,
        .driver = {
                .pm = pm_sleep_ptr(&qaic_pm_ops),
        },
-- 
2.43.0

Reply via email to