From: Zack McKevitt <[email protected]>

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.

Reported-by: Sashiko <[email protected]>
Link: https://lore.kernel.org/all/[email protected]/
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]>
---
Changes in v2:
- Add the missing AIC200VF PCI ID to qaic_ids
- Handle teardown of VF in qaic_pci_sriov_configure() and qaic_pci_remove()
- Take dev_lock in qaic_pci_sriov_configure() before reading qdev->dev_state
- Link to v1: 
https://lore.kernel.org/all/[email protected]/
---
 drivers/accel/qaic/mhi_controller.c | 192 +++++++++++++++++++++++++++-
 drivers/accel/qaic/qaic.h           |   1 +
 drivers/accel/qaic/qaic_drv.c       |  47 +++++++
 3 files changed, 238 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 c1bb6db78d12..9e1e184efe0d 100644
--- a/drivers/accel/qaic/qaic_drv.c
+++ b/drivers/accel/qaic/qaic_drv.c
@@ -40,6 +40,7 @@ MODULE_IMPORT_NS("DMA_BUF");
 #define PCI_DEVICE_ID_QCOM_AIC080      0xa080
 #define PCI_DEVICE_ID_QCOM_AIC100      0xa100
 #define PCI_DEVICE_ID_QCOM_AIC200      0xa110
+#define PCI_DEVICE_ID_QCOM_AIC200VF    0xa111
 #define QAIC_NAME                      "qaic"
 #define QAIC_DESC                      "Qualcomm Cloud AI Accelerators"
 #define CNTL_MAJOR                     5
@@ -78,6 +79,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");
@@ -610,6 +618,8 @@ static void qaic_pci_remove(struct pci_dev *pdev)
 {
        struct qaic_device *qdev = pci_get_drvdata(pdev);
 
+       pci_disable_sriov(pdev);
+
        if (!qdev)
                return;
 
@@ -666,6 +676,7 @@ static const struct pci_device_id qaic_ids[] = {
        { PCI_DEVICE_DATA(QCOM, AIC080, (kernel_ulong_t)&aic080_config), },
        { PCI_DEVICE_DATA(QCOM, AIC100, (kernel_ulong_t)&aic100_config), },
        { PCI_DEVICE_DATA(QCOM, AIC200, (kernel_ulong_t)&aic200_config), },
+       { PCI_DEVICE_DATA(QCOM, AIC200VF, (kernel_ulong_t)&aic200vf_config), },
        { }
 };
 MODULE_DEVICE_TABLE(pci, qaic_ids);
@@ -762,6 +773,41 @@ 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 rcu_id;
+       int ret;
+
+       if (num_vfs == 0) {
+               pci_disable_sriov(pdev);
+               return 0;
+       }
+
+       rcu_id = srcu_read_lock(&qdev->dev_lock);
+       /* Qaic device must be online to process VF bringup */
+       if (qdev->dev_state == QAIC_OFFLINE) {
+               ret = -ENODEV;
+               goto unlock_dev_srcu;
+       }
+       if (qdev->dev_state == QAIC_BOOT) {
+               ret = -EBUSY;
+               goto unlock_dev_srcu;
+       }
+
+       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));
+               goto unlock_dev_srcu;
+       }
+
+       dev_dbg(&pdev->dev, "Successfully enabled %d VFs\n", num_vfs);
+unlock_dev_srcu:
+       srcu_read_unlock(&qdev->dev_lock, rcu_id);
+       return ret ?: num_vfs;
+}
+
 static struct pci_driver qaic_pci_driver = {
        .name = QAIC_NAME,
        .id_table = qaic_ids,
@@ -769,6 +815,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