accel/qaic: Add support for AI200 virtual functions

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 <thanson@qti.qualcomm.com>
Signed-off-by: Troy Hanson <thanson@qti.qualcomm.com>
Signed-off-by: Zack McKevitt <zmckevit@qti.qualcomm.com>
Signed-off-by: Youssef Samir <youssef.abdulrahman@oss.qualcomm.com>
Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
[jhugo: drop Sashiko tags from code review]
Signed-off-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Link: https://patch.msgid.link/20260831135008.1418190-1-youssef.abdulrahman@oss.qualcomm.com
This commit is contained in:
Zack McKevitt 2026-08-31 15:50:08 +02:00 committed by Jeff Hugo
parent 018e5a0219
commit c274d6aaa3
3 changed files with 238 additions and 2 deletions

View File

@ -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 */

View File

@ -35,6 +35,7 @@
enum aic_families {
FAMILY_AIC100,
FAMILY_AIC200,
FAMILY_AIC200_VF,
FAMILY_MAX,
};

View File

@ -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),
},