diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:22 +0000 |
commit | b20732900e4636a467c0183a47f7396700f5f743 (patch) | |
tree | 42f079ff82e701ebcb76829974b4caca3e5b6798 /drivers/accel/ivpu | |
parent | Adding upstream version 6.8.12. (diff) | |
download | linux-b20732900e4636a467c0183a47f7396700f5f743.tar.xz linux-b20732900e4636a467c0183a47f7396700f5f743.zip |
Adding upstream version 6.9.7.upstream/6.9.7
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/accel/ivpu')
-rw-r--r-- | drivers/accel/ivpu/ivpu_debugfs.c | 32 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_drv.c | 12 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_drv.h | 7 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_fw.c | 49 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_fw_log.c | 6 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_gem.c | 70 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_gem.h | 6 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_hw_37xx.c | 10 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_hw_40xx.c | 10 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_ipc.c | 12 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_job.c | 20 | ||||
-rw-r--r-- | drivers/accel/ivpu/ivpu_pm.c | 12 | ||||
-rw-r--r-- | drivers/accel/ivpu/vpu_boot_api.h | 46 | ||||
-rw-r--r-- | drivers/accel/ivpu/vpu_jsm_api.h | 32 |
14 files changed, 195 insertions, 129 deletions
diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c index 7cb962e214..d09d29775b 100644 --- a/drivers/accel/ivpu/ivpu_debugfs.c +++ b/drivers/accel/ivpu/ivpu_debugfs.c @@ -287,22 +287,6 @@ static const struct file_operations fw_trace_level_fops = { }; static ssize_t -ivpu_reset_engine_fn(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) -{ - struct ivpu_device *vdev = file->private_data; - - if (!size) - return -EINVAL; - - if (ivpu_jsm_reset_engine(vdev, DRM_IVPU_ENGINE_COMPUTE)) - return -ENODEV; - if (ivpu_jsm_reset_engine(vdev, DRM_IVPU_ENGINE_COPY)) - return -ENODEV; - - return size; -} - -static ssize_t ivpu_force_recovery_fn(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) { struct ivpu_device *vdev = file->private_data; @@ -327,6 +311,22 @@ static const struct file_operations ivpu_force_recovery_fops = { .write = ivpu_force_recovery_fn, }; +static ssize_t +ivpu_reset_engine_fn(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) +{ + struct ivpu_device *vdev = file->private_data; + + if (!size) + return -EINVAL; + + if (ivpu_jsm_reset_engine(vdev, DRM_IVPU_ENGINE_COMPUTE)) + return -ENODEV; + if (ivpu_jsm_reset_engine(vdev, DRM_IVPU_ENGINE_COPY)) + return -ENODEV; + + return size; +} + static const struct file_operations ivpu_reset_engine_fops = { .owner = THIS_MODULE, .open = simple_open, diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index bad1ccc81a..51d3f1a55d 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -45,11 +45,11 @@ MODULE_PARM_DESC(test_mode, "Test mode mask. See IVPU_TEST_MODE_* macros."); u8 ivpu_pll_min_ratio; module_param_named(pll_min_ratio, ivpu_pll_min_ratio, byte, 0644); -MODULE_PARM_DESC(pll_min_ratio, "Minimum PLL ratio used to set VPU frequency"); +MODULE_PARM_DESC(pll_min_ratio, "Minimum PLL ratio used to set NPU frequency"); u8 ivpu_pll_max_ratio = U8_MAX; module_param_named(pll_max_ratio, ivpu_pll_max_ratio, byte, 0644); -MODULE_PARM_DESC(pll_max_ratio, "Maximum PLL ratio used to set VPU frequency"); +MODULE_PARM_DESC(pll_max_ratio, "Maximum PLL ratio used to set NPU frequency"); bool ivpu_disable_mmu_cont_pages; module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0644); @@ -312,13 +312,13 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev) ivpu_ipc_consumer_del(vdev, &cons); if (!ret && ipc_hdr.data_addr != IVPU_IPC_BOOT_MSG_DATA_ADDR) { - ivpu_err(vdev, "Invalid VPU ready message: 0x%x\n", + ivpu_err(vdev, "Invalid NPU ready message: 0x%x\n", ipc_hdr.data_addr); return -EIO; } if (!ret) - ivpu_dbg(vdev, PM, "VPU ready message received successfully\n"); + ivpu_dbg(vdev, PM, "NPU ready message received successfully\n"); return ret; } @@ -519,6 +519,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev) atomic64_set(&vdev->unique_id_counter, 0); xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1); + xa_init_flags(&vdev->db_xa, XA_FLAGS_ALLOC1); lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key); INIT_LIST_HEAD(&vdev->bo_list); @@ -590,6 +591,7 @@ err_mmu_gctx_fini: err_shutdown: ivpu_shutdown(vdev); err_xa_destroy: + xa_destroy(&vdev->db_xa); xa_destroy(&vdev->submitted_jobs_xa); xa_destroy(&vdev->context_xa); return ret; @@ -624,6 +626,8 @@ static void ivpu_dev_fini(struct ivpu_device *vdev) ivpu_mmu_reserved_context_fini(vdev); ivpu_mmu_global_context_fini(vdev); + drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->db_xa)); + xa_destroy(&vdev->db_xa); drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa)); xa_destroy(&vdev->submitted_jobs_xa); drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->context_xa)); diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index e7a9e84994..bb4374d0ea 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -36,6 +36,9 @@ #define IVPU_USER_CONTEXT_MIN_SSID 2 #define IVPU_USER_CONTEXT_MAX_SSID (IVPU_USER_CONTEXT_MIN_SSID + 63) +#define IVPU_MIN_DB 1 +#define IVPU_MAX_DB 255 + #define IVPU_NUM_ENGINES 2 #define IVPU_PLATFORM_SILICON 0 @@ -118,6 +121,8 @@ struct ivpu_device { struct xarray context_xa; struct xa_limit context_xa_limit; + struct xarray db_xa; + struct mutex bo_list_lock; /* Protects bo_list */ struct list_head bo_list; @@ -188,7 +193,7 @@ static inline int ivpu_hw_gen(struct ivpu_device *vdev) case PCI_DEVICE_ID_LNL: return IVPU_HW_40XX; default: - ivpu_err(vdev, "Unknown VPU device\n"); + ivpu_err(vdev, "Unknown NPU device\n"); return 0; } } diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 5fa8bd4603..1457300828 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -46,15 +46,13 @@ static char *ivpu_firmware; module_param_named_unsafe(firmware, ivpu_firmware, charp, 0644); -MODULE_PARM_DESC(firmware, "VPU firmware binary in /lib/firmware/.."); +MODULE_PARM_DESC(firmware, "NPU firmware binary in /lib/firmware/.."); -/* TODO: Remove mtl_vpu.bin from names after transition to generation based FW names */ static struct { int gen; const char *name; } fw_names[] = { { IVPU_HW_37XX, "vpu_37xx.bin" }, - { IVPU_HW_37XX, "mtl_vpu.bin" }, { IVPU_HW_37XX, "intel/vpu/vpu_37xx_v0.0.bin" }, { IVPU_HW_40XX, "vpu_40xx.bin" }, { IVPU_HW_40XX, "intel/vpu/vpu_40xx_v0.0.bin" }, @@ -250,6 +248,7 @@ static int ivpu_fw_update_global_range(struct ivpu_device *vdev) static int ivpu_fw_mem_init(struct ivpu_device *vdev) { struct ivpu_fw_info *fw = vdev->fw; + struct ivpu_addr_range fw_range; int log_verb_size; int ret; @@ -257,16 +256,19 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) if (ret) return ret; - fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size, DRM_IVPU_BO_WC); + fw_range.start = fw->runtime_addr; + fw_range.end = fw->runtime_addr + fw->runtime_size; + fw->mem = ivpu_bo_create(vdev, &vdev->gctx, &fw_range, fw->runtime_size, + DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE); if (!fw->mem) { - ivpu_err(vdev, "Failed to allocate firmware runtime memory\n"); + ivpu_err(vdev, "Failed to create firmware runtime memory buffer\n"); return -ENOMEM; } - fw->mem_log_crit = ivpu_bo_alloc_internal(vdev, 0, IVPU_FW_CRITICAL_BUFFER_SIZE, - DRM_IVPU_BO_CACHED); + fw->mem_log_crit = ivpu_bo_create_global(vdev, IVPU_FW_CRITICAL_BUFFER_SIZE, + DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE); if (!fw->mem_log_crit) { - ivpu_err(vdev, "Failed to allocate critical log buffer\n"); + ivpu_err(vdev, "Failed to create critical log buffer\n"); ret = -ENOMEM; goto err_free_fw_mem; } @@ -276,18 +278,19 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) else log_verb_size = IVPU_FW_VERBOSE_BUFFER_SMALL_SIZE; - fw->mem_log_verb = ivpu_bo_alloc_internal(vdev, 0, log_verb_size, DRM_IVPU_BO_CACHED); + fw->mem_log_verb = ivpu_bo_create_global(vdev, log_verb_size, + DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE); if (!fw->mem_log_verb) { - ivpu_err(vdev, "Failed to allocate verbose log buffer\n"); + ivpu_err(vdev, "Failed to create verbose log buffer\n"); ret = -ENOMEM; goto err_free_log_crit; } if (fw->shave_nn_size) { - fw->mem_shave_nn = ivpu_bo_alloc_internal(vdev, vdev->hw->ranges.shave.start, - fw->shave_nn_size, DRM_IVPU_BO_WC); + fw->mem_shave_nn = ivpu_bo_create(vdev, &vdev->gctx, &vdev->hw->ranges.shave, + fw->shave_nn_size, DRM_IVPU_BO_WC); if (!fw->mem_shave_nn) { - ivpu_err(vdev, "Failed to allocate shavenn buffer\n"); + ivpu_err(vdev, "Failed to create shavenn buffer\n"); ret = -ENOMEM; goto err_free_log_verb; } @@ -296,11 +299,11 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) return 0; err_free_log_verb: - ivpu_bo_free_internal(fw->mem_log_verb); + ivpu_bo_free(fw->mem_log_verb); err_free_log_crit: - ivpu_bo_free_internal(fw->mem_log_crit); + ivpu_bo_free(fw->mem_log_crit); err_free_fw_mem: - ivpu_bo_free_internal(fw->mem); + ivpu_bo_free(fw->mem); return ret; } @@ -309,13 +312,13 @@ static void ivpu_fw_mem_fini(struct ivpu_device *vdev) struct ivpu_fw_info *fw = vdev->fw; if (fw->mem_shave_nn) { - ivpu_bo_free_internal(fw->mem_shave_nn); + ivpu_bo_free(fw->mem_shave_nn); fw->mem_shave_nn = NULL; } - ivpu_bo_free_internal(fw->mem_log_verb); - ivpu_bo_free_internal(fw->mem_log_crit); - ivpu_bo_free_internal(fw->mem); + ivpu_bo_free(fw->mem_log_verb); + ivpu_bo_free(fw->mem_log_crit); + ivpu_bo_free(fw->mem); fw->mem_log_verb = NULL; fw->mem_log_crit = NULL; @@ -469,6 +472,8 @@ static void ivpu_fw_boot_params_print(struct ivpu_device *vdev, struct vpu_boot_ boot_params->d0i3_residency_time_us); ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_entry_vpu_ts = %llu\n", boot_params->d0i3_entry_vpu_ts); + ivpu_dbg(vdev, FW_BOOT, "boot_params.system_time_us = %llu\n", + boot_params->system_time_us); } void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *boot_params) @@ -480,11 +485,14 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params boot_params->d0i3_residency_time_us = ktime_us_delta(ktime_get_boottime(), vdev->hw->d0i3_entry_host_ts); boot_params->d0i3_entry_vpu_ts = vdev->hw->d0i3_entry_vpu_ts; + boot_params->system_time_us = ktime_to_us(ktime_get_real()); ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_residency_time_us = %lld\n", boot_params->d0i3_residency_time_us); ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_entry_vpu_ts = %llu\n", boot_params->d0i3_entry_vpu_ts); + ivpu_dbg(vdev, FW_BOOT, "boot_params.system_time_us = %llu\n", + boot_params->system_time_us); boot_params->save_restore_ret_address = 0; vdev->pm->is_warmboot = true; @@ -562,6 +570,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params boot_params->d0i3_residency_time_us = 0; boot_params->d0i3_entry_vpu_ts = 0; + boot_params->system_time_us = ktime_to_us(ktime_get_real()); wmb(); /* Flush WC buffers after writing bootparams */ ivpu_fw_boot_params_print(vdev, boot_params); diff --git a/drivers/accel/ivpu/ivpu_fw_log.c b/drivers/accel/ivpu/ivpu_fw_log.c index f6770f5e82..ef0adb5e0f 100644 --- a/drivers/accel/ivpu/ivpu_fw_log.c +++ b/drivers/accel/ivpu/ivpu_fw_log.c @@ -20,7 +20,7 @@ unsigned int ivpu_log_level = IVPU_FW_LOG_ERROR; module_param(ivpu_log_level, uint, 0444); MODULE_PARM_DESC(ivpu_log_level, - "VPU firmware default trace level: debug=" __stringify(IVPU_FW_LOG_DEBUG) + "NPU firmware default trace level: debug=" __stringify(IVPU_FW_LOG_DEBUG) " info=" __stringify(IVPU_FW_LOG_INFO) " warn=" __stringify(IVPU_FW_LOG_WARN) " error=" __stringify(IVPU_FW_LOG_ERROR) @@ -121,11 +121,11 @@ void ivpu_fw_log_print(struct ivpu_device *vdev, bool only_new_msgs, struct drm_ u32 next = 0; while (fw_log_ptr(vdev, vdev->fw->mem_log_crit, &next, &log_header) == 0) - fw_log_print_buffer(vdev, log_header, "VPU critical", only_new_msgs, p); + fw_log_print_buffer(vdev, log_header, "NPU critical", only_new_msgs, p); next = 0; while (fw_log_ptr(vdev, vdev->fw->mem_log_verb, &next, &log_header) == 0) - fw_log_print_buffer(vdev, log_header, "VPU verbose", only_new_msgs, p); + fw_log_print_buffer(vdev, log_header, "NPU verbose", only_new_msgs, p); } void ivpu_fw_log_clear(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c index e9ddbe9f50..1b409dbd33 100644 --- a/drivers/accel/ivpu/ivpu_gem.c +++ b/drivers/accel/ivpu/ivpu_gem.c @@ -172,8 +172,7 @@ struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t siz return &bo->base.base; } -static struct ivpu_bo * -ivpu_bo_create(struct ivpu_device *vdev, u64 size, u32 flags) +static struct ivpu_bo *ivpu_bo_alloc(struct ivpu_device *vdev, u64 size, u32 flags) { struct drm_gem_shmem_object *shmem; struct ivpu_bo *bo; @@ -201,7 +200,7 @@ ivpu_bo_create(struct ivpu_device *vdev, u64 size, u32 flags) return bo; } -static int ivpu_bo_open(struct drm_gem_object *obj, struct drm_file *file) +static int ivpu_gem_bo_open(struct drm_gem_object *obj, struct drm_file *file) { struct ivpu_file_priv *file_priv = file->driver_priv; struct ivpu_device *vdev = file_priv->vdev; @@ -224,7 +223,7 @@ static int ivpu_bo_open(struct drm_gem_object *obj, struct drm_file *file) return ivpu_bo_alloc_vpu_addr(bo, &file_priv->ctx, range); } -static void ivpu_bo_free(struct drm_gem_object *obj) +static void ivpu_gem_bo_free(struct drm_gem_object *obj) { struct ivpu_device *vdev = to_ivpu_device(obj->dev); struct ivpu_bo *bo = to_ivpu_bo(obj); @@ -245,8 +244,8 @@ static void ivpu_bo_free(struct drm_gem_object *obj) } static const struct drm_gem_object_funcs ivpu_gem_funcs = { - .free = ivpu_bo_free, - .open = ivpu_bo_open, + .free = ivpu_gem_bo_free, + .open = ivpu_gem_bo_open, .print_info = drm_gem_shmem_object_print_info, .pin = drm_gem_shmem_object_pin, .unpin = drm_gem_shmem_object_unpin, @@ -272,9 +271,9 @@ int ivpu_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fi if (size == 0) return -EINVAL; - bo = ivpu_bo_create(vdev, size, args->flags); + bo = ivpu_bo_alloc(vdev, size, args->flags); if (IS_ERR(bo)) { - ivpu_err(vdev, "Failed to create BO: %pe (ctx %u size %llu flags 0x%x)", + ivpu_err(vdev, "Failed to allocate BO: %pe (ctx %u size %llu flags 0x%x)", bo, file_priv->ctx.id, args->size, args->flags); return PTR_ERR(bo); } @@ -289,33 +288,28 @@ int ivpu_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fi } struct ivpu_bo * -ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 flags) +ivpu_bo_create(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, + struct ivpu_addr_range *range, u64 size, u32 flags) { - const struct ivpu_addr_range *range; - struct ivpu_addr_range fixed_range; struct iosys_map map; struct ivpu_bo *bo; int ret; - drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(vpu_addr)); - drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(size)); + if (drm_WARN_ON(&vdev->drm, !range)) + return NULL; - if (vpu_addr) { - fixed_range.start = vpu_addr; - fixed_range.end = vpu_addr + size; - range = &fixed_range; - } else { - range = &vdev->hw->ranges.global; - } + drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(range->start)); + drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(range->end)); + drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(size)); - bo = ivpu_bo_create(vdev, size, flags); + bo = ivpu_bo_alloc(vdev, size, flags); if (IS_ERR(bo)) { - ivpu_err(vdev, "Failed to create BO: %pe (vpu_addr 0x%llx size %llu flags 0x%x)", - bo, vpu_addr, size, flags); + ivpu_err(vdev, "Failed to allocate BO: %pe (vpu_addr 0x%llx size %llu flags 0x%x)", + bo, range->start, size, flags); return NULL; } - ret = ivpu_bo_alloc_vpu_addr(bo, &vdev->gctx, range); + ret = ivpu_bo_alloc_vpu_addr(bo, ctx, range); if (ret) goto err_put; @@ -323,11 +317,14 @@ ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 fla if (ret) goto err_put; - dma_resv_lock(bo->base.base.resv, NULL); - ret = drm_gem_shmem_vmap(&bo->base, &map); - dma_resv_unlock(bo->base.base.resv); - if (ret) - goto err_put; + if (flags & DRM_IVPU_BO_MAPPABLE) { + dma_resv_lock(bo->base.base.resv, NULL); + ret = drm_gem_shmem_vmap(&bo->base, &map); + dma_resv_unlock(bo->base.base.resv); + + if (ret) + goto err_put; + } return bo; @@ -336,13 +333,20 @@ err_put: return NULL; } -void ivpu_bo_free_internal(struct ivpu_bo *bo) +struct ivpu_bo *ivpu_bo_create_global(struct ivpu_device *vdev, u64 size, u32 flags) +{ + return ivpu_bo_create(vdev, &vdev->gctx, &vdev->hw->ranges.global, size, flags); +} + +void ivpu_bo_free(struct ivpu_bo *bo) { struct iosys_map map = IOSYS_MAP_INIT_VADDR(bo->base.vaddr); - dma_resv_lock(bo->base.base.resv, NULL); - drm_gem_shmem_vunmap(&bo->base, &map); - dma_resv_unlock(bo->base.base.resv); + if (bo->flags & DRM_IVPU_BO_MAPPABLE) { + dma_resv_lock(bo->base.base.resv, NULL); + drm_gem_shmem_vunmap(&bo->base, &map); + dma_resv_unlock(bo->base.base.resv); + } drm_gem_object_put(&bo->base.base); } diff --git a/drivers/accel/ivpu/ivpu_gem.h b/drivers/accel/ivpu/ivpu_gem.h index a8559211c7..fb7117c13e 100644 --- a/drivers/accel/ivpu/ivpu_gem.h +++ b/drivers/accel/ivpu/ivpu_gem.h @@ -28,8 +28,10 @@ int ivpu_bo_pin(struct ivpu_bo *bo); void ivpu_bo_unbind_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx); struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t size); -struct ivpu_bo *ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 flags); -void ivpu_bo_free_internal(struct ivpu_bo *bo); +struct ivpu_bo *ivpu_bo_create(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, + struct ivpu_addr_range *range, u64 size, u32 flags); +struct ivpu_bo *ivpu_bo_create_global(struct ivpu_device *vdev, u64 size, u32 flags); +void ivpu_bo_free(struct ivpu_bo *bo); int ivpu_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file); int ivpu_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file); diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index 5e392b6823..bd25e2d9fb 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -13,7 +13,7 @@ #include "ivpu_pm.h" #define TILE_FUSE_ENABLE_BOTH 0x0 -#define TILE_SKU_BOTH_MTL 0x3630 +#define TILE_SKU_BOTH 0x3630 /* Work point configuration values */ #define CONFIG_1_TILE 0x01 @@ -226,7 +226,7 @@ static int ivpu_pll_drive(struct ivpu_device *vdev, bool enable) ret = ivpu_hw_37xx_wait_for_vpuip_bar(vdev); if (ret) { - ivpu_err(vdev, "Timed out waiting for VPUIP bar\n"); + ivpu_err(vdev, "Timed out waiting for NPU IP bar\n"); return ret; } } @@ -587,7 +587,7 @@ static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev) struct ivpu_hw_info *hw = vdev->hw; hw->tile_fuse = TILE_FUSE_ENABLE_BOTH; - hw->sku = TILE_SKU_BOTH_MTL; + hw->sku = TILE_SKU_BOTH; hw->config = WP_CONFIG_2_TILE_4_3_RATIO; ivpu_pll_init_frequency_ratios(vdev); @@ -760,10 +760,10 @@ static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev) ivpu_hw_37xx_save_d0i3_entry_timestamp(vdev); if (!ivpu_hw_37xx_is_idle(vdev)) - ivpu_warn(vdev, "VPU not idle during power down\n"); + ivpu_warn(vdev, "NPU not idle during power down\n"); if (ivpu_hw_37xx_reset(vdev)) { - ivpu_err(vdev, "Failed to reset VPU\n"); + ivpu_err(vdev, "Failed to reset NPU\n"); ret = -EIO; } diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c index 0be353ad87..b0b88d4c89 100644 --- a/drivers/accel/ivpu/ivpu_hw_40xx.c +++ b/drivers/accel/ivpu/ivpu_hw_40xx.c @@ -80,11 +80,11 @@ static char *ivpu_platform_to_str(u32 platform) { switch (platform) { case IVPU_PLATFORM_SILICON: - return "IVPU_PLATFORM_SILICON"; + return "SILICON"; case IVPU_PLATFORM_SIMICS: - return "IVPU_PLATFORM_SIMICS"; + return "SIMICS"; case IVPU_PLATFORM_FPGA: - return "IVPU_PLATFORM_FPGA"; + return "FPGA"; default: return "Invalid platform"; } @@ -768,7 +768,7 @@ static int ivpu_hw_40xx_reset(struct ivpu_device *vdev) int ret = 0; if (ivpu_hw_40xx_ip_reset(vdev)) { - ivpu_err(vdev, "Failed to reset VPU IP\n"); + ivpu_err(vdev, "Failed to reset NPU IP\n"); ret = -EIO; } @@ -926,7 +926,7 @@ static int ivpu_hw_40xx_power_down(struct ivpu_device *vdev) ivpu_hw_40xx_save_d0i3_entry_timestamp(vdev); if (!ivpu_hw_40xx_is_idle(vdev) && ivpu_hw_40xx_ip_reset(vdev)) - ivpu_warn(vdev, "Failed to reset the VPU\n"); + ivpu_warn(vdev, "Failed to reset the NPU\n"); if (ivpu_pll_disable(vdev)) { ivpu_err(vdev, "Failed to disable PLL\n"); diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index f4c5392483..56ff067f63 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -58,8 +58,8 @@ static void ivpu_ipc_mem_fini(struct ivpu_device *vdev) { struct ivpu_ipc_info *ipc = vdev->ipc; - ivpu_bo_free_internal(ipc->mem_rx); - ivpu_bo_free_internal(ipc->mem_tx); + ivpu_bo_free(ipc->mem_rx); + ivpu_bo_free(ipc->mem_tx); } static int @@ -471,13 +471,13 @@ int ivpu_ipc_init(struct ivpu_device *vdev) struct ivpu_ipc_info *ipc = vdev->ipc; int ret; - ipc->mem_tx = ivpu_bo_alloc_internal(vdev, 0, SZ_16K, DRM_IVPU_BO_WC); + ipc->mem_tx = ivpu_bo_create_global(vdev, SZ_16K, DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE); if (!ipc->mem_tx) { ivpu_err(vdev, "Failed to allocate mem_tx\n"); return -ENOMEM; } - ipc->mem_rx = ivpu_bo_alloc_internal(vdev, 0, SZ_16K, DRM_IVPU_BO_WC); + ipc->mem_rx = ivpu_bo_create_global(vdev, SZ_16K, DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE); if (!ipc->mem_rx) { ivpu_err(vdev, "Failed to allocate mem_rx\n"); ret = -ENOMEM; @@ -510,9 +510,9 @@ int ivpu_ipc_init(struct ivpu_device *vdev) return 0; err_free_rx: - ivpu_bo_free_internal(ipc->mem_rx); + ivpu_bo_free(ipc->mem_rx); err_free_tx: - ivpu_bo_free_internal(ipc->mem_tx); + ivpu_bo_free(ipc->mem_tx); return ret; } diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index e70cfb8593..a49bc9105e 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -30,19 +30,26 @@ static void ivpu_cmdq_ring_db(struct ivpu_device *vdev, struct ivpu_cmdq *cmdq) static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv, u16 engine) { + struct xa_limit db_xa_limit = {.max = IVPU_MAX_DB, .min = IVPU_MIN_DB}; struct ivpu_device *vdev = file_priv->vdev; struct vpu_job_queue_header *jobq_header; struct ivpu_cmdq *cmdq; + int ret; cmdq = kzalloc(sizeof(*cmdq), GFP_KERNEL); if (!cmdq) return NULL; - cmdq->mem = ivpu_bo_alloc_internal(vdev, 0, SZ_4K, DRM_IVPU_BO_WC); + ret = xa_alloc(&vdev->db_xa, &cmdq->db_id, NULL, db_xa_limit, GFP_KERNEL); + if (ret) { + ivpu_err(vdev, "Failed to allocate doorbell id: %d\n", ret); + goto err_free_cmdq; + } + + cmdq->mem = ivpu_bo_create_global(vdev, SZ_4K, DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE); if (!cmdq->mem) - goto cmdq_free; + goto err_erase_xa; - cmdq->db_id = file_priv->ctx.id + engine * ivpu_get_context_count(vdev); cmdq->entry_count = (u32)((ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header)) / sizeof(struct vpu_job_queue_entry)); @@ -55,7 +62,9 @@ static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv, u16 e return cmdq; -cmdq_free: +err_erase_xa: + xa_erase(&vdev->db_xa, cmdq->db_id); +err_free_cmdq: kfree(cmdq); return NULL; } @@ -65,7 +74,8 @@ static void ivpu_cmdq_free(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *c if (!cmdq) return; - ivpu_bo_free_internal(cmdq->mem); + ivpu_bo_free(cmdq->mem); + xa_erase(&file_priv->vdev->db_xa, cmdq->db_id); kfree(cmdq); } diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index 64618fc2ce..4f5ea46673 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -22,7 +22,7 @@ static bool ivpu_disable_recovery; module_param_named_unsafe(disable_recovery, ivpu_disable_recovery, bool, 0644); -MODULE_PARM_DESC(disable_recovery, "Disables recovery when VPU hang is detected"); +MODULE_PARM_DESC(disable_recovery, "Disables recovery when NPU hang is detected"); static unsigned long ivpu_tdr_timeout_ms; module_param_named(tdr_timeout_ms, ivpu_tdr_timeout_ms, ulong, 0644); @@ -116,11 +116,11 @@ static void ivpu_pm_recovery_work(struct work_struct *work) char *evt[2] = {"IVPU_PM_EVENT=IVPU_RECOVER", NULL}; int ret; - ivpu_err(vdev, "Recovering the VPU (reset #%d)\n", atomic_read(&vdev->pm->reset_counter)); + ivpu_err(vdev, "Recovering the NPU (reset #%d)\n", atomic_read(&vdev->pm->reset_counter)); ret = pm_runtime_resume_and_get(vdev->drm.dev); if (ret) - ivpu_err(vdev, "Failed to resume VPU: %d\n", ret); + ivpu_err(vdev, "Failed to resume NPU: %d\n", ret); ivpu_fw_log_dump(vdev); @@ -258,10 +258,10 @@ int ivpu_pm_runtime_suspend_cb(struct device *dev) ret = ivpu_suspend(vdev); if (ret) - ivpu_err(vdev, "Failed to set suspend VPU: %d\n", ret); + ivpu_err(vdev, "Failed to suspend NPU: %d\n", ret); if (!hw_is_idle) { - ivpu_err(vdev, "VPU failed to enter idle, force suspended.\n"); + ivpu_err(vdev, "NPU failed to enter idle, force suspended.\n"); ivpu_fw_log_dump(vdev); ivpu_pm_prepare_cold_boot(vdev); } else { @@ -307,7 +307,7 @@ int ivpu_rpm_get_if_active(struct ivpu_device *vdev) { int ret; - ret = pm_runtime_get_if_active(vdev->drm.dev, false); + ret = pm_runtime_get_if_in_use(vdev->drm.dev); drm_WARN_ON(&vdev->drm, ret < 0); return ret; diff --git a/drivers/accel/ivpu/vpu_boot_api.h b/drivers/accel/ivpu/vpu_boot_api.h index 04c9542585..87cac7bc73 100644 --- a/drivers/accel/ivpu/vpu_boot_api.h +++ b/drivers/accel/ivpu/vpu_boot_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: MIT */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (c) 2020-2023, Intel Corporation. */ #ifndef VPU_BOOT_API_H @@ -27,12 +27,12 @@ * Minor version changes when API backward compatibility is preserved. * Resets to 0 if Major version is incremented. */ -#define VPU_BOOT_API_VER_MINOR 20 +#define VPU_BOOT_API_VER_MINOR 22 /* * API header changed (field names, documentation, formatting) but API itself has not been changed */ -#define VPU_BOOT_API_VER_PATCH 4 +#define VPU_BOOT_API_VER_PATCH 0 /* * Index in the API version table @@ -41,7 +41,7 @@ #define VPU_BOOT_API_VER_INDEX 0 /* ------------ FW API version information end ---------------------*/ -#pragma pack(push, 1) +#pragma pack(push, 4) /* * Firmware image header format @@ -66,9 +66,17 @@ struct vpu_firmware_header { /* Size of memory require for firmware execution */ u32 runtime_size; u32 shave_nn_fw_size; - /* Size of primary preemption buffer. */ + /* + * Size of primary preemption buffer, assuming a 2-job submission queue. + * NOTE: host driver is expected to adapt size accordingly to actual + * submission queue size and device capabilities. + */ u32 preemption_buffer_1_size; - /* Size of secondary preemption buffer. */ + /* + * Size of secondary preemption buffer, assuming a 2-job submission queue. + * NOTE: host driver is expected to adapt size accordingly to actual + * submission queue size and device capabilities. + */ u32 preemption_buffer_2_size; /* Space reserved for future preemption-related fields. */ u32 preemption_reserved[6]; @@ -181,10 +189,10 @@ struct vpu_warm_boot_section { #define VPU_PRESENT_CALL_PERIOD_MS_MAX 10000 /** - * Macros to enable various operation modes within the VPU. + * Macros to enable various power profiles within the NPU. * To be defined as part of 32 bit mask. */ -#define VPU_OP_MODE_SURVIVABILITY 0x1 +#define POWER_PROFILE_SURVIVABILITY 0x1 struct vpu_boot_params { u32 magic; @@ -317,7 +325,15 @@ struct vpu_boot_params { u64 d0i3_residency_time_us; /* Value of VPU perf counter at the time of entering D0i3 state . */ u64 d0i3_entry_vpu_ts; - u32 pad4[20]; + /* + * The system time of the host operating system in microseconds. + * E.g the number of microseconds since 1st of January 1970, or whatever date the + * host operating system uses to maintain system time. + * This value will be used to track system time on the VPU. + * The KMD is required to update this value on every VPU reset. + */ + u64 system_time_us; + u32 pad4[18]; /* Warm boot information: 0x400 - 0x43F */ u32 warm_boot_sections_count; u32 warm_boot_start_address_reference; @@ -344,10 +360,14 @@ struct vpu_boot_params { u32 vpu_focus_present_timer_ms; /* VPU ECC Signaling */ u32 vpu_uses_ecc_mca_signal; - /* Values defined by VPU_OP_MODE* macros */ - u32 vpu_operation_mode; - /* Unused/reserved: 0x480 - 0xFFF */ - u32 pad6[736]; + /* Values defined by POWER_PROFILE* macros */ + u32 power_profile; + /* Microsecond value for DCT active cycle */ + u32 dct_active_us; + /* Microsecond value for DCT inactive cycle */ + u32 dct_inactive_us; + /* Unused/reserved: 0x488 - 0xFFF */ + u32 pad6[734]; }; /* diff --git a/drivers/accel/ivpu/vpu_jsm_api.h b/drivers/accel/ivpu/vpu_jsm_api.h index 7da7622742..e46f353121 100644 --- a/drivers/accel/ivpu/vpu_jsm_api.h +++ b/drivers/accel/ivpu/vpu_jsm_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: MIT */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (c) 2020-2023, Intel Corporation. */ /** @@ -27,7 +27,7 @@ /* * API header changed (field names, documentation, formatting) but API itself has not been changed */ -#define VPU_JSM_API_VER_PATCH 0 +#define VPU_JSM_API_VER_PATCH 6 /* * Index in the API version table @@ -43,8 +43,11 @@ /* Max number of impacted contexts that can be dealt with the engine reset command */ #define VPU_MAX_ENGINE_RESET_IMPACTED_CONTEXTS 3 -/** Pack the API structures for now, once alignment issues are fixed this can be removed */ -#pragma pack(push, 1) +/* + * Pack the API structures to enforce binary compatibility + * Align to 8 bytes for optimal performance + */ +#pragma pack(push, 8) /* * Engine indexes. @@ -125,6 +128,19 @@ #define VPU_HWS_MAX_REALTIME_PRIORITY_LEVEL 31U /* + * vpu_jsm_engine_reset_context flag definitions + */ +#define VPU_ENGINE_RESET_CONTEXT_FLAG_COLLATERAL_DAMAGE_MASK BIT(0) +#define VPU_ENGINE_RESET_CONTEXT_HANG_PRIMARY_CAUSE 0 +#define VPU_ENGINE_RESET_CONTEXT_COLLATERAL_DAMAGE 1 + +/* + * Invalid command queue handle identifier. Applies to cmdq_id and cmdq_group + * in this API. + */ +#define VPU_HWS_INVALID_CMDQ_HANDLE 0ULL + +/* * Job format. */ struct vpu_job_queue_entry { @@ -613,7 +629,7 @@ struct vpu_jsm_engine_reset_context { u32 reserved_0; /* Command queue id */ u64 cmdq_id; - /* Flags: 0: cause of hang; 1: collateral damage of reset */ + /* See VPU_ENGINE_RESET_CONTEXT_* defines */ u64 flags; }; @@ -730,11 +746,7 @@ struct vpu_ipc_msg_payload_hws_create_cmdq { u32 host_ssid; /* Engine for which queue is being created */ u32 engine_idx; - /* - * Cmdq group may be set to 0 or equal to - * cmdq_id while each priority band contains - * only single engine instances. - */ + /* Cmdq group: only used for HWS logging of state changes */ u64 cmdq_group; /* Command queue id */ u64 cmdq_id; |