diff options
Diffstat (limited to 'drivers/accel/qaic')
| -rw-r--r-- | drivers/accel/qaic/mhi_controller.c | 192 | ||||
| -rw-r--r-- | drivers/accel/qaic/qaic.h | 1 | ||||
| -rw-r--r-- | drivers/accel/qaic/qaic_data.c | 22 | ||||
| -rw-r--r-- | drivers/accel/qaic/qaic_debugfs.c | 1 | ||||
| -rw-r--r-- | drivers/accel/qaic/qaic_drv.c | 48 | ||||
| -rw-r--r-- | drivers/accel/qaic/qaic_ras.c | 1 | ||||
| -rw-r--r-- | drivers/accel/qaic/qaic_ssr.c | 1 | ||||
| -rw-r--r-- | drivers/accel/qaic/qaic_timesync.c | 1 | ||||
| -rw-r--r-- | drivers/accel/qaic/sahara.c | 2 |
9 files changed, 262 insertions, 7 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_data.c b/drivers/accel/qaic/qaic_data.c index ef0351b6dc9b..ee35e13091b3 100644 --- a/drivers/accel/qaic/qaic_data.c +++ b/drivers/accel/qaic/qaic_data.c @@ -15,6 +15,7 @@ #include <linux/math64.h> #include <linux/mm.h> #include <linux/moduleparam.h> +#include <linux/overflow.h> #include <linux/scatterlist.h> #include <linux/spinlock.h> #include <linux/srcu.h> @@ -455,7 +456,12 @@ static int create_sgt(struct qaic_device *qdev, struct sg_table **sgt_out, u64 s int order; if (size) { - nr_pages = DIV_ROUND_UP(size, PAGE_SIZE); + u64 nr_pages_u64 = DIV_ROUND_UP_ULL(size, PAGE_SIZE); + + if (overflows_type(nr_pages_u64, int)) + return -E2BIG; + + nr_pages = nr_pages_u64; /* * calculate how much extra we are going to allocate, to remove * later @@ -1834,15 +1840,16 @@ int qaic_perf_stats_bo_ioctl(struct drm_device *dev, void *data, struct drm_file goto free_ent; } bo = to_qaic_bo(obj); + ret = mutex_lock_interruptible(&bo->lock); + if (ret) + goto put_obj; if (!bo->sliced) { - drm_gem_object_put(obj); ret = -EINVAL; - goto free_ent; + goto unlock_bo; } if (bo->dbc->id != args->hdr.dbc_id) { - drm_gem_object_put(obj); ret = -EINVAL; - goto free_ent; + goto unlock_bo; } /* * perf stats ioctl is called before wait ioctl is complete then @@ -1858,7 +1865,12 @@ int qaic_perf_stats_bo_ioctl(struct drm_device *dev, void *data, struct drm_file bo->perf_stats.req_received_ts), 1000); ent[i].queue_level_before = bo->perf_stats.queue_level_before; ent[i].num_queue_element = bo->total_slice_nents; +unlock_bo: + mutex_unlock(&bo->lock); +put_obj: drm_gem_object_put(obj); + if (ret) + goto free_ent; } if (copy_to_user(u64_to_user_ptr(args->data), ent, args->hdr.count * sizeof(*ent))) diff --git a/drivers/accel/qaic/qaic_debugfs.c b/drivers/accel/qaic/qaic_debugfs.c index 95c78e12dd61..909a4d774d90 100644 --- a/drivers/accel/qaic/qaic_debugfs.c +++ b/drivers/accel/qaic/qaic_debugfs.c @@ -5,6 +5,7 @@ #include <linux/debugfs.h> #include <linux/device.h> +#include <linux/device-id/mhi.h> #include <linux/fs.h> #include <linux/list.h> #include <linux/mhi.h> diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c index 0acf6cdd44f8..9e1e184efe0d 100644 --- a/drivers/accel/qaic/qaic_drv.c +++ b/drivers/accel/qaic/qaic_drv.c @@ -4,6 +4,7 @@ /* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include <linux/delay.h> +#include <linux/device-id/mhi.h> #include <linux/dma-mapping.h> #include <linux/idr.h> #include <linux/interrupt.h> @@ -39,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 @@ -77,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"); @@ -609,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; @@ -665,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); @@ -761,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, @@ -768,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), }, diff --git a/drivers/accel/qaic/qaic_ras.c b/drivers/accel/qaic/qaic_ras.c index e0205c2cda3d..236e520f708f 100644 --- a/drivers/accel/qaic/qaic_ras.c +++ b/drivers/accel/qaic/qaic_ras.c @@ -5,6 +5,7 @@ #include <asm/byteorder.h> #include <linux/device.h> +#include <linux/device-id/mhi.h> #include <linux/kernel.h> #include <linux/mhi.h> diff --git a/drivers/accel/qaic/qaic_ssr.c b/drivers/accel/qaic/qaic_ssr.c index a98928654959..418f14936f9a 100644 --- a/drivers/accel/qaic/qaic_ssr.c +++ b/drivers/accel/qaic/qaic_ssr.c @@ -8,6 +8,7 @@ #include <drm/drm_managed.h> #include <linux/devcoredump.h> #include <linux/device.h> +#include <linux/device-id/mhi.h> #include <linux/kernel.h> #include <linux/mhi.h> #include <linux/workqueue.h> diff --git a/drivers/accel/qaic/qaic_timesync.c b/drivers/accel/qaic/qaic_timesync.c index 45e5f0728ebe..b5162677ccc4 100644 --- a/drivers/accel/qaic/qaic_timesync.c +++ b/drivers/accel/qaic/qaic_timesync.c @@ -2,6 +2,7 @@ /* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include <linux/device-id/mhi.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/math64.h> diff --git a/drivers/accel/qaic/sahara.c b/drivers/accel/qaic/sahara.c index c7c0b3eb4b65..e951181e424f 100644 --- a/drivers/accel/qaic/sahara.c +++ b/drivers/accel/qaic/sahara.c @@ -3,6 +3,7 @@ /* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include <linux/devcoredump.h> +#include <linux/device-id/mhi.h> #include <linux/firmware.h> #include <linux/limits.h> #include <linux/mhi.h> @@ -880,6 +881,7 @@ static void sahara_mhi_remove(struct mhi_device *mhi_dev) cancel_work_sync(&context->fw_work); cancel_work_sync(&context->dump_work); + cancel_work_sync(&context->read_data_work); vfree(context->mem_dump); sahara_release_image(context); mhi_unprepare_from_transfer(mhi_dev); |
