diff options
73 files changed, 1227 insertions, 827 deletions
diff --git a/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml b/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml index 9e5864de49e7..b308047c1edf 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-edp-legacy.yaml @@ -31,13 +31,9 @@ properties: # AUO B116XAK01 eDP TFT LCD panel - auo,b116xa01 # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel - - auo,b133han05 - # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel - auo,b133htn01 # AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel - auo,b133xtn01 - # AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel - - auo,b140han06 # BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel - boe,nv101wxmn51 # BOE NV133FHM-N61 13.3" FHD (1920x1080) TFT LCD Panel @@ -56,8 +52,6 @@ properties: - innolux,n125hce-gn1 # Innolux P120ZDG-BF1 12.02 inch eDP 2K display panel - innolux,p120zdg-bf1 - # InfoVision Optoelectronics M133NWF4 R0 13.3" FHD (1920x1080) TFT LCD panel - - ivo,m133nwf4-r0 # King & Display KD116N21-30NV-A010 eDP TFT LCD panel - kingdisplay,kd116n21-30nv-a010 # LG LP079QX1-SP0V 7.9" (1536x2048 pixels) TFT LCD panel @@ -78,10 +72,6 @@ properties: - sharp,ld-d5116z01b # Sharp 12.3" (2400x1600 pixels) TFT LCD panel - sharp,lq123p1jx31 - # Sharp 14" (1920x1080 pixels) TFT LCD panel - - sharp,lq140m1jw46 - # Starry 12.2" (1920x1200 pixels) TFT LCD panel - - starry,kr122ea0sra backlight: true ddc-i2c-bus: true diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml index e796a1ff8c82..278399adc550 100644 --- a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml +++ b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml @@ -34,6 +34,7 @@ properties: - const: arm,mali-valhall-jm # Mali Valhall GPU model/revision is fully discoverable - items: - enum: + - mediatek,mt8188-mali - mediatek,mt8192-mali - const: arm,mali-valhall-jm # Mali Valhall GPU model/revision is fully discoverable @@ -195,7 +196,9 @@ allOf: properties: compatible: contains: - const: mediatek,mt8183b-mali + enum: + - mediatek,mt8183b-mali + - mediatek,mt8188-mali then: properties: power-domains: diff --git a/MAINTAINERS b/MAINTAINERS index 6a1660480782..d57874b983ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7196,6 +7196,7 @@ L: dri-devel@lists.freedesktop.org S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/gpu/vkms.rst +F: drivers/gpu/drm/ci/xfails/vkms* F: drivers/gpu/drm/vkms/ DRM DRIVER FOR VIRTUALBOX VIRTUAL GPU diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c index 10d6408c9831..6f86f8df30db 100644 --- a/drivers/accel/ivpu/ivpu_debugfs.c +++ b/drivers/accel/ivpu/ivpu_debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include <linux/debugfs.h> @@ -381,6 +381,39 @@ static const struct file_operations ivpu_resume_engine_fops = { .write = ivpu_resume_engine_fn, }; +static int dct_active_get(void *data, u64 *active_percent) +{ + struct ivpu_device *vdev = data; + + *active_percent = vdev->pm->dct_active_percent; + + return 0; +} + +static int dct_active_set(void *data, u64 active_percent) +{ + struct ivpu_device *vdev = data; + int ret; + + if (active_percent > 100) + return -EINVAL; + + ret = ivpu_rpm_get(vdev); + if (ret) + return ret; + + if (active_percent) + ret = ivpu_pm_dct_enable(vdev, active_percent); + else + ret = ivpu_pm_dct_disable(vdev); + + ivpu_rpm_put(vdev); + + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(ivpu_dct_fops, dct_active_get, dct_active_set, "%llu\n"); + void ivpu_debugfs_init(struct ivpu_device *vdev) { struct dentry *debugfs_root = vdev->drm.debugfs_root; @@ -409,7 +442,9 @@ void ivpu_debugfs_init(struct ivpu_device *vdev) debugfs_create_file("resume_engine", 0200, debugfs_root, vdev, &ivpu_resume_engine_fops); - if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX) + if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX) { debugfs_create_file("fw_profiling_freq_drive", 0200, debugfs_root, vdev, &fw_profiling_freq_fops); + debugfs_create_file("dct", 0644, debugfs_root, vdev, &ivpu_dct_fops); + } } diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index f3e0d55f4adb..c91400ecf926 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -58,11 +58,11 @@ module_param_named(sched_mode, ivpu_sched_mode, int, 0444); MODULE_PARM_DESC(sched_mode, "Scheduler mode: 0 - Default scheduler, 1 - Force HW scheduler"); bool ivpu_disable_mmu_cont_pages; -module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0644); +module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0444); MODULE_PARM_DESC(disable_mmu_cont_pages, "Disable MMU contiguous pages optimization"); bool ivpu_force_snoop; -module_param_named(force_snoop, ivpu_force_snoop, bool, 0644); +module_param_named(force_snoop, ivpu_force_snoop, bool, 0444); MODULE_PARM_DESC(force_snoop, "Force snooping for NPU host memory access"); struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv) @@ -391,8 +391,13 @@ int ivpu_boot(struct ivpu_device *vdev) ivpu_hw_irq_enable(vdev); ivpu_ipc_enable(vdev); - if (ivpu_fw_is_cold_boot(vdev)) + if (ivpu_fw_is_cold_boot(vdev)) { + ret = ivpu_pm_dct_init(vdev); + if (ret) + return ret; + return ivpu_hw_sched_init(vdev); + } return 0; } @@ -446,6 +451,26 @@ static const struct drm_driver driver = { .minor = DRM_IVPU_DRIVER_MINOR, }; +static void ivpu_context_abort_invalid(struct ivpu_device *vdev) +{ + struct ivpu_file_priv *file_priv; + unsigned long ctx_id; + + mutex_lock(&vdev->context_list_lock); + + xa_for_each(&vdev->context_xa, ctx_id, file_priv) { + if (!file_priv->has_mmu_faults || file_priv->aborted) + continue; + + mutex_lock(&file_priv->lock); + ivpu_context_abort_locked(file_priv); + file_priv->aborted = true; + mutex_unlock(&file_priv->lock); + } + + mutex_unlock(&vdev->context_list_lock); +} + static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg) { struct ivpu_device *vdev = arg; @@ -459,6 +484,12 @@ static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg) case IVPU_HW_IRQ_SRC_IPC: ivpu_ipc_irq_thread_handler(vdev); break; + case IVPU_HW_IRQ_SRC_MMU_EVTQ: + ivpu_context_abort_invalid(vdev); + break; + case IVPU_HW_IRQ_SRC_DCT: + ivpu_pm_dct_irq_thread_handler(vdev); + break; default: ivpu_err_ratelimited(vdev, "Unknown IRQ source: %u\n", irq_src); break; @@ -664,14 +695,14 @@ static void ivpu_bo_unbind_all_user_contexts(struct ivpu_device *vdev) static void ivpu_dev_fini(struct ivpu_device *vdev) { + ivpu_jobs_abort_all(vdev); + ivpu_pm_cancel_recovery(vdev); ivpu_pm_disable(vdev); ivpu_prepare_for_reset(vdev); ivpu_shutdown(vdev); ivpu_ms_cleanup_all(vdev); - ivpu_jobs_abort_all(vdev); ivpu_job_done_consumer_fini(vdev); - ivpu_pm_cancel_recovery(vdev); ivpu_bo_unbind_all_user_contexts(vdev); ivpu_ipc_fini(vdev); diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 39df96a7623b..63f13b697eed 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -32,6 +32,8 @@ #define IVPU_HW_IP_50XX 50 #define IVPU_HW_IP_60XX 60 +#define IVPU_HW_IP_REV_LNL_B0 4 + #define IVPU_HW_BTRS_MTL 1 #define IVPU_HW_BTRS_LNL 2 @@ -102,6 +104,7 @@ struct ivpu_wa_table { bool interrupt_clear_with_0; bool disable_clock_relinquish; bool disable_d0i3_msg; + bool wp0_during_power_up; }; struct ivpu_hw_info; @@ -147,7 +150,6 @@ struct ivpu_device { int boot; int jsm; int tdr; - int reschedule_suspend; int autosuspend; int d0i3_entry_msg; } timeout; @@ -168,6 +170,7 @@ struct ivpu_file_priv { struct ivpu_bo *ms_info_bo; bool has_mmu_faults; bool bound; + bool aborted; }; extern int ivpu_dbg_mask; @@ -184,6 +187,7 @@ extern bool ivpu_force_snoop; #define IVPU_TEST_MODE_D0I3_MSG_ENABLE BIT(5) #define IVPU_TEST_MODE_PREEMPTION_DISABLE BIT(6) #define IVPU_TEST_MODE_HWS_EXTRA_EVENTS BIT(7) +#define IVPU_TEST_MODE_DISABLE_TIMEOUTS BIT(8) extern int ivpu_test_mode; struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv); diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 1fc4befe7461..de3d66116375 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include <linux/firmware.h> @@ -123,6 +123,14 @@ ivpu_fw_check_api_ver_lt(struct ivpu_device *vdev, const struct vpu_firmware_hea return false; } +static bool is_within_range(u64 addr, size_t size, u64 range_start, size_t range_size) +{ + if (addr < range_start || addr + size > range_start + range_size) + return false; + + return true; +} + static int ivpu_fw_parse(struct ivpu_device *vdev) { struct ivpu_fw_info *fw = vdev->fw; @@ -205,10 +213,24 @@ static int ivpu_fw_parse(struct ivpu_device *vdev) fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size; fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_size; + if (fw_hdr->ro_section_start_address && !is_within_range(fw_hdr->ro_section_start_address, + fw_hdr->ro_section_size, + fw_hdr->image_load_address, + fw_hdr->image_size)) { + ivpu_err(vdev, "Invalid read-only section: start address 0x%llx, size %u\n", + fw_hdr->ro_section_start_address, fw_hdr->ro_section_size); + return -EINVAL; + } + + fw->read_only_addr = fw_hdr->ro_section_start_address; + fw->read_only_size = fw_hdr->ro_section_size; + ivpu_dbg(vdev, FW_BOOT, "Size: file %lu image %u runtime %u shavenn %u\n", fw->file->size, fw->image_size, fw->runtime_size, fw->shave_nn_size); ivpu_dbg(vdev, FW_BOOT, "Address: runtime 0x%llx, load 0x%llx, entry point 0x%llx\n", fw->runtime_addr, image_load_addr, fw->entry_point); + ivpu_dbg(vdev, FW_BOOT, "Read-only section: address 0x%llx, size %u\n", + fw->read_only_addr, fw->read_only_size); return 0; } @@ -270,6 +292,13 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) return -ENOMEM; } + ret = ivpu_mmu_context_set_pages_ro(vdev, &vdev->gctx, fw->read_only_addr, + fw->read_only_size); + if (ret) { + ivpu_err(vdev, "Failed to set firmware image read-only\n"); + goto err_free_fw_mem; + } + 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) { diff --git a/drivers/accel/ivpu/ivpu_fw.h b/drivers/accel/ivpu/ivpu_fw.h index 66fc7da3ab0f..40d9d17be3f5 100644 --- a/drivers/accel/ivpu/ivpu_fw.h +++ b/drivers/accel/ivpu/ivpu_fw.h @@ -30,6 +30,8 @@ struct ivpu_fw_info { u32 dvfs_mode; u32 primary_preempt_buf_size; u32 secondary_preempt_buf_size; + u64 read_only_addr; + u32 read_only_size; }; int ivpu_fw_init(struct ivpu_device *vdev); diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index 9f5e3875baf1..27f0fe4d54e0 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -61,37 +61,48 @@ static void wa_init(struct ivpu_device *vdev) if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) vdev->wa.interrupt_clear_with_0 = ivpu_hw_btrs_irqs_clear_with_0_mtl(vdev); - if (ivpu_device_id(vdev) == PCI_DEVICE_ID_LNL) + if (ivpu_device_id(vdev) == PCI_DEVICE_ID_LNL && + ivpu_revision(vdev) < IVPU_HW_IP_REV_LNL_B0) vdev->wa.disable_clock_relinquish = true; + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + vdev->wa.wp0_during_power_up = true; + IVPU_PRINT_WA(punit_disabled); IVPU_PRINT_WA(clear_runtime_mem); IVPU_PRINT_WA(interrupt_clear_with_0); IVPU_PRINT_WA(disable_clock_relinquish); + IVPU_PRINT_WA(wp0_during_power_up); } static void timeouts_init(struct ivpu_device *vdev) { - if (ivpu_is_fpga(vdev)) { + if (ivpu_test_mode & IVPU_TEST_MODE_DISABLE_TIMEOUTS) { + vdev->timeout.boot = -1; + vdev->timeout.jsm = -1; + vdev->timeout.tdr = -1; + vdev->timeout.autosuspend = -1; + vdev->timeout.d0i3_entry_msg = -1; + } else if (ivpu_is_fpga(vdev)) { vdev->timeout.boot = 100000; vdev->timeout.jsm = 50000; vdev->timeout.tdr = 2000000; - vdev->timeout.reschedule_suspend = 1000; vdev->timeout.autosuspend = -1; vdev->timeout.d0i3_entry_msg = 500; } else if (ivpu_is_simics(vdev)) { vdev->timeout.boot = 50; vdev->timeout.jsm = 500; vdev->timeout.tdr = 10000; - vdev->timeout.reschedule_suspend = 10; vdev->timeout.autosuspend = -1; vdev->timeout.d0i3_entry_msg = 100; } else { vdev->timeout.boot = 1000; vdev->timeout.jsm = 500; vdev->timeout.tdr = 2000; - vdev->timeout.reschedule_suspend = 10; - vdev->timeout.autosuspend = 10; + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + vdev->timeout.autosuspend = 10; + else + vdev->timeout.autosuspend = 100; vdev->timeout.d0i3_entry_msg = 5; } } @@ -125,6 +136,13 @@ int ivpu_hw_power_up(struct ivpu_device *vdev) { int ret; + if (IVPU_WA(wp0_during_power_up)) { + /* WP requests may fail when powering down, so issue WP 0 here */ + ret = wp_disable(vdev); + if (ret) + ivpu_warn(vdev, "Failed to disable workpoint: %d\n", ret); + } + ret = ivpu_hw_btrs_d0i3_disable(vdev); if (ret) ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h index 8ddf9f93189d..1c0c98e3afb8 100644 --- a/drivers/accel/ivpu/ivpu_hw.h +++ b/drivers/accel/ivpu/ivpu_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020 - 2024 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_HW_H__ @@ -15,6 +15,8 @@ #define IVPU_HW_IRQ_FIFO_LENGTH 1024 #define IVPU_HW_IRQ_SRC_IPC 1 +#define IVPU_HW_IRQ_SRC_MMU_EVTQ 2 +#define IVPU_HW_IRQ_SRC_DCT 3 struct ivpu_addr_range { resource_size_t start; diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c index 13734d1abc7d..745e5248803d 100644 --- a/drivers/accel/ivpu/ivpu_hw_btrs.c +++ b/drivers/accel/ivpu/ivpu_hw_btrs.c @@ -504,6 +504,8 @@ static int ip_reset_lnl(struct ivpu_device *vdev) int ret; u32 val; + ivpu_hw_btrs_clock_relinquish_disable_lnl(vdev); + ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, 0, TIMEOUT_US); if (ret) { ivpu_err(vdev, "Wait for *_TRIGGER timed out\n"); @@ -641,8 +643,11 @@ bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq) if (!status) return false; - if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, status)) + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, status)) { ivpu_dbg(vdev, IRQ, "Survivability IRQ\n"); + if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_DCT)) + ivpu_err_ratelimited(vdev, "IRQ FIFO full\n"); + } if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status)) ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ)); @@ -692,21 +697,40 @@ bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq) return true; } -static void dct_drive_40xx(struct ivpu_device *vdev, u32 dct_val) |
